Follow-up to #50: native gamepad + touch hardware bindings (GameController / NSTouch) #51
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#51
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #50, which shipped the full input device-state layer (
53bb441): multi-key held state, analog axes/vectors, mouse, and a Godot-style injection API (Input.press/Input.set_mouse/Input.set_pad/Input.set_touch) that already drives gamepads and touch deterministically for replays, AI, and network-fed input. The read APIs (Input.pad_button/pad_axis/pad_connected,Input.touch_count/touch_x/touch_y) are complete and tested; this tracks the remaining native hardware bindings that feed the same injected state on a real device.in_pad_*(viaInput.set_pad), map to SDL standard names, and emit hotplugPadConnected/PadDisconnectedevents. A new native binding alongside cocoa.ll (windowed only; DCE'd headless, likewin_held/win_mouse).in_touch_*(viaInput.set_touch) from platform touch events, and add tap / hold / basic gesture recognition over the point stream.locationInWindowintowin_mouse(framebuffer-pixel space, y-flipped) so windowed games get the cursor position withoutInput.set_mouse.Each binding only populates the state buffers the device layer already reads, so no API changes — purely the OS glue. Related: #50 (the shipped device layer), #7 (action maps + replay).
Shipped in
d6ca320— the native hardware side of the #50 device layer, feeding the same state buffers the read APIs already consume (no API changes).Native mouse position —
win_mouseincocoa.llnow reads the live cursor via-mouseLocationOutsideOfEventStream, converts window points to framebuffer pixels and y-flips it, so windowed games getInput.mouse_x/ywithoutInput.set_mouse(theW_mx/W_myslots were declared but never written before).Gamepad — GameController.framework — a new
win_padbinding walks[GCController controllers]each frame and packs every connected extended gamepad intoin_pad_*(viaInput.set_pad): buttons inSDL_GameControllerButtonorder (A/B/X/Y, shoulders, menu/options, dpad, stick clicks, triggers), and left/right thumbsticks as 16.16 fixed with the Y axis negated to match SDL's "down is positive" convention.objc_getClass("GCController")reaches the classes by name, so a plain-frameworklink dead-strips it — the windowed link now uses-needed_framework,GameControllerto force the load command (asserted by a new regression test). Hotplug is implicit: a disconnected pad simply stops appearing incontrollers, so its slot reportspad_connected == falsethe next frame.Touch — NSTouch — the view now accepts indirect (trackpad) touches (
setAllowedTouchTypes:), and itstouchesBegan/Moved/Ended/Cancelledhandlers snapshot the currently-touching set intoin_touch_*(viaInput.set_touch), mappingnormalizedPosition(0..1, bottom-left) to framebuffer pixels.Native mouse buttons/wheel were already wired in #50; this completes the position piece noted in the third checkbox.
The whole binding is DCE'd out of a headless build (all three are only reached on the
is_windowed()branch), andInput.set_pad/set_touchinjection keeps working on every target, so replays, AI, and network-fed input are unchanged.platform.jsgains zero-fill stubs for the device imports so a windowed wasm build still links. Full suite + self-host suite green (79 + 29).