aboutsummaryrefslogtreecommitdiff
path: root/ui/pointer_input_sensor.gd
diff options
context:
space:
mode:
Diffstat (limited to 'ui/pointer_input_sensor.gd')
-rw-r--r--ui/pointer_input_sensor.gd117
1 files changed, 117 insertions, 0 deletions
diff --git a/ui/pointer_input_sensor.gd b/ui/pointer_input_sensor.gd
new file mode 100644
index 0000000..f99fc17
--- /dev/null
+++ b/ui/pointer_input_sensor.gd
@@ -0,0 +1,117 @@
+extends Control
+class_name PointerInputSensor
+
+# All on_ACTION signals have a single argument of type PointerInputData.
+signal on_press
+signal on_release
+#signal on_release_outside
+signal on_click
+signal on_enter
+signal on_exit
+#signal on_exit_app_window
+signal on_begin_drag
+signal on_drag
+signal on_end_drag
+signal on_scroll
+
+enum PointerInputAction {
+ UNDEFINED,
+ ON_PRESS,
+ ON_RELEASE,
+# ON_RELEASE_OUTSIDE,
+ ON_CLICK,
+ ON_ENTER,
+ ON_EXIT,
+# ON_EXIT_APP_WINDOW,
+ ON_BEGIN_DRAG,
+ ON_DRAG,
+ ON_END_DRAG,
+ ON_SCROLL,
+}
+
+class PointerInputData:
+ var target: PointerInputSensor
+ var event: InputEvent
+ var index := -1
+ var initial_position := Vector2.ZERO
+ var current_position := Vector2.ZERO
+ var relative_position := Vector2.ZERO
+ var velocity := Vector2.ZERO
+ var was_dragged := false
+ var is_pressed := false
+ var scroll := 0.0
+ var action: int = PointerInputAction.UNDEFINED
+
+
+export var drag_threshold_cm: float = 0.250
+
+var pointer: PointerInputData
+
+onready var screen_dpcm := float(OS.get_screen_dpi()) / 2.54
+
+
+func _ready():
+ pointer = PointerInputData.new()
+ pointer.target = self
+ connect("mouse_entered", self, "_on_enter_exit", [true])
+ connect("mouse_exited", self, "_on_enter_exit", [false])
+
+
+func _on_enter_exit(is_inside: bool):
+ pointer.action = PointerInputAction.ON_ENTER if is_inside else PointerInputAction.ON_EXIT
+ emit_signal("on_enter" if is_inside else "on_exit", pointer)
+
+
+func _gui_input(event: InputEvent):
+
+ # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable.
+ if event is InputEventScreenTouch || event is InputEventScreenDrag:
+ if event.index != 0:
+ return
+
+ pointer.event = event
+ pointer.action = PointerInputAction.UNDEFINED
+ pointer.velocity = Vector2.ZERO
+ pointer.relative_position = Vector2.ZERO
+ pointer.scroll = 0.0
+ pointer.current_position = get_global_mouse_position()
+
+ if event is InputEventScreenTouch && (pointer.is_pressed == false || pointer.index == event.index):
+ var touch := event as InputEventScreenTouch
+ pointer.is_pressed = event.pressed
+
+ if pointer.is_pressed:
+ pointer.index = touch.index
+ pointer.initial_position = pointer.current_position
+ pointer.action = PointerInputAction.ON_PRESS
+ emit_signal("on_press", pointer)
+ else:
+ pointer.action = PointerInputAction.ON_RELEASE
+ emit_signal("on_release", pointer)
+ if pointer.was_dragged == false:
+ pointer.action = PointerInputAction.ON_CLICK
+ emit_signal("on_click", pointer)
+ else:
+ pointer.action = PointerInputAction.ON_END_DRAG
+ emit_signal("on_end_drag", pointer)
+ pointer.index = -1
+ pointer.was_dragged = false
+
+ if event is InputEventScreenDrag && event.index == pointer.index:
+ var drag := event as InputEventScreenDrag
+ pointer.velocity = drag.speed
+ pointer.relative_position = drag.relative
+ if pointer.was_dragged == false && pointer.current_position.distance_to(pointer.initial_position) > drag_threshold_cm * screen_dpcm:
+ pointer.was_dragged = true
+ pointer.action = PointerInputAction.ON_BEGIN_DRAG
+ emit_signal("on_begin_drag", pointer)
+ pointer.action = PointerInputAction.ON_DRAG
+ emit_signal("on_drag", pointer)
+
+ if event is InputEventMouseButton && event.is_pressed():
+ if event.button_index == BUTTON_WHEEL_UP || event.button_index == BUTTON_WHEEL_DOWN:
+ pointer.scroll = -1.0 if event.button_index == BUTTON_WHEEL_UP else 1.0
+ pointer.action = PointerInputAction.ON_SCROLL
+ emit_signal("on_scroll", pointer)
+
+