0 votes

Hello,

I am trying to create a custom module in C++. In it I create a new Sprite, which I then set to be the child node of another node. I store a pointer to this Sprite to access it later.

I have created methods to edit the Sprite (e.g. change texture). To do this I just access the Sprite via the pointer, and this works fine.

The problem is when I save, close and reopen the project. The pointer is no longer pointing to the Sprite, so I cannot access it. Via get_child() I can get a Node corresponding to the Sprite, but from this I cannot do things such as change the texture, as these are Sprite methods.

Is there a way to load a child node as a subclass of Node, such as Sprite, or a way to store the Sprites such that I can access them even after closing and reopening the program?

Thanks for any help

asked Mar 8, 2019 in Engine by Nick74044 (21 points)

1 Answer

0 votes

The question here is about ownership. If you expect your sprite to be saved as part of the scene, then maybe it's not the best idea for your C++ node to create it. The reason is, if the scene is loaded back, your C++ class would end up creating it again instead of getting the sprite that was loaded from your previous save. Eventually you could create the sprite if it doesn't exist yet if that's what you actually want, but you need to ensure some checks.
Note that if you want the sprite to be saved as part of the scene, you have to set its owner property (https://docs.godotengine.org/en/3.0/classes/class_node.html#member-variables)

Once the node is saved in the scene, you should get it back when the node received NOTIFICATION_READY. In GDScript, that's typically something like:

onready var _sprite = get_node("Sprite")

The C++ equivalent is:

void YourNode::_notification(int p_what) {
    if (p_what == NOTIFICATION_READY) {
        Node *node = get_node("Sprite");
        ERR_FAIL_COND(node == NULL); // Don't crash if the node wasnt found
        _sprite = node.cast_to<Sprite>();
        ERR_FAIL_COND(_sprite == NULL); // Be careful if the node wasn't a sprite, who knows
    }
}

Error handling is a bit more paranoid than GDScript because in case of failure, you would get a crash, which is hard to debug and not friendly for people using your module. Also, if the node is exposed, you should listen for exit_tree in case the sprite gets removed from the tree so you can set your pointer back to null.

If however you don't want the child node to be saved as part of the scene (and then not show up as modifiable in the scene tree), your C++ node will have to create it each time in its constructor, a bit like many other nodes in Godot do (Have a look at ColorPicker, it creates child buttons and sliders for example). In that situation you don't need get_node() or get_child() since nodes are created and owned by you, there is less need for paranoid checks because the user is a lot less likely to be able to mess with them.

answered Mar 8, 2019 by Zylann (27,004 points)
edited Mar 8, 2019 by Zylann
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.