Skip to content

Add an option to orient motion controls for a handheld - #4932

Open
elpendor wants to merge 1 commit into
shadps4-emu:mainfrom
elpendor:motion-controls-vertical
Open

Add an option to orient motion controls for a handheld#4932
elpendor wants to merge 1 commit into
shadps4-emu:mainfrom
elpendor:motion-controls-vertical

Conversation

@elpendor

@elpendor elpendor commented Aug 28, 2026

Copy link
Copy Markdown

Closes #3871.

SDL reports gamepad motion in the frame of a controller lying face up, which is how a DualShock is held — so passing event->gsensor.data straight through is correct for one. A handheld is held upright instead, and its frame is 90 degrees away about X. X is left-right in both, so pitch arrives correctly while yaw and roll land on each other: tilting the device moves the camera, turning it does nothing. On a Steam Deck a real 90 degree yaw arrives as -89.1 on z against +23.5 on y.

Input.motion_controls_vertical rotates motion -90 degrees about X — (x, y, z) to (x, -z, y) — before it reaches the emulated pad. Gyro and accelerometer both, since they share the frame. Per-game overrideable like the other input settings.

Off by default, and not auto-detected: nothing SDL reports says how a device is being held, and the rotation is wrong for a controller resting face up.

Built and run on a Steam Deck (OLED) in a retail game with motion controls. Off, behaviour is unchanged; on, a 90 degree yaw reads 92.0 about true vertical and the camera turns with the device.

No GUI checkbox here — config and per-game overrides only. Happy to add one to the Qt settings dialog if that is wanted.

Comment thread src/sdl_window.cpp Outdated
///
/// Off by default: nothing SDL reports says how the device is being held.
static void OrientMotionForDevice(const float in[3], float out[3]) {
if (!EmulatorSettings.IsMotionControlsVertical()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can save an unnecessary copy of this buffer by inlining this logic into GameController::UpdateGyro, replacing the memcpy there.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — the transform now writes straight into gyro_buf/accel_buf, so the stack buffer is gone.

One thing it ran into: input_mouse.cpp's EmulateGyro calls both functions too, with values already in the frame a game expects (a constant (0, 9.81, 0) accel and mouse deltas mapped to pitch/yaw). Rotating those would break mouse gyro whenever the option is on, so the functions take a device_frame flag defaulting to false, and only sdl_window.cpp passes true.

Also added the setting to the Big Picture Input tab, under "Enable Motion Controls" — it had no UI before, so the only way to reach it was hand-editing the config.

Rebased on current main.

@elpendor
elpendor force-pushed the motion-controls-vertical branch from fd84429 to e49b100 Compare September 1, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Toggle for Vertical Oriented Motion Controls

2 participants