Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
a738f15
docs: add Steam Controller v2 (2025) HID protocol notes + capture har…
C0rn3j Aug 2, 2026
c8c234c
gui: offer all 4 grips + right-stick press in modeshift combo chooser
Patola Jun 15, 2026
8841102
gui: add 2nd grips + right-stick press to remaining button choosers
Patola Jun 15, 2026
ad3790a
sc2/gui: bind capacitive stick touch; label left stick
Patola Jun 15, 2026
5e4acc8
steamdeck: map capacitive stick touch (parity with v2)
Patola Jun 15, 2026
6816d6b
sc2/gui: bind capacitive handle grip sensing (Steam Controller only)
Patola Jun 15, 2026
43af98b
gui: dedicated v2 (Steam Controller 2025) image + stick-touch/grip-se…
C0rn3j Aug 2, 2026
40f1d7a
fix: Ignore X11 errors
C0rn3j Jul 19, 2026
67fdc86
fix: Catch failing generators and log them instead of crashing the menu
C0rn3j Jul 19, 2026
c94152c
fix: Let long vertical menu lists scroll
C0rn3j Jul 19, 2026
4abbdd6
osd: per-controller binding display with a v2 (Steam Controller 2025)…
Patola Jun 18, 2026
89a0053
gui: "Edit Bindings" opens the OSD-keyboard bindings editor (sc-contr…
Patola Jun 18, 2026
c9b3bcd
gui: remove the abandoned controller-driven OSD edit mode (osd_mode)
Patola Jun 19, 2026
e4f44ac
gui: add "Act on release" (inverted button) for always-on sensors
Patola Jun 19, 2026
e2d9a2a
gui: fix Input Test Mode for the v2 controller
Patola Jun 19, 2026
8dca488
gui: show the right stick and d-pad in Input Test Mode
Patola Jun 19, 2026
68cd3de
daemon: remember each controller's profile across (re)connects
Patola Jun 19, 2026
adad7f3
gui: replace the per-controller profile bars with a controller selector
Patola Jun 20, 2026
4c4cde6
fix(gui): make "Restart emulation" wait for the old daemon to exit
Patola Jun 20, 2026
8c0c8cf
fix(usb/sc_dongle): keep the v1 dongle alive when GET_SERIAL stalls
C0rn3j Jul 12, 2026
9a9b524
fix(osd): Add input locking to prevent stuck keys
C0rn3j Jul 15, 2026
51d1822
fix(daemon): release a held action when locking so its key-up isn't lost
Patola Jul 3, 2026
bda7947
fix(osd): keep generic face-button icons for the v2 quick menu
Patola Jul 3, 2026
daf4870
fix(osd): cancel the quick-menu auto-timeout on quit
Patola Jul 3, 2026
affb120
fix(mapper): stop the v2 right stick crashing in set_button under a m…
Patola Jun 21, 2026
30d3205
fix(gui): Input Test mode — selected controller, viewBox cursor, re-a…
Patola Jun 28, 2026
0087c34
feat(controller-images): Input Test highlights and test-area fixes (S…
Patola Jun 28, 2026
dc965b7
fix(gui,images): correct Deck back-button mapping + stick-touch Input…
Patola Jun 28, 2026
6df7ad4
fix(config): default "disable emulation on close" ON for Steam Deck
Patola Jun 28, 2026
4a9fed2
feat(gui,images): per-controller button-image override + Deck back-bu…
Patola Jun 28, 2026
9468952
fix(packaging,images): package per-controller icon dirs; Deck icons t…
Patola Jun 28, 2026
121b7a2
feat(images): consistent around-controller icons for Deck & SC2 (from…
Patola Jun 28, 2026
0d7b7d3
fix(images): lighten the Deck Steam/QAM button infill
Patola Jul 3, 2026
ece6180
fix(gui): SC v1 mislayout
Patola Jun 28, 2026
fe9e4b7
fix(gui): Deck button layout — D-Pad to top, Steam to the left column
Patola Jun 28, 2026
4462c3d
fix(gui,osd): SC2 hover offset + invisible OSD submenus
Patola Jun 28, 2026
4870a8b
fix(gui): Deck stick/dpad hover highlight
Patola Jun 29, 2026
5dc9477
feat(gui): show the Steam logo on the Steam Controller v1 C button
Patola Jun 29, 2026
d07c48e
fix(gui): size the SC v1 Steam logo to the generic C button
Patola Jun 29, 2026
8810d08
fix(gui): clear Input Test highlights when it is turned off
Patola Jul 1, 2026
c7ee8cd
fix(gui): Deck back-paddle order in side panel (L4/R4 above L5/R5)
Patola Jul 2, 2026
9bc67a1
build(images): add an svgo config and wire the asset generators to mi…
Patola Jul 3, 2026
2dd3ba1
perf(images): svgo-optimize the SC1/SC2/Deck SVGs
Patola Jul 3, 2026
5c81b0f
style(types): annotate the Steam Controller v2 / Deck changeset
C0rn3j Aug 2, 2026
7967780
fix(osd): Steam Deck OSD menu - helpers work in the AppImage, no Turn…
C0rn3j Jul 12, 2026
5415737
binding-display: auto-generate the template from controller art
Patola Jul 4, 2026
635d5d4
binding-display: add Steam Deck support
Patola Jul 4, 2026
0b98565
sccdaemon: show/lock the invoking controller for Display Bindings
Patola Jul 4, 2026
9030745
osd/binding-display: fit the window to the screen (Steam Deck)
Patola Jul 4, 2026
7d551ff
osd/binding-display: shrink v1 labels to fit their boxes
Patola Jul 4, 2026
26ab25a
binding-display: honor group transforms when placing markers (Deck)
Patola Jul 4, 2026
e4b524a
binding-display: add ds4/ds5/x360 templates
Patola Jul 4, 2026
6ec3c39
input-test: square the degenerate stick/pad test-areas
Patola Jul 4, 2026
41b76d9
input-test: track and highlight the DS4/DS5 touchpad
Patola Jul 4, 2026
48efb42
mapper: guard rstick/dpad state access for gamepads on the HID decoder
Patola Jul 4, 2026
fa754b3
modifiers: neutralize a released absolute-gyro action in ModeModifier
Patola Jul 5, 2026
1996197
gui: fix gyro Per-Axis mouse-axis labels + add a Clear button
Patola Jul 5, 2026
f6d8273
fix(gyro,gui): make gyro->mouse fully work (routing, labels, directio…
Patola Jul 6, 2026
de835b3
fix(actions): decode euler gyros in TiltAction (rest false-fires, axi…
Patola Jul 9, 2026
3325778
gyro: intuitive mouse semantics -- Absolute = laser pointer, relative…
Patola Jul 10, 2026
b6ec2b1
tests,docs: cover the 'inverted' modifier (3 long-failing meta-tests)
Patola Jul 11, 2026
2a46334
fix(gyro): align "Mouse (Desktop)" signs with the calibrated rate table
Patola Jul 12, 2026
c9ed1ef
gui: per-controller grip/paddle button lists (gyro enablers, chords, …
Patola Jul 12, 2026
6b44448
fix(gyro): make the Recenter Gyro special action actually recenter
Patola Jul 12, 2026
c43e881
docs: add a "Using multiple controllers" section to the README
Patola Jun 19, 2026
881bbab
docs(README): document the controller selector and add a multi-contro…
Patola Jun 21, 2026
cf0de64
docs(appimage): document AppImage udev steps
C0rn3j Jul 12, 2026
7ed3dc1
docs(TODO.md): Add changes
Patola Jun 15, 2026
236bd6a
gui: name the Bluetooth hidraw DualShock 4 in the controller list
Patola Jul 26, 2026
0ac0c6b
sc1: convert the hardware quaternion to EUREL euler angles (one gyro …
Patola Jul 26, 2026
2ad2bb1
fix(gyro): re-center absolute gyro at every activation, not at release
Patola Jul 26, 2026
1298431
fix(gyro): scale gyro output to the target axis' own range
Patola Aug 2, 2026
613c439
fix(modeshift): give analog range conditions hysteresis
Patola Aug 2, 2026
d2a6658
fix(gyro): apply per-axis sensitivity once, before clamping
Patola Aug 2, 2026
1049009
fix(sc2): enable the IMU quaternion stream, not just rates and accel
Patola Aug 8, 2026
b7e8839
fix(gui): make "Mouse (Emulate Stick)" actually emulate a stick
Patola Aug 8, 2026
d797581
feat(sc2): simulate the touchpad click with haptics
Patola Aug 10, 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
Loading