diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0df4df36bcd9..af06ccb88573 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1067,7 +1067,7 @@ void EditorNode::_resources_reimported(const Vector &p_resources) { reload_instances_with_path_in_edited_scenes(E); } - scene_tabs->set_current_tab(current_tab); + _set_current_scene_nocheck(current_tab); } void EditorNode::_sources_changed(bool p_exist) { @@ -5719,8 +5719,14 @@ void EditorNode::reload_scene(const String &p_path) { if (scene_idx == -1) { if (get_edited_scene()) { + int current_history_id = editor_data.get_current_edited_scene_history_id(); + bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id); + // Scene is not open, so at it might be instantiated. We'll refresh the whole scene later. - EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id()); + EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id); + if (is_unsaved) { + EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id); + } } return; } @@ -5770,7 +5776,6 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node * } void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) { - int original_edited_scene_idx = editor_data.get_edited_scene(); HashMap> edited_scene_map; Array replaced_nodes; @@ -5801,14 +5806,34 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins HashMap> local_scene_cache; local_scene_cache[p_instance_path] = instance_scene_packed_scene; + // Save the current scene state/selection in case of lost. + Dictionary editor_state = _get_main_scene_state(); + editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state); + editor_selection->clear(); + + int original_edited_scene_idx = editor_data.get_edited_scene(); + Node *original_edited_scene_root = editor_data.get_edited_scene_root(); + + // Prevent scene roots with the same name from being in the tree at the same time. + scene_root->remove_child(original_edited_scene_root); + for (const KeyValue> &edited_scene_map_elem : edited_scene_map) { // Set the current scene. int current_scene_idx = edited_scene_map_elem.key; editor_data.set_edited_scene(current_scene_idx); Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx); - // Clear the history for this tab (should we allow history to be retained?). - EditorUndoRedoManager::get_singleton()->clear_history(); + // Make sure the node is in the tree so that editor_selection can add node smoothly. + scene_root->add_child(current_edited_scene); + + // Restore the state so that the selection can be updated. + editor_state = editor_data.restore_edited_scene_state(editor_selection, &editor_history); + + int current_history_id = editor_data.get_current_edited_scene_history_id(); + bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id); + + // Clear the history for this affected tab. + EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id); // Update the version editor_data.is_scene_changed(current_scene_idx); @@ -5818,6 +5843,52 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins update_node_reference_modification_table_for_node(current_edited_scene, current_edited_scene, edited_scene_map_elem.value, edited_scene_global_modification_table); for (Node *original_node : edited_scene_map_elem.value) { + String original_node_file_path = original_node->get_scene_file_path(); + + // Load a replacement scene for the node. + Ref current_packed_scene; + if (original_node_file_path == p_instance_path) { + // If the node file name directly matches the scene we're replacing, + // just load it since we already cached it. + current_packed_scene = instance_scene_packed_scene; + } else { + // Otherwise, check the inheritance chain, reloading and caching any scenes + // we require along the way. + List required_load_paths; + + // Do we need to check if the paths are empty? + if (!original_node_file_path.is_empty()) { + required_load_paths.push_front(original_node_file_path); + } + Ref inherited_state = original_node->get_scene_inherited_state(); + while (inherited_state.is_valid()) { + String inherited_path = inherited_state->get_path(); + // Do we need to check if the paths are empty? + if (!inherited_path.is_empty()) { + required_load_paths.push_front(inherited_path); + } + inherited_state = inherited_state->get_base_scene_state(); + } + + // Ensure the inheritance chain is loaded in the correct order so that cache can + // be properly updated. + for (String path : required_load_paths) { + if (!local_scene_cache.find(path)) { + current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err); + local_scene_cache[path] = current_packed_scene; + } else { + current_packed_scene = local_scene_cache[path]; + } + } + } + + ERR_FAIL_COND(current_packed_scene.is_null()); + + // Instantiate early so that caches cleared on load in SceneState can be rebuilt early. + Node *instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); + + ERR_FAIL_NULL(instantiated_node); + // Walk the tree for the current node and extract relevant diff data, storing it in the modification table. // For additional nodes which are part of the current scene, they get added to the addition table. HashMap modification_table; @@ -5875,53 +5946,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins is_editable = owner->is_editable_instance(original_node); } - // Load a replacement scene for the node. - Ref current_packed_scene; - if (original_node->get_scene_file_path() == p_instance_path) { - // If the node file name directly matches the scene we're replacing, - // just load it since we already cached it. - current_packed_scene = instance_scene_packed_scene; - } else { - // Otherwise, check the inheritance chain, reloading and caching any scenes - // we require along the way. - List required_load_paths; - String scene_path = original_node->get_scene_file_path(); - // Do we need to check if the paths are empty? - if (!scene_path.is_empty()) { - required_load_paths.push_front(scene_path); - } - Ref inherited_state = original_node->get_scene_inherited_state(); - while (inherited_state.is_valid()) { - String inherited_path = inherited_state->get_path(); - // Do we need to check if the paths are empty? - if (!inherited_path.is_empty()) { - required_load_paths.push_front(inherited_path); - } - inherited_state = inherited_state->get_base_scene_state(); - } - - // Ensure the inheritance chain is loaded in the correct order so that cache can - // be properly updated. - for (String path : required_load_paths) { - if (!local_scene_cache.find(path)) { - current_packed_scene = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP, &err); - local_scene_cache[path] = current_packed_scene; - } else { - current_packed_scene = local_scene_cache[path]; - } - } - } - - ERR_FAIL_COND(current_packed_scene.is_null()); - - // Instantiate the node. - Node *instantiated_node = nullptr; - if (current_packed_scene.is_valid()) { - instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); - } - - ERR_FAIL_NULL(instantiated_node); - // For clear instance state for path recaching. instantiated_node->set_scene_instance_state(Ref()); @@ -5932,7 +5956,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins instantiated_node->set_name(original_node->get_name()); // Is this replacing the edited root node? - String original_node_file_path = original_node->get_scene_file_path(); if (current_edited_scene == original_node) { instantiated_node->set_scene_instance_state(original_node->get_scene_instance_state()); @@ -5943,13 +5966,7 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins instantiated_node->set_scene_inherited_state(state); instantiated_node->set_scene_file_path(String()); } - editor_data.set_edited_scene_root(instantiated_node); current_edited_scene = instantiated_node; - - if (original_node->is_inside_tree()) { - SceneTreeDock::get_singleton()->set_edited_scene(current_edited_scene); - original_node->get_tree()->set_edited_scene_root(instantiated_node); - } } // Replace the original node with the instantiated version. @@ -6046,8 +6063,18 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins } } + if (is_unsaved) { + EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id); + } + + // Save the current handled scene state. + editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state); + editor_selection->clear(); + // Cleanup the history of the changes. editor_history.cleanup_history(); + + scene_root->remove_child(current_edited_scene); } // For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes. @@ -6055,10 +6082,14 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins _notify_nodes_scene_reimported(this, replaced_nodes); edited_scene_map.clear(); - } - editor_data.set_edited_scene(original_edited_scene_idx); - _edit_current(); + editor_data.set_edited_scene(original_edited_scene_idx); + + original_edited_scene_root = editor_data.get_edited_scene_root(); + scene_root->add_child(original_edited_scene_root); + + editor_data.restore_edited_scene_state(editor_selection, &editor_history); + } } int EditorNode::plugin_init_callback_count = 0;