Godot-proposals: Add a method to rotate around a point

Created on 15 Nov 2019  路  7Comments  路  Source: godotengine/godot-proposals

Describe the project you are working on:
A learning project, where I rotate the level around the player.

Describe the problem or limitation you are having in your project:
Normally if you want to rotate everything around a certain point, you add a parent node acting as pivot. In my case it's not viable, because the "pivot" is moving and I don't want to move everything with the pivot. So my workaround is this:

var trans := global_transform
var parent := get_parent()
parent.remove_child(self)

player.get_node("Rotator").add_child(self)
global_transform = trans
player.get_node("Rotator").rotation_degrees += rot
trans = global_transform
player.get_node("Rotator").remove_child(self)

parent.add_child(self)
global_transform = trans

Describe how this feature / enhancement will help you overcome this problem or limitation:
It would change the above code into

rotate_around(player.global_position, rot)

I guess it would help people with similar problem too.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:
N/A

Describe implementation detail for your proposal (in code), if possible:
A method in Node2D that has the equivalent functionality of the long code above.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
10 lines is more than "few". Maybe.

Is there a reason why this should be core and not an add-on in the asset library?:
It's impossible to extend base types with plugins.

core

Most helpful comment

Ok, the last one works. But as you can see, it's some complex math that most users won't even know about. Godot already has some convenience functions, adding a helpful two-liner wouldn't probably hurt. Or at least it could be documented somewhere.

All 7 comments

You can use Transform math for this:

global_transform = player.global_transform * Transform2D().rotated(angle).translated(offset)

You can use Transform math for this:

Nope, this doesn't work.

It sure does. I use it all the time.

extends Sprite

export(NodePath) var player_path
onready var player = get_node(player_path)

var angle = 0

func _process(delta):
    player.global_position = get_global_mouse_position()

    angle += delta
    var offset = Vector2(32, 0)
    global_transform = player.global_transform * Transform2D().rotated(angle).translated(offset)

GIF

Eh, care to look at my project?
NowaSekcja.zip

I'm doing the rotation in LevelRotate.gd. Compare your line with how my original code works. I guess offset might be important here, but I'm not sure what it should be.

It can be an order of execution issue. The correct order would be: player moves -> level moves -> offset calculation to be used in the next frame. Also, the physics engine changes the player position throws off the system even more.

Anyway, you can do a parent/child relationship like your workaround directly with math. Get a transform that is local to the level from the player and then rotates it.

func do_rotation():
    var local = player.global_transform.affine_inverse() * global_transform
    global_transform = player.global_transform * local.rotated(rot * 0.01)

Ok, the last one works. But as you can see, it's some complex math that most users won't even know about. Godot already has some convenience functions, adding a helpful two-liner wouldn't probably hurt. Or at least it could be documented somewhere.

Some concepts and operations are documented in https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html and https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html

But I agree, I often want to rotate around a point too and it is a common operation that could be a helper function. However, it should be a method in the Transform2D class then a wrapper in Node2D like others: Transform2D().rotated() and Nore2D.rotate(), Transform2D().translated and Node2D.translate(), etc. Also for Transform and Spatial.

Transform2D Transform2D.rotated(Vector2 origin, float, radians)
void Node2D.rotate(Vector2 origin, float, radians)

Transform Transform.rotated_around(Vector3 origin, Vector3 axis, float phi)
void Spatial.rotate_around(Vector3 origin, Vector3 axis, float phi)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

IllusiveS picture IllusiveS  路  3Comments

rainlizard picture rainlizard  路  3Comments

davthedev picture davthedev  路  3Comments

wijat picture wijat  路  3Comments

lupoDharkael picture lupoDharkael  路  3Comments