0 votes

Hi,

I have a problem with the editor tools!

My custom class has an export variable (NodePath) with setter+getter functions, and I want to do something with the selected node (with the node itself, not with the path), after the selection!

Here is my code:

tool
extends Node2D

export(NodePath) var path setget setPath, getPath

func getPath():
    return path

func setPath(newPath):
    print("setPath()")
    path = newPath
    if(path != null && path != ""):
        print(str("path: ", path))

        if(has_node(path)):
            var node = get_node(path)
            print(str("name of the node: ", node.get_name()))
        else:
            print(">> WTF? <<")
    else:
        print("path is empty")

And a screenshot:
enter image description here

When I choose a node (inspector), the setPath() function called properly and everything works fine.
The output:

setPath()
path: ../Sprite
name of the node: Sprite

But when I save the project (CTRL+S), the has_node() can not find the node (the path variable is OK), and I don't understand why.
The output:

setPath()
path: ../Sprite
>> WTF? <<

What am I doing wrong?

(Godot Engine 2.1.3 stable win64)

asked Jul 12, 2017 in Engine by bruteforce (584 points)

1 Answer

+2 votes

When you load a scene in Godot, its variables are set before the children to be added to the tree, so it's possible your child node doesn't exist at the time. It could even happen that your node isn't in the tree yet, which is fine since the loader only sets variables.

If you want to deal with loading, you can also do your initialization in _ready() so that you'll have access to the node there.

answered Jul 13, 2017 by Zylann (24,561 points)

Hi Zylann ,
Thank you for the answer!

The CustomNode's _ready() called only once: when i add it to the root.
The Sprite node exists (I added it manually in the editor), and it is in the tree of course,

I do not understand, why has_node() works in one case (selection), and why not in the other (save scene).
I did not change anything between the 2 operations...

The editor still has to add it to the game tree. The editor has its own tree. They aren't the same thing.

Thanks!
I just need a starting point (function/event... anything), when a node is selected, and I can work with this selected node (in tool mode).
I assumed, this point is the NodePath variable's setter method...
How should I do this properly?

Thank you!

The onready var is_ready = true suggestion does not seem to work in tool mode (the variable has no value: not true, not false... just null).

I tried the call_deferred too.

The new test code:

tool
extends Node2D

export(NodePath) var path setget setPath, getPath

func getPath():
    return path

func setPath(newPath):
    print("setPath()")
    path = newPath
    call_deferred("set_my_path")

func set_my_path():
    print("set_my_path()") 

Output 1 (when I select a node):

setPath()
set_my_path()

The functions called as I expected.

Output 2 (save scene without any modifications):

setPath()

The set_my_path() was not called.

Output 3 (save scene, afler I changed anything in the code... ie: empty line then save)

setPath()
setPath()
set_my_path()

The setPath() called twice, and the set_my_path() called once...

I still don't know what is happening here exactly, but I just realized maybe it doesn't matter.
(Is there a detailed description somewhere?)

Now I think, that the set_my_path() (via call_deferred) is called only, if something has changed (in this case the has_node() also works perfectly).
This information is actually enough for me.

What do you think?

From my understanding you want to use a function every time you change your path variable in the editor, or I'm I missing some thing? I'm asking this, because setget is not very useful unless you change the path.

Yes, I want to do some things, mostly draw helper lines, change textures... etc. based on the selected node. Only in tool mode.
That's why I need this method.
I just surprised that the setter called when I save the scene... and the different outputs confused me.

Thank you for your time, and sorry for the lame questions... I don't have much experience with Godot (and game development)

They aren't lame questions. I don't really know why setgets is called when the scene is loaded and when the scene is closed. I guess those variable are changing for some reason. I know when I was first messing with setget my game would crash on start up for this very reason, and I had to play with it until it worked. Good luck on your game!

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.