Jelajahi Sumber

Fix crash on reimport scene with animations

Hilderin 1 tahun lalu
induk
melakukan
769424388e
4 mengubah file dengan 35 tambahan dan 0 penghapusan
  1. 10 0
      editor/editor_data.cpp
  2. 1 0
      editor/editor_data.h
  3. 22 0
      editor/editor_node.cpp
  4. 2 0
      editor/editor_node.h

+ 10 - 0
editor/editor_data.cpp

@@ -141,6 +141,16 @@ void EditorSelectionHistory::add_object(ObjectID p_object, const String &p_prope
 	current_elem_idx++;
 	current_elem_idx++;
 }
 }
 
 
+void EditorSelectionHistory::replace_object(ObjectID p_old_object, ObjectID p_new_object) {
+	for (HistoryElement &element : history) {
+		for (int index = 0; index < element.path.size(); index++) {
+			if (element.path[index].object == p_old_object) {
+				element.path.write[index].object = p_new_object;
+			}
+		}
+	}
+}
+
 int EditorSelectionHistory::get_history_len() {
 int EditorSelectionHistory::get_history_len() {
 	return history.size();
 	return history.size();
 }
 }

+ 1 - 0
editor/editor_data.h

@@ -74,6 +74,7 @@ public:
 	// Adds an object to the selection history. A property name can be passed if the target is a subresource of the given object.
 	// Adds an object to the selection history. A property name can be passed if the target is a subresource of the given object.
 	// If the object should not change the main screen plugin, it can be set as inspector only.
 	// If the object should not change the main screen plugin, it can be set as inspector only.
 	void add_object(ObjectID p_object, const String &p_property = String(), bool p_inspector_only = false);
 	void add_object(ObjectID p_object, const String &p_property = String(), bool p_inspector_only = false);
+	void replace_object(ObjectID p_old_object, ObjectID p_new_object);
 
 
 	int get_history_len();
 	int get_history_len();
 	int get_history_pos();
 	int get_history_pos();

+ 22 - 0
editor/editor_node.cpp

@@ -4446,6 +4446,21 @@ void EditorNode::update_reimported_diff_data_for_additional_nodes(
 	}
 	}
 }
 }
 
 
+void EditorNode::replace_history_reimported_nodes(Node *p_original_root_node, Node *p_new_root_node, Node *p_node) {
+	NodePath scene_path_to_node = p_original_root_node->get_path_to(p_node);
+	Node *new_node = p_new_root_node->get_node_or_null(scene_path_to_node);
+	if (new_node) {
+		editor_history.replace_object(p_node->get_instance_id(), new_node->get_instance_id());
+	} else {
+		editor_history.replace_object(p_node->get_instance_id(), ObjectID());
+	}
+
+	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);
+	}
+}
+
 void EditorNode::open_request(const String &p_path) {
 void EditorNode::open_request(const String &p_path) {
 	if (!opening_prev) {
 	if (!opening_prev) {
 		List<String>::Element *prev_scene_item = previous_scenes.find(p_path);
 		List<String>::Element *prev_scene_item = previous_scenes.find(p_path);
@@ -6094,6 +6109,13 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
 					owned_node->set_owner(nullptr);
 					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);
+
 				// 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);

+ 2 - 0
editor/editor_node.h

@@ -843,6 +843,8 @@ public:
 			List<AdditiveNodeEntry> &p_addition_list);
 			List<AdditiveNodeEntry> &p_addition_list);
 	bool is_additional_node_in_scene(Node *p_edited_scene, Node *p_reimported_root, Node *p_node);
 	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);
+
 	bool is_scene_open(const String &p_path);
 	bool is_scene_open(const String &p_path);
 	bool is_multi_window_enabled() const;
 	bool is_multi_window_enabled() const;