Browse Source

Don't mark cached previously pinned AnimationMixers

AnimationPlayerEditor will hold on to pointers to no-longer existing
Nodes that were previously pinned. Make sure to not mark them as dirty
if they are not already inside the cache.

This fixes #102108
HP van Braam 8 months ago
parent
commit
0b30ecc758
2 changed files with 23 additions and 3 deletions
  1. 22 3
      editor/gui/scene_tree_editor.cpp
  2. 1 0
      editor/gui/scene_tree_editor.h

+ 22 - 3
editor/gui/scene_tree_editor.cpp

@@ -924,12 +924,19 @@ void SceneTreeEditor::_update_tree(bool p_scroll_to_selected) {
 		// If pinned state changed, update the currently pinned node.
 		if (AnimationPlayerEditor::get_singleton()->is_pinned() != node_cache.current_has_pin) {
 			node_cache.current_has_pin = AnimationPlayerEditor::get_singleton()->is_pinned();
-			node_cache.mark_dirty(pinned_node);
+			if (node_cache.has(pinned_node)) {
+				node_cache.mark_dirty(pinned_node);
+			}
 		}
 		// If the current pinned node changed update both the old and new node.
 		if (node_cache.current_pinned_node != pinned_node) {
-			node_cache.mark_dirty(pinned_node);
-			node_cache.mark_dirty(node_cache.current_pinned_node);
+			// get_editing_node() will return deleted nodes. If the nodes are not in cache don't try to mark them.
+			if (node_cache.has(pinned_node)) {
+				node_cache.mark_dirty(pinned_node);
+			}
+			if (node_cache.has(node_cache.current_pinned_node)) {
+				node_cache.mark_dirty(node_cache.current_pinned_node);
+			}
 			node_cache.current_pinned_node = pinned_node;
 		}
 
@@ -2373,6 +2380,10 @@ HashMap<Node *, SceneTreeEditor::CachedNode>::Iterator SceneTreeEditor::NodeCach
 	return I;
 }
 
+bool SceneTreeEditor::NodeCache::has(Node *p_node) {
+	return get(p_node, false).operator bool();
+}
+
 void SceneTreeEditor::NodeCache::remove(Node *p_node, bool p_recursive) {
 	if (!p_node) {
 		return;
@@ -2382,6 +2393,11 @@ void SceneTreeEditor::NodeCache::remove(Node *p_node, bool p_recursive) {
 		editor->selected = nullptr;
 	}
 
+	if (p_node == current_pinned_node) {
+		current_pinned_node = nullptr;
+		current_has_pin = false;
+	}
+
 	editor->marked.erase(p_node);
 
 	HashMap<Node *, CachedNode>::Iterator I = cache.find(p_node);
@@ -2419,6 +2435,7 @@ void SceneTreeEditor::NodeCache::mark_dirty(Node *p_node, bool p_parents) {
 		if (!p_parents) {
 			break;
 		}
+
 		node = node->get_parent();
 	}
 }
@@ -2483,4 +2500,6 @@ void SceneTreeEditor::NodeCache::clear() {
 	}
 	cache.clear();
 	to_delete.clear();
+	current_pinned_node = nullptr;
+	current_has_pin = false;
 }

+ 1 - 0
editor/gui/scene_tree_editor.h

@@ -90,6 +90,7 @@ class SceneTreeEditor : public Control {
 
 		HashMap<Node *, CachedNode>::Iterator add(Node *p_node, TreeItem *p_item);
 		HashMap<Node *, CachedNode>::Iterator get(Node *p_node, bool p_deleted_ok = true);
+		bool has(Node *p_node);
 		void remove(Node *p_node, bool p_recursive = false);
 		void mark_dirty(Node *p_node, bool p_parents = true);
 		void mark_children_dirty(Node *p_node, bool p_recursive = false);