From d5c2a641f02f761642a3ca76761c8df5b7cd8384 Mon Sep 17 00:00:00 2001 From: ALEKSEY KAPUSTYANENKO Date: Fri, 9 Feb 2024 14:33:06 +0400 Subject: [PATCH] Add rotary input support. Fix documentation --- doc/classes/InputEventMouseButton.xml | 1 + doc/classes/ProjectSettings.xml | 3 ++ main/main.cpp | 2 +- .../lib/src/org/godotengine/godot/Godot.kt | 2 ++ .../godot/input/GodotInputHandler.java | 30 +++++++++++++++++-- 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml index 57137e4bef46..7e2ea6975517 100644 --- a/doc/classes/InputEventMouseButton.xml +++ b/doc/classes/InputEventMouseButton.xml @@ -5,6 +5,7 @@ Stores information about mouse click events. See [method Node._input]. + [b]Note:[/b] On Wear OS devices, rotary input is mapped to [constant MOUSE_BUTTON_WHEEL_UP] and [constant MOUSE_BUTTON_WHEEL_DOWN]. This can be changed to [constant MOUSE_BUTTON_WHEEL_LEFT] and [constant MOUSE_BUTTON_WHEEL_RIGHT] with the [member ProjectSettings.input_devices/pointing/android/rotary_input_scroll_axis] setting. $DOCS_URL/tutorials/inputs/inputevent.html diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 12d7f90bd23c..a0794e7efa03 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1358,6 +1358,9 @@ If [code]true[/code], multi-touch pan and scale gestures are enabled on Android devices. + + 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. + If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen. diff --git a/main/main.cpp b/main/main.cpp index bc2a6107b55e..b463264a73d6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2857,7 +2857,7 @@ Error Main::setup2() { GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false); GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false); - + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1); OS::get_singleton()->benchmark_end_measure("Startup", "Setup Window and Boot"); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt index da86e67c7d33..3189d3de1da3 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -596,11 +596,13 @@ class Godot(private val context: Context) : SensorEventListener { // These properties are defined after Godot setup completion, so we retrieve them here. val longPressEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click")) val panScaleEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures")) + val rotaryInputAxis = java.lang.Integer.parseInt(GodotLib.getGlobal("input_devices/pointing/android/rotary_input_scroll_axis")); runOnUiThread { renderView?.inputHandler?.apply { enableLongPress(longPressEnabled) enablePanningAndScalingGestures(panScaleEnabled) + setRotaryInputAxis(rotaryInputAxis) } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index 38c115ad7f6a..fe971cf44291 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -57,6 +57,9 @@ import java.util.Set; public class GodotInputHandler implements InputManager.InputDeviceListener { 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 SparseArray mJoysticksDevices = new SparseArray<>(4); @@ -71,6 +74,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { */ private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN; + private static int rotaryInputAxis = ROTARY_INPUT_VERTICAL_AXIS; + public GodotInputHandler(GodotRenderView godotView) { final Context context = godotView.getView().getContext(); mRenderView = godotView; @@ -102,6 +107,13 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { 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 void setRotaryInputAxis(int axis) { + rotaryInputAxis = axis; + } + private boolean isKeyEventGameDevice(int source) { // Note that keyboards are often (SOURCE_KEYBOARD | SOURCE_DPAD) if (source == (InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD)) @@ -484,8 +496,22 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { final float tiltX = (float)-Math.sin(orientation) * tiltMult; final float tiltY = (float)Math.cos(orientation) * tiltMult; - final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL); + float verticalFactor = 0; + 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; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { sourceMouseRelative = event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE);