瀏覽代碼

Rotary input for 3.x

Aleksey Kapustyanenko 1 年之前
父節點
當前提交
99c8cd2b17

+ 1 - 0
doc/classes/InputEventMouseButton.xml

@@ -5,6 +5,7 @@
 	</brief_description>
 	<description>
 		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>
 	<tutorials>
 		<link>$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html</link>

+ 3 - 0
doc/classes/ProjectSettings.xml

@@ -682,6 +682,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>

+ 5 - 0
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");
 

+ 2 - 0
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()) {

+ 28 - 2
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<Joystick> 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);