0 votes

I am going to make an input system which depends on me being able to detect the location of a mouse or touch input on the screen. Basically, there will be a touch/click somewhere on the screen, and I will append the location of that touch or click into an array which will be used for gestures and on screen motions, so for example, 5 consecutive frames with increasing x value would be interpreted as a swipe to the right.

How might I go about this?

in Engine by (251 points)

1 Answer

0 votes
Best answer

Create your own class that extends from inputs
Do all your input processing in _unhandled_input(event):
send input to rest of the engine for processing
Add as a Sigleton

Guestures.gd

class_name Guestures extends Node

class LongPress extends InputEventAction:
    const DELAY_TIME = 0.5
    var position = Vector2(0,0)
    var timer = Timer.new()

    func _init():
        timer.connect("timeout", self, "_on_long_press")

    func start(event):
        position = event.position
        if timer.is_stopped(): timer.start(DELAY_TIME)

    func is_valid():
        return position != Vector2(0,0)

    func cancel():
        position = Vector2(0,0)
        timer.stop()

    func as_text():
        return "GuestureLongPress : position=" + str(position)

    func _on_long_press():
        pressed = true
        Input.parse_input_event(self)

var touches = Array()
var drags = Array()
var long_press = LongPress.new()

func _unhandled_input(event):
    if event is InputEventScreenTouch:
        if event.pressed:
            touches[event.index] = event 
            if event.index == 0:
                long_press.start(event)
        else:
            touches.erase(event.index)
            drags.erase(event.index)
            if long_press.is_valid():
                long_press.pressed = false
                Input.parse_input_event(long_press)
            long_press.cancel()

    elif event is InputEventScreenDrag:
        drags[event.index] = event
        long_press.cancel()

Input.parse_input_event(event) sends the event to all nodes to be handled so you could do on any node

func _input(event):
    if event is Guesture.Longpress:
        if event.is_pressed():
            foo()

To add more Gestures just add more classes like for e.g

class Pinch extends InputEventAction:

another thing to note is if you want syntax highlighting for your gestures then add them to their own files and use class_name instead of class for e.g. class_name InputEventScreenLongpress extends InputEventAction

by (4,480 points)
selected by

That helps, how might I make this also apply for mouse clicks?

Set
Project Settings > Input Devices > Pointing > Emulate Touch from Mouse to true

or in the _unhandled_input(event):function change InputEventScreenTouch to InputEventMouseButton and InputEventScreenDrag to InputEventMouseMotion

Using both is also and option

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.