瀏覽代碼

Merge pull request #95225 from Hilderin/fix-performance-reimport-file

Fix performance issue reimport file reload scene
Rémi Verschelde 1 年之前
父節點
當前提交
4bef4d9808
共有 2 個文件被更改,包括 410 次插入391 次删除
  1. 389 377
      editor/editor_node.cpp
  2. 21 14
      editor/editor_node.h

+ 389 - 377
editor/editor_node.cpp

@@ -3870,17 +3870,18 @@ void EditorNode::_set_current_scene_nocheck(int p_idx) {
 	changing_scene = true;
 	editor_data.save_edited_scene_state(editor_selection, &editor_history, _get_main_scene_state());
 
-	if (get_editor_data().get_edited_scene_root()) {
-		if (get_editor_data().get_edited_scene_root()->get_parent() == scene_root) {
-			scene_root->remove_child(get_editor_data().get_edited_scene_root());
-		}
-	}
+	Node *old_scene = get_editor_data().get_edited_scene_root();
 
 	editor_selection->clear();
 	editor_data.set_edited_scene(p_idx);
 
 	Node *new_scene = editor_data.get_edited_scene_root();
 
+	// Remove the scene only if it's a new scene, preventing performance issues when adding and removing scenes.
+	if (old_scene && new_scene != old_scene && old_scene->get_parent() == scene_root) {
+		scene_root->remove_child(old_scene);
+	}
+
 	if (Popup *p = Object::cast_to<Popup>(new_scene)) {
 		p->show();
 	}
@@ -4154,21 +4155,23 @@ HashMap<StringName, Variant> EditorNode::get_modified_properties_for_node(Node *
 	p_node->get_property_list(&pinfo);
 	for (const PropertyInfo &E : pinfo) {
 		if (E.usage & PROPERTY_USAGE_STORAGE) {
+			bool node_reference = (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE);
+			if (p_node_references_only && !node_reference) {
+				continue;
+			}
 			bool is_valid_revert = false;
 			Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_node, E.name, &is_valid_revert);
 			Variant current_value = p_node->get(E.name);
 			if (is_valid_revert) {
 				if (PropertyUtils::is_property_value_different(p_node, current_value, revert_value)) {
 					// If this property is a direct node reference, save a NodePath instead to prevent corrupted references.
-					if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_NODE_TYPE) {
+					if (node_reference) {
 						Node *target_node = Object::cast_to<Node>(current_value);
 						if (target_node) {
 							modified_property_map[E.name] = p_node->get_path_to(target_node);
 						}
 					} else {
-						if (!p_node_references_only) {
-							modified_property_map[E.name] = current_value;
-						}
+						modified_property_map[E.name] = current_value;
 					}
 				}
 			}
@@ -4178,6 +4181,27 @@ HashMap<StringName, Variant> EditorNode::get_modified_properties_for_node(Node *
 	return modified_property_map;
 }
 
+HashMap<StringName, Variant> EditorNode::get_modified_properties_reference_to_nodes(Node *p_node, List<Node *> &p_nodes_referenced_by) {
+	HashMap<StringName, Variant> modified_property_map;
+
+	List<PropertyInfo> pinfo;
+	p_node->get_property_list(&pinfo);
+	for (const PropertyInfo &E : pinfo) {
+		if (E.usage & PROPERTY_USAGE_STORAGE) {
+			if (E.type != Variant::OBJECT || E.hint != PROPERTY_HINT_NODE_TYPE) {
+				continue;
+			}
+			Variant current_value = p_node->get(E.name);
+			Node *target_node = Object::cast_to<Node>(current_value);
+			if (target_node && p_nodes_referenced_by.find(target_node)) {
+				modified_property_map[E.name] = p_node->get_path_to(target_node);
+			}
+		}
+	}
+
+	return modified_property_map;
+}
+
 void EditorNode::update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification) {
 	if (p_node) {
 		// First, attempt to restore the script property since it may affect the get_property_list method.
@@ -4264,28 +4288,6 @@ void EditorNode::update_node_from_node_modification_entry(Node *p_node, Modifica
 	}
 }
 
-void EditorNode::update_node_reference_modification_table_for_node(
-		Node *p_root,
-		Node *p_node,
-		List<Node *> p_excluded_nodes,
-		HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
-	if (!p_excluded_nodes.find(p_node)) {
-		HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, false);
-
-		if (!modified_properties.is_empty()) {
-			ModificationNodeEntry modification_node_entry;
-			modification_node_entry.property_table = modified_properties;
-
-			p_modification_table[p_root->get_path_to(p_node)] = modification_node_entry;
-		}
-
-		for (int i = 0; i < p_node->get_child_count(); i++) {
-			Node *child = p_node->get_child(i);
-			update_node_reference_modification_table_for_node(p_root, child, p_excluded_nodes, p_modification_table);
-		}
-	}
-}
-
 bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimported_root, Node *p_node) {
 	if (p_node == p_reimported_root) {
 		return false;
@@ -4328,11 +4330,39 @@ bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimp
 void EditorNode::get_preload_scene_modification_table(
 		Node *p_edited_scene,
 		Node *p_reimported_root,
-		Node *p_node, HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
-	// Only take the nodes that are in the base imported scene. The additional nodes will be managed
-	// after the resources are reimported. It's not important to check which property has
-	// changed on nodes that will not be reimported because they are not part of the reimported scene.
-	if (!is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
+		Node *p_node, InstanceModificationsEntry &p_instance_modifications) {
+	if (is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
+		// Only save additional nodes which have an owner since this was causing issues transient ownerless nodes
+		// which get recreated upon scene tree entry.
+		// For now instead, assume all ownerless nodes are transient and will have to be recreated.
+		if (p_node->get_owner()) {
+			HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, true);
+			if (p_node->get_owner() == p_edited_scene) {
+				AdditiveNodeEntry new_additive_node_entry;
+				new_additive_node_entry.node = p_node;
+				new_additive_node_entry.parent = p_reimported_root->get_path_to(p_node->get_parent());
+				new_additive_node_entry.owner = p_node->get_owner();
+				new_additive_node_entry.index = p_node->get_index();
+
+				Node2D *node_2d = Object::cast_to<Node2D>(p_node);
+				if (node_2d) {
+					new_additive_node_entry.transform_2d = node_2d->get_transform();
+				}
+				Node3D *node_3d = Object::cast_to<Node3D>(p_node);
+				if (node_3d) {
+					new_additive_node_entry.transform_3d = node_3d->get_transform();
+				}
+
+				p_instance_modifications.addition_list.push_back(new_additive_node_entry);
+			}
+			if (!modified_properties.is_empty()) {
+				ModificationNodeEntry modification_node_entry;
+				modification_node_entry.property_table = modified_properties;
+
+				p_instance_modifications.modifications[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
+			}
+		}
+	} else {
 		HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, false);
 
 		// Find all valid connections to other nodes.
@@ -4391,58 +4421,42 @@ void EditorNode::get_preload_scene_modification_table(
 			modification_node_entry.connections_from = valid_connections_from;
 			modification_node_entry.groups = groups;
 
-			p_modification_table[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
+			p_instance_modifications.modifications[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
 		}
 	}
 
 	for (int i = 0; i < p_node->get_child_count(); i++) {
-		Node *child = p_node->get_child(i);
-		get_preload_scene_modification_table(p_edited_scene, p_reimported_root, child, p_modification_table);
+		get_preload_scene_modification_table(p_edited_scene, p_reimported_root, p_node->get_child(i), p_instance_modifications);
 	}
 }
 
-void EditorNode::update_reimported_diff_data_for_additional_nodes(
-		Node *p_edited_scene,
-		Node *p_reimported_root,
+void EditorNode::get_preload_modifications_reference_to_nodes(
+		Node *p_root,
 		Node *p_node,
-		HashMap<NodePath, ModificationNodeEntry> &p_modification_table,
-		List<AdditiveNodeEntry> &p_addition_list) {
-	if (is_additional_node_in_scene(p_edited_scene, p_reimported_root, p_node)) {
-		// Only save additional nodes which have an owner since this was causing issues transient ownerless nodes
-		// which get recreated upon scene tree entry.
-		// For now instead, assume all ownerless nodes are transient and will have to be recreated.
-		if (p_node->get_owner()) {
-			HashMap<StringName, Variant> modified_properties = get_modified_properties_for_node(p_node, true);
-			if (p_node->get_owner() == p_edited_scene) {
-				AdditiveNodeEntry new_additive_node_entry;
-				new_additive_node_entry.node = p_node;
-				new_additive_node_entry.parent = p_reimported_root->get_path_to(p_node->get_parent());
-				new_additive_node_entry.owner = p_node->get_owner();
-				new_additive_node_entry.index = p_node->get_index();
+		List<Node *> &p_excluded_nodes,
+		List<Node *> &p_instance_list_with_children,
+		HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
+	if (!p_excluded_nodes.find(p_node)) {
+		HashMap<StringName, Variant> modified_properties = get_modified_properties_reference_to_nodes(p_node, p_instance_list_with_children);
 
-				Node2D *node_2d = Object::cast_to<Node2D>(p_node);
-				if (node_2d) {
-					new_additive_node_entry.transform_2d = node_2d->get_relative_transform_to_parent(node_2d->get_parent());
-				}
-				Node3D *node_3d = Object::cast_to<Node3D>(p_node);
-				if (node_3d) {
-					new_additive_node_entry.transform_3d = node_3d->get_relative_transform(node_3d->get_parent());
-				}
+		if (!modified_properties.is_empty()) {
+			ModificationNodeEntry modification_node_entry;
+			modification_node_entry.property_table = modified_properties;
 
-				p_addition_list.push_back(new_additive_node_entry);
-			}
-			if (!modified_properties.is_empty()) {
-				ModificationNodeEntry modification_node_entry;
-				modification_node_entry.property_table = modified_properties;
+			p_modification_table[p_root->get_path_to(p_node)] = modification_node_entry;
+		}
 
-				p_modification_table[p_reimported_root->get_path_to(p_node)] = modification_node_entry;
-			}
+		for (int i = 0; i < p_node->get_child_count(); i++) {
+			get_preload_modifications_reference_to_nodes(p_root, p_node->get_child(i), p_excluded_nodes, p_instance_list_with_children, p_modification_table);
 		}
 	}
+}
 
+void EditorNode::get_children_nodes(Node *p_node, List<Node *> &p_nodes) {
 	for (int i = 0; i < p_node->get_child_count(); i++) {
 		Node *child = p_node->get_child(i);
-		update_reimported_diff_data_for_additional_nodes(p_edited_scene, p_reimported_root, child, p_modification_table, p_addition_list);
+		p_nodes.push_back(child);
+		get_children_nodes(child, p_nodes);
 	}
 }
 
@@ -4456,8 +4470,7 @@ void EditorNode::replace_history_reimported_nodes(Node *p_original_root_node, No
 	}
 
 	for (int i = 0; i < p_node->get_child_count(); i++) {
-		Node *child = p_node->get_child(i);
-		replace_history_reimported_nodes(p_original_root_node, p_new_root_node, child);
+		replace_history_reimported_nodes(p_original_root_node, p_new_root_node, p_node->get_child(i));
 	}
 }
 
@@ -5831,25 +5844,6 @@ void EditorNode::reload_scene(const String &p_path) {
 	scene_tabs->set_current_tab(current_tab);
 }
 
-void EditorNode::get_edited_scene_map(const String &p_instance_path, HashMap<int, List<Node *>> &p_edited_scene_map) {
-	// Walk through each opened scene to get a global list of all instances which match
-	// the current reimported scenes.
-	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
-		if (editor_data.get_scene_path(i) == p_instance_path) {
-			continue;
-		}
-		Node *edited_scene_root = editor_data.get_edited_scene_root(i);
-
-		if (edited_scene_root) {
-			List<Node *> valid_nodes;
-			find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, p_instance_path, valid_nodes);
-			if (valid_nodes.size() > 0) {
-				p_edited_scene_map[i] = valid_nodes;
-			}
-		}
-	}
-}
-
 void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, List<Node *> &p_instance_list) {
 	String scene_file_path = p_node->get_scene_file_path();
 
@@ -5872,393 +5866,411 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
 	}
 
 	for (int i = 0; i < p_node->get_child_count(); i++) {
-		Node *child = p_node->get_child(i);
-		find_all_instances_inheriting_path_in_node(p_root, child, p_instance_path, p_instance_list);
+		find_all_instances_inheriting_path_in_node(p_root, p_node->get_child(i), p_instance_path, p_instance_list);
 	}
 }
 
 void EditorNode::preload_reimporting_with_path_in_edited_scenes(const String &p_instance_path) {
-	HashMap<int, List<Node *>> edited_scene_map;
 	scenes_modification_table.clear();
 
-	get_edited_scene_map(p_instance_path, edited_scene_map);
+	EditorProgress progress("preload_reimporting_scene", TTR("Preparing scenes for reload"), editor_data.get_edited_scene_count());
 
-	if (edited_scene_map.size() > 0) {
-		scenes_modification_table.clear();
+	int original_edited_scene_idx = editor_data.get_edited_scene();
 
-		int original_edited_scene_idx = editor_data.get_edited_scene();
-		Node *original_edited_scene_root = editor_data.get_edited_scene_root();
+	// Walk through each opened scene to get a global list of all instances which match
+	// the current reimported scenes.
+	for (int current_scene_idx = 0; current_scene_idx < editor_data.get_edited_scene_count(); current_scene_idx++) {
+		progress.step(vformat(TTR("Analyzing scene %s"), editor_data.get_scene_title(current_scene_idx)), current_scene_idx);
 
-		// Prevent scene roots with the same name from being in the tree at the same time.
-		scene_root->remove_child(original_edited_scene_root);
+		if (editor_data.get_scene_path(current_scene_idx) == p_instance_path) {
+			continue;
+		}
+		Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
+
+		if (edited_scene_root) {
+			List<Node *> instance_list;
+			find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, p_instance_path, instance_list);
+			if (instance_list.size() > 0) {
+				SceneModificationsEntry scene_motifications;
+				editor_data.set_edited_scene(current_scene_idx);
 
-		for (const KeyValue<int, List<Node *>> &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);
+				List<Node *> instance_list_with_children;
+				for (Node *original_node : instance_list) {
+					InstanceModificationsEntry instance_modifications;
 
-			// Make sure the node is in the tree so that editor_selection can add node smoothly.
-			scene_root->add_child(current_edited_scene);
+					// Fetching all the modified properties of the nodes reimported scene.
+					get_preload_scene_modification_table(edited_scene_root, original_node, original_node, instance_modifications);
 
-			for (Node *original_node : edited_scene_map_elem.value) {
-				// Fetching all the modified properties of the nodes reimported scene.
-				HashMap<NodePath, ModificationNodeEntry> modification_table;
-				get_preload_scene_modification_table(current_edited_scene, original_node, original_node, modification_table);
+					instance_modifications.original_node = original_node;
+					scene_motifications.instance_list.push_back(instance_modifications);
 
-				if (modification_table.size() > 0) {
-					NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
-					scenes_modification_table[current_scene_idx][scene_path_to_node] = modification_table;
+					instance_list_with_children.push_back(original_node);
+					get_children_nodes(original_node, instance_list_with_children);
 				}
-			}
 
-			scene_root->remove_child(current_edited_scene);
-		}
+				// Search the scene to find nodes that references the nodes will be recreated.
+				get_preload_modifications_reference_to_nodes(edited_scene_root, edited_scene_root, instance_list, instance_list_with_children, scene_motifications.other_instances_modifications);
 
-		editor_data.set_edited_scene(original_edited_scene_idx);
-		scene_root->add_child(original_edited_scene_root);
+				scenes_modification_table[current_scene_idx] = scene_motifications;
+			}
+		}
 	}
+
+	editor_data.set_edited_scene(original_edited_scene_idx);
+
+	progress.step(TTR("Preparation done."), editor_data.get_edited_scene_count());
 }
 
 void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_instance_path) {
-	HashMap<int, List<Node *>> edited_scene_map;
+	if (scenes_modification_table.size() == 0) {
+		return;
+	}
 	Array replaced_nodes;
 
-	get_edited_scene_map(p_instance_path, edited_scene_map);
+	EditorProgress progress("reloading_scene", TTR("Scenes reloading"), editor_data.get_edited_scene_count());
+	progress.step(TTR("Reloading..."), 0, true);
 
-	if (edited_scene_map.size() > 0) {
-		// Reload the new instance.
-		Error err;
-		Ref<PackedScene> instance_scene_packed_scene = ResourceLoader::load(p_instance_path, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err);
+	// Reload the new instance.
+	Error err;
+	Ref<PackedScene> instance_scene_packed_scene = ResourceLoader::load(p_instance_path, "", ResourceFormatLoader::CACHE_MODE_REPLACE, &err);
 
-		ERR_FAIL_COND(err != OK);
-		ERR_FAIL_COND(instance_scene_packed_scene.is_null());
+	ERR_FAIL_COND(err != OK);
+	ERR_FAIL_COND(instance_scene_packed_scene.is_null());
 
-		HashMap<String, Ref<PackedScene>> local_scene_cache;
-		local_scene_cache[p_instance_path] = instance_scene_packed_scene;
+	HashMap<String, Ref<PackedScene>> 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();
+	// 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();
+	int original_edited_scene_idx = editor_data.get_edited_scene();
 
-		// 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 (KeyValue<int, SceneModificationsEntry> &scene_modifications_elem : scenes_modification_table) {
+		// Set the current scene.
+		int current_scene_idx = scene_modifications_elem.key;
+		SceneModificationsEntry *scene_modifications = &scene_modifications_elem.value;
 
-		for (const KeyValue<int, List<Node *>> &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);
+		editor_data.set_edited_scene(current_scene_idx);
+		Node *current_edited_scene = editor_data.get_edited_scene_root(current_scene_idx);
 
-			// Make sure the node is in the tree so that editor_selection can add node smoothly.
+		// Make sure the node is in the tree so that editor_selection can add node smoothly.
+		if (original_edited_scene_idx != current_scene_idx) {
+			// Prevent scene roots with the same name from being in the tree at the same time.
+			Node *original_edited_scene_root = editor_data.get_edited_scene_root(original_edited_scene_idx);
+			if (original_edited_scene_root && original_edited_scene_root->get_name() == current_edited_scene->get_name()) {
+				scene_root->remove_child(original_edited_scene_root);
+			}
 			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);
+		// Restore the state so that the selection can be updated.
+		editor_state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
 
-			// Clear the history for this affected tab.
-			EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id);
+		int current_history_id = editor_data.get_current_edited_scene_history_id();
+		bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id);
 
-			// Update the version
-			editor_data.is_scene_changed(current_scene_idx);
+		// Clear the history for this affected tab.
+		EditorUndoRedoManager::get_singleton()->clear_history(false, current_history_id);
 
-			// Contains modifications in the edited scene which reference nodes inside of any nodes we will be reimporting.
-			HashMap<NodePath, ModificationNodeEntry> edited_scene_global_modification_table;
-			update_node_reference_modification_table_for_node(current_edited_scene, current_edited_scene, edited_scene_map_elem.value, edited_scene_global_modification_table);
+		// Update the version
+		editor_data.is_scene_changed(current_scene_idx);
 
-			for (Node *original_node : edited_scene_map_elem.value) {
-				String original_node_file_path = original_node->get_scene_file_path();
+		for (InstanceModificationsEntry instance_modifications : scene_modifications->instance_list) {
+			Node *original_node = instance_modifications.original_node;
+			String original_node_file_path = original_node->get_scene_file_path();
 
-				// Load a replacement scene for the node.
-				Ref<PackedScene> current_packed_scene;
-				Ref<PackedScene> base_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<String> required_load_paths;
+			// Load a replacement scene for the node.
+			Ref<PackedScene> current_packed_scene;
+			Ref<PackedScene> base_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<String> 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<SceneState> 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 (!original_node_file_path.is_empty()) {
-						required_load_paths.push_front(original_node_file_path);
-					}
-					Ref<SceneState> 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();
+					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 (current_packed_scene.is_valid()) {
-							base_packed_scene = current_packed_scene;
-						}
-						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];
-						}
+				// Ensure the inheritance chain is loaded in the correct order so that cache can
+				// be properly updated.
+				for (String path : required_load_paths) {
+					if (current_packed_scene.is_valid()) {
+						base_packed_scene = current_packed_scene;
+					}
+					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 = nullptr;
-
-				// If we are in a inherit scene, it's easier to create a new base scene and
-				// grab the node from there.
-				// When scene_path_to_node is '.' and we have scene_inherited_state, it's because
-				// it's a muli-level inheritance scene. We should use
-				NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
-				Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
-				if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != p_instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
-					Node *root_node = scene_state->instantiate(SceneState::GenEditState::GEN_EDIT_STATE_INSTANCE);
-					instantiated_node = root_node->get_node(scene_path_to_node);
-
-					if (instantiated_node) {
-						if (instantiated_node->get_parent()) {
-							// Remove from the root so we can delete it from memory.
-							instantiated_node->get_parent()->remove_child(instantiated_node);
-							// No need of the additional children that could have been added to the node
-							// in the base scene. That will be managed by the 'addition_list' later.
-							_remove_all_not_owned_children(instantiated_node, instantiated_node);
-							memdelete(root_node);
-						}
-					} else {
-						// Should not happen because we checked with find_node_by_path before, just in case.
+			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 = nullptr;
+
+			// If we are in a inherit scene, it's easier to create a new base scene and
+			// grab the node from there.
+			// When scene_path_to_node is '.' and we have scene_inherited_state, it's because
+			// it's a muli-level inheritance scene. We should use
+			NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
+			Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
+			if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != p_instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
+				Node *root_node = scene_state->instantiate(SceneState::GenEditState::GEN_EDIT_STATE_INSTANCE);
+				instantiated_node = root_node->get_node(scene_path_to_node);
+
+				if (instantiated_node) {
+					if (instantiated_node->get_parent()) {
+						// Remove from the root so we can delete it from memory.
+						instantiated_node->get_parent()->remove_child(instantiated_node);
+						// No need of the additional children that could have been added to the node
+						// in the base scene. That will be managed by the 'addition_list' later.
+						_remove_all_not_owned_children(instantiated_node, instantiated_node);
 						memdelete(root_node);
 					}
+				} else {
+					// Should not happen because we checked with find_node_by_path before, just in case.
+					memdelete(root_node);
 				}
+			}
 
-				if (!instantiated_node) {
-					// If no base scene was found to create the node, we will use the reimported packed scene directly.
-					// But, when the current edited scene is the reimported scene, it's because it's a inherited scene
-					// of the reimported scene. In that case, we will not instantiate current_packed_scene, because
-					// we would reinstanciate ourself. Using the base scene is better.
-					if (current_edited_scene == original_node) {
-						if (base_packed_scene.is_valid()) {
-							instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
-						} else {
-							instantiated_node = instance_scene_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
-						}
+			if (!instantiated_node) {
+				// If no base scene was found to create the node, we will use the reimported packed scene directly.
+				// But, when the current edited scene is the reimported scene, it's because it's a inherited scene
+				// of the reimported scene. In that case, we will not instantiate current_packed_scene, because
+				// we would reinstanciate ourself. Using the base scene is better.
+				if (current_edited_scene == original_node) {
+					if (base_packed_scene.is_valid()) {
+						instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
 					} else {
-						instantiated_node = current_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
+						instantiated_node = instance_scene_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
 					}
+				} else {
+					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<NodePath, ModificationNodeEntry> modification_table;
-				List<AdditiveNodeEntry> addition_list;
-				if (scenes_modification_table.has(current_scene_idx) && scenes_modification_table[current_scene_idx].has(scene_path_to_node)) {
-					modification_table = scenes_modification_table[current_scene_idx][scene_path_to_node];
-				}
-				update_reimported_diff_data_for_additional_nodes(current_edited_scene, original_node, original_node, modification_table, addition_list);
+			}
+			ERR_FAIL_NULL(instantiated_node);
 
-				// Disconnect all relevant connections, all connections from and persistent connections to.
-				for (const KeyValue<NodePath, ModificationNodeEntry> &modification_table_entry : modification_table) {
-					for (Connection conn : modification_table_entry.value.connections_from) {
+			// Disconnect all relevant connections, all connections from and persistent connections to.
+			for (const KeyValue<NodePath, ModificationNodeEntry> &modification_table_entry : instance_modifications.modifications) {
+				for (Connection conn : modification_table_entry.value.connections_from) {
+					conn.signal.get_object()->disconnect(conn.signal.get_name(), conn.callable);
+				}
+				for (ConnectionWithNodePath cwnp : modification_table_entry.value.connections_to) {
+					Connection conn = cwnp.connection;
+					if (conn.flags & CONNECT_PERSIST) {
 						conn.signal.get_object()->disconnect(conn.signal.get_name(), conn.callable);
 					}
-					for (ConnectionWithNodePath cwnp : modification_table_entry.value.connections_to) {
-						Connection conn = cwnp.connection;
-						if (conn.flags & CONNECT_PERSIST) {
-							conn.signal.get_object()->disconnect(conn.signal.get_name(), conn.callable);
-						}
-					}
 				}
+			}
 
-				// Store all the paths for any selected nodes which are ancestors of the node we're replacing.
-				List<NodePath> selected_node_paths;
-				for (Node *selected_node : editor_selection->get_selected_node_list()) {
-					if (selected_node == original_node || original_node->is_ancestor_of(selected_node)) {
-						selected_node_paths.push_back(original_node->get_path_to(selected_node));
-						editor_selection->remove_node(selected_node);
-					}
+			// Store all the paths for any selected nodes which are ancestors of the node we're replacing.
+			List<NodePath> selected_node_paths;
+			for (Node *selected_node : editor_selection->get_selected_node_list()) {
+				if (selected_node == original_node || original_node->is_ancestor_of(selected_node)) {
+					selected_node_paths.push_back(original_node->get_path_to(selected_node));
+					editor_selection->remove_node(selected_node);
 				}
+			}
 
-				// Remove all nodes which were added as additional elements (they will be restored later).
-				for (AdditiveNodeEntry additive_node_entry : addition_list) {
-					Node *addition_node = additive_node_entry.node;
-					addition_node->get_parent()->remove_child(addition_node);
-				}
+			// Remove all nodes which were added as additional elements (they will be restored later).
+			for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
+				Node *addition_node = additive_node_entry.node;
+				addition_node->get_parent()->remove_child(addition_node);
+			}
 
-				// Clear ownership of the nodes (kind of hack to workaround an issue with
-				// replace_by when called on nodes in other tabs).
-				List<Node *> nodes_owned_by_original_node;
-				original_node->get_owned_by(original_node, &nodes_owned_by_original_node);
-				for (Node *owned_node : nodes_owned_by_original_node) {
-					owned_node->set_owner(nullptr);
-				}
+			// Clear ownership of the nodes (kind of hack to workaround an issue with
+			// replace_by when called on nodes in other tabs).
+			List<Node *> nodes_owned_by_original_node;
+			original_node->get_owned_by(original_node, &nodes_owned_by_original_node);
+			for (Node *owned_node : nodes_owned_by_original_node) {
+				owned_node->set_owner(nullptr);
+			}
 
-				// Replace the old nodes in the history with the new ones.
-				// Otherwise, the history will contain old nodes, and some could still be
-				// instantiated if used elsewhere, causing the "current edited item" to be
-				// linked to a node that will be destroyed later. This caused the editor to
-				// crash when reimporting scenes with animations when "Editable children" was enabled.
-				replace_history_reimported_nodes(original_node, instantiated_node, original_node);
+			// Replace the old nodes in the history with the new ones.
+			// Otherwise, the history will contain old nodes, and some could still be
+			// instantiated if used elsewhere, causing the "current edited item" to be
+			// linked to a node that will be destroyed later. This caused the editor to
+			// crash when reimporting scenes with animations when "Editable children" was enabled.
+			replace_history_reimported_nodes(original_node, instantiated_node, original_node);
 
-				// Delete all the remaining node children.
-				while (original_node->get_child_count()) {
-					Node *child = original_node->get_child(0);
+			// Delete all the remaining node children.
+			while (original_node->get_child_count()) {
+				Node *child = original_node->get_child(0);
 
-					original_node->remove_child(child);
-					child->queue_free();
-				}
+				original_node->remove_child(child);
+				child->queue_free();
+			}
 
-				// Reset the editable instance state.
-				bool is_editable = true;
-				Node *owner = original_node->get_owner();
-				if (owner) {
-					is_editable = owner->is_editable_instance(original_node);
-				}
+			// Reset the editable instance state.
+			bool is_editable = true;
+			Node *owner = original_node->get_owner();
+			if (owner) {
+				is_editable = owner->is_editable_instance(original_node);
+			}
 
-				bool original_node_is_displayed_folded = original_node->is_displayed_folded();
-				bool original_node_scene_instance_load_placeholder = original_node->get_scene_instance_load_placeholder();
+			bool original_node_is_displayed_folded = original_node->is_displayed_folded();
+			bool original_node_scene_instance_load_placeholder = original_node->get_scene_instance_load_placeholder();
 
-				// Update the name to match
-				instantiated_node->set_name(original_node->get_name());
+			// Update the name to match
+			instantiated_node->set_name(original_node->get_name());
 
-				// Is this replacing the edited root node?
+			// Is this replacing the edited root node?
 
-				if (current_edited_scene == original_node) {
-					// Set the instance as un inherited scene of itself.
-					instantiated_node->set_scene_inherited_state(instantiated_node->get_scene_instance_state());
-					instantiated_node->set_scene_instance_state(nullptr);
-					instantiated_node->set_scene_file_path(original_node_file_path);
-					current_edited_scene = instantiated_node;
-					editor_data.set_edited_scene_root(current_edited_scene);
-				}
+			if (current_edited_scene == original_node) {
+				// Set the instance as un inherited scene of itself.
+				instantiated_node->set_scene_inherited_state(instantiated_node->get_scene_instance_state());
+				instantiated_node->set_scene_instance_state(nullptr);
+				instantiated_node->set_scene_file_path(original_node_file_path);
+				current_edited_scene = instantiated_node;
+				editor_data.set_edited_scene_root(current_edited_scene);
 
-				// Replace the original node with the instantiated version.
-				original_node->replace_by(instantiated_node, false);
+				if (original_edited_scene_idx == current_scene_idx) {
+					// How that the editor executes a redraw while destroying or progressing the EditorProgress,
+					// it crashes when the root scene has been replaced because the edited scene
+					// was freed and no longer in the scene tree.
+					SceneTreeDock::get_singleton()->set_edited_scene(current_edited_scene);
+					if (get_tree()) {
+						get_tree()->set_edited_scene_root(current_edited_scene);
+					}
+				}
+			}
 
-				// Mark the old node for deletion.
-				original_node->queue_free();
+			// Replace the original node with the instantiated version.
+			original_node->replace_by(instantiated_node, false);
 
-				// Restore the folded and placeholder state from the original node.
-				instantiated_node->set_display_folded(original_node_is_displayed_folded);
-				instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
+			// Mark the old node for deletion.
+			original_node->queue_free();
 
-				if (owner) {
-					Ref<SceneState> ss_inst = owner->get_scene_instance_state();
-					if (ss_inst.is_valid()) {
-						ss_inst->update_instance_resource(p_instance_path, current_packed_scene);
-					}
+			// Restore the folded and placeholder state from the original node.
+			instantiated_node->set_display_folded(original_node_is_displayed_folded);
+			instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
 
-					owner->set_editable_instance(instantiated_node, is_editable);
+			if (owner) {
+				Ref<SceneState> ss_inst = owner->get_scene_instance_state();
+				if (ss_inst.is_valid()) {
+					ss_inst->update_instance_resource(p_instance_path, current_packed_scene);
 				}
 
-				// Attempt to re-add all the additional nodes.
-				for (AdditiveNodeEntry additive_node_entry : addition_list) {
-					Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
+				owner->set_editable_instance(instantiated_node, is_editable);
+			}
 
-					if (!parent_node) {
-						parent_node = current_edited_scene;
-					}
+			// Attempt to re-add all the additional nodes.
+			for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
+				Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
 
-					parent_node->add_child(additive_node_entry.node);
-					parent_node->move_child(additive_node_entry.node, additive_node_entry.index);
-					// If the additive node's owner was the node which got replaced, update it.
-					if (additive_node_entry.owner == original_node) {
-						additive_node_entry.owner = instantiated_node;
-					}
+				if (!parent_node) {
+					parent_node = current_edited_scene;
+				}
 
-					additive_node_entry.node->set_owner(additive_node_entry.owner);
+				parent_node->add_child(additive_node_entry.node);
+				parent_node->move_child(additive_node_entry.node, additive_node_entry.index);
+				// If the additive node's owner was the node which got replaced, update it.
+				if (additive_node_entry.owner == original_node) {
+					additive_node_entry.owner = instantiated_node;
+				}
 
-					// If the parent node was lost, attempt to restore the original global transform.
-					{
-						Node2D *node_2d = Object::cast_to<Node2D>(additive_node_entry.node);
-						if (node_2d) {
-							node_2d->set_transform(additive_node_entry.transform_2d);
-						}
+				additive_node_entry.node->set_owner(additive_node_entry.owner);
 
-						Node3D *node_3d = Object::cast_to<Node3D>(additive_node_entry.node);
-						if (node_3d) {
-							node_3d->set_transform(additive_node_entry.transform_3d);
-						}
+				// If the parent node was lost, attempt to restore the original global transform.
+				{
+					Node2D *node_2d = Object::cast_to<Node2D>(additive_node_entry.node);
+					if (node_2d) {
+						node_2d->set_transform(additive_node_entry.transform_2d);
 					}
-				}
 
-				// Restore the selection.
-				if (selected_node_paths.size()) {
-					for (NodePath selected_node_path : selected_node_paths) {
-						Node *selected_node = instantiated_node->get_node_or_null(selected_node_path);
-						if (selected_node) {
-							editor_selection->add_node(selected_node);
-						}
+					Node3D *node_3d = Object::cast_to<Node3D>(additive_node_entry.node);
+					if (node_3d) {
+						node_3d->set_transform(additive_node_entry.transform_3d);
 					}
-					editor_selection->update();
 				}
+			}
 
-				// Attempt to restore the modified properties and signals for the instantitated node and all its owned children.
-				for (KeyValue<NodePath, ModificationNodeEntry> &E : modification_table) {
-					NodePath new_current_path = E.key;
-					Node *modifiable_node = instantiated_node->get_node_or_null(new_current_path);
-
-					update_node_from_node_modification_entry(modifiable_node, E.value);
+			// Restore the selection.
+			if (selected_node_paths.size()) {
+				for (NodePath selected_node_path : selected_node_paths) {
+					Node *selected_node = instantiated_node->get_node_or_null(selected_node_path);
+					if (selected_node) {
+						editor_selection->add_node(selected_node);
+					}
 				}
-				// Add the newly instantiated node to the edited scene's replaced node list.
-				replaced_nodes.push_back(instantiated_node);
+				editor_selection->update();
 			}
 
 			// Attempt to restore the modified properties and signals for the instantitated node and all its owned children.
-			for (KeyValue<NodePath, ModificationNodeEntry> &E : edited_scene_global_modification_table) {
+			for (KeyValue<NodePath, ModificationNodeEntry> &E : instance_modifications.modifications) {
 				NodePath new_current_path = E.key;
-				Node *modifiable_node = current_edited_scene->get_node_or_null(new_current_path);
+				Node *modifiable_node = instantiated_node->get_node_or_null(new_current_path);
 
-				if (modifiable_node) {
-					update_node_from_node_modification_entry(modifiable_node, E.value);
-				}
+				update_node_from_node_modification_entry(modifiable_node, E.value);
 			}
+			// Add the newly instantiated node to the edited scene's replaced node list.
+			replaced_nodes.push_back(instantiated_node);
+		}
 
-			if (is_unsaved) {
-				EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id);
+		// Attempt to restore the modified properties and signals for the instantitated node and all its owned children.
+		for (KeyValue<NodePath, ModificationNodeEntry> &E : scene_modifications->other_instances_modifications) {
+			NodePath new_current_path = E.key;
+			Node *modifiable_node = current_edited_scene->get_node_or_null(new_current_path);
+
+			if (modifiable_node) {
+				update_node_from_node_modification_entry(modifiable_node, E.value);
 			}
+		}
 
-			// Save the current handled scene state.
-			editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state);
-			editor_selection->clear();
+		if (is_unsaved) {
+			EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id);
+		}
 
-			// Cleanup the history of the changes.
-			editor_history.cleanup_history();
+		// Save the current handled scene state.
+		editor_data.save_edited_scene_state(editor_selection, &editor_history, editor_state);
+		editor_selection->clear();
 
-			scene_root->remove_child(current_edited_scene);
-		}
+		// Cleanup the history of the changes.
+		editor_history.cleanup_history();
 
-		// For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes.
-		// To inform anything that depends on them that they should update as appropriate.
-		_notify_nodes_scene_reimported(this, replaced_nodes);
+		if (original_edited_scene_idx != current_scene_idx) {
+			scene_root->remove_child(current_edited_scene);
 
-		edited_scene_map.clear();
+			// Ensure the current edited scene is re-added if removed earlier because it has the same name
+			// as the reimported scene. The editor could crash when reloading SceneTreeDock if the current
+			// edited scene is not in the scene tree.
+			Node *original_edited_scene_root = editor_data.get_edited_scene_root(original_edited_scene_idx);
+			if (original_edited_scene_root && !original_edited_scene_root->get_parent()) {
+				scene_root->add_child(original_edited_scene_root);
+			}
+		}
+	}
 
-		editor_data.set_edited_scene(original_edited_scene_idx);
+	// For the whole editor, call the _notify_nodes_scene_reimported with a list of replaced nodes.
+	// To inform anything that depends on them that they should update as appropriate.
+	_notify_nodes_scene_reimported(this, replaced_nodes);
 
-		original_edited_scene_root = editor_data.get_edited_scene_root();
-		scene_root->add_child(original_edited_scene_root);
+	editor_data.set_edited_scene(original_edited_scene_idx);
 
-		editor_data.restore_edited_scene_state(editor_selection, &editor_history);
-	}
+	editor_data.restore_edited_scene_state(editor_selection, &editor_history);
 
 	scenes_modification_table.clear();
+
+	progress.step(TTR("Reloading done."), editor_data.get_edited_scene_count());
 }
 
 void EditorNode::_remove_all_not_owned_children(Node *p_node, Node *p_owner) {

+ 21 - 14
editor/editor_node.h

@@ -797,6 +797,7 @@ public:
 	Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false);
 
 	HashMap<StringName, Variant> get_modified_properties_for_node(Node *p_node, bool p_node_references_only);
+	HashMap<StringName, Variant> get_modified_properties_reference_to_nodes(Node *p_node, List<Node *> &p_nodes_referenced_by);
 
 	struct AdditiveNodeEntry {
 		Node *node = nullptr;
@@ -820,27 +821,34 @@ public:
 		List<Node::GroupInfo> groups;
 	};
 
-	HashMap<int, HashMap<NodePath, HashMap<NodePath, ModificationNodeEntry>>> scenes_modification_table;
+	struct InstanceModificationsEntry {
+		Node *original_node;
+		List<Node *> instance_list;
+		HashMap<NodePath, ModificationNodeEntry> modifications;
+		List<AdditiveNodeEntry> addition_list;
+	};
 
-	void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
+	struct SceneModificationsEntry {
+		List<InstanceModificationsEntry> instance_list;
+		HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
+	};
 
-	void update_node_reference_modification_table_for_node(
-			Node *p_root,
-			Node *p_node,
-			List<Node *> p_excluded_nodes,
-			HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
+	HashMap<int, SceneModificationsEntry> scenes_modification_table;
+
+	void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
 
 	void get_preload_scene_modification_table(
 			Node *p_edited_scene,
 			Node *p_reimported_root,
-			Node *p_node, HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
+			Node *p_node, InstanceModificationsEntry &p_instance_modifications);
 
-	void update_reimported_diff_data_for_additional_nodes(
-			Node *p_edited_scene,
-			Node *p_reimported_root,
+	void get_preload_modifications_reference_to_nodes(
+			Node *p_root,
 			Node *p_node,
-			HashMap<NodePath, ModificationNodeEntry> &p_modification_table,
-			List<AdditiveNodeEntry> &p_addition_list);
+			List<Node *> &p_excluded_nodes,
+			List<Node *> &p_instance_list_with_children,
+			HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
+	void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
 	bool is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimported_root, Node *p_node);
 
 	void replace_history_reimported_nodes(Node *p_original_root_node, Node *p_new_root_node, Node *p_node);
@@ -898,7 +906,6 @@ public:
 
 	void reload_scene(const String &p_path);
 
-	void get_edited_scene_map(const String &p_instance_path, HashMap<int, List<Node *>> &p_edited_scene_map);
 	void find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, List<Node *> &p_instance_list);
 	void preload_reimporting_with_path_in_edited_scenes(const String &p_path);
 	void reload_instances_with_path_in_edited_scenes(const String &p_path);