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

Add rotary input support for Android platform #88130

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/classes/InputEventMouseButton.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</brief_description>
<description>
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.
</description>
<tutorials>
<link title="Using InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,9 @@
<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.
</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">
If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
</member>
Expand Down
2 changes: 1 addition & 1 deletion main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
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<Joystick> mJoysticksDevices = new SparseArray<>(4);

Expand All @@ -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;
Expand Down Expand Up @@ -102,6 +107,13 @@ public void enablePanningAndScalingGestures(boolean 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 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))
Expand Down Expand Up @@ -484,8 +496,22 @@ static boolean handleMouseEvent(final MotionEvent event) {
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);
Expand Down
Loading