Merge pull request #88490 from AlekseyKapustyanenko/Rotary-input-3.x

[3.x] Add rotary input support for Android platform
This commit is contained in:
lawnjelly 2024-03-08 14:11:51 +00:00 committed by GitHub
commit 758daacd24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 39 additions and 2 deletions

View file

@ -5,6 +5,7 @@
</brief_description> </brief_description>
<description> <description>
Contains mouse click information. See [method Node._input]. Contains mouse click information. See [method Node._input].
[b]Note:[/b] On Wear OS devices, rotary input is mapped to [constant BUTTON_WHEEL_UP] and [constant BUTTON_WHEEL_DOWN]. This can be changed to [constant BUTTON_WHEEL_LEFT] and [constant BUTTON_WHEEL_RIGHT] with the [member ProjectSettings.input_devices/pointing/android/rotary_input_scroll_axis] setting.
</description> </description>
<tutorials> <tutorials>
<link>$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html</link> <link>$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html</link>

View file

@ -682,6 +682,9 @@
<member name="input_devices/pointing/android/enable_pan_and_scale_gestures" type="bool" setter="" getter="" default="false"> <member name="input_devices/pointing/android/enable_pan_and_scale_gestures" type="bool" setter="" getter="" default="false">
If [code]true[/code], multi-touch pan and scale gestures are enabled on Android devices. If [code]true[/code], multi-touch pan and scale gestures are enabled on Android devices.
</member> </member>
<member name="input_devices/pointing/android/rotary_input_scroll_axis" type="int" setter="" getter="" default="1">
On Wear OS devices, defines which axis of the mouse wheel rotary input is mapped to. This rotary input is usually performed by rotating the physical or virtual (touch-based) bezel on a smartwatch.
</member>
<member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true"> <member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true">
If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen. If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
</member> </member>

View file

@ -1581,6 +1581,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
GLOBAL_DEF("input_devices/pointing/android/enable_long_press_as_right_click", false); GLOBAL_DEF("input_devices/pointing/android/enable_long_press_as_right_click", false);
GLOBAL_DEF("input_devices/pointing/android/enable_pan_and_scale_gestures", false); GLOBAL_DEF("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
GLOBAL_DEF("input_devices/pointing/android/rotary_input_scroll_axis", 1);
ProjectSettings::get_singleton()->set_custom_property_info("input_devices/pointing/android/rotary_input_scroll_axis",
PropertyInfo(Variant::INT,
"input_devices/pointing/android/rotary_input_scroll_axis",
PROPERTY_HINT_ENUM, "Horizontal,Vertical"));
MAIN_PRINT("Main: Load Translations and Remaps"); MAIN_PRINT("Main: Load Translations and Remaps");

View file

@ -336,6 +336,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
// These properties are defined after Godot setup completion, so we retrieve them here. // These properties are defined after Godot setup completion, so we retrieve them here.
boolean longPressEnabled = Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click")); boolean longPressEnabled = Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click"));
boolean panScaleEnabled = Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures")); boolean panScaleEnabled = Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures"));
int rotaryInputAxis = java.lang.Integer.parseInt(GodotLib.getGlobal("input_devices/pointing/android/rotary_input_scroll_axis"));
runOnUiThread(() -> { runOnUiThread(() -> {
GodotView renderView = getRenderView(); GodotView renderView = getRenderView();
@ -344,6 +345,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
inputHandler.enableLongPress(longPressEnabled); inputHandler.enableLongPress(longPressEnabled);
inputHandler.enablePanningAndScalingGestures(panScaleEnabled); inputHandler.enablePanningAndScalingGestures(panScaleEnabled);
} }
GodotInputHandler.setRotaryInputAxis(rotaryInputAxis);
}); });
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {

View file

@ -57,6 +57,9 @@ import java.util.Set;
public class GodotInputHandler implements InputManager.InputDeviceListener { public class GodotInputHandler implements InputManager.InputDeviceListener {
private static final String TAG = GodotInputHandler.class.getSimpleName(); private static final String TAG = GodotInputHandler.class.getSimpleName();
private static final int ROTARY_INPUT_VERTICAL_AXIS = 1;
private static final int ROTARY_INPUT_HORIZONTAL_AXIS = 0;
private final SparseIntArray mJoystickIds = new SparseIntArray(4); private final SparseIntArray mJoystickIds = new SparseIntArray(4);
private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<>(4); private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<>(4);
@ -71,6 +74,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
*/ */
private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN; private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
private static int rotaryInputAxis = ROTARY_INPUT_VERTICAL_AXIS;
public GodotInputHandler(GodotView godotView) { public GodotInputHandler(GodotView godotView) {
final Context context = godotView.getContext(); final Context context = godotView.getContext();
this.godotView = godotView; this.godotView = godotView;
@ -102,6 +107,13 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
this.godotGestureHandler.setPanningAndScalingEnabled(enable); this.godotGestureHandler.setPanningAndScalingEnabled(enable);
} }
/**
* On Wear OS devices, sets which axis of the mouse wheel rotary input is mapped to. This is 1 (vertical axis) by default.
*/
public static void setRotaryInputAxis(int axis) {
rotaryInputAxis = axis;
}
private boolean isKeyEventGameDevice(int source) { private boolean isKeyEventGameDevice(int source) {
// Note that keyboards are often (SOURCE_KEYBOARD | SOURCE_DPAD) // Note that keyboards are often (SOURCE_KEYBOARD | SOURCE_DPAD)
if (source == (InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD)) if (source == (InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD))
@ -473,8 +485,22 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
final float y = event.getY(); final float y = event.getY();
final int buttonsMask = event.getButtonState(); final int buttonsMask = event.getButtonState();
final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL); float verticalFactor = 0;
final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL); float horizontalFactor = 0;
// If event came from RotaryEncoder (Bezel or Crown rotate event on Wear OS smart watches),
// convert it to mouse wheel event.
if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) {
if (rotaryInputAxis == ROTARY_INPUT_HORIZONTAL_AXIS) {
horizontalFactor = -event.getAxisValue(MotionEvent.AXIS_SCROLL);
} else {
// If rotaryInputAxis is not ROTARY_INPUT_HORIZONTAL_AXIS then use default ROTARY_INPUT_VERTICAL_AXIS axis.
verticalFactor = -event.getAxisValue(MotionEvent.AXIS_SCROLL);
}
} else {
verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
}
boolean sourceMouseRelative = false; boolean sourceMouseRelative = false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
sourceMouseRelative = event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE); sourceMouseRelative = event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE);