0 votes

I want to rotate an Area2D around its pivot according to how far it was dragged. Essentially, the rotate tool in many image editing softwares. Kind of like this. https://imgur.com/a/Vc44VcM

extends Area2D
func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_RIGHT:
            if event.is_action_released("right_click"):
                state = NONE
            else:
                if mouseOnMe:
                    get_parent().set_selected(self)
                    initialOrientation = rotation 
                    #Can I use this somehow?
                    state = ROTATING

func _process(_delta):
    if state == ROTATING:
        var vector = get_global_mouse_position() - global_position
        var angle = vector.angle()
        rotation = angle

This works perfectly only when I select the right side of the Area2D, but when I select the left side of it, it rotates 180 degrees, and only then follows the behavior I want (Same for any other value that isn't 0 degrees). Notice in the video I sent, the rotation happens according to the initial reference point of the first click.

Godot version 3.4.2
in Engine by (62 points)

did you solve your problem?

No, my method that I have listed only works if you select the right side of the Area2D.. I’m not sure how to make it rotate depending on the mouse movement and not just “face the mouse”.

2 Answers

+1 vote
Best answer

Hello CollyBlargle,

take a look at this YouTube Video

Godot Mouse Drag Rotate Tutorial
from Game Designer Online

I think that should help

by (130 points)
selected by

This behavior is not quite similar to what I want. While this system's rotation is dependent on the mouse's x position, I want both the x and y values to be considered to make a "polar coordinate" rotation system, similar to how it is in many image editing softwares.

I know that it wasn't exakt your request, but the math should be the same.

You need

  1. the start rotation of your object = A
  2. the angle to the start drag point = B
  3. the angle to the current mouse drag point = C

you calculate the new rotaion of the object X by

X = C - B + A

With C - B you calculate your delta rotation while you drag and than you add the delta to A, so basicly the rotation bevor drag + the drag delta

Here is the code, i deactivted getparent().setselected(self) just for the example, because i got an error and didnt know what you tried to accomplish

extends Area2D
var mouseDragStartAngle = 0
func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_RIGHT:
            if event.is_action_released("right_click"):
                state = NONE
            else:
                if mouseOnMe:
                    #get_parent().set_selected(self)
                    initialOrientation = rotation 
                    #Can I use this somehow?
                    mouseDragStartAngle = (get_global_mouse_position() - global_position).angle()
                    state = ROTATING

func _process(_delta):
    if state == ROTATING:
        var vector = get_global_mouse_position() - global_position
        var mouseDragCurrentAngle = vector.angle()
        rotation = (mouseDragCurrentAngle - mouseDragStartAngle) + initialOrientation

you can see i only added mouseDragStartAngle and changed the calculation of rotation

Ah! I see. I implemented A without B, and implemented B without A before, and was frustrated that they didn't work individually. Thank you!

0 votes

Hi, my solution uses local coordinates instead of global coordinates of mouse cursor -> method CanvasItem.get_local_mouse_position(); it is more consistent with the rotation of an object.
In addition, I use the event InputEventMouseMotion to update the rotation of the Area2D node, instead of the _process() function.

The line get_local_mouse_position().rotated(rotation) retrieves the position vector of the mouse pointer in the local space, which must be rotated by the rotation angle of Area2D node.

extends Area2D
enum { NONE, ROTATING}

var state = NONE
var mouse_on_me: bool = false
var initial_mouse_pos: Vector2
var initial_angle: float

func _input(event: InputEvent) -> void:
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_RIGHT:
            if event.pressed: # press button
                if mouse_on_me:
                    initial_angle = rotation
                    initial_mouse_pos = get_local_mouse_position().rotated(rotation)
                    state = ROTATING
            else: # release button
                state = NONE


    if event is InputEventMouseMotion:
        if state == ROTATING:
            var current_mouse_pos: Vector2 = get_local_mouse_position().rotated(rotation)
            var angle = initial_mouse_pos.angle_to(current_mouse_pos)
            rotation = angle + initial_angle

func _on_Area2D_mouse_entered() -> void:
    mouse_on_me = true

func _on_Area2D_mouse_exited() -> void:
    mouse_on_me = false
by (56 points)
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.