Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: reimplement touch-to-mouse controls in the engine #1773

Merged

Conversation

ivan-mogilko
Copy link
Contributor

@ivan-mogilko ivan-mogilko commented Sep 12, 2022

This reimplements touch-to-mouse controls inside the engine, similar to the control scheme of 3.5.1 (before moving to SDL2 and new Android port), with minor differences. Touch-to-mouse emulates mouse buttons and motion, letting players to control AGS games with Android port. The 3.6.0 currently uses default SDL2 emulation, which only supports LMB, but that's not enough for games which require RMB too.

Mouse emulation is enabled using a config setting ("[touch]", "emulate_mouse"). This parameter may have several values, acting as a choice between the control schemes. Right now it supports 2 schemes: a default SDL2-like scheme and reimplementation of an old AGS scheme (see below). The touch-to-mouse may also be disabled completely. In theory, it may be disabled also by the game's own setting, which is useful, for example, if AGS will have a proper touch API in the future version (see #1538).

The SDL2's internal touch-to-mouse is disabled using hints (SDL_HINT_TOUCH_MOUSE_EVENTS and SDL_HINT_MOUSE_TOUCH_EVENTS).

Control schemes:

1. SDL2-style. LMB drag only.

  • Only the first finger (id = 0) is tracked, others are ignored;
  • Touch up and down events directly correspond to mouse up and down events; so you put finger down to press mouse button, and release a finger to release a mouse button.
  • Touch motion directly corresponds to the mouse motion.

Pros: simple;
Cons: no RMB emulation, cannot move cursor without holding a button down (for example: to scan around the room without issuing any commands).

This style is more or less suitable for one-click game control scheme, and especially games with drag-n-drop controls.

2. Classic AGS-style.

  • One finger tap is LMB (mouse click issued when you release the finger);
  • Two finger tap is RMB; you may hold 1st finger and keep tapping 2nd finger to keep "clicking" RMB, - this may be used for instance to cycle verbs in Sierra-style games.
  • Dragging a finger means mouse movement, but without a button down.
  • Double tap + drag: means mouse movement with LMB down. This means you have to quickly tap once and then press finger again to start a drag. This is implemented after another user's suggestion in the old ticket Occasional crash to desktop on Android & controls question.  #275, also mentioned in Android: improve the touch-to-mouse input control scheme #1716. The original method to start a drag was long-click, but I had concerns that it's not obvious when the dragging starts. With double tap it's more explicit, in my opinion.

Potential TODO:

  • Add control scheme selection to the AGS Player's preferences and save to android.cfg.
  • Tidy code by gathering variables into structs.

This implements touch-to-mouse emulation, following the SDL2's example:
* Only the first finger (id = 0) is tracked, others are ignored;
* Touch up and down events directly correspond to mouse up and down events;
* Touch motion directly corresponds to the mouse motion.

This style is suitable for one-click game control scheme, and games with drag-n-drop controls.
* One finger tap is LMB;
* Two finger tap is RMB;
* Dragging a finger means mouse movement, but without a button down.
The drag-n-drop (move cursor with emulated LMB held down) is activated by double tapping + holding (that is - hold on second tap).
@ivan-mogilko ivan-mogilko added type: enhancement a suggestion or necessity to have something improved system: android context: input labels Sep 12, 2022
@ivan-mogilko ivan-mogilko added this to the 3.6.0 milestone Sep 12, 2022
@ericoporto
Copy link
Member

Hey, this looks really good! Can you explain how do I test these modes on my device? Is there any of them selected by default?

@ivan-mogilko
Copy link
Contributor Author

Hey, this looks really good! Can you explain how do I test these modes on my device? Is there any of them selected by default?

This may be done simply through the default config file (acsetup.cfg)

[touch]
emulate_mouse = 1 // 0,1,2 - disabled, first scheme, second scheme

Default value is 1 (sdl-style).

@ericoporto
Copy link
Member

ericoporto commented Sep 12, 2022

So the scheme 2 appears to work great.

But, if I enable relative mouse control, the cursor doesn't move at all. Relative is the one if you move your finger deltaX,deltaY, it moves the same amount of the cursor, accounting for stopping at screen borders. It's useful because you can see the cursor instead of having it hidden by your finger.

Add control scheme selection to the AGS Player's preferences and save to android.cfg.

I can do that later, as #1770 showed I may need also readjust the preferences to remove unused options.

@ivan-mogilko ivan-mogilko force-pushed the android--touch2mouse branch 2 times, most recently from 17469aa to 6f9c569 Compare September 12, 2022 20:46
@ivan-mogilko
Copy link
Contributor Author

Hm, I made relative controls working, but when it's disabled the cursor now has very strange movement, looks like either it reports dx/dy incorrectly, or I'm using them incorrectly. What happens is that the relative movement seem to be doubled when moving left/up and halved when moving right/down.

Is there a distinct way to tell whether engine is working in relative or absolute touch mode?

@ericoporto
Copy link
Member

ericoporto commented Sep 12, 2022

I believe it's this line that enables the Relative mouse mode:

Mouse_EnableControl(usetup.mouse_ctrl_enabled);

if (on)
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, String::FromFormat("%.2f", Mouse::Speed).GetCStr());
else
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, "1.0");

I think on desktop this is used for infinite mouse mode - I remember I used for my pseudo FPS game.

I think you can just check for usetup.mouse_ctrl_enabled.

Question: Does your relative mode imply that the SDL own relative mode has to be disabled? (because it isn't and I was wondering if that could cause the movement being doubled in some directions)

@ivan-mogilko ivan-mogilko force-pushed the android--touch2mouse branch 3 times, most recently from 1f203dc to e5eec12 Compare September 14, 2022 23:27
@ivan-mogilko
Copy link
Contributor Author

ivan-mogilko commented Sep 14, 2022

Question: Does your relative mode imply that the SDL own relative mode has to be disabled? (because it isn't and I was wondering if that could cause the movement being doubled in some directions)

That appeared to be float rounding errors, they caused delta movement to be larger towards zero and smaller when moving away from zero.

This error was not with relative mode, but with non-relative mode; anyway, in the end I changed the code so now it's not a problem.

I think the relative mode should work too, unless I made a mistake with a coordinate difference calculation again...

@ericoporto
Copy link
Member

So, the relative mode while the finger is on screen works, as the finger moves, the cursor moves with the same delta, all alright.

But if I lift the finger, next time the finger touches the screen, the cursor teleports to somewhere. I think it's moving the delta between the last position the finger was on screen and the new one. Ideally nothing would happen, and as the finger motioned the cursor would move from the position it was.

@ivan-mogilko ivan-mogilko force-pushed the android--touch2mouse branch 2 times, most recently from 112e7ea to 0c879ba Compare September 15, 2022 15:13
@ericoporto
Copy link
Member

ericoporto commented Sep 15, 2022

Hey, the relative movement works perfectly in Android now! Apparently something broke on compiling on Linux, I can take a look at that when I am back home.

Edit: I think it's missing an #include <cmath>

@ericoporto
Copy link
Member

Looks good now! :) Tested again and it's working.

@ivan-mogilko
Copy link
Contributor Author

Alright, I think what's left is a control scheme selection in the player's Preferences;
also "Long click" option should be removed.

@ivan-mogilko
Copy link
Contributor Author

Changed preferences, now has "touch-to-mouse emulation" selection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
context: input system: android type: enhancement a suggestion or necessity to have something improved
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants