Skip to content

Fix for lose state on change parent with reparent method

Rafał Mikrut requested to merge github/fork/HeartoLazor/master into master

Created by: HeartoLazor

Recap from issues/requests: https://github.com/okamstudio/godot/pull/1943 https://github.com/okamstudio/godot/issues/1905 http://www.godotengine.org/forum/viewtopic.php?f=11&t=1117#p9336

Some nodes loses his state on remove_child / add_child on change parent For example, on this demo which moves a node called traveler with animation/timer from left container to right one, and viceversa on move button, the animation cicles the text from 3,2,1, start, then loops a,b,c,d,e,f,g on a label. Timer loops a countdown of 10 seconds:

with:

child.get_parent().remove_child(child) destination_node.add_child(child) https://gfycat.com/AmpleTotalChanticleer

As you can see, when the node parent changes, the animation receives the notification exit_tree() and stop the animation, and if autoplay of an animation is on, when the ready notification is received, resets the animation too.

with:

child.reparent(destination_node) https://gfycat.com/SmartDeadDoctorfish

With the reparent, the state from the traveler doesn't change

The objetive of the reparent method is to move a node from one parent to another, without the loss of state on node or his childrens or the need of patch each children with gdscripts aimed only to change this behaviour, all implemented in a non-destructive way (add_child/remove_child, enter_tree/exit_tree, ready, works as always if you don't reparent)

the signature of reparent is: node_to_change_parent.reparent(destination_node)

Reparent ignores only ready event and give the tools for know when the node is reparenting and take actions on event enter_tree/exit_tree from each type of node, so reparent vs remove_child/add_child method:

  • The reparent only ignores the ready event
  • Now exist a new method for query called "is_reparenting()", this one should be queried on enter_tree or exit_tree for skip/change behaviour on problematic nodes who loses his state on reparent.
  • Two new notifications,NOTIFICATION_REPARENTING and NOTIFICATION_REPARENTED, those are called when the reparenting process start and ends, its like an exit/enter tree. This events set the bool of is_reparenting to true and false on node.cpp

For now we modified/check this node as an example with the enter_tree /exit_tree on reparenting behaviour using the is_reparenting() flag: Animation Player

Also the demo from video for testing reparenting is added to demos/misc/reparent_tester with many features for debbuging issues and test if some another nodes lose state on reparent or if you want to see the issue on action change this lines: qu20zol 1 uncomment the two remove_child/add_child and comment reparent lines on main.gd and viceversa for move with reparent

We need some Help with the check and implement the behaviour of conserve state on another nodes with the demo, but the core for reparent is finished.

The behaviour of loss of state described here was a big issue on my shmup, which abuses of move bullets from a local node attached on the ships, to a global one. This with the aim of the burst of bullets follow the coordinates from the ship and when is finished moves to a global node, so the bullets doesn't follow the ship coordinates anymore. Without reparent the animations from the laser show the spawn animation again on mid air, same with timers or other strange behaviour. On the next video is the shmup using reparent for local to global, where all is fixed, look at the behaviour of the laser: https://gfycat.com/AnchoredMistyCoati

Merge request reports