Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
1e0441f
docs: add Steam Controller v2 (2025) HID protocol notes + capture har…
Patola Jun 14, 2026
fee0c12
docs: add v2 command channel (from Steam usbmon capture)
Patola Jun 14, 2026
a2f5246
sc2: scaffold the new Steam Controller (v2) driver
Patola Jun 14, 2026
0146db3
sc2: lenient input transfer for mixed-length reports
Patola Jun 14, 2026
d47b7f0
sc2: enable driver + fix live bring-up bugs
Patola Jun 14, 2026
3558da9
docs: confirm gyro enable command and IMU location
Patola Jun 14, 2026
17c15d0
sc2: decode and parse the IMU (accel / quaternion / gyro)
Patola Jun 14, 2026
3950360
sc2: map the 4th system button (View)
Patola Jun 14, 2026
fa8910c
sc2: fix gyro pitch polarity (verified live)
Patola Jun 14, 2026
0e15364
daemon: fix Feedback socket command (bytes/str bugs)
Patola Jun 14, 2026
84e2f3f
sc2: implement click haptics (output report 0x82)
Patola Jun 14, 2026
3ffb8a5
sc2: support the wired (USB-C, 0x1302) transport
Patola Jun 14, 2026
182581a
sc2: GUI controller config (images/sc2.config.json)
Patola Jun 14, 2026
af356b2
mapper: fix right pad / stick / dpad for non-Deck HAS_RSTICK controllers
Patola Jun 14, 2026
aecb4af
gui: offer all 4 grips + right-stick press in modeshift combo chooser
Patola Jun 15, 2026
5c33e55
gui: add 2nd grips + right-stick press to remaining button choosers
Patola Jun 15, 2026
9433f88
sc2/gui: bind capacitive stick touch; label left stick
Patola Jun 15, 2026
122bc82
steamdeck: map capacitive stick touch (parity with v2)
Patola Jun 15, 2026
8d2a6ba
sc2/gui: bind capacitive handle grip sensing (Steam Controller only)
Patola Jun 15, 2026
f5508b1
TODO: invertible grip sensing (act on release)
Patola Jun 15, 2026
f41c5e8
gui: rename grip-sensing labels to "Grip Touched"
Patola Jun 15, 2026
cff668d
gui: add sc2 controller icons (fix red/unassigned icon)
Patola Jun 15, 2026
1749f6d
TODO: capture v2 GUI plan (stick "Touch" tab, grip on main, v2 artwork)
Patola Jun 15, 2026
f85e401
gui: dedicated v2 (Steam Controller 2025) image + stick-touch/grip-se…
Patola Jun 16, 2026
2ec35ce
osd: general OSD menu fixes (generators, long-menu scroll, autoswitch)
Patola Jun 18, 2026
a920e42
fix controller turn-off/on: keep last image, Puck re-attaches
Patola Jun 18, 2026
387c45c
osd: fix the on-screen keyboard on Wayland (+ restore redraw_background)
Patola Jun 18, 2026
e3f22c4
osd: per-controller binding display with a v2 (Steam Controller 2025)…
Patola Jun 18, 2026
4488a50
gui: "Edit Bindings" opens the OSD-keyboard bindings editor (sc-contr…
Patola Jun 18, 2026
b0a016a
gui: remove the abandoned controller-driven OSD edit mode (osd_mode)
Patola Jun 19, 2026
b7299b2
sc2: correct release year to 2026 and document the stick-press mapping
Patola Jun 19, 2026
60e48fb
gui: add "Act on release" (inverted button) for always-on sensors
Patola Jun 19, 2026
fb6d612
gui: fix Input Test Mode for the v2 controller
Patola Jun 19, 2026
72665e3
docs(todo): mark "Act on release" done; scope per-controller profile …
Patola Jun 19, 2026
1cf065b
gui: show the right stick and d-pad in Input Test Mode
Patola Jun 19, 2026
792e014
docs: correct Steam Controller 2 release year to 2026 in README
Patola Jun 19, 2026
00889be
daemon: remember each controller's profile across (re)connects
Patola Jun 19, 2026
58e0472
docs: add a "Using multiple controllers" section to the README
Patola Jun 19, 2026
1c8650e
images: give the Steam Controller v2 a distinct controller icon
Patola Jun 20, 2026
e710046
gui: replace the per-controller profile bars with a controller selector
Patola Jun 20, 2026
b42597a
fix(sc_dongle): repair a Python 2->3 port bug that dropped v1 control…
Patola Jun 20, 2026
d2d05d8
fix(gui): make "Restart emulation" wait for the old daemon to exit
Patola Jun 20, 2026
e68d3bc
docs(TODO): note per-controller icons and the serials-on multi-v1 lim…
Patola Jun 20, 2026
5c898df
fix(usb/sc_dongle): keep the v1 dongle alive when GET_SERIAL stalls
Patola Jun 20, 2026
954f1b8
docs(TODO): scope continuous "HD rumble" (v2 haptics) as a future entry
Patola Jun 20, 2026
1ffa593
fix(osd): support Python 3.13
Patola Jul 3, 2026
f408014
fix(osd): shape menu/radial windows on Wayland via cairo clip
Patola Jul 3, 2026
d052992
fix(daemon): release a held action when locking so its key-up isn't lost
Patola Jul 3, 2026
9cfba22
fix(osd): keep generic face-button icons for the v2 quick menu
Patola Jul 3, 2026
b21eaec
fix(osd): cancel the quick-menu auto-timeout on quit
Patola Jul 3, 2026
9206a4e
fix(mapper): stop the v2 right stick crashing in set_button under a m…
Patola Jun 21, 2026
e779507
docs(README): document the controller selector and add a multi-contro…
Patola Jun 21, 2026
481d20c
fix(uinput): build Keys/Axes/Rels enums via the functional IntEnum API
Patola Jun 21, 2026
26d3a7f
fix(appimage): bundle libxml2 and icu so librsvg works on minimal hosts
Patola Jun 21, 2026
f108235
fix(gui): Input Test mode β€” selected controller, viewBox cursor, re-a…
Patola Jun 28, 2026
3d22b29
feat(controller-images): Input Test highlights and test-area fixes (S…
Patola Jun 28, 2026
f338fab
fix(gui,images): correct Deck back-button mapping + stick-touch Input…
Patola Jun 28, 2026
a41335c
fix(config): default "disable emulation on close" ON for Steam Deck
Patola Jun 28, 2026
3d808cb
feat(gui,images): per-controller button-image override + Deck back-bu…
Patola Jun 28, 2026
eafbaaf
fix(packaging,images): package per-controller icon dirs; Deck icons t…
Patola Jun 28, 2026
e614c16
feat(images): consistent around-controller icons for Deck & SC2 (from…
Patola Jun 28, 2026
fadbbb5
fix(images): lighten the Deck Steam/QAM button infill
Patola Jul 3, 2026
d7da336
fix(images): space out the SC2 rear-paddle labels
Patola Jul 3, 2026
22418cc
fix(gui,appimage): SC v1 mislayout + missing OSD daemon dependency
Patola Jun 28, 2026
d15da11
fix(gui): Deck button layout β€” D-Pad to top, Steam to the left column
Patola Jun 28, 2026
241711e
fix(gui,osd): SC2 hover offset + invisible OSD submenus
Patola Jun 28, 2026
d17367c
fix(gui): Deck stick/dpad hover highlight
Patola Jun 29, 2026
6b8c865
fix(daemon): spawn helpers with a valid Python when sys.executable is…
Patola Jun 29, 2026
3ac542d
feat(gui): show the Steam logo on the Steam Controller v1 C button
Patola Jun 29, 2026
fd53bc8
fix(appimage): bundle ayatana appindicator so the tray icon works
Patola Jun 29, 2026
807c274
fix(gui): size the SC v1 Steam logo to the generic C button
Patola Jun 29, 2026
b05f2f7
docs(todo): record Deck OSD menu fixes
Patola Jun 29, 2026
4275361
fix(appimage): bundle libdbusmenu so the tray icon works
Patola Jun 29, 2026
afb3213
fix(appimage): explicitly bundle libdbusmenu for the tray icon
Patola Jun 29, 2026
d9fb924
docs(todo): refine Deck OSD-menu item, add Deck tray-icon note
Patola Jun 29, 2026
ec3089f
fix(appimage): brand AppImages as sc-controller-cc
Patola Jun 29, 2026
2d5c010
docs(todo): defer AppImage desktop app-id rebrand to org.patola.sc-co…
Patola Jun 29, 2026
2b378da
fix(gui): repair "register new controller" (BUTTON_ORDER import)
Patola Jul 1, 2026
adcb73b
fix(gui): clear Input Test highlights when it is turned off
Patola Jul 1, 2026
7fd7833
build(appimage): single jammy build, drop zsync/sha256; document AppI…
Patola Jul 1, 2026
9ce8607
docs(readme): note the Steam Deck doesn't need the udev rules
Patola Jul 1, 2026
03ea5f8
fix(gui): Deck back-paddle order in side panel (L4/R4 above L5/R5)
Patola Jul 2, 2026
0154a11
build(images): add an svgo config and wire the asset generators to mi…
Patola Jul 3, 2026
830e678
perf(images): svgo-optimize the SC1/SC2/Deck SVGs
Patola Jul 3, 2026
fe2d288
style(types): annotate the Steam Controller v2 / Deck changeset
Patola Jul 3, 2026
b84d3a6
fix(gui): use freedesktop icon-names for the profile save/edit buttons
Patola Jul 4, 2026
21ffe31
docs(todo): note the remaining deprecated new_from_stock icon calls
Patola Jul 4, 2026
599c8b4
docs(todo): drop items that are now implemented or superseded
Patola Jul 4, 2026
e206727
fix(osd): Steam Deck OSD menu - helpers work in the AppImage, no Turn…
Patola Jul 4, 2026
19c5f67
binding-display: auto-generate the template from controller art
Patola Jul 4, 2026
92e2f8f
binding-display: add Steam Deck support
Patola Jul 4, 2026
8e6fab8
sccdaemon: show/lock the invoking controller for Display Bindings
Patola Jul 4, 2026
d09ede5
osd/binding-display: fit the window to the screen (Steam Deck)
Patola Jul 4, 2026
a07c3a9
osd/binding-display: shrink v1 labels to fit their boxes
Patola Jul 4, 2026
250ae80
binding-display: honor group transforms when placing markers (Deck)
Patola Jul 4, 2026
c7a2033
binding-display: add ds4/ds5/x360 templates
Patola Jul 4, 2026
ad26245
input-test: square the degenerate stick/pad test-areas
Patola Jul 4, 2026
3a89939
input-test: track and highlight the DS4/DS5 touchpad
Patola Jul 4, 2026
cb9a4c0
mapper: guard rstick/dpad state access for gamepads on the HID decoder
Patola Jul 4, 2026
8791fba
ds4/ds5: scale HID touchpad coordinates into the pad range
Patola Jul 4, 2026
3806433
docs(todo): note remaining DualShock 4 / DualSense issues
Patola Jul 4, 2026
70d92f3
ds4: add a Bluetooth hidraw driver (DS4HidRawController)
Patola Jul 5, 2026
9c7c030
sc2: warn once if the controller reports 0x45 instead of 0x42
Patola Jul 5, 2026
e06f7b6
docs(todo): note DS4 gyro + Bluetooth rumble/lightbar follow-ups
Patola Jul 5, 2026
50c166b
modifiers: neutralize a released absolute-gyro action in ModeModifier
Patola Jul 5, 2026
21e2595
ds4: synthesize absolute-gyro orientation from the raw gyro
Patola Jul 5, 2026
d432964
gui: fix gyro Per-Axis mouse-axis labels + add a Clear button
Patola Jul 5, 2026
aabec04
docs(todo): DS4 gyro absolute works (drift + mouse-serialization foll…
Patola Jul 5, 2026
b939f22
build(appimage): restore multi-base builds and zsync/sha256; release …
Patola Jul 5, 2026
b334221
build: require Python >=3.11; revert the 3.10 enum workaround
Patola Jul 5, 2026
b62c4f1
ds4: scaffold accel drift-correction for absolute gyro (disabled, pur…
Patola Jul 6, 2026
d420f1c
fix(uinput): keep the functional enum so the jammy AppImage (Python 3…
Patola Jul 6, 2026
762543a
fix(gyro,gui): make gyro->mouse fully work (routing, labels, directio…
Patola Jul 6, 2026
baa394e
fix(usb): pass syspath to the fail callback on USBErrorBusy
Patola Jul 9, 2026
204b5a9
ds4: enable accel drift-correction, calibrated on hardware
Patola Jul 9, 2026
1dc1406
fix(actions): decode euler gyros in TiltAction (rest false-fires, axi…
Patola Jul 9, 2026
d68aeb2
gyro: intuitive mouse semantics -- Absolute = laser pointer, relative…
Patola Jul 10, 2026
5c2b49f
sc2: correct the IMU report layout; euler-convert the quaternion (EUREL)
Patola Jul 11, 2026
8f10984
gui(sc2): put the LT/RT hover areas on the drawn triggers
Patola Jul 11, 2026
3919532
feat: Add a nixpkg for NixOS users and rootless
ThomasEricB Jul 2, 2026
f645827
feat: Add Testing Capabilities to Nixpkg
ThomasEricB Jul 2, 2026
8e3100a
build(appimage): let pip install the wheel on jammy's Python 3.10
Patola Jul 11, 2026
633864e
tests,docs: cover the 'inverted' modifier (3 long-failing meta-tests)
Patola Jul 11, 2026
adf07ab
build(appimage): actually run the test suite in non-jammy builds
Patola Jul 11, 2026
b503c5c
Update package.nix for version 0.6.0.4
ThomasEricB Jul 11, 2026
4240d49
Merge upstream/main (jammy kept, checksums kept, our Wayland OSD fix …
Patola Jul 11, 2026
7057a43
docs(todo): evaluate selectable output device (Xbox / DS4-DS5 / none)
Patola Jul 11, 2026
a7f61f1
fix(gyro): align "Mouse (Desktop)" signs with the calibrated rate table
Patola Jul 12, 2026
4e5ef15
gui: per-controller grip/paddle button lists (gyro enablers, chords, …
Patola Jul 12, 2026
e6826e6
fix(gyro): make the Recenter Gyro special action actually recenter
Patola Jul 12, 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
27 changes: 26 additions & 1 deletion .github/workflows/appimage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ jobs:
arch: amd64
- platform: linux/arm64
arch: arm64
# CI builds every base for compatibility coverage / downloadable
# artifacts, but releases attach only the most-compatible jammy pair
# (Ubuntu 22.04, glibc 2.35 - runs on everything newer: Ubuntu 22.04+,
# Debian 12+, Arch, etc.); see the release job's download pattern below.
# Add bases here freely - they won't bloat the release.
base:
# jammy stays in the fork even though upstream dropped it: it is the
# RELEASE base (glibc 2.35 covers Ubuntu 22.04 LTS onwards).
- os: ubuntu
codename: jammy
pubkey: 871920D1991BC93C
recipe: AppImageBuilder.yml
- os: ubuntu
codename: noble
pubkey: 871920D1991BC93C
Expand Down Expand Up @@ -122,6 +133,8 @@ jobs:
# os: ubuntu-24.04-arm

base:
- os: ubuntu
codename: jammy
- os: ubuntu
codename: noble
- os: ubuntu
Expand Down Expand Up @@ -173,9 +186,21 @@ jobs:
- name: Download artifacts
uses: actions/download-artifact@v8
with:
pattern: appimage-*
# CI builds all bases, but only the most-compatible jammy AppImages
# (one per arch) are attached to the release. Widen this pattern to
# ship additional bases.
pattern: appimage-jammy-*
path: assets
merge-multiple: true
# Kept in the fork although upstream dropped it: our releases ship
# per-asset .sha256 checksums.
- name: Create checksum for release assets
shell: bash
run: |
algo="${SHA_ALGORITHM:-256}"
find assets -type f | while read -r asset; do
shasum --binary --algorithm "${algo}" "${asset}" >"${asset}.sha${algo}"
done
- name: Upload artifacts to GitHub release
uses: softprops/action-gh-release@v3
with:
Expand Down
4 changes: 2 additions & 2 deletions AppImageBuilder.debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ script:
AppDir:
app_info:
id: org.c0rn3j.sc-controller
name: sc-controller
name: sc-controller-cc
version: "{{APPIMAGE_VERSION}}"
icon: sc-controller
exec: usr/bin/python3
Expand Down Expand Up @@ -214,4 +214,4 @@ AppDir:

AppImage:
arch: "{{APPIMAGE_ARCH}}"
update-information: "gh-releases-zsync|C0rn3j|sc-controller|latest|sc-controller-*-{{APPIMAGE_APT_DISTRO}}-{{APPIMAGE_ARCH}}.AppImage.zsync"
update-information: "gh-releases-zsync|Patola|sc-controller-cc|latest|sc-controller-cc-*-{{APPIMAGE_APT_DISTRO}}-{{APPIMAGE_ARCH}}.AppImage.zsync"
4 changes: 2 additions & 2 deletions AppImageBuilder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ script:
AppDir:
app_info:
id: org.c0rn3j.sc-controller
name: sc-controller
name: sc-controller-cc
version: "{{APPIMAGE_VERSION}}"
icon: sc-controller
exec: usr/bin/python3
Expand Down Expand Up @@ -207,4 +207,4 @@ AppDir:

AppImage:
arch: "{{APPIMAGE_ARCH}}"
update-information: "gh-releases-zsync|C0rn3j|sc-controller|latest|sc-controller-*-{{APPIMAGE_APT_DISTRO}}-{{APPIMAGE_ARCH}}.AppImage.zsync"
update-information: "gh-releases-zsync|Patola|sc-controller-cc|latest|sc-controller-cc-*-{{APPIMAGE_APT_DISTRO}}-{{APPIMAGE_ARCH}}.AppImage.zsync"
20 changes: 18 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ RUN <<EOR
set -eu

# Workaround for outstanding fix of https://bugs.launchpad.net/ubuntu/+source/python-build/+bug/1992108
# (upstream dropped this with jammy support; our releases still build on jammy)
. /etc/os-release
if [ "${UBUNTU_CODENAME-}" = 'jammy' ]; then
echo >>/etc/apt/sources.list.d/jammy-proposed.list 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-proposed universe'
echo >>/etc/apt/sources.list.d/jammy-proposed.list 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-proposed universe'
fi

apt-get update
export DEBIAN_FRONTEND=noninteractive
Expand Down Expand Up @@ -40,8 +45,19 @@ RUN <<EOR
python -m venv .env
. .env/bin/activate
pip install libusb1 pytest vdf
python -m pytest tests
pip install --prefix "${TARGET}/usr" --no-warn-script-location dist/*.whl
# Tests need Python 3.11+, which jammy (3.10) lacks. os-release must be
# sourced HERE: each RUN is a fresh shell, so the previous RUN's sourcing
# doesn't carry over -- the old unquoted, unset ${UBUNTU_CODENAME} made
# this test error out and silently skip the suite on EVERY base.
. /etc/os-release
if [ "${UBUNTU_CODENAME-}" != 'jammy' ]; then
python -m pytest tests
fi
# --ignore-requires-python: the wheel declares the >=3.11 source-install
# floor, but the jammy AppImage bundles jammy's Python 3.10, where the
# runtime is deliberately kept working (the enums use the functional
# IntEnum API); without the flag pip refuses the install on jammy.
pip install --prefix "${TARGET}/usr" --no-warn-script-location --ignore-requires-python dist/*.whl

# Save version
PYTHONPATH=$(find "${TARGET}" -type d -name site-packages) \
Expand Down
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 @@ -79,3 +141,32 @@ docker build -o build-output --build-arg BASE_CODENAME=noble .
- Optionally checkout a branch or a tag, like `python3`(default) or `v0.4.9.8.8`
- Execute `./run.sh`, this automatically builds the project into a venv called `.env`, 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`

### 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.
Loading