Sfoglia il codice sorgente

Merge pull request #96144 from SaracenOne/reimport_owner_instance

Make reimported models reimport their owner.
Rémi Verschelde 1 anno fa
parent
commit
7a4c03418a
3 ha cambiato i file con 81 aggiunte e 61 eliminazioni
  1. 72 40
      editor/editor_node.cpp
  2. 9 2
      editor/editor_node.h
  3. 0 19
      scene/resources/packed_scene.cpp

+ 72 - 40
editor/editor_node.cpp

@@ -4404,6 +4404,21 @@ bool EditorNode::is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimp
 	return true;
 	return true;
 }
 }
 
 
+void EditorNode::get_scene_editor_data_for_node(Node *p_root, Node *p_node, HashMap<NodePath, SceneEditorDataEntry> &p_table) {
+	SceneEditorDataEntry new_entry;
+	new_entry.is_display_folded = p_node->is_displayed_folded();
+
+	if (p_root != p_node) {
+		new_entry.is_editable = p_root->is_editable_instance(p_node);
+	}
+
+	p_table.insert(p_root->get_path_to(p_node), new_entry);
+
+	for (int i = 0; i < p_node->get_child_count(); i++) {
+		get_scene_editor_data_for_node(p_root, p_node->get_child(i), p_table);
+	}
+}
+
 void EditorNode::get_preload_scene_modification_table(
 void EditorNode::get_preload_scene_modification_table(
 		Node *p_edited_scene,
 		Node *p_edited_scene,
 		Node *p_reimported_root,
 		Node *p_reimported_root,
@@ -4510,7 +4525,7 @@ void EditorNode::get_preload_scene_modification_table(
 void EditorNode::get_preload_modifications_reference_to_nodes(
 void EditorNode::get_preload_modifications_reference_to_nodes(
 		Node *p_root,
 		Node *p_root,
 		Node *p_node,
 		Node *p_node,
-		List<Node *> &p_excluded_nodes,
+		HashSet<Node *> &p_excluded_nodes,
 		List<Node *> &p_instance_list_with_children,
 		List<Node *> &p_instance_list_with_children,
 		HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
 		HashMap<NodePath, ModificationNodeEntry> &p_modification_table) {
 	if (!p_excluded_nodes.find(p_node)) {
 	if (!p_excluded_nodes.find(p_node)) {
@@ -5984,12 +5999,14 @@ void EditorNode::reload_scene(const String &p_path) {
 	scene_tabs->set_current_tab(current_tab);
 	scene_tabs->set_current_tab(current_tab);
 }
 }
 
 
-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) {
+void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, HashSet<Node *> &p_instance_list) {
 	String scene_file_path = p_node->get_scene_file_path();
 	String scene_file_path = p_node->get_scene_file_path();
 
 
-	// This is going to get messy...
+	bool valid_instance_found = false;
+
+	// Attempt to find all the instances matching path we're going to reload.
 	if (p_node->get_scene_file_path() == p_instance_path) {
 	if (p_node->get_scene_file_path() == p_instance_path) {
-		p_instance_list.push_back(p_node);
+		valid_instance_found = true;
 	} else {
 	} else {
 		Node *current_node = p_node;
 		Node *current_node = p_node;
 
 
@@ -5997,7 +6014,7 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
 		while (inherited_state.is_valid()) {
 		while (inherited_state.is_valid()) {
 			String inherited_path = inherited_state->get_path();
 			String inherited_path = inherited_state->get_path();
 			if (inherited_path == p_instance_path) {
 			if (inherited_path == p_instance_path) {
-				p_instance_list.push_back(p_node);
+				valid_instance_found = true;
 				break;
 				break;
 			}
 			}
 
 
@@ -6005,6 +6022,19 @@ void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *
 		}
 		}
 	}
 	}
 
 
+	// Instead of adding this instance directly, if its not owned by the scene, walk its ancestors
+	// and find the first node still owned by the scene. This is what we will reloading instead.
+	if (valid_instance_found) {
+		Node *current_node = p_node;
+		while (true) {
+			if (current_node->get_owner() == p_root || current_node->get_owner() == nullptr) {
+				p_instance_list.insert(current_node);
+				break;
+			}
+			current_node = current_node->get_parent();
+		}
+	}
+
 	for (int i = 0; i < p_node->get_child_count(); i++) {
 	for (int i = 0; i < p_node->get_child_count(); i++) {
 		find_all_instances_inheriting_path_in_node(p_root, p_node->get_child(i), 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);
 	}
 	}
@@ -6023,20 +6053,20 @@ void EditorNode::preload_reimporting_with_path_in_edited_scenes(const List<Strin
 		Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
 		Node *edited_scene_root = editor_data.get_edited_scene_root(current_scene_idx);
 
 
 		if (edited_scene_root) {
 		if (edited_scene_root) {
-			SceneModificationsEntry scene_motifications;
+			SceneModificationsEntry scene_modifications;
 
 
 			for (const String &instance_path : p_scenes) {
 			for (const String &instance_path : p_scenes) {
 				if (editor_data.get_scene_path(current_scene_idx) == instance_path) {
 				if (editor_data.get_scene_path(current_scene_idx) == instance_path) {
 					continue;
 					continue;
 				}
 				}
 
 
-				List<Node *> instance_list;
-				find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, instance_path, instance_list);
-				if (instance_list.size() > 0) {
+				HashSet<Node *> instances_to_reimport;
+				find_all_instances_inheriting_path_in_node(edited_scene_root, edited_scene_root, instance_path, instances_to_reimport);
+				if (instances_to_reimport.size() > 0) {
 					editor_data.set_edited_scene(current_scene_idx);
 					editor_data.set_edited_scene(current_scene_idx);
 
 
 					List<Node *> instance_list_with_children;
 					List<Node *> instance_list_with_children;
-					for (Node *original_node : instance_list) {
+					for (Node *original_node : instances_to_reimport) {
 						InstanceModificationsEntry instance_modifications;
 						InstanceModificationsEntry instance_modifications;
 
 
 						// Fetching all the modified properties of the nodes reimported scene.
 						// Fetching all the modified properties of the nodes reimported scene.
@@ -6044,19 +6074,19 @@ void EditorNode::preload_reimporting_with_path_in_edited_scenes(const List<Strin
 
 
 						instance_modifications.original_node = original_node;
 						instance_modifications.original_node = original_node;
 						instance_modifications.instance_path = instance_path;
 						instance_modifications.instance_path = instance_path;
-						scene_motifications.instance_list.push_back(instance_modifications);
+						scene_modifications.instance_list.push_back(instance_modifications);
 
 
 						instance_list_with_children.push_back(original_node);
 						instance_list_with_children.push_back(original_node);
 						get_children_nodes(original_node, instance_list_with_children);
 						get_children_nodes(original_node, instance_list_with_children);
 					}
 					}
 
 
 					// Search the scene to find nodes that references the nodes will be recreated.
 					// 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);
+					get_preload_modifications_reference_to_nodes(edited_scene_root, edited_scene_root, instances_to_reimport, instance_list_with_children, scene_modifications.other_instances_modifications);
 				}
 				}
 			}
 			}
 
 
-			if (scene_motifications.instance_list.size() > 0) {
-				scenes_modification_table[current_scene_idx] = scene_motifications;
+			if (scene_modifications.instance_list.size() > 0) {
+				scenes_modification_table[current_scene_idx] = scene_modifications;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -6179,10 +6209,10 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 			// Instantiate early so that caches cleared on load in SceneState can be rebuilt early.
 			// Instantiate early so that caches cleared on load in SceneState can be rebuilt early.
 			Node *instantiated_node = nullptr;
 			Node *instantiated_node = nullptr;
 
 
-			// If we are in a inherit scene, it's easier to create a new base scene and
+			// If we are in a inherited scene, it's easier to create a new base scene and
 			// grab the node from there.
 			// grab the node from there.
 			// When scene_path_to_node is '.' and we have scene_inherited_state, it's because
 			// 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
+			// it's a multi-level inheritance scene. We should use
 			NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
 			NodePath scene_path_to_node = current_edited_scene->get_path_to(original_node);
 			Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
 			Ref<SceneState> scene_state = current_edited_scene->get_scene_inherited_state();
 			if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != instance_modifications.instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
 			if (scene_path_to_node != "." && scene_state.is_valid() && scene_state->get_path() != instance_modifications.instance_path && scene_state->find_node_by_path(scene_path_to_node) >= 0) {
@@ -6206,9 +6236,9 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 
 
 			if (!instantiated_node) {
 			if (!instantiated_node) {
 				// If no base scene was found to create the node, we will use the reimported packed scene directly.
 				// 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.
+				// But, when the current edited scene is the reimported scene, it's because it's an inherited scene
+				// derived from the reimported scene. In that case, we will not instantiate current_packed_scene, because
+				// we would reinstantiate ourself. Using the base scene is better.
 				if (current_edited_scene == original_node) {
 				if (current_edited_scene == original_node) {
 					if (base_packed_scene.is_valid()) {
 					if (base_packed_scene.is_valid()) {
 						instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
 						instantiated_node = base_packed_scene->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
@@ -6264,6 +6294,17 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 			// crash when reimporting scenes with animations when "Editable children" was enabled.
 			// crash when reimporting scenes with animations when "Editable children" was enabled.
 			replace_history_reimported_nodes(original_node, instantiated_node, original_node);
 			replace_history_reimported_nodes(original_node, instantiated_node, original_node);
 
 
+			// Reset the editable instance state.
+			HashMap<NodePath, SceneEditorDataEntry> scene_editor_data_table;
+			Node *owner = original_node->get_owner();
+			if (!owner) {
+				owner = original_node;
+			}
+
+			get_scene_editor_data_for_node(owner, original_node, scene_editor_data_table);
+
+			bool original_node_scene_instance_load_placeholder = original_node->get_scene_instance_load_placeholder();
+
 			// Delete all the remaining node children.
 			// Delete all the remaining node children.
 			while (original_node->get_child_count()) {
 			while (original_node->get_child_count()) {
 				Node *child = original_node->get_child(0);
 				Node *child = original_node->get_child(0);
@@ -6272,16 +6313,6 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 				child->queue_free();
 				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);
-			}
-
-			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
 			// Update the name to match
 			instantiated_node->set_name(original_node->get_name());
 			instantiated_node->set_name(original_node->get_name());
 
 
@@ -6312,19 +6343,9 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 			// Mark the old node for deletion.
 			// Mark the old node for deletion.
 			original_node->queue_free();
 			original_node->queue_free();
 
 
-			// Restore the folded and placeholder state from the original node.
-			instantiated_node->set_display_folded(original_node_is_displayed_folded);
+			// Restore the placeholder state from the original node.
 			instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
 			instantiated_node->set_scene_instance_load_placeholder(original_node_scene_instance_load_placeholder);
 
 
-			if (owner) {
-				Ref<SceneState> ss_inst = owner->get_scene_instance_state();
-				if (ss_inst.is_valid()) {
-					ss_inst->update_instance_resource(instance_modifications.instance_path, current_packed_scene);
-				}
-
-				owner->set_editable_instance(instantiated_node, is_editable);
-			}
-
 			// Attempt to re-add all the additional nodes.
 			// Attempt to re-add all the additional nodes.
 			for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
 			for (AdditiveNodeEntry additive_node_entry : instance_modifications.addition_list) {
 				Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
 				Node *parent_node = instantiated_node->get_node_or_null(additive_node_entry.parent);
@@ -6356,6 +6377,17 @@ void EditorNode::reload_instances_with_path_in_edited_scenes() {
 				}
 				}
 			}
 			}
 
 
+			// Restore the scene's editable instance and folded states.
+			for (HashMap<NodePath, SceneEditorDataEntry>::Iterator I = scene_editor_data_table.begin(); I; ++I) {
+				Node *node = owner->get_node_or_null(I->key);
+				if (node) {
+					if (owner != node) {
+						owner->set_editable_instance(node, I->value.is_editable);
+					}
+					node->set_display_folded(I->value.is_display_folded);
+				}
+			}
+
 			// Restore the selection.
 			// Restore the selection.
 			if (selected_node_paths.size()) {
 			if (selected_node_paths.size()) {
 				for (NodePath selected_node_path : selected_node_paths) {
 				for (NodePath selected_node_path : selected_node_paths) {

+ 9 - 2
editor/editor_node.h

@@ -852,12 +852,19 @@ public:
 		HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
 		HashMap<NodePath, ModificationNodeEntry> other_instances_modifications;
 	};
 	};
 
 
+	struct SceneEditorDataEntry {
+		bool is_editable;
+		bool is_display_folded;
+	};
+
 	HashMap<int, SceneModificationsEntry> scenes_modification_table;
 	HashMap<int, SceneModificationsEntry> scenes_modification_table;
 	List<String> scenes_reimported;
 	List<String> scenes_reimported;
 	List<String> resources_reimported;
 	List<String> resources_reimported;
 
 
 	void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
 	void update_node_from_node_modification_entry(Node *p_node, ModificationNodeEntry &p_node_modification);
 
 
+	void get_scene_editor_data_for_node(Node *p_root, Node *p_node, HashMap<NodePath, SceneEditorDataEntry> &p_table);
+
 	void get_preload_scene_modification_table(
 	void get_preload_scene_modification_table(
 			Node *p_edited_scene,
 			Node *p_edited_scene,
 			Node *p_reimported_root,
 			Node *p_reimported_root,
@@ -866,7 +873,7 @@ public:
 	void get_preload_modifications_reference_to_nodes(
 	void get_preload_modifications_reference_to_nodes(
 			Node *p_root,
 			Node *p_root,
 			Node *p_node,
 			Node *p_node,
-			List<Node *> &p_excluded_nodes,
+			HashSet<Node *> &p_excluded_nodes,
 			List<Node *> &p_instance_list_with_children,
 			List<Node *> &p_instance_list_with_children,
 			HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
 			HashMap<NodePath, ModificationNodeEntry> &p_modification_table);
 	void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
 	void get_children_nodes(Node *p_node, List<Node *> &p_nodes);
@@ -927,7 +934,7 @@ public:
 
 
 	void reload_scene(const String &p_path);
 	void reload_scene(const String &p_path);
 
 
-	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 find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, HashSet<Node *> &p_instance_list);
 	void preload_reimporting_with_path_in_edited_scenes(const List<String> &p_scenes);
 	void preload_reimporting_with_path_in_edited_scenes(const List<String> &p_scenes);
 	void reload_instances_with_path_in_edited_scenes();
 	void reload_instances_with_path_in_edited_scenes();
 
 

+ 0 - 19
scene/resources/packed_scene.cpp

@@ -1354,25 +1354,6 @@ Ref<SceneState> SceneState::get_base_scene_state() const {
 	return Ref<SceneState>();
 	return Ref<SceneState>();
 }
 }
 
 
-void SceneState::update_instance_resource(String p_path, Ref<PackedScene> p_packed_scene) {
-	ERR_FAIL_COND(p_packed_scene.is_null());
-
-	for (const NodeData &nd : nodes) {
-		if (nd.instance >= 0) {
-			if (!(nd.instance & FLAG_INSTANCE_IS_PLACEHOLDER)) {
-				int instance_id = nd.instance & FLAG_MASK;
-				Ref<PackedScene> original_packed_scene = variants[instance_id];
-				if (original_packed_scene.is_valid()) {
-					if (original_packed_scene->get_path() == p_path) {
-						variants.remove_at(instance_id);
-						variants.insert(instance_id, p_packed_scene);
-					}
-				}
-			}
-		}
-	}
-}
-
 int SceneState::find_node_by_path(const NodePath &p_node) const {
 int SceneState::find_node_by_path(const NodePath &p_node) const {
 	ERR_FAIL_COND_V_MSG(node_path_cache.is_empty(), -1, "This operation requires the node cache to have been built.");
 	ERR_FAIL_COND_V_MSG(node_path_cache.is_empty(), -1, "This operation requires the node cache to have been built.");