Tags: UsersFirst/tandemonium-controller-lab
Tags
chore(core): release 0.4.1 Adds SensorFusion.gravityRollRadians() — drift-free roll from the gravity vector for lean-to-steer input (#109). Backward-compatible with 0.4.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qnt4svMm6b8zkWfSk75vW
chore(core): release 0.4.0 Multiple Steam Controllers + WebHID-first pooling (#108). New public API: MAX_CONTROLLERS, playerSlotIds(), isPresentableEntry(), ControllerManager.presentablePoolEntries(), and connectHidForSlot's { prompt } option. Backward-compatible with 0.3.x callers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qnt4svMm6b8zkWfSk75vW
core: add ControllerManager.claimHidDeviceForSlot + release 0.3.2 The HID-only counterpart of claimPadForSlot: claim a specific HID device into a specific seat, for controllers invisible to the Gamepad API (Steam Controller Puck, DualSense-BT). The versus lobby calls it for HID-only join candidates; it was crashing / silently failing so a Steam Controller couldn't ACTIVE/ASSIGN. Resolves the pool entry (streaming sibling for a fan-out Puck), claims + attaches it. Tested. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNqB4zV3F6aBAg6LUxuvBY
core: add ControllerManager.claimPadForSlot + release 0.3.1 Adds a public "claim a SPECIFIC pad into a SPECIFIC slot" API for versus/co-op seat assignment (the game's versus lobby calls mgr.claimPadForSlot(slotId, gp) when a controller presses to join a chosen seat). Distinct from claimFirstAvailable (which picks a pad); here the caller supplies both. Rejects occupied/unknown slots, missing pads, and a pad already seated. Tested. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNqB4zV3F6aBAg6LUxuvBY
chore(core): release 0.3.0 — WebHID-first controller support Bumps @usersfirst/controller-core after the seat-select lobby + overlay picker + single-owner pool merge (#102): DS4/DualSense/Steam/Switch Pro parsing (buttons, sticks, triggers, Capture/paddles), per-unit identity, phantom/stall recovery. Tag core-v0.3.0 pins the vendored copy for downstream (Tandemonium game). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNqB4zV3F6aBAg6LUxuvBY
PlayStation BT IMU: guard against accel-as-gyro offset shift (macOS s… …ide-to-side) (#83) First pass at the macOS BT DualSense "side to side" fusion bug. The IMU-offset probe already runs on Bluetooth (the docstring claiming USB-only was stale); the gap was the selection in init(), which trusted the documented offset whenever its at-rest ACCEL looked ~1g — without checking gyro. A byte-shifted offset (e.g. macOS/IOKit including the leading report-ID byte in the BT 0x31 DataView) reads an accel axis AS a gyro axis, so its at-rest "gyro" sits near gravity (~8192). Fusion integrates that as rotation → the model swings side to side, exactly the in-game symptom. - Extract the selection into a testable `_chooseImuOffset(probe)` and add an accel-as-gyro guard: reject the default when its at-rest |gyro| is pinned near gravity, and recover the cleanest candidate (~1g accel AND near-zero gyro). The high-gyro gate means a small real bias / a handled pad never trips it, so the existing off-by-2 still-pad protection is preserved. - Add raw-bytes + length diagnostic logging on the probe so a macOS BT 0x31 capture (the key unknown) is one console line away. - Fix the stale "USB only" probe docstring. - Tests: default-kept, macOS accel-as-gyro recovery, off-by-2 still-pad protection, and motion fallback (89 pass). Hardware-verification pending: needs a real macOS + DualSense BT capture to confirm the exact byte mechanism (length/report-ID-byte) and that the fix lands the correct orientation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017NiS2a4jZ877XgftkH1Dd1
feat(core): Phase 1 scaffold — InputFrame contract + WebHID-first arb… …iter (#80) Introduce the source-agnostic input architecture from the plan doc, WebHID as the foundational spine and Steam Input reserved as an optional adapter: - input-frame.js: the normalized InputFrame contract + pure helpers (makeEmptyFrame, frameFromGamepad, quatToPlain, identityMatchKey, chooseSource). Zero deps; motion.quaternion is a plain IPC-safe object. - sources/base-source.js: ControllerSource abstract base (mirrors ControllerDriver). - sources/webhid-source.js: WebHIDSource wrapping the existing ControllerManager (the default/primary source). - sources/gamepad-source.js: GamepadAPISource (driver-less fallback, no gyro). - input-arbiter.js: InputArbiter — composes sources, dedups the same physical controller across them, and reads exactly ONE per controller (WebHID-first; forced for Deck built-in; per-controller opt-in preference). - Barrel + package.json subpath exports for the above. - test/input-frame.test.js: 15 dependency-free tests (contract helpers + arbiter dedup/force/preference/resilience). Core suite: 100 pass. SteamInputSource intentionally NOT added here — it lands in the optional @usersfirst/controller-steam package (Phase 2). core stays Steam-free. Refs #80. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcfARPqppdCKv8f3iWkhFu
Grip sense: bar reacts to grip, glow rework, distinct definitions Grip-sense glow (on-top marker) and bars (handle strip meshes) are now two clearly separate, independently-toggled indicators: - Bars react to grip: sit at an inert rest grey and ease to the grip color (with a fixed emissive lift) while that side is gripped — so the bar itself reads activation (#74). Per-side materials are cloned so left/right light independently. Driven by setGripBarsVisible, independent of the glow. - Glow rework: the cylinder reads as a real glow again — a band texture that wraps the full circumference (consistent from any angle) and fills most of the length with soft fades at the ends, using normal blending so it stays visible over the light handles (additive vanished over near-white). The Glow Length slider now scales the lit length as expected. - gripMarkerYaw knob (per profile, degrees) angles each glow's bumper/trigger end toward the controller centerline; set to 18 for the Steam Controller. - Decoupled the bar's lit emissive from the Grip Glow Brightness slider (fixed GRIP_BAR_LIT_EMISSIVE) so brightness is glow-only, matching its label. Refreshed all stale "bars are static/cosmetic" docs + tooltips. Also: fix settings dropdowns rendering light text on a white popup on Windows (color-scheme: dark + explicit option colors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ci: stamp commit + build time into the overlay, and roll "latest" rel… …ease on main Adds a build stamp (short commit SHA linking to the commit + UTC build time) to the overlay app and the landing page, injected at build time — mirrors the `lobby-version` stamp in petegordon/tandemonium. - scripts/stamp-build-version.js rewrites the `#build-version` placeholder in one or more HTML files from $BUILD_STAMP; no-ops locally (stays "dev build"). - build-desktop.yml stamps apps/overlay/src/index.html before packaging, so the Windows .exe and macOS .app show which build they are. - deploy-pages.yml stamps the web overlay AND web/index.html landing page, so you can confirm build freshness before downloading. Also fixes the stale website download: the release job now runs on every push to main, publishing/refreshing a single rolling `webhid-overlay-latest` release (make_latest) whose assets the landing page's /releases/latest/download/... link follows. Previously releases were cut only on tags/manual dispatch, so main pushes built throwaway run artifacts and the .exe download never updated. Semver `webhid-overlay-v*` tags still produce their own named releases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PreviousNext