Skip to content

Conversation

@HsunLu
Copy link

@HsunLu HsunLu commented Dec 11, 2025

This PR introduces a new mouse mode: Right Stick Vector Trackpad.

This mode is designed to emulate the camera control experience found in native mobile FPS/TPS games (e.g., COD Mobile, PUBG Mobile). It allows users to control the in-game camera (Right Stick) by swiping anywhere on the touchscreen.

Unlike standard joystick emulation which can feel "floaty," this implementation calculates the velocity vector of the finger swipe. Crucially, it stops the stick output immediately when the finger stops moving, providing a responsive, 1:1 aiming feel without unwanted inertia or drift.

Additionally, this PR refactors the touch input handling to use float coordinates instead of int. This preserves sub-pixel precision from the Android touchscreen, resulting in significantly smoother mouse and aim movement.

Key Features
Mobile-Style Camera Control: Maps touchscreen swipes to the controller's Right Stick output using vector calculation.

Instant Stop Logic: The camera stops rotating the moment the finger stops moving (when delta is 0), solving the "drifting" issue common in other emulation methods.

Circular Clamping: Implements vector magnitude calculation to ensure the output remains within a perfect circle (avoiding the "square deadzone" issue where diagonal input exceeds physical limits).

Radial Anti-Deadzone: Applies deadzone compensation radially to the vector, significantly improving micro-aiming precision and preventing small movements from being eaten by the game's deadzone.

Double Tap R3: Double-tapping anywhere on the screen triggers a Right Stick Button (R3) press.

Single Touch Operation: Restricts input to the first active pointer to prevent interference from accidental multi-touch.

Customizable Settings: Added a configuration dialog accessible from both Stream Settings and the In-Game Overlay. Users can adjust:

Sensitivity X

Sensitivity Y

Anti-Deadzone Compensation

Changes
High-Precision Input: Updated the TouchContext interface and all implementations (AbsoluteTouchContext, RelativeTouchContext, TrackpadContext) to pass float coordinates. This eliminates quantization errors caused by casting to int, providing smoother tracking.

Added RightStickTouchContext to handle the core vector math and touch logic.

Updated StreamSettings and GameMenu to include the new configuration UI (using a shared layout).

Updated Game to support dynamic reconfiguration of the right stick parameters without restarting the stream.

Modified ControllerHandler to correctly merge the touch aim context into the controller packet.

Fixed existing lint error in values-ru.

How to Test

  1. Enable the on-screen controller or connect a physical gamepad.

  2. Open the in-game menu -> "Select Mouse Mode", and choose "Right Stick Vector Trackpad".

  3. Start a game that uses the Right Stick for camera control (e.g., an FPS game).

  4. Swipe on the screen to look around.

  5. Double-tap on the screen to verify R3 input.

  6. Open the in-game menu -> "Advanced" -> "Right Stick Vector Trackpad", and verify that the sensitivity/deadzone settings can be adjusted on the fly.

- Added new mouse mode for controlling view with right stick vector input
- Implemented circular clamping and radial anti-deadzone
- Added configuration dialog in Game Menu and Settings
- Support sensitivity and deadzone customization
@HsunLu HsunLu force-pushed the feature/right-stick-vector-trackpad branch from a7e5b67 to c9dfd2d Compare December 11, 2025 01:17
@ClassicOldSong
Copy link
Owner

Thank you, but I remember there's another pending PR trying to do the same thing...

I don't have time to review all of these right now, I'll review them as soon I get some free time.

@HsunLu
Copy link
Author

HsunLu commented Dec 12, 2025

Thank you for the update! I completely understand that you are busy.
​To help save your time when you eventually get to review this, I have analyzed the pending PR #330 and compared it with my implementation here. While both PRs aim to support "Touchpad as Right Stick," my implementation focuses on precision and configurability which are critical for FPS games.

​Here is a quick summary of the key differences:

​Input Precision (Float vs Int):
​This PR refactors the touch input pipeline to use float instead of int. This allows for sub-pixel precision, which is essential for smooth aiming on high-resolution screens.
PR #330 keeps using int, which can lead to "stair-stepping" movement affecting micro-adjustments.

​Aiming Algorithm (Radial vs Linear):
​I implemented Radial Anti-Deadzone and Circular Clamping. This approach ensures consistent sensitivity at any angle (maintaining a perfect 1:1 feel whether moving diagonally or cardinally). Unlike simple axial calculations, this prevents the "square deadzone" effect where diagonal movement feels faster or different from horizontal/vertical movement.
​PR #330 uses a simple accumulation/decay method, which often results in a "floaty" or "drifting" feel that is hard to stop precisely.

​Configurability:
​Since different games have different deadzones and sensitivity requirements, a simple on/off switch is often not enough.
​This PR adds a dedicated configuration UI allowing users to tune X/Y sensitivity and deadzone compensation independently.
PR #330 only adds a boolean toggle.

​Architecture:
​This implementation introduces a clean RightStickTouchContext that integrates directly into the controller aggregation logic, ensuring it works correctly alongside physical controllers without interference. It also includes a "Double Tap for R3" feature which is very useful for FPS games (melee/crouch).

​I hope this summary helps you make a decision when you have free time. No rush!

​(P.S. I am not a native English speaker and used translation software for this reply. Please excuse any readability issues.)

@ClassicOldSong
Copy link
Owner

The problem is, the final packet sent out is still in in, not float, so using float doesn't make much sense.

I want to know how much AI did you use in this PR and are you fully understanding the code you committed. A PR with 17 files changed can be painful to review, and can be disastrous when merging with other prs that modified too much files.

@HsunLu
Copy link
Author

HsunLu commented Jan 26, 2026

Actually, using float is crucial for calculating the delta, even if the final output is an integer.

If we cast to int too early (before applying sensitivity), we lose all sub-pixel movements.

Picture this scenario (Micro-aiming): Imagine a user moves their finger just a tiny bit: 0.4 pixels, and they have high sensitivity set to 5.0.

With Int (Early truncation): The 0.4 gets cut down to 0 immediately. 0 * 5 is still 0. The game sees nothing.

With Float (My approach): We keep the 0.4. 0.4 * 5.0 gives us 2.0. We send 2 to the PC. The game sees movement.

Since Android gives us these high-precision floats, holding onto them until the last possible second prevents that "stair-stepping" choppy feel.

On the PR size and AI concerns:

I fully understand your hesitation. A 16-file PR can indeed look daunting.

I want to personally assure you: I fully understand every single line here.

I personally designed the core architecture and logic, including the vector math for joystick emulation, the radial anti-deadzone algorithm, circular clamping, and the TouchContext refactoring.

I treated AI only as a verification tool (to double-check the vector math formulas) and a typing assistant (for generating the tedious XML layout boilerplate and translations). It did not write the core logic.

The PR looks big, but it's actually quite "hollow" structurally:

The Real Logic (Just 1 File): Almost 100% of the new algorithm lives in RightStickTouchContext.java.

The Precision Refactor (5 Files): Files like TouchContext.java and Game.java just have mechanical updates (changing int to float) to support the precision I mentioned above.

The Fluff (11 Files - Low Risk): The rest is just Strings, Translations, and Layout XMLs for the settings UI. They are static and won't break the game logic.

I hope this clears things up! I'm happy to help walk through any specific part if needed.

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.

2 participants