From 2115bced93dc85ea04d5d5b51d022063a05c4c2f Mon Sep 17 00:00:00 2001 From: Benjamin Riley Date: Wed, 25 Sep 2019 17:06:05 +1000 Subject: [PATCH] 'Save Branch as Scene' adds to undo history When saving a branch as a scene, can now undo replacing the original branch with the new branch scene. 'Save Branch as Scene' previously would not mark the original scene as changed, and therefore no prompt would appear if the scene was closed immediately after saving the branch. The new branch scene is not deleted when undo-ing. --- editor/scene_tree_dock.cpp | 41 ++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 2ddf1f705674..4ca38ff75efa 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -250,22 +250,37 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) return; } + UndoRedo *undo_redo = editor->get_undo_redo(); + undo_redo->create_action(TTR("Replace with Branch Scene")); + Node *parent = base->get_parent(); int pos = base->get_index(); - parent->remove_child(base); - parent->add_child(instanced_scene); - parent->move_child(instanced_scene, pos); - instanced_scene->set_owner(edited_scene); - editor_selection->clear(); - editor_selection->add_node(instanced_scene); - scene_tree->set_selected(instanced_scene); + undo_redo->add_do_method(parent, "remove_child", base); + undo_redo->add_undo_method(parent, "remove_child", instanced_scene); + undo_redo->add_do_method(parent, "add_child", instanced_scene); + undo_redo->add_undo_method(parent, "add_child", base); + undo_redo->add_do_method(parent, "move_child", instanced_scene, pos); + undo_redo->add_undo_method(parent, "move_child", base, pos); - // Delete the node as late as possible because before another one is selected - // an editor plugin could be referencing it to do something with it before - // switching to another (or to none); and since some steps of changing the - // editor state are deferred, the safest thing is to do this is as the last - // step of this function and also by enqueing instead of memdelete()-ing it here - base->queue_delete(); + List owned; + base->get_owned_by(base->get_owner(), &owned); + Array owners; + for (List::Element *F = owned.front(); F; F = F->next()) { + owners.push_back(F->get()); + } + undo_redo->add_do_method(instanced_scene, "set_owner", edited_scene); + undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners); + + undo_redo->add_do_method(editor_selection, "clear"); + undo_redo->add_undo_method(editor_selection, "clear"); + undo_redo->add_do_method(editor_selection, "add_node", instanced_scene); + undo_redo->add_undo_method(editor_selection, "add_node", base); + undo_redo->add_do_property(scene_tree, "set_selected", instanced_scene); + undo_redo->add_undo_property(scene_tree, "set_selected", base); + + undo_redo->add_do_reference(instanced_scene); + undo_redo->add_undo_reference(base); + undo_redo->commit_action(); } bool SceneTreeDock::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {