Giter VIP home page Giter VIP logo

federico-ciuffardi / godottouchinputmanager Goto Github PK

View Code? Open in Web Editor NEW
486.0 14.0 33.0 111 KB

Asset that improves touch input support (includes new gestures) in the Godot game engine. It also translates mouse input to touch input.

License: MIT License

GDScript 100.00%
godot godot3 touchscreen gestures gesture-recognition godot-touch-input-manager gdscript godot-engine gesture gesture-recognizer godot-addon godot-plugin godot4

godottouchinputmanager's Introduction

Godot Touch Input Manager

Godot Touch Input Manager (GDTIM) is an asset that improves touch input support (includes new gestures) in the Godot game engine. You just need to autoload a script and it will start analyzing the touch input. When a gesture is detected a Custom Input Event corresponding to the detected gesture will be created and fed up to the Godot built in Input Event system so it triggers functions like _input(InputEvent event). There is also a signal for each gesture if you prefer using signals to the aforementioned.

There are two active PRs that add some GDTIM gestures as native Godot events, one for version 3.x and one for version 4.x, if you are interested, please show your support there.

Table of contents

How to use

Examples

Demo

Demo

Documentation

Supported gestures

Gesture name Signal Custom input event / Signal arg Description
Single finger touch single_touch InputEventSingleScreenTouch Touch with a single finger
Single finger tap single_tap InputEventSingleScreenTap Fast press and release with a single finger
Single finger long press single_long_press InputEventSingleScreenLongPress Press and hold with a single finger
Single finger drag single_drag InputEventSingleScreenDrag Drag with a single finger
Single finger swipe single_swipe InputEventSingleScreenSwipe Fast drag and release with a single finger
Multiple finger tap multi_tap InputEventMultiScreenTap Fast press and release with multiple fingers
Multiple finger long press multi_long_press InputEventMultiScreenLongPress Press and hold with multiple fingers
Multiple finger drag multi_drag InputEventMultiScreenDrag Drag with multiple fingers (same direction)
Multiple finger swipe multi_swipe InputEventMultiScreenTap Fast drag and release with multiple fingers
Pinch pinch InputEventScreenPinch Drag with multiple fingers (inward/outward)
Twist twist InputEventScreenTwist Drag with multiple fingers (rotate)
Raw gesture raw_gesture 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 to the Godot built in Input Event system so it triggers functions like _input(InputEvent event).

Gesture emulation

The gestures can be triggered by named input actions with specific names. If the input action does not exists there is a default event that will trigger the gesture.

The following table shows the default event and the names of the input actions that will trigger each of the gestures that can be emulated.

Gesture name Input action name Default event
Single touch single_touch *
Multiple touch (2 fingers) multi_touch Middle click
Pinch (outward) pinch_outward Scroll up
Pinch (inward) pinch_inward Scroll down
Twist twist Right click
Single finger swipe (up) single_swipe_up w
Single finger swipe (up-right) single_swipe_up_right e
Single finger swipe (right) single_swipe_right d
Single finger swipe (down-right) single_swipe_down_right c
Single finger swipe (down) single_swipe_down x
Single finger swipe (down-left) single_swipe_down_left z
Single finger swipe (left) single_swipe_left a
Single finger swipe (left-up) single_swipe_up_left q
Multiple finger swipe (up) multi_swipe_up i
Multiple finger swipe (up-right) multi_swipe_up_right o
Multiple finger swipe (right) multi_swipe_right l
Multiple finger swipe (down-right) multi_swipe_down_right .
Multiple finger swipe (down) multi_swipe_down ,
Multiple finger swipe (down-left) multi_swipe_down_left m
Multiple finger swipe (left) multi_swipe_left j
Multiple finger swipe (left-up) multi_swipe_up_left u

* There are two options to enable single finger gestures:

  1. Go to Project > Project Settings > General > Input Devices > Pointing and turn on Emulate Touch From Mouse to emulate a single finger touch with the left click.
  2. Go to Project > Project Settings > General > Input Devices > Pointing and turn off both Emulate Touch From Mouse and Emulate Mouse From Touch. Then set an input action called single_touch.

Configuration

These are located in the first lines of 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
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 custom event
FINGER_SIZE 100.0 The distance between the fingers must be less than fingers*FINGER_SIZE pixels for the multiple finger tap and multiple finger swipe 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 and multiple finger swipe 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 and multiple finger tap 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 and multiple finger tap 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 and multiple finger swipe 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 and multiple finger swipe 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 and multi-finger long press 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 and multiple finger long press gestures to be recognized.

FAQ

How can I get GDTIM to work when using control nodes?

By default, the control nodes consume events and therefore GDTIM cannot analyze them. To prevent this, set Mouse>Filter to Ignore on control nodes as needed.

image

For more information see the documentation.

GDTIM events don't trigger collisions, is there a way to fix it?

Custom input events do not trigger collisions, at the moment the solution is to manually check for collisions between shapes and events. For more information and ideas on how to do this see this issue.

Versioning

Using SemVer for versioning. For the versions available, see the releases.

Authors

  • Federico Ciuffardi

Feel free to append yourself here if you've made contributions.

Note

Thank you for checking out this repository, you can send all your questions and comments to [email protected].

If you are willing to contribute in any way, please contact me.

godottouchinputmanager's People

Contributors

aaronfranke avatar btzr-io avatar dave2 avatar didifred avatar federico-ciuffardi avatar n-ziermann avatar omarshehata avatar rehhouari avatar splizard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

godottouchinputmanager's Issues

Support LongPress gesture.

Mobile/Touch interfaces often feature a long press gesture, that triggers after touching a specific point on the screen for a period of time (ie 500ms). This would be a neat addition to the input manager.

Missing CollisionObject input_event integration.

I've found this project incredibly helpful for building the mobile/touch camera input for my 3D project. I wanted to use the SingleTouch/SingleTap events for selecting objects in the scene howevever the events don't appear to propogate through to the CollisionObject input_event signal.

https://docs.godotengine.org/en/stable/classes/class_collisionobject.html

I've had a look through the Readme here and also at the Godot documentation, there doesn't appear to be a simple way to enable this.

Here's two ideas on how this could be achieved:

  1. emit a raycast from the primary camera whenever these events are triggered and then call _input_event on the collider.
  2. provide a helper function for converting the Godot touch events inside of a _input_event handler (leveraging the existing raycasts), for example:
func _on_input(camera, event, position, normal, shape_idx):
    var gestures = InputGestureEvents(event)
    for gesture in gestures:
        // handle events

Unsafe warning

I have this warning on v4.2.1.stable.official, no sure if this is something of concern ?

InputManager.gd:288 @ _emit(): An input event object is being parsed more than once in the same frame, which is unsafe.
If you are generating events in a script, you have to instantiate a new event instead of sending the same one more than once, unless the original one was sent on an earlier frame.
You can call duplicate() on the event to get a new instance with identical values.
  <C++ Source>   core/input/input.cpp:962 @ parse_input_event()
  <Stack Trace>  InputManager.gd:288 @ _emit()
                 InputManager.gd:210 @ _handle_screen_drag()
                 InputManager.gd:129 @ _unhandled_input()

Pinch not working when over buttons.

Hello developers,

image
This image above is a map with buttons on them.
There seems to be an issue when pinching over these buttons.

There is an option for "mouse filter". This is useful when using a ScrollContainer containing buttons . ScrollContainer also has a "deadzone" to avoid touching and dragging issues over buttons.
Looking into these can help solve the problem.

Great work on the Plugin!

Tapping quick does not register as tap. And Pinch/Twist constantly switching to Multiple finger drag.

This addon looked incredible promising, and I would have loved to use it in my Android projects, but upon first testing it seemed very laggy and buggy.

To test my impression, I added a simple counter to check if all my taps are registered:

extends Node2D

onready var label = $Label
onready var label2 = $Label2


var tap_counter = 0

func _input(event):
	if (event is InputEventMultiScreenDrag or
		event is InputEventSingleScreenDrag or
		event is InputEventScreenPinch or
		event is InputEventScreenTwist or
		event is InputEventSingleScreenTap or
		event is InputEventSingleScreenTouch):
			label.text = event.as_text()
	if event is InputEventMultiScreenDrag:
		label2.text = "Multiple finger drag"
	elif event is InputEventSingleScreenDrag:
		label2.text = "Single finger drag"
	elif event is InputEventScreenPinch:
		label2.text = "Pinch"
	elif event is InputEventScreenTwist:
		label2.text = "Twist"
	elif event is InputEventSingleScreenTap:
		tap_counter +=1
		label2.text = "Single finger tap "+ str(tap_counter)
	elif event is InputEventSingleScreenTouch:
		label2.text = "Single finger touch"

My impression seemed correct since taps after a certain frequency don't register at all any more.
That's very unfortunate, because the features of this addon would be really amazing if they would work.

Pinch and "Twist" also did not seem reliable at all, constantly switching to "Multiple finger drag"

InputEventMultiScreenTap - Feature Request

Thanks for the great library!

The only thing that was missing for me was position finger X. In one application I'm just drawing lines for which I need start vector, end vector.

Can those be pulled out of RawGesture presses[]?

Get touch from an Area3D

Area3D touches are not obtained and the documentation is not clear how to solve this, any help?

This is what I tried:
if event is InputEventScreenTouch and event.pressed:

Not working with Godot 4.2.1

I updated my Gogot engine from 4.1.3 to 4.2.1 and touches stopped to work on mobile. When I downgraded back to 4.1.3 it is working now again.

event.position in InputEventScreenPinch not centered during first few events

Nice work! Here's a minor bug I ran into.

Environment

  • Godot 3.2 stable
  • Deployed to iPhone X

How to reproduce

Run the following code and pinch the screen.

	if event is InputEventScreenPinch:
		print(event.position)

Expected behavior

event.position is always centered

Encountered behavior

event.position is not centered but contains the last value of InputEventSingleScreenDrag for the first few events when starting to pinch the screen.

InputEvent* misleading

ciao,
vedo che sei italiano quindi bentrovato!
Vedo che usi oggetti che chiami "InputEvent*", ma in realtà non sono oggetti compatibili con la classe InputEvent dell'engine in quanto di fatto utilizzi segnali e non eventi.
Per quanto è vero che un nome è sempre e solo un nome, nella pratica è altamente fuorviante, perchè viene automatico pensare di scrivere in _input(event) if event is InputEventScreenPinch: che non funzionerà mai.
Consiglio di cambiare nomi a questi oggetti, al fine di mantenere chiarezza e linearità con il resto dell'engine.

ciao

Condition "!is_visible_in_tree()" is true

I add player control to the already prepared scene using your plugin. The player doesn't move and I get an error:

E 0:00:02.469 _input: Condition "!is_visible_in_tree()" is true.
<C++ Source> scene/2d/touch_screen_button.cpp:201 @ _input()

изображение

If I remove everything from the tree except the player, then there is no error and he moves.
What am I doing wrong?

Implement a Pan gesture

I need help with managing pan gesture. Currently I'm facing problem with zooming and panning. The panning interferes with zooming controls and I dont know how to fix them.

Memory Leaks at RawGesture.gd and Util.gd

Error Log: WARNING: ObjectDB instances leaked at exit (run with --verbose for details).
at: cleanup (core/object.cpp:2070)
Leaked instance: GDScript:6674 - Resource path:
Leaked instance: GDScript:6675 - Resource path:
Leaked instance: GDScriptNativeClass:769
Leaked instance: GDScript:6672 - Resource path: res://addons/GDTIM-Demo-v2_1_2/RawGesture.gd
Leaked instance: GDScript:6676 - Resource path:
Leaked instance: GDScript:6673 - Resource path: res://addons/GDTIM-Demo-v2_1_2/Util.gd
Leaked instance: GDScriptNativeClass:753
Hint: Leaked instances typically happen when nodes are removed from the scene tree (with remove_child()) but not freed (with free() or queue_free()).
ERROR: Resources still in use at exit (run with --verbose for details).
at: clear (core/resource.cpp:417)
Resource still in use: res://addons/GDTIM-Demo-v2_1_2/Util.gd (GDScript)
Resource still in use: res://addons/GDTIM-Demo-v2_1_2/RawGesture.gd (GDScript)
Orphan StringName: drags
Orphan StringName: copy
Orphan StringName: latest_time
Orphan StringName: Reference
Orphan StringName: as_text
Orphan StringName: new
Orphan StringName: GDScriptNativeClass
Orphan StringName: callv
Orphan StringName: releases
Orphan StringName: duplicate
Orphan StringName: latest_event_id
Orphan StringName: i_es
Orphan StringName: relative
Orphan StringName: get_script
Orphan StringName: now
Orphan StringName: index
Orphan StringName: f
Orphan StringName: back
Orphan StringName: _update_screen_drag
Orphan StringName: get
Orphan StringName: start_time
Orphan StringName: Util
Orphan StringName: value
Orphan StringName: Touch
Orphan StringName: is_consistent
Orphan StringName: speed
Orphan StringName: get_ticks_usec
Orphan StringName: es
Orphan StringName: active_touches
Orphan StringName: res://addons/GDTIM-Demo-v2_1_2/RawGesture.gd
Orphan StringName: time
Orphan StringName: rollback_absolute
Orphan StringName: append
Orphan StringName: pop_back
Orphan StringName: res://addons/GDTIM-Demo-v2_1_2/Util.gd
Orphan StringName: keys
Orphan StringName: erase
Orphan StringName: property_name
Orphan StringName: elapsed_time
Orphan StringName: events_name
Orphan StringName: has
Orphan StringName: pressed
Orphan StringName: presses
Orphan StringName: InputEventScreenTouch
Orphan StringName: position
Orphan StringName: length
Orphan StringName: history
Orphan StringName: Drag
Orphan StringName: _add_history
Orphan StringName: diff_limit
Orphan StringName: Event
Orphan StringName: event
Orphan StringName: empty
Orphan StringName: InputEventScreenDrag
Orphan StringName: InputEventAction
Orphan StringName: type
Orphan StringName: get_ends
Orphan StringName: _init
Orphan StringName: size
Orphan StringName: map_callv
Orphan StringName: centroid
Orphan StringName: GDScript
Orphan StringName: _update_screen_touch
Orphan StringName: rollback_relative
Orphan StringName: SEC_IN_USEC
Orphan StringName: vargs
Orphan StringName: length_limit
Orphan StringName: get_linear_event_history
Orphan StringName: values
StringName: 69 unclaimed string names at exit.
Error: Process completed with exit code 1.

single_taps not recognized after resuming from pause menu

First, excellent plugin! I'm developing a little Tetris game for mobile and have been using your plugin with great success. Up until now. :)

I have made a pause menu for my game now, and using the in-built Godot pause system by setting get_tree().paused = true. And when I resume the game again with get_tree().paused = false, my single finger taps are no longer recognized. Drags and long presses are. Really weird... On the computer it works, but not on the mobile.

I've been looking through InputManager.gd and testing out a few things, but couldn't get it to work no matter what. I really don't know what's causing this. Could there be some timers that are still running in your script even if the game is paused, and they therefore go out of bounds? I see this condtion:

if raw_gesture.elapsed_time < TAP_TIME_LIMIT and distance <= TAP_DISTANCE_LIMIT:
					_emit("single_tap", InputEventSingleScreenTap.new(raw_gesture))

I figured that maybe raw_gesture.elapsed_time was being incremented during pause, but I really have no clue what's going on in your code.

Do you think you could maybe take a look in this?

VARARGS arent there? Swipe Direction?

Ive been searching for 3 days and still couldnt find it, i can detect a swipe, but i dont know how i can get the direction, looking at the code it seems to be EMITTED, but the emission dont work when i connect them via code or via godot ui, and they dont come with VARAGRS.

any kind of help is appreciated.
image

Bad download hash

hey there - I went to load this asset in Godot 3.2 and got the following error:

Asset Download Error
Bad download hash, assuming file has been tampered with.

Screen Shot 2020-03-25 at 10 21 12 PM

Method for detecting swipe release

Hey, have you worked out a way to detect when a swipe has ended? Is there a way to use is_action_just_released with InputEventSingleScreenDrag?

I've been trying to hack something together for a few days no with no luck, so I thought I'd see if it's something you'd already solved.

Thanks for your code base.

Godot 4 Support

I'm playing around with the current alpha of Godot 4 (4.0-alpha14), and there's quite a few changes which need to be made for at least importing properly.

I can provide a patch but it would probably need a new major version or branch because the changes are not backwards compatible.

Inconsistent usage of event attributes

Again, great work! I've got a minor suggestion when it comes to consistency of event attributes:

Under drag events like InputEventSingleScreenDrag, event.relative relates to event.position. Under InputEventScreenPinch and InputEventScreenTwist, however, event.relative relates to event.distance and angle (the former undocumented btw) while event.position is still present.

I think it'd be preferable to keep event.relative related to event.position and introduce different attributes for distance and angle.

multi_tap arbitrary distance support

Is there currently a way to have multi tap events fire regardless of finger distance? I tried editing some InputManager constants to no avail.

PS: thanks a ton for making this! if you're at all interested I can create a pull request for C# compatibility

InputEventMultiScreenDrag fingers not reset

THIS ONLY OCCURS ON GODOT WEB EXPORT:
The fingers property of input event InputEventMultiScreenDrag is not reset.
It always contains the maximum number of fingers that triggered that event.
So if you triggered the event with 2 fingers, then fingers = 2.
After that, you trigger the event with 3 fingers, then finger = 3.
Then you trigger the event again with 2 fingers, then finger = 3.

Suggestion: any_tap signal

I'm working on a tapping game, and due to the fast pace it happens where the player can tap with multiple fingers, on different objects, currently using single_tap which wont register any of those taps which can be frustrating.

I found a way to get to get the position of multiple taps from InputEventMultiScreenTap by looking into the raw_event.centroid function, and i can make a push request to add something like InputEventMultiScreenTap.positions array with them if you'd want.
But more than that I think it could be helpful to have a signal that is emitted on either single_tap or multi_tap, with positions array property for cases such as mine.
I can also implement this.

thanks for the great plugin!

Only works on the edges of the screen when using a Control Node instead Node2d

So following the demo, this works
image
But this does not
image

I am unfamiliar with the differences between the two in Godot, so this may just be a misunderstanding. Using emulated touch from mouse if I put my cursor at the border of the window and scroll I am able to get a pinch event, but anywhere else it comes in as a normal InputEventMouseButton.

I am using this to test:

func _unhandled_input(event):
	if event is InputEventScreenPinch:
		print("Pinch: " + str(ev.speed))

I have also tested with a different project using pinch to zoom in and out, with a web export and using an Android browser. The behavior seems to be the same.

Swipe, tap input not received when use get_tree().paused on Mobile device

Swipe and tap input not received when use get_tree().paused on Mobile device.
Godot version: 4.1 rc, 4.0 stable.
Device testing: Android 11, iPhone 11.

Steps to reproduce:

  • Use get_tree().paused = true then get_tree().paused = false for UI show, hide (pause mode).
  • Swipe and tap input not received anymore. (Ex: InputEventSingleScreenSwipe and InputEventSingleScreenTap)
  • Other inputs such as drag, touch, pinch are still received normally.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.