I fiddled a little in the editor and this is what I came up with:
Use an Area2D with a CollisionShape2D that has the shape you want for dragging (be it a circle or a handle), make sure it is set as pickable=true
, Then use a script that listens to the Area2D input_event
signal so you'll know when the mouse clicks on it:
After that you need further input processing and a bit of math:
crank.gd
extends Sprite
var dragging = false
func _ready():
# Connect to the Area2D input signal so we know when the user clicks on it
get_node("ClickArea").connect("input_event", self, "_on_area_input_event")
set_process_input(true)
func _on_area_input_event(viewport, event, shape):
if event.type == InputEvent.MOUSE_BUTTON:
# Start dragging when the user presses the mouse button over the clickable area
dragging = event.pressed
func _input(event):
if dragging:
if event.type == InputEvent.MOUSE_MOTION:
var motion = event.relative_pos
var new_pos = get_global_mouse_pos()
var prev_pos = new_pos - motion
var center = get_global_pos()
# Calculate the angular motion of the crank based on the arc made with the mouse
var angle = (prev_pos - center).angle_to(new_pos - center)
rotate(angle)
elif event.type == InputEvent.MOUSE_BUTTON and event.pressed == false:
# Stop dragging when the user releases the mouse button
dragging = false
Here is the example project: http://zylannprods.fr/dl/godot/DragRotate.zip
You probably have a more complete setup, you might adapt it for your needs :)