godot-touch-camera-2d
godot-touch-camera-2d copied to clipboard
A simple implementation of Godot's Camera2D uptimized for touch inputs
Table of Contents
- Introduction
- Configuration
- Compatibility
- Functioning
- Mouse inputs support
- Move the camera while zooming
- Zoom at a specific point
- Stop moving on camera's limit
- Fling animation
-
Known issues
- Control Nodes
- Emulating touch from mouse
- Contributing
Introduction
The necessity of a camera with touch inputs support bring me to search the web for a solution, without much success.
Some implementations that I found look promising, but I always came across some behavior that just don't work the way I expected, like the impossibility of move the camera while zooming, or even the zoom itself, amplifying the center of the screen when I was focused in something that simply disappear, forcing me to move the camera on every zoom ajustement.
It lead me to implement a solution that fit my needs in any scenario used. So here it is.
⬆ back to top
Configuration
Put the TouchCamera2D.gd script somewhere on your project and make sure
the class icon path points to the correct svg file (touch_camera_icon.svg)
or simply delete everything after class_name TouchCamera2D
.
If everything is done right you should be able to add the camera as a node on your scene tree.
Set the parameters you need and make sure to mark the camera as the current
one (it can also be set via script by calling camera_reference.make_current()
).
Done, it should be ready.
⬆ back to top
Compatibility
Tested using the Godot versions 3.2+
⬆ back to top
Functioning
The camera captures and interprets the unhandled inputs, so make sure the inputs
reaches the camera's _unhandled_input(event: InputEvent)
method. If needed you
can call it directly by script, like this camera_reference._unhandled_input(event)
.
The camera supports touch and drag (or click and drag) to move the camera's position,
two fingers pinch to zoom in/out (or mouse wheel) and fling animation to
fast move the camera.
⬆ back to top
Mouse inputs support
The camera can handle the mouse inputs right out of the box without the need of emulating touch from mouse. If needed, you can ignore the mouse inputs by unmarking the Handle Mouse Inputs on the Inspector panel.
The mouse inputs supported are left click and drag to pan the camera, and the mouse wheel up/down to zoom in and out.
⬆ back to top
Move the camera while zooming
By default, the camera move while you applying zoom, so you don't have to remove a finger to move the camera if needed.
It can be turned off on the Inspector panel by disabling Move While Zooming.
⬆ back to top
Zoom at a specific point
When applying zoom, is expected that the point you're focused in always stays on screen. The camera will do that if the Zoom At Point is set true on the Inspector panel. Otherwise the camera will zoom in/out relative to the camera's position.
⬆ back to top
Stop moving on camera's limit
If you change the value of the camera's limits, by default, the script will stop moving the camera's position to prevent pan issues. But if you desire a more smooth action, the script can allow the user to move the camera beyond the limit. After the move action be released the camera will move itself to the limit smoothly.
⬆ back to top
Fling animation
A fling animation occurs when the user make a fast swipe motion releasing the finger of the screen immediately after the action. It causes the camera to move with an initial velocity and gradually slows down until it stops.
In the properties panel you can turn off the fling animation or adjust the deceleration rate of the camera, as well as the minimum velocity to be considerate to perform a fling motion.
⬆ back to top
Known issues
Control Nodes
As said above, the camera catches the unhandled inputs to work. But what if this events never reaches the camera? Well, the camera will not do anything.
A good example of this is Nodes that inherits Control
. The Control
nodes always handle the inputs that occur inside them, even when your
code don't do anything with it. In this cases you can call the camera's
_unhandled_input(event: InputEvent)
method directly passing the event
to it.
The problem with that is the fact that control nodes events have their
position relative to the node itself. So if you touch in the middle of
a 20x20 node, the event.position
will be (10, 10)
, independely of the
viewport size.
For moving the camera it don't represents a lot of trouble, but for zoom at a specific point the camera need the position relative to the viewport. Otherwise the camera will go crazy, e.g. positioning itself at 10, 10 while you are focusing an object at 1000, 1000.
A work around, is to manipulate the event's position before calling the camera's method, adding the node's position to the event's position. But you'll have to test it well to see if it behaves properly.
⬆ back to top
Emulating touch from mouse
If you need to emulate touch from mouse and the Handle Mouse Events are set true, it causes an issue while moving the camera.
The engine will trigger the camera's _unhandled_input(event: InputEvent)
twice, one for the mouse and one for the emulated touch. For zoom action
it's not a big of a deal, since this action is handled independently for the
mouse and touch. But when moving the camera it causes the drag to double, e.g
clicking and dragging the mouse 10 pixels, will move the camera 20.
So, if you really need to emulate the touch, you'll need to ajust the script. Just delete everything related to the mouse inputs from the code. Again, the zoom action is not affected for the emulated touch. So you can leave it there if you want.
Contributing
Feel free to suggest any improvements for the script or for this README translation.
⬆ back to top