소스 검색

Fix `AnimationPlayer` crash when it's made the scene root

When an AnimationPlayer is made root of a scene,
the track links may become broken and clicking on
them will crash.

Current master branch also breaks node links when
AnimationPlayer is made scene root, and can also
crash the engine if another node was made scene
root prior to the AnimationPlayer.

This happens because when made root, the editor
loses track of AnimPlayer's root node. By keeping
a copy of the AnimPlayer's root_node, the track
links remain functional.

Fixes #91043.

(cherry picked from commit e905be82491dc75cd6056d76875d2754c58ae59e)
Arsh Panesar 1 년 전
부모
커밋
26cc13705a
2개의 변경된 파일17개의 추가작업 그리고 1개의 파일을 삭제
  1. 15 1
      editor/plugins/animation_player_editor_plugin.cpp
  2. 2 0
      editor/plugins/animation_player_editor_plugin.h

+ 15 - 1
editor/plugins/animation_player_editor_plugin.cpp

@@ -339,7 +339,17 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
 
 			track_editor->set_animation(anim, animation_is_readonly);
 			Node *root = player->get_node_or_null(player->get_root_node());
-			if (root) {
+
+			// Player shouldn't access parent if it's the scene root.
+			if (!root || (player == get_tree()->get_edited_scene_root() && player->get_root_node() == SceneStringName(path_pp))) {
+				NodePath cached_root_path = player->get_path_to(get_cached_root_node());
+				if (player->get_node_or_null(cached_root_path) != nullptr) {
+					player->set_root_node(cached_root_path);
+				} else {
+					player->set_root_node(SceneStringName(path_pp)); // No other choice, preventing crash.
+				}
+			} else {
+				cached_root_node_id = root->get_instance_id(); // Caching as `track_editor` can lose track of player's root node.
 				track_editor->set_root(root);
 			}
 		}
@@ -1824,6 +1834,10 @@ AnimationMixer *AnimationPlayerEditor::fetch_mixer_for_library() const {
 	return original_node;
 }
 
+Node *AnimationPlayerEditor::get_cached_root_node() const {
+	return Object::cast_to<Node>(ObjectDB::get_instance(cached_root_node_id));
+}
+
 bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
 	bool is_valid = true;
 	if (!p_anim.is_valid()) {

+ 2 - 0
editor/plugins/animation_player_editor_plugin.h

@@ -52,6 +52,7 @@ class AnimationPlayerEditor : public VBoxContainer {
 	AnimationPlayerEditorPlugin *plugin = nullptr;
 	AnimationMixer *original_node = nullptr; // For pinned mark in SceneTree.
 	AnimationPlayer *player = nullptr; // For AnimationPlayerEditor, could be dummy.
+	ObjectID cached_root_node_id;
 	bool is_dummy = false;
 
 	enum {
@@ -251,6 +252,7 @@ public:
 	AnimationMixer *get_editing_node() const;
 	AnimationPlayer *get_player() const;
 	AnimationMixer *fetch_mixer_for_library() const;
+	Node *get_cached_root_node() const;
 
 	static AnimationPlayerEditor *get_singleton() { return singleton; }