diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml
index f48aca2e3aa..9af7f9b4537 100644
--- a/doc/classes/InputEventMouseButton.xml
+++ b/doc/classes/InputEventMouseButton.xml
@@ -5,6 +5,7 @@
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.
$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 6b3bee98e4c..b6554b631fd 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -682,6 +682,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 5e6e612d515..62726113fc7 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -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_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");
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index ac903cab5d0..c79baead83b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -335,6 +335,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
// 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 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(() -> {
GodotView renderView = getRenderView();
@@ -343,6 +344,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
inputHandler.enableLongPress(longPressEnabled);
inputHandler.enablePanningAndScalingGestures(panScaleEnabled);
}
+ GodotInputHandler.setRotaryInputAxis(rotaryInputAxis);
});
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
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 2e8b415dfea..872da45c7fa 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(GodotView godotView) {
final Context context = godotView.getContext();
this.godotView = 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 static 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))
@@ -473,8 +485,22 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
final float y = event.getY();
final int buttonsMask = event.getButtonState();
- 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);