diff options
author | twobit <tdetoy@twobitadder.net> | 2023-09-10 00:09:24 -0400 |
---|---|---|
committer | twobit <tdetoy@twobitadder.net> | 2023-10-26 13:08:05 -0400 |
commit | b4aa6ad36eb1d523eb5eef41f8572ea654ac0745 (patch) | |
tree | b3250d88786d41b86cc6e49073a36ab6c6aaa753 | |
parent | fc99492d3066098e938449b10e02f8e01d07e2d1 (diff) | |
download | redot-engine-b4aa6ad36eb1d523eb5eef41f8572ea654ac0745.tar.gz |
Fix `reparent` losing owner if relationship to original owner is not broken
-rw-r--r-- | doc/classes/Node.xml | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 34 |
2 files changed, 34 insertions, 2 deletions
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 7510d6bb64..be5931926a 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -679,7 +679,7 @@ <param index="0" name="new_parent" type="Node" /> <param index="1" name="keep_global_transform" type="bool" default="true" /> <description> - Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent. + Changes the parent of this [Node] to the [param new_parent]. The node needs to already have a parent. The node's [member owner] is preserved if its owner is still reachable from the new location (i.e., the node is still a descendant of the new parent after the operation). If [param keep_global_transform] is [code]true[/code], the node's global transform will be preserved if supported. [Node2D], [Node3D] and [Control] support this argument (but [Control] keeps only position). </description> </method> diff --git a/scene/main/node.cpp b/scene/main/node.cpp index d8a50c4313..973650c27b 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1715,8 +1715,40 @@ void Node::reparent(Node *p_parent, bool p_keep_global_transform) { return; } + bool preserve_owner = data.owner && (data.owner == p_parent || data.owner->is_ancestor_of(p_parent)); + Node *owner_temp = data.owner; + LocalVector<Node *> common_parents; + + // If the new parent is related to the owner, find all children of the reparented node who have the same owner so that we can reassign them. + if (preserve_owner) { + LocalVector<Node *> to_visit; + + to_visit.push_back(this); + common_parents.push_back(this); + + while (to_visit.size() > 0) { + Node *check = to_visit[to_visit.size() - 1]; + to_visit.resize(to_visit.size() - 1); + + for (int i = 0; i < check->get_child_count(); i++) { + Node *child = check->get_child(i, false); + to_visit.push_back(child); + if (child->data.owner == owner_temp) { + common_parents.push_back(child); + } + } + } + } + data.parent->remove_child(this); p_parent->add_child(this); + + // Reassign the old owner to those found nodes. + if (preserve_owner) { + for (Node *E : common_parents) { + E->set_owner(owner_temp); + } + } } Node *Node::get_parent() const { @@ -1904,7 +1936,7 @@ void Node::set_owner(Node *p_owner) { return; } - Node *check = this->get_parent(); + Node *check = get_parent(); bool owner_valid = false; while (check) { |