Skip to content

Commit

Permalink
Fix ownership bugs in node copy and pasting.
Browse files Browse the repository at this point in the history
  • Loading branch information
SaracenOne committed Oct 19, 2023
1 parent f8818f8 commit 861cc7b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
29 changes: 21 additions & 8 deletions editor/scene_tree_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,16 +493,25 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {

// Preserve ownership relations ready for pasting.
List<Node *> owned;
node->get_owned_by(node->get_owner() ? node->get_owner() : node, &owned);
Node *owner = node;
while (owner) {
List<Node *> cur_owned;
node->get_owned_by(owner, &cur_owned);
owner = owner->get_owner();
for (Node *F : cur_owned) {
owned.push_back(F);
}
}

for (Node *F : owned) {
if (!duplimap.has(F) || F == node) {
continue;
}
Node *d = duplimap[F];
// Only use this as a marker that ownership needs to be assigned when pasting.
// The actual owner doesn't matter.
d->set_owner(dup);
// Only use nullptr as a marker that ownership may need to be assigned when pasting.
// The ownership is subsequently tracked in the node_clipboard_edited_scene_owned list.
d->set_owner(nullptr);
node_clipboard_edited_scene_owned.push_back(d);
}

node_clipboard.push_back(dup);
Expand Down Expand Up @@ -3493,14 +3502,17 @@ List<Node *> SceneTreeDock::paste_nodes(bool p_paste_as_sibling) {

for (KeyValue<const Node *, Node *> &E2 : duplimap) {
Node *d = E2.value;
// When copying, all nodes that should have an owner assigned here were given node as an owner.
if (d != dup && E2.key->get_owner() == node) {
ur->add_do_method(d, "set_owner", owner);
// When copying, all nodes that should have an owner assigned here were given nullptr as an owner
// and added to the node_clipboard_edited_scene_owned list.
if (d != dup && E2.key->get_owner() == nullptr) {
if (node_clipboard_edited_scene_owned.find(E2.key)) {
ur->add_do_method(d, "set_owner", edited_scene);
}
}
}

if (dup != owner) {
ur->add_do_method(dup, "set_owner", owner);
ur->add_do_method(dup, "set_owner", edited_scene);
}
ur->add_do_method(editor_selection, "add_node", dup);

Expand Down Expand Up @@ -3647,6 +3659,7 @@ void SceneTreeDock::_clear_clipboard() {
memdelete(E);
}
node_clipboard.clear();
node_clipboard_edited_scene_owned.clear();
clipboard_resource_remap.clear();
}

Expand Down
1 change: 1 addition & 0 deletions editor/scene_tree_dock.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class SceneTreeDock : public VBoxContainer {
EditorSelection *editor_selection = nullptr;

List<Node *> node_clipboard;
List<Node *> node_clipboard_edited_scene_owned;
String clipboard_source_scene;
HashMap<String, HashMap<Ref<Resource>, Ref<Resource>>> clipboard_resource_remap;

Expand Down

0 comments on commit 861cc7b

Please sign in to comment.