Skip to content

Commit

Permalink
Add {single,multiple} long press
Browse files Browse the repository at this point in the history
  • Loading branch information
Federico-Ciuffardi committed May 11, 2022
1 parent 427f2cc commit 9eb7390
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 39 deletions.
15 changes: 15 additions & 0 deletions CustomInputEvents/InputEventMultiScreenLongPress.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class_name InputEventMultiScreenLongPress
extends InputEventAction

var position : Vector2
var fingers : int
var raw_gesture : RawGesture

func _init(_raw_gesture : RawGesture = null) -> void:
raw_gesture = _raw_gesture
if raw_gesture:
fingers = raw_gesture.size()
position = raw_gesture.centroid("presses", "position")

func as_text() -> String:
return "position=" + str(position) + "|fingers=" + str(fingers)
14 changes: 14 additions & 0 deletions CustomInputEvents/InputEventSingleScreenLongPress.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class_name InputEventSingleScreenLongPress
extends InputEventAction

var position : Vector2
var raw_gesture : RawGesture

func _init(_raw_gesture : RawGesture = null) -> void:
raw_gesture = _raw_gesture
if raw_gesture:
position = raw_gesture.presses[0].position


func as_text() -> String:
return "position=" + str(position)
38 changes: 31 additions & 7 deletions InputManager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const MULTI_FINGER_RELEASE_THRESHOLD : float = 0.1
const TAP_TIME_LIMIT : float = 0.2
const TAP_DISTANCE_LIMIT : float = 25.0

const LONG_PRESS_TIME_THRESHOLD : float = 0.75
const LONG_PRESS_DISTANCE_LIMIT : float = 25.0

const SWIPE_TIME_LIMIT : float = 0.5
const SWIPE_DISTANCE_THRESHOLD : float = 200.0

Expand Down Expand Up @@ -52,9 +55,11 @@ signal single_tap
signal single_touch
signal single_drag
signal single_swipe
signal single_long_press
signal multi_drag
signal multi_tap
signal multi_swipe
signal multi_long_press
signal pinch
signal twist
signal raw_gesture
Expand All @@ -77,6 +82,7 @@ var _mouse_event : int = Gesture.NONE


var _drag_startup_timer : Timer = Timer.new()
var _long_press_timer : Timer = Timer.new()

var _single_touch_cancelled : bool = false
var _single_drag_enabled : bool = false
Expand All @@ -86,7 +92,8 @@ var _single_drag_enabled : bool = false
#############

func _ready() -> void:
_add_timer(_drag_startup_timer, "_on_drag_startup_timeout")
_add_timer(_drag_startup_timer, "_on_drag_startup_timer_timeout")
_add_timer(_long_press_timer, "_on_long_press_timer_timeout")

if DEFAULT_BINDIGS:
_set_default_action("multi_swipe_up" , _native_key_event(KEY_I))
Expand Down Expand Up @@ -130,11 +137,13 @@ func _handle_mouse_motion(event : InputEventMouseMotion) -> void:
if _mouse_event == Gesture.SINGLE_DRAG:
_emit("drag", _native_drag_event(0, event.position, event.relative, event.speed))
elif _mouse_event == Gesture.MULTI_DRAG:
var multi_drag_event = InputEventMultiScreenDrag.new()
multi_drag_event.position = event.position
multi_drag_event.relative = event.relative
multi_drag_event.fingers = 2
_emit("multi_drag", multi_drag_event)
var offset = Vector2(5,5)
var e0 = _native_drag_event(0, event.position-offset, event.relative, event.speed)
raw_gesture._update_screen_drag(e0)
_emit("multi_drag", InputEventMultiScreenDrag.new(raw_gesture,e0))
var e1 = _native_drag_event(1, event.position+offset, event.relative, event.speed)
raw_gesture._update_screen_drag(e1)
_emit("multi_drag", InputEventMultiScreenDrag.new(raw_gesture,e1))
elif _mouse_event == Gesture.TWIST:
var rel1 = event.position - _mouse_event_press_position
var rel2 = rel1 + event.relative
Expand All @@ -155,6 +164,7 @@ func _handle_screen_touch(event : InputEventScreenTouch) -> void:
var index : int = event.index
if event.pressed:
if raw_gesture.size() == 1: # First and only touch
_long_press_timer.start(LONG_PRESS_TIME_THRESHOLD)
_single_touch_cancelled = false
_emit("single_touch", InputEventSingleScreenTouch.new(raw_gesture))
elif !_single_touch_cancelled :
Expand Down Expand Up @@ -297,11 +307,25 @@ func _identify_gesture(_raw_gesture : RawGesture) -> int:
else: # sector == 1 or sector == 3:
return Gesture.TWIST

func _on_drag_startup_timeout() -> void:
func _on_drag_startup_timer_timeout() -> void:
_single_drag_enabled = raw_gesture.drags.size() == 1

func _on_long_press_timer_timeout() -> void:
var ends_centroid : Vector2 = Util.centroid(raw_gesture.get_ends().values())
var starts_centroid : Vector2 = raw_gesture.centroid("presses", "position")
var distance : float = (ends_centroid - starts_centroid).length()

if raw_gesture.releases.empty() and distance <= LONG_PRESS_DISTANCE_LIMIT and\
raw_gesture.is_consistent(LONG_PRESS_DISTANCE_LIMIT, FINGER_SIZE*raw_gesture.size()):
if _single_touch_cancelled:
_emit("multi_long_press", InputEventMultiScreenLongPress.new(raw_gesture))
else:
_emit("single_long_press", InputEventSingleScreenLongPress.new(raw_gesture))


func _end_gesture() -> void:
_single_drag_enabled = false
_long_press_timer.stop()
raw_gesture = RawGesture.new()

# create a native touch event
Expand Down
50 changes: 27 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ This asset was ported to be added to Godot and is now a milestone for version 4.

### Supported gestures

| Gesture name | Signal | Custom input event / Signal arg | Description |
|-----------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| Single finger tap | single_tap | [InputEventSingleScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenTap) | Fast press and release with a single finger |
| Single finger touch | single_touch | [InputEventSingleScreenTouch](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenTouch) | Touch with a single finger |
| Single finger drag | single_drag | [InputEventSingleScreenDrag](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenDrag) | Drag with a single finger |
| Single finger swipe | single_swipe | [InputEventSingleScreenSwipe](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenSwipe) | Fast drag and release with a single finger |
| Multiple finger tap | multi_tap | [InputEventMultiScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenTap) | Fast press and release with multiple fingers |
| Multiple finger drag | multi_drag | [InputEventMultiScreenDrag](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenDrag) | Drag with multiple fingers (same direction) |
| Multiple finger swipe | multi_swipe | [InputEventMultiScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenTap) | Fast drag and release with multiple fingers |
| Pinch | pinch | [InputEventScreenPinch](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventScreenPinch) | Drag with multiple fingers (inward/outward) |
| Twist | twist | [InputEventScreenTwist](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventScreenTwist) | Drag with multiple fingers (rotate) |
| Raw gesture | raw_gesture | [RawGesture](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/RawGesture) | Raw gesture state
| Gesture name | Signal | Custom input event / Signal arg | Description |
|----------------------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| Single finger touch | single_touch | [InputEventSingleScreenTouch](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenTouch) | Touch with a single finger |
| Single finger tap | single_tap | [InputEventSingleScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenTap) | Fast press and release with a single finger |
| Single finger long press | single_long_press | [InputEventSingleScreenLongPress](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenLongPress) | Press and hold with a single finger |
| Single finger drag | single_drag | [InputEventSingleScreenDrag](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenDrag) | Drag with a single finger |
| Single finger swipe | single_swipe | [InputEventSingleScreenSwipe](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventSingleScreenSwipe) | Fast drag and release with a single finger |
| Multiple finger tap | multi_tap | [InputEventMultiScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenTap) | Fast press and release with multiple fingers |
| Multiple finger long press | multi_long_press | [InputEventMultiScreenLongPress](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenLongPress) | Press and hold with multiple fingers |
| Multiple finger drag | multi_drag | [InputEventMultiScreenDrag](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenDrag) | Drag with multiple fingers (same direction) |
| Multiple finger swipe | multi_swipe | [InputEventMultiScreenTap](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventMultiScreenTap) | Fast drag and release with multiple fingers |
| Pinch | pinch | [InputEventScreenPinch](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventScreenPinch) | Drag with multiple fingers (inward/outward) |
| Twist | twist | [InputEventScreenTwist](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/InputEventScreenTwist) | Drag with multiple fingers (rotate) |
| Raw gesture | raw_gesture | [RawGesture](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/wiki/RawGesture) | Raw gesture state

When one of these gestures is detected a Custom Input Event corresponding to the detected gesture will be created and [fed up](https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-parse-input-event) to the Godot built in Input Event system so it triggers functions like [`_input(InputEvent event)`](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-input).

Expand Down Expand Up @@ -85,17 +87,19 @@ that will trigger each of the gestures that can be emulated.
These are located in the first lines of [InputManager.gd](https://github.com/Federico-Ciuffardi/Godot-Touch-Input-Manager/blob/master/InputManager.gd), to change them modify the
values on the script.

| Name | Default value | Description |
|--------------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DEFAULT_BINDIGS | true | Enable or disable default events for [gesture emulation](#gesture-emulation) |
| DEBUG | false | Enable or disable debug information |
| DRAG_STARTUP_TIME | 0.2 | Time from first native drag event to first [single finger drag](#gestures-supported) custom event |
| FINGER_SIZE | 100.0 | The distance between the fingers must be less than `fingers*FINGER_SIZE` for the [multiple finger tap](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. Setting it to `INF` removes this restriction. |
| MULTI_FINGER_RELEASE_THRESHOLD | 0.1 | All fingers must be released within `MULTI_FINGER_REALEASE_THRESHOLD` seconds before the gesture ends for the [multiple finger tap](#gestures-supported) and [multiple finger swipe](#gestures-supported) gestures to be recognized |
| TAP_TIME_LIMIT | 0.2 | The time between the first press and the last release must be less than `TAP_TIME_LIMIT` for the [single finger tap](#supported-gestures) and [multiple finger tap](#supported-gestures) gestures to be recognized |
| TAP_DISTANCE_LIMIT | 25.0 | The centroid of the finger presses must differ less than `TAP_DISTANCE_LIMIT` from the centroid of the finger releases for the [single finger tap](#supported-gestures) and [multiple finger tap](#supported-gestures) gestures to be recognized. |
| SWIPE_TIME_LIMIT | 0.5 | The time between the first press and the last release must be less than `SWIPE_TIME_LIMIT` for the [single finger swipe](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. |
| SWIPE_DISTANCE_THRESHOLD | 200.0 | The centroid of the finger presses must differ by more than `SWIPE_DISTANCE_THRESHOLD` from the centroid of the finger releases for the [single finger swipe](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. |
| Name | Default value | Description |
|--------------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DEFAULT_BINDIGS | true | Enable or disable default events for [gesture emulation](#gesture-emulation) |
| DEBUG | false | Enable or disable debug information |
| DRAG_STARTUP_TIME | 0.2 | Seconds from the first native drag event to the first [single finger drag](#gestures-supported) custom event |
| FINGER_SIZE | 100.0 | The distance between the fingers must be less than `fingers*FINGER_SIZE` pixels for the [multiple finger tap](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. Setting it to `INF` removes this restriction. |
| MULTI_FINGER_RELEASE_THRESHOLD | 0.1 | All fingers must be released within `MULTI_FINGER_REALEASE_THRESHOLD` seconds before the gesture ends for the [multiple finger tap](#gestures-supported) and [multiple finger swipe](#gestures-supported) gestures to be recognized |
| TAP_TIME_LIMIT | 0.2 | The time between the first press and the last release must be less than `TAP_TIME_LIMIT` seconds for the [single finger tap](#supported-gestures) and [multiple finger tap](#supported-gestures) gestures to be recognized |
| TAP_DISTANCE_LIMIT | 25.0 | The centroid of the finger presses must differ less than `TAP_DISTANCE_LIMIT` pixels from the centroid of the finger releases for the [single finger tap](#supported-gestures) and [multiple finger tap](#supported-gestures) gestures to be recognized. |
| SWIPE_TIME_LIMIT | 0.5 | The time between the first press and the last release must be less than `SWIPE_TIME_LIMIT` seconds for the [single finger swipe](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. |
| SWIPE_DISTANCE_THRESHOLD | 200.0 | The centroid of the finger presses must differ by more than `SWIPE_DISTANCE_THRESHOLD` pixels from the centroid of the finger releases for the [single finger swipe](#supported-gestures) and [multiple finger swipe](#supported-gestures) gestures to be recognized. |
| LONG_PRESS_TIME_THRESHOLD | 0.75 | The fingers must press for `LONG_PRESS_TIME_THRESHOLD` seconds for [single-finger long press](#gestures-supported) and [multi-finger long press](#gestures-supported) gestures to be recognized. |
| LONG_PRESS_DISTANCE_LIMIT | 25.0 | The centroid of the finger presses must differ less than `LONG_PRESS_DISTANCE_LIMIT` pixels from the centroid of the fingers last positions for the [single finger long press](#supported-gestures) and [multiple finger long press](#supported-gestures) gestures to be recognized. |


## Versioning
Expand Down
Loading

0 comments on commit 9eb7390

Please sign in to comment.