diff options
| author | dam <dam@gudinoff> | 2021-12-27 03:31:03 +0000 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2021-12-27 03:31:03 +0000 |
| commit | 5b863fdc25848817ef11f0c1a33ef45a4160aa2c (patch) | |
| tree | fc02e32880c4eb72597424da0055bf2172ea7da0 /touch_scroll.gd | |
| parent | a2af4c7d07259a091deabdceaa5da1a2f7757c5e (diff) | |
| download | surgery-log-5b863fdc25848817ef11f0c1a33ef45a4160aa2c.tar.zst surgery-log-5b863fdc25848817ef11f0c1a33ef45a4160aa2c.zip | |
Allow to scroll database screen without selecting item on touch-down.
Diffstat (limited to 'touch_scroll.gd')
| -rw-r--r-- | touch_scroll.gd | 134 |
1 files changed, 79 insertions, 55 deletions
diff --git a/touch_scroll.gd b/touch_scroll.gd index ea92087..f2aeca7 100644 --- a/touch_scroll.gd +++ b/touch_scroll.gd @@ -1,66 +1,90 @@ extends Control +const VELOCITY_DECAYING_FACTOR: float = 5.5 +const DRAG_THRESHOLD_CM: float = 0.250 -func _gui_input(event: InputEvent): -#func _input(event: InputEvent): -# return - if event is InputEventScreenDrag: - self.v_scroll.value -= event.relative.y -# accept_event() +var pointer: Dictionary +var anchor: float +var offset: float +var screen_dpcm: float + +onready var target: Control = get_parent() +onready var target_scroll: VScrollBar = get_parent().get_v_scroll() + + +func _ready(): + pointer = { + index = -1, + initial_position = Vector2.ZERO, + current_position = Vector2.ZERO, + velocity = Vector2.ZERO, + was_dragged = false, + is_active = false, + } + screen_dpcm = float(OS.get_screen_dpi()) / 2.54 -#func _gui_input(event): -# accept_event() -# get_tree().set_input_as_handled() -# if event is InputEventScreenDrag: -# get_parent().v_scroll.value -= event.relative.y +func _process(delta: float): + if pointer.is_active: + var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y) + offset = anchor + dragged_distance + self.target_scroll.value = offset + elif pointer.velocity.length() > 0.5: + pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + offset -= pointer.velocity.y * delta + self.target_scroll.value = offset -export(float) var drag_threshold = 5 -onready var touch_enabled = OS.has_touchscreen_ui_hint() -onready var v_scroll = get_parent().get_v_scroll() -var dragging = false -var pressed = false -var last_event -# must be _input, as _gui_input has bugs, with no touch.pressed = false events -# see: https://github.com/godotengine/godot/issues/16761 -func _input_disabled(event): -#func _gui_input(event): +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 + + if event is InputEventScreenTouch && (pointer.is_active == false || pointer.index == event.index): + var touch := event as InputEventScreenTouch + pointer.is_active = event.pressed + pointer.current_position = touch.position + if pointer.is_active: + pointer.index = touch.index + pointer.initial_position = touch.position + anchor = self.target_scroll.value + else: + if pointer.was_dragged == false: # Click detected. + simulate_gui_click() + pointer.index = -1 + pointer.was_dragged = false - if not visible: - return + if event is InputEventScreenDrag && event.index == pointer.index: + var drag := event as InputEventScreenDrag + pointer.current_position = drag.position + pointer.velocity = drag.speed + if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM: + pointer.was_dragged = true - if not touch_enabled: - return - if event is InputEventScreenDrag: - accept_event() - if event.speed == Vector2(): - # we're on a device and speed is broken - # see: https://github.com/godotengine/godot/issues/3623 - event.speed = event.relative - if abs(event.speed.y) >= drag_threshold: - # scroll the list - dragging = true - v_scroll.value -= event.relative.y - return +func simulate_gui_click(): + + var position := self.get_global_mouse_position() - target.rect_global_position + + var event_touch := InputEventScreenTouch.new() + event_touch.index = 0 + event_touch.position = position + + var event_mouse := InputEventMouseButton.new() + event_mouse.button_index = BUTTON_LEFT + event_mouse.button_mask = BUTTON_MASK_LEFT + event_mouse.position = position + + event_mouse.pressed = true + event_touch.pressed = true + target._gui_input(event_mouse) + target._gui_input(event_touch) + + event_mouse.pressed = false + event_touch.pressed = false + target._gui_input(event_mouse) + target._gui_input(event_touch) + - if event is InputEventScreenTouch: - if event.index == 0: - accept_event() - if dragging && event.pressed == false: - # prints("end drag") - dragging = false - pressed = false - else: - if event.pressed && pressed == false: - # prints("touch start") - pressed = true - # TODO: prevent select highlight - elif !event.pressed && pressed == true: - # prints("touch end and accept") - pressed = false - var ev = InputEventAction.new() - ev.action = "ui_accept" - ev.pressed = true - Input.parse_input_event(ev) |
