cak3_lover
cak3_lover

Reputation: 1958

How to invoke a function when changing position?

I'm trying to invoke a function everytime the position of a position2D node is changed

I tried to override the setter as given in the docs like this:

extends Position2D
tool

func set_position(value):
    print("changed position ",value)
    self.position=value;

what am I missing here? is there a way to achieve what I'm trying?

Upvotes: 4

Views: 2434

Answers (1)

Theraot
Theraot

Reputation: 40315

The method set_position is not virtual. You are not overriding it. At best you are hiding it.

If you want to follow that approach, intercept the property instead, using _set (Notice that the documentation mentions that _set is virtual). The idea is that we are going to take the attempt to set position, do whatever we want to do when it is set, and then let it continue normally.

func _set(property:String, value) -> bool:
    if property == "position":
        print("changed position ",value)

    return false

And you should see that when you modify the position in the inspector panel, you get the message.


I suspect that is not enough for you. In particular the above solution does not detect when the position changes because you drag the Position2D in the editor.

This is becase when you move the Position2D in the editor, Godot is not setting the position property. Instead it is (after digging in the source code) calling the undocumented method _edit_set_position… Which you can also call from GDScript! Anyway, the point is we cannot intercept it (and we cannot override it. Yes, I tried).


Instead we are going to use _notification. We are looking for NOTIFICATION_TRANSFORM_CHANGED, but to get that notification we need to enable it with set_notify_transform. The code looks like this:

tool
extends Position2D

func _enter_tree() -> void:
    set_notify_transform(true)

func _notification(what: int) -> void:
    if what == NOTIFICATION_TRANSFORM_CHANGED:
        print("changed position", position)

With this approach you will also be able to react to when the user moves the Position2D in the editor by dragging it around or with the keyboard directional keys. Which are the cases where Godot uses _edit_set_position. Or any other means that we could not intercept with the initial approach.

You can use this approach if you need to do something every time the Node2D moves, but it does not move very often.

By the way, this also works for 3D.

Upvotes: 4

Related Questions