diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml index 34af030d9..90c58554b 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.md diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 782aa73c3..59f90dcd5 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -829,6 +829,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 30ebe8287..a40ced695 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1633,6 +1633,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/pandemoniumengine/pandemonium/Pandemonium.java b/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/Pandemonium.java index ef1fe85bf..22af80283 100644 --- a/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/Pandemonium.java +++ b/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/Pandemonium.java @@ -333,6 +333,7 @@ public class Pandemonium extends Fragment implements SensorEventListener, IDownl // These properties are defined after Godot setup completion, so we retrieve them here. boolean longPressEnabled = Boolean.parseBoolean(PandemoniumLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click")); boolean panScaleEnabled = Boolean.parseBoolean(PandemoniumLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures")); + int rotaryInputAxis = java.lang.Integer.parseInt(PandemoniumLib.getGlobal("input_devices/pointing/android/rotary_input_scroll_axis")); runOnUiThread(() -> { PandemoniumView renderView = getRenderView(); @@ -341,6 +342,7 @@ public class Pandemonium extends Fragment implements SensorEventListener, IDownl inputHandler.enableLongPress(longPressEnabled); inputHandler.enablePanningAndScalingGestures(panScaleEnabled); } + PandemoniumInputHandler.setRotaryInputAxis(rotaryInputAxis); }); for (PandemoniumPlugin plugin : pluginRegistry.getAllPlugins()) { diff --git a/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumInputHandler.java b/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumInputHandler.java index d582618cc..28b9a85cb 100644 --- a/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumInputHandler.java +++ b/platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumInputHandler.java @@ -58,6 +58,9 @@ import java.util.Set; public class PandemoniumInputHandler implements InputManager.InputDeviceListener { private static final String TAG = PandemoniumInputHandler.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,7 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener * Used to decide whether mouse capture can be enabled. */ private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN; + private static int rotaryInputAxis = ROTARY_INPUT_VERTICAL_AXIS; public PandemoniumInputHandler(PandemoniumView pandemoniumView) { final Context context = pandemoniumView.getContext(); @@ -103,6 +107,13 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener this.pandemoniumGestureHandler.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)) @@ -474,9 +485,23 @@ public class PandemoniumInputHandler 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);