Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
011a31c
docs: add Steam Controller v2 (2025) HID protocol notes + capture har…
C0rn3j Aug 2, 2026
33410da
gui: offer all 4 grips + right-stick press in modeshift combo chooser
Patola Jun 15, 2026
ff91490
gui: add 2nd grips + right-stick press to remaining button choosers
Patola Jun 15, 2026
e32676e
sc2/gui: bind capacitive stick touch; label left stick
Patola Jun 15, 2026
953fc91
steamdeck: map capacitive stick touch (parity with v2)
Patola Jun 15, 2026
cfcbfe1
sc2/gui: bind capacitive handle grip sensing (Steam Controller only)
Patola Jun 15, 2026
d4243ce
gui: dedicated v2 (Steam Controller 2025) image + stick-touch/grip-se…
C0rn3j Aug 2, 2026
b1f06fd
fix: Ignore X11 errors
C0rn3j Jul 19, 2026
e248a10
fix: Catch failing generators and log them instead of crashing the menu
C0rn3j Jul 19, 2026
428afcd
fix: Let long vertical menu lists scroll
C0rn3j Jul 19, 2026
46771b4
osd: per-controller binding display with a v2 (Steam Controller 2025)…
Patola Jun 18, 2026
56fb35c
gui: "Edit Bindings" opens the OSD-keyboard bindings editor (sc-contr…
Patola Jun 18, 2026
d1c42c2
gui: remove the abandoned controller-driven OSD edit mode (osd_mode)
Patola Jun 19, 2026
ae899ed
gui: add "Act on release" (inverted button) for always-on sensors
Patola Jun 19, 2026
60d3eef
gui: fix Input Test Mode for the v2 controller
Patola Jun 19, 2026
1d2016e
gui: show the right stick and d-pad in Input Test Mode
Patola Jun 19, 2026
efd40e1
daemon: remember each controller's profile across (re)connects
Patola Jun 19, 2026
64b8166
gui: replace the per-controller profile bars with a controller selector
Patola Jun 20, 2026
d65b236
fix(gui): make "Restart emulation" wait for the old daemon to exit
Patola Jun 20, 2026
b330a81
fix(usb/sc_dongle): keep the v1 dongle alive when GET_SERIAL stalls
C0rn3j Jul 12, 2026
a4ae647
fix(osd): Add input locking to prevent stuck keys
C0rn3j Jul 15, 2026
0e70619
fix(daemon): release a held action when locking so its key-up isn't lost
Patola Jul 3, 2026
966102b
fix(osd): keep generic face-button icons for the v2 quick menu
Patola Jul 3, 2026
297241d
fix(osd): cancel the quick-menu auto-timeout on quit
Patola Jul 3, 2026
87fcb99
fix(mapper): stop the v2 right stick crashing in set_button under a m…
Patola Jun 21, 2026
6a6281b
fix(gui): Input Test mode — selected controller, viewBox cursor, re-a…
Patola Jun 28, 2026
41f3bdd
feat(controller-images): Input Test highlights and test-area fixes (S…
Patola Jun 28, 2026
a1291cc
fix(gui,images): correct Deck back-button mapping + stick-touch Input…
Patola Jun 28, 2026
51616b8
fix(config): default "disable emulation on close" ON for Steam Deck
Patola Jun 28, 2026
e030eea
feat(gui,images): per-controller button-image override + Deck back-bu…
Patola Jun 28, 2026
66b20d1
fix(packaging,images): package per-controller icon dirs; Deck icons t…
Patola Jun 28, 2026
52da228
feat(images): consistent around-controller icons for Deck & SC2 (from…
Patola Jun 28, 2026
2bdd84f
fix(images): lighten the Deck Steam/QAM button infill
Patola Jul 3, 2026
a12f58a
fix(gui): SC v1 mislayout
Patola Jun 28, 2026
f4ae10d
fix(gui): Deck button layout — D-Pad to top, Steam to the left column
Patola Jun 28, 2026
fa15599
fix(gui,osd): SC2 hover offset + invisible OSD submenus
Patola Jun 28, 2026
6870ed0
fix(gui): Deck stick/dpad hover highlight
Patola Jun 29, 2026
f3b7224
feat(gui): show the Steam logo on the Steam Controller v1 C button
Patola Jun 29, 2026
3b3906e
fix(gui): size the SC v1 Steam logo to the generic C button
Patola Jun 29, 2026
ef294ef
fix(gui): clear Input Test highlights when it is turned off
Patola Jul 1, 2026
3bb4cd2
fix(gui): Deck back-paddle order in side panel (L4/R4 above L5/R5)
Patola Jul 2, 2026
ceef075
build(images): add an svgo config and wire the asset generators to mi…
Patola Jul 3, 2026
cccc3f9
perf(images): svgo-optimize the SC1/SC2/Deck SVGs
Patola Jul 3, 2026
5052c07
style(types): annotate the Steam Controller v2 / Deck changeset
C0rn3j Aug 2, 2026
0d40e60
fix(osd): Steam Deck OSD menu - helpers work in the AppImage, no Turn…
C0rn3j Jul 12, 2026
399ee48
binding-display: auto-generate the template from controller art
Patola Jul 4, 2026
bd6f268
binding-display: add Steam Deck support
Patola Jul 4, 2026
3d93c28
sccdaemon: show/lock the invoking controller for Display Bindings
Patola Jul 4, 2026
539f28e
osd/binding-display: fit the window to the screen (Steam Deck)
Patola Jul 4, 2026
c99fa0b
osd/binding-display: shrink v1 labels to fit their boxes
Patola Jul 4, 2026
dd490b2
binding-display: honor group transforms when placing markers (Deck)
Patola Jul 4, 2026
0fc73ac
binding-display: add ds4/ds5/x360 templates
Patola Jul 4, 2026
efa2a50
input-test: square the degenerate stick/pad test-areas
Patola Jul 4, 2026
6dd57ef
input-test: track and highlight the DS4/DS5 touchpad
Patola Jul 4, 2026
822fa7e
mapper: guard rstick/dpad state access for gamepads on the HID decoder
Patola Jul 4, 2026
b8fadc6
modifiers: neutralize a released absolute-gyro action in ModeModifier
Patola Jul 5, 2026
130de92
gui: fix gyro Per-Axis mouse-axis labels + add a Clear button
Patola Jul 5, 2026
8bbc72c
fix(gyro,gui): make gyro->mouse fully work (routing, labels, directio…
Patola Jul 6, 2026
bcb56a2
fix(actions): decode euler gyros in TiltAction (rest false-fires, axi…
Patola Jul 9, 2026
88f3fff
gyro: intuitive mouse semantics -- Absolute = laser pointer, relative…
Patola Jul 10, 2026
2f904ec
tests,docs: cover the 'inverted' modifier (3 long-failing meta-tests)
Patola Jul 11, 2026
60d8d16
fix(gyro): align "Mouse (Desktop)" signs with the calibrated rate table
Patola Jul 12, 2026
592ba3d
gui: per-controller grip/paddle button lists (gyro enablers, chords, …
Patola Jul 12, 2026
508a560
fix(gyro): make the Recenter Gyro special action actually recenter
Patola Jul 12, 2026
c6e1f36
docs: add a "Using multiple controllers" section to the README
Patola Jun 19, 2026
0467d21
docs(README): document the controller selector and add a multi-contro…
Patola Jun 21, 2026
46f08f0
docs(appimage): document AppImage udev steps
C0rn3j Jul 12, 2026
f39c439
docs(TODO.md): Add changes
Patola Jun 15, 2026
a4eb28f
gui: name the Bluetooth hidraw DualShock 4 in the controller list
Patola Jul 26, 2026
0418e20
sc1: convert the hardware quaternion to EUREL euler angles (one gyro …
Patola Jul 26, 2026
e49b457
fix(gyro): re-center absolute gyro at every activation, not at release
Patola Jul 26, 2026
9afb7db
fix(gyro): scale gyro output to the target axis' own range
Patola Aug 2, 2026
fbc2198
fix(modeshift): give analog range conditions hysteresis
Patola Aug 2, 2026
b4bff7e
fix(gyro): apply per-axis sensitivity once, before clamping
Patola Aug 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ User-mode driver, mapper and GTK3 based GUI for Steam Controller, DS4 and many o

## Features
- Allows to setup, configure and use the Steam Controller without ever launching Steam
- Connect multiple controllers at the same time
- Connect multiple controllers at the same time, each with its own remembered profile
- Supports profiles switchable in GUI or with controller button
- Stick, Pads and Gyroscope input
- Steam Controller 2 (2026) support, including its capacitive stick-touch and grip sensors — bind actions to them directly, or use them as conditions in mode-shift combinations
- Haptic Feedback and in-game Rumble support
- OSD, Menus, On-Screen Keyboard for desktop *and* in games.
- Automatic profile switching based on active window.
Expand All @@ -23,6 +24,50 @@ User-mode driver, mapper and GTK3 based GUI for Steam Controller, DS4 and many o

Based on [Standalone Steam Controller Driver](https://github.com/ynsta/steamcontroller) by [Ynsta](https://github.com/ynsta).

## Using multiple controllers

SC Controller can drive several controllers at once — Steam Controllers (v1 and
v2), a DualShock 4 and others can all be connected together.

- **One window, two bars: pick the controller, then its profile.** Just connect
them: a controller-selector bar lists every connected controller (by type,
numbered when you have more than one of the same model) together with its
current profile; choosing one shows it on the big controller image, and a
second bar sets that controller's profile. There is no separate window per
device. The controller that connected *first* is the primary one — it is the
one drawn by default and the target when a command (a menu, the OSD) does not
name a specific controller.
- **Each controller keeps its own profile.** Selecting a controller and setting
a profile applies only to that controller. The choice is remembered and
restored automatically the next time that controller connects, so you do not
have to re-pick it every session.
- **Disconnecting is safe.** Turning one controller off (or letting it go idle)
leaves the window and the other controllers untouched; when it comes back it
returns to its remembered profile.

![SC Controller with three controllers connected](docs/multiple-controllers.jpg?raw=true)

*Two Steam Controller v1s and a Steam Controller v2 connected at once: the
selector at the top lists each controller — numbered when there are duplicates —
alongside its current profile.*

### Telling controllers apart

How a controller is identified — and therefore which remembered profile and
per-controller settings it gets — is governed by **Use Serial Numbers to
Identify Controllers** in *Settings*:

- **Off (default):** controllers are identified by connection order (first
connected, second connected, …). This is simplest for a fixed setup, but if
you change which controller powers on first they will swap profiles.
- **On:** each controller is identified by its own hardware serial number, so
its profile and settings follow the physical device no matter what order
things connect in.

Turn this **on** when you regularly use more than one controller — especially
two of the same model, such as two Steam Controllers — and want each to reliably
keep its own profile.

## Like what I'm doing?

You can check out the ways to donate on [my website](https://rys.rs/donate), or just go straight to my [Ko-Fi](https://ko-fi.com/martinrys).
Expand All @@ -40,6 +85,23 @@ Linux:
- **Void Linux:** Packaged as [sc-controller](https://github.com/void-linux/void-packages/blob/master/srcpkgs/sc-controller/template) - Run `xbps-install -S sc-controller` in a terminal, points to archived Ryochan7's fork at the time of writing
- **Others:** You can attempt to use one of the AppImages (try all, AppImages built on older distributions tend to work better), or a package meant for your parent distribution if applicable. Flatpak is planned.

### AppImage: install the udev rules

The AppImage is self-contained but **cannot install the udev rules** it needs (those live in a system directory). Without them your user can't access the controller and SC Controller can't create the virtual gamepad (`/dev/uinput`), so a detected controller appears to "do nothing". Distro packages install these rules for you; **AppImage users must do it once, by hand:**

1. Download `69-sc-controller.rules` from the [latest release](https://github.com/Patola/sc-controller-cc/releases/latest).
2. Copy it into place — this needs `sudo`:
```sh
sudo cp 69-sc-controller.rules /etc/udev/rules.d/69-sc-controller.rules
```
3. Reload and re-apply the rules:
```sh
sudo udevadm control --reload-rules && sudo udevadm trigger
```
4. Unplug and replug the controller (or its wireless dongle) — or reboot.

Only the AppImage needs this; the Arch and other distro packages already ship these rules. **The Steam Deck doesn't need it either** — SteamOS already ships udev rules for Steam devices, so the AppImage works out of the box there.

Windows:
- It should be possible to get it running as per the [wiki](https://github.com/C0rn3j/sc-controller/wiki/Running-SC-Controller-on-Windows), but this is untested and might be broken, report a bug if so

Expand Down Expand Up @@ -80,3 +142,32 @@ docker build -o build-output --build-arg BASE_CODENAME=noble .
- Optionally checkout a branch or a tag, like `main`(default) or `v0.6.2`
- Execute `./run.sh`, this automatically builds the project into a venv called `.venv`, activates it and runs sc-controller, which in turn runs scc-daemon if one does not run already
- If you are debugging an issue, running `./run.sh daemon` first will launch the daemon in debug mode, allowing you to launch sc-controller in another terminal with `./run.sh` - note that sc-controller launched via `run.sh` always runs in debug mode too.

### Regenerating controller artwork (for contributors)

Some SVG assets under `images/` are **generated** from source drawings by scripts
in `tools/`, so edit the source and rerun the script rather than hand-editing the
committed output. All scripts run from the repository root and optimise their
output with [`svgo`](https://github.com/svg/svgo) when it is on `PATH` (optional;
without it the SVGs are just left un-minified). The `svgo` config
(`tools/svgo.config.js`) deliberately preserves the element ids, `<rect>`
geometry, `viewBox` and `display:none` layers that the GUI relies on.

- **`tools/gen_sc2_image.py`** — builds the Steam Controller v2 GUI artwork
(`images/controller-images/sc2.svg`, the face-button glyphs and side-panel
icons) from the traced sources in `tools/` (`sc2-source.svg`, `sc2-assets/`).

- **`tools/gen_binding_display.py`** — builds the per-controller *Display Current
Bindings* templates in `images/binding-display/<gui-background>.svg`. Instead of
a hand-drawn asset per controller, it derives each template straight from that
controller's GUI drawing (`images/controller-images/<name>.svg`): it scales the
drawing into the OSD canvas, recolours it into the binding-display palette
(green outlines over two greys on a dark backdrop) and drops a marker ring at
each control's `AREA_*` anchor so the binding boxes can draw connector lines to
them. The OSD then picks the file up automatically via the controller's gui
`background` name (see `scc/osd/binding_display.py`, `_resolve_image`).

To add a controller: give it an entry in the script's `CONTROLLERS` table (its
source drawing + which `AREA_*` anchors each binding box points at) and a
matching box layout in `LAYOUTS` in `scc/osd/binding_display.py`, then rerun the
script. Controllers that share a physical control set can share a layout.
143 changes: 143 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,135 @@
List of (possibly) planned features in no particular order:

- Selectable output device: virtual Xbox (today's default), virtual DS4/DS5,
or NO virtual controller at all. The current "Xbox 360 pad" is just a
generic uinput device wearing an X360 identity defined entirely in
config["output"] (scc/config.py: vendor/product/name/buttons/axes), so the
architecture already treats identity as data. Three tiers of work:
- no-controller mode (keyboard+mouse only) ALREADY EXISTS as the
undocumented SCC_NOGAMEPAD env var (scc/mapper.py create_gamepad);
promote it to a config key + GUI toggle (trivial), or per-profile
(moderate: create/destroy the uinput gamepad on profile switch).
Essential for games that refuse mouse/keyboard input while any
controller is detected;
- evdev-level DS4/DS5 identity presets (Sony VID/PID + the button/axis
layout SDL's gamecontrollerdb expects on the classic path): preset
table + GUI dropdown; gives PlayStation glyphs in most games, but no
gyro/touchpad/lightbar (those ride on hidraw, which uinput cannot
fake; SDL HIDAPI just falls back to evdev);
- faithful DS4/DS5 emulation via /dev/uhid: present a real HID device so
the kernel's hid-playstation binds and exposes motion/touchpad nodes
-> native in-game gyro from ANY supported controller. Big: a uhid
backend beside uinput, authentic report descriptors/streams, a udev
rule for /dev/uhid. Prior art exists (fake-DS4-over-uhid projects).

- DualShock 4 / DualSense (ds4/ds5) polish. The HID driver is now functional
(mapper rstick/dpad guards, touchpad coordinate scaling + click highlight), but
rough edges remain:
- the two analog sticks are asymmetric in Input Test -- the left and right
stick brighten / behave differently from each other;
- the input icons drawn around the controller are the generic ones, not the
DualShock face symbols (cross / circle / square / triangle);
- the DS4 gyro works as relative and absolute (host-side euler integration in
_step_orientation, verified on hardware) but the absolute path is gyro-only,
so it DRIFTS and gimbals on large combined rotations. The clean next step is
accelerometer drift-correction: fuse gyro + accel (complementary filter) to
pin pitch/roll to the gravity vector -- the raw accel is still in q1-q3 right
after decode, before _step_orientation overwrites them (yaw has no absolute
reference without a magnetometer, so it drifts inherently);
- gyro -> MOUSE routes to the stick instead: an Axes/Rels IntEnum value
collision (ABS_X == REL_X) makes a mouse axis serialize/round-trip as a stick
axis. The gyro editor labels + chooser display are fixed, but the save/reload
path still needs a proper Axes-vs-Rels disambiguation; use gamepad axes for
gyro meanwhile;
- no rumble: neither DS4Controller nor DS4HidRawController drives the pad (the
DS5 driver does) -- port the DS5/kernel output report; over Bluetooth the
DS4HidRawController is input-only, so rumble + lightbar there need output
reports with the BT CRC32 wrapper (mirror DS5HidRawController);
- the lightbar LED is not driven (no DS4-specific set_led);
- DS5 is UNVERIFIED (no DualSense hardware here): its HID touchpad scaling was
added by analogy to the DS4 (DualSense pad assumed 1920x1080) and not tested;
the DS5HidRawController touchpad is still unscaled and stores cpad as unsigned
c_uint16, which can't hold the signed scaled range -- it needs a field type
change as well as scaling.
- Multiple on-screen menus (and possibly keyboards) when using multiple controllers
- Injecting emulated xbox controller into wine
- mnuImage right-click "change background" menu has no `sc2` entry (the v2
image is selected automatically via sc2.config.json `gui.background`, but
it can't be picked manually from that menu yet).
- Custom small (24px) controller icons per supported controller. Today only the
Steam Controller v1 (sc-*) and v2 (sc2-*) have bespoke top-down glyphs; every
other type (deck, ds4, ds5, evdev, hid, scbt, fake) reuses the same generic
silhouette, just recolored. Draw a distinct glyph per type so each controller
is recognisable at a glance. The v2 glyph could also be refined further (its
trackpads are necessarily small at 24px).
- Steam Controller v1 GET_SERIAL reliability (nicety). The flaky v1 serial read
is now handled gracefully - usb.py retries a stalled control request instead of
tearing the dongle down, and sc_dongle falls back to a generated id if it never
reads - so multiple v1s with "Use Serial Numbers" on are detected reliably.
Remaining nicety: investigate *why* GET_SERIAL stalls, so a v1 always ends up
with its real serial (today a persistent stall yields a positional id instead).
- Continuous "HD rumble" for the Steam Controller v2 (and v1/Deck). The SC pads
are LRA voice-coil actuators, not ERM spin-motors. We already drive single
pulses (v1: FEEDBACK report 0x8F; v2: interrupt-OUT report 0x82, effect 0x01 =
one click) which suit pad/scroll detents but NOT sustained, amplitude/
frequency-modulated game rumble. Gap: the v2's continuous-rumble report is
unknown (see sc2.py feedback(): "sustained game rumble may need another report,
not yet found"); the v2 uses its own report scheme (interrupt-OUT 0x82),
distinct from the Deck's feature-report commands, so it needs confirming for
the v2 specifically. Approach (do NOT brute-force the HID space by trial and
error - a wrong report just does nothing and gives no signal):
1. Read the canonical implementations: SDL's hidapi Steam driver
(SDL_hidapi_steam.c / SDL_hidapi_steamdeck.c - ID_TRIGGER_RUMBLE_CMD plus
the left/right gain "magic numbers") and the Linux kernel
drivers/hid/hid-steam.c (FF play_effect, derived from SDL's Deck code).
2. Check first whether SDL3 already rumbles the v2 by its VID/PID - if so,
its source *is* the v2 report format and no capture is needed.
3. Otherwise capture ground truth: run Steam Input on the v2, trigger rumble
(Steam's controller rumble test, or a rumbling game) and capture the USB
OUTPUT reports with usbmon + Wireshark; decode the continuous-rumble
report Steam actually sends.
4. Replicate it in sc2.py feedback() and diff the emitted bytes against the
capture to confirm.
5. Map the emulated gamepad's FF_RUMBLE strong/weak magnitudes to the LRA's
amplitude/frequency/gain and tune for feel (LRA != ERM, so a curve is
needed).
Plumbing already exists (emulated gamepad FF -> controller.feedback()); the
missing piece is the v2 continuous-rumble report itself. Refs: SDL hidapi steam
driver, kernel hid-steam.c, and Alice Mikhaylenko's "Steam Deck, HID, and
libmanette adventures" writeup.
- Deck OSD menu fixes. (a) "Display Current Bindings..." and "Run Program..."
ship disabled in the menu settings; once enabled they appear in the OSD, but
selecting them does nothing - their shell() actions (scc-osd-show-bindings,
scc-osd-launcher) don't actually run/work on the Deck. Make them functional.
(b) Remove "Turn Controller OFF" from the Deck's OSD menu - the Deck's
built-in controller can't be powered off (today it shows and does nothing).
Entries defined in scc/gui/global_settings.py (~L45-58, e.g.
"Turn Controller OFF" -> osd(turnoff())); menu data in
default_menus/Default.menu.
- Generalize the OSD "Turn Controller OFF" hiding. It's currently hidden only
for the Deck's built-in controls (controller type == "deck", checked in
scc/osd/menu.py against the --controller-type the daemon passes). Replace that
hardcoded type check with a per-controller capability (a ControllerFlags bit or
a controller.can_turnoff()) so any controller that can't be powered off
remotely hides the entry, not just the Deck.
- Deck tray/status icon not visible. On the Steam Deck the status (tray) icon
doesn't appear even with the option enabled - works on desktop now that
libdbusmenu is bundled, so this is a Deck/gamescope SNI-tray-host issue to
investigate.
- Rebrand the AppImage desktop app-id. app_info.id in AppImageBuilder.yml /
AppImageBuilder.debian.yml is still org.c0rn3j.sc-controller (upstream), so the
installed .desktop carries the upstream id, and the after_bundle step symlinks
it as org.c0rn3j.sc-controller.desktop. Switch both to org.patola.sc-controller-cc
once the fork is stable and we have committed/PR'd to upstream.
- Replace the last deprecated GTK stock-icon calls. macro_editor.py (the
up/down/delete buttons) and modeshift_editor.py (the clear button) still call
`Gtk.Image.new_from_stock("gtk-go-up" / "gtk-go-down" / "gtk-delete", ...)`.
They render today (GTK maps the stock id to an icon internally) but the stock
API is deprecated; move them to `Gtk.Image.new_from_icon_name` with freedesktop
names (go-up / go-down / edit-delete, or the -symbolic variants - all present in
Adwaita/Breeze). Same class as the profile_switcher.py save/edit buttons, which
were actively blank because `new_from_icon_name` was handed the stock ids
"gtk-save"/"gtk-edit" (now document-save / document-edit).

Hard stuff:
- Injecting emulated xbox controller into PlayOnLinux
Expand All @@ -10,7 +138,22 @@ Very hard stuff:
- Visual feedback in binding editor ( [what this guy says](https://www.reddit.com/r/linux_gaming/comments/5pcdmr/sc_controller_use_steam_controller_without_steam/dcqpvf4/) )

**Done** stuff:
- "Act on release" (inverted button): a general InvertedButtonModifier plus a
checkbox in the button action editor (next to Toggle/Repeat) that fires a
binding on *release* instead of press - for always-on sensors like the
capacitive grips. Round-trips with the Custom Action `inverted(...)` token.
- Dedicated v2 controller artwork: traced SVG (tools/sc2-source.svg) wired by
tools/gen_sc2_image.py into controller-images/sc2.svg + v2 face-overlay
glyphs (button-images/sc2_*.svg, lifted from the drawn symbols so the face
buttons are blank in the art -> no duplication, monochrome ABXY, round Steam,
single dots) + v2 side-panel icons (images/sc2/*.svg, per-controller override
added in app.apply_gui_config_buttons). Control-name ids on sticks/pads/dpad/
bumpers + grip-touch shapes so everything highlights on hover; darker body
(#b8b8b8). sc2.config.json points at it all. Replaces the borrowed Deck image.
- Multicontroller support
- Per-controller profile memory: each controller's profile is remembered by id
(config["controllers"][id]["profile"]) and restored on (re)connect - follows
the physical device with "Use Serial Numbers" on, per-slot otherwise.
- Configurable gamepad type (e.g. 4 axes and 16 buttons)
- Steam Profile import
- Radial Menu for the Joystick/Trackpad
Expand Down
8 changes: 8 additions & 0 deletions docs/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,14 @@ A button whenever physical button is pressed.
#### <a name="released"></a> released(action)
Creates action that occurs for brief moment when button is released.

#### <a name="inverted"></a> inverted(action)
Acts on release: swaps press and release, so the wrapped action is held while
the physical button is NOT pressed and released while it is. Meant for
always-on sensors such as the capacitive handle grips, which read "on" the
whole time the controller is held - inverting them fires the action when you
let go. Unlike `pressed`/`released`, which emit a momentary tap, this is a
true held inversion of the button state.

#### <a name="touched"></a> pressed(action)
Creates action that occurs for brief moment when finger touches pad.

Expand Down
Binary file added docs/multiple-controllers.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion glade/action_editor.glade
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@
<property name="destroy-with-parent">True</property>
<property name="type-hint">dialog</property>
<signal name="destroy" handler="on_Dialog_destroy" swapped="no"/>
<signal name="key-press-event" handler="on_Dialog_key_press_event" swapped="no"/>
<child>
<!-- n-columns=3 n-rows=7 -->
<object class="GtkGrid" id="grEditor">
Expand Down
Loading