Selaa lähdekoodia

Merge pull request #65196 from TokageItLab/fix-redraw-anim-tree

Fix redraw timing in `AnimationBlendTreeEditor`
Rémi Verschelde 3 vuotta sitten
vanhempi
commit
80802d2718

+ 8 - 0
doc/classes/AnimationNodeBlendTree.xml

@@ -87,6 +87,14 @@
 			The global offset of all sub-nodes.
 		</member>
 	</members>
+	<signals>
+		<signal name="node_changed">
+			<param index="0" name="node_name" type="StringName" />
+			<description>
+				Emitted when the input port information is changed.
+			</description>
+		</signal>
+	</signals>
 	<constants>
 		<constant name="CONNECTION_OK" value="0">
 			The connection was successful.

+ 5 - 0
doc/classes/AnimationPlayer.xml

@@ -268,6 +268,11 @@
 				[b]Note:[/b] This signal is not emitted if an animation is looping.
 			</description>
 		</signal>
+		<signal name="animation_list_changed">
+			<description>
+				Notifies when an animation list is changed.
+			</description>
+		</signal>
 		<signal name="animation_started">
 			<param index="0" name="anim_name" type="StringName" />
 			<description>

+ 7 - 0
doc/classes/AnimationTree.xml

@@ -54,6 +54,13 @@
 			The root animation node of this [AnimationTree]. See [AnimationNode].
 		</member>
 	</members>
+	<signals>
+		<signal name="animation_player_changed">
+			<description>
+				Emitted when the [member anim_player] is changed.
+			</description>
+		</signal>
+	</signals>
 	<constants>
 		<constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessCallback">
 			The animations will progress during the physics frame (i.e. [method Node._physics_process]).

+ 34 - 21
editor/plugins/animation_blend_tree_editor_plugin.cpp

@@ -101,13 +101,13 @@ void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_propert
 	undo_redo->create_action(TTR("Parameter Changed:") + " " + String(p_property), UndoRedo::MERGE_ENDS);
 	undo_redo->add_do_property(tree, p_property, p_value);
 	undo_redo->add_undo_property(tree, p_property, tree->get(p_property));
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 	updating = false;
 }
 
-void AnimationNodeBlendTreeEditor::_update_graph() {
+void AnimationNodeBlendTreeEditor::update_graph() {
 	if (updating || blend_tree.is_null()) {
 		return;
 	}
@@ -364,8 +364,8 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
 		to_slot = -1;
 	}
 
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 }
 
@@ -416,8 +416,8 @@ void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Ve
 	undo_redo->create_action(TTR("Node Moved"));
 	undo_redo->add_do_method(blend_tree.ptr(), "set_node_position", p_which, p_to / EDSCALE);
 	undo_redo->add_undo_method(blend_tree.ptr(), "set_node_position", p_which, p_from / EDSCALE);
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 	updating = false;
 }
@@ -437,8 +437,8 @@ void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int
 	undo_redo->create_action(TTR("Nodes Connected"));
 	undo_redo->add_do_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
 	undo_redo->add_undo_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index);
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 }
 
@@ -453,8 +453,8 @@ void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from,
 	undo_redo->create_action(TTR("Nodes Disconnected"));
 	undo_redo->add_do_method(blend_tree.ptr(), "disconnect_node", p_to, p_to_index);
 	undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", p_to, p_to_index, p_from);
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 	updating = false;
 }
@@ -468,8 +468,8 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options,
 	undo_redo->create_action(TTR("Set Animation"));
 	undo_redo->add_do_method(anim.ptr(), "set_animation", option);
 	undo_redo->add_undo_method(anim.ptr(), "set_animation", anim->get_animation());
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 }
 
@@ -491,8 +491,8 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
 		}
 	}
 
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 }
 
@@ -819,7 +819,7 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
 			_update_theme();
 
 			if (is_visible_in_tree()) {
-				_update_graph();
+				update_graph();
 			}
 		} break;
 
@@ -900,12 +900,23 @@ void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) {
 }
 
 void AnimationNodeBlendTreeEditor::_bind_methods() {
-	ClassDB::bind_method("_update_graph", &AnimationNodeBlendTreeEditor::_update_graph);
+	ClassDB::bind_method("update_graph", &AnimationNodeBlendTreeEditor::update_graph);
 	ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters);
 }
 
 AnimationNodeBlendTreeEditor *AnimationNodeBlendTreeEditor::singleton = nullptr;
 
+// AnimationNode's "node_changed" signal means almost update_input.
+void AnimationNodeBlendTreeEditor::_node_changed(const StringName &p_node_name) {
+	// TODO:
+	// Here is executed during the commit of EditorNode::undo_redo, it is not possible to create an undo_redo action here.
+	// The disconnect when the number of enabled inputs decreases is done in AnimationNodeBlendTree and update_graph().
+	// This means that there is no place to register undo_redo actions.
+	// In order to implement undo_redo correctly, we may need to implement AnimationNodeEdit such as AnimationTrackKeyEdit
+	// and add it to _node_selected() with EditorNode::get_singleton()->push_item(AnimationNodeEdit).
+	update_graph();
+}
+
 void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<AnimationNode> p_node) {
 	if (blend_tree.is_null()) {
 		return;
@@ -940,8 +951,8 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
 	undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name);
 	undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + prev_name, base_path + name);
 	undo_redo->add_undo_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + name, base_path + prev_name);
-	undo_redo->add_do_method(this, "_update_graph");
-	undo_redo->add_undo_method(this, "_update_graph");
+	undo_redo->add_do_method(this, "update_graph");
+	undo_redo->add_undo_method(this, "update_graph");
 	undo_redo->commit_action();
 	updating = false;
 	gn->set_name(new_name);
@@ -979,7 +990,7 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
 		}
 	}
 
-	_update_graph(); // Needed to update the signal connections with the new name.
+	update_graph(); // Needed to update the signal connections with the new name.
 }
 
 void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) {
@@ -996,6 +1007,7 @@ bool AnimationNodeBlendTreeEditor::can_edit(const Ref<AnimationNode> &p_node) {
 
 void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) {
 	if (blend_tree.is_valid()) {
+		blend_tree->disconnect("node_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_changed));
 		blend_tree->disconnect("removed_from_graph", callable_mp(this, &AnimationNodeBlendTreeEditor::_removed_from_graph));
 	}
 
@@ -1008,9 +1020,10 @@ void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) {
 	} else {
 		read_only = EditorNode::get_singleton()->is_resource_read_only(blend_tree);
 
+		blend_tree->connect("node_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_changed));
 		blend_tree->connect("removed_from_graph", callable_mp(this, &AnimationNodeBlendTreeEditor::_removed_from_graph));
 
-		_update_graph();
+		update_graph();
 	}
 
 	add_node->set_disabled(read_only);

+ 3 - 2
editor/plugins/animation_blend_tree_editor_plugin.h

@@ -71,8 +71,6 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
 	int to_slot = -1;
 	String from_node = "";
 
-	void _update_graph();
-
 	struct AddOption {
 		String name;
 		String type;
@@ -95,6 +93,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
 	void _node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which);
 	void _node_renamed(const String &p_text, Ref<AnimationNode> p_node);
 	void _node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node);
+	void _node_changed(const StringName &p_node_name);
 
 	bool updating;
 
@@ -150,6 +149,8 @@ public:
 	virtual bool can_edit(const Ref<AnimationNode> &p_node) override;
 	virtual void edit(const Ref<AnimationNode> &p_node) override;
 
+	void update_graph();
+
 	AnimationNodeBlendTreeEditor();
 };
 

+ 15 - 0
editor/plugins/animation_tree_editor_plugin.cpp

@@ -50,10 +50,18 @@
 #include "scene/scene_string_names.h"
 
 void AnimationTreeEditor::edit(AnimationTree *p_tree) {
+	if (p_tree && !p_tree->is_connected("animation_player_changed", callable_mp(this, &AnimationTreeEditor::_animation_list_changed))) {
+		p_tree->connect("animation_player_changed", callable_mp(this, &AnimationTreeEditor::_animation_list_changed), CONNECT_DEFERRED);
+	}
+
 	if (tree == p_tree) {
 		return;
 	}
 
+	if (tree && tree->is_connected("animation_player_changed", callable_mp(this, &AnimationTreeEditor::_animation_list_changed))) {
+		tree->disconnect("animation_player_changed", callable_mp(this, &AnimationTreeEditor::_animation_list_changed));
+	}
+
 	tree = p_tree;
 
 	Vector<String> path;
@@ -73,6 +81,13 @@ void AnimationTreeEditor::_path_button_pressed(int p_path) {
 	}
 }
 
+void AnimationTreeEditor::_animation_list_changed() {
+	AnimationNodeBlendTreeEditor *bte = AnimationNodeBlendTreeEditor::get_singleton();
+	if (bte) {
+		bte->update_graph();
+	}
+}
+
 void AnimationTreeEditor::_update_path() {
 	while (path_hb->get_child_count() > 1) {
 		memdelete(path_hb->get_child(1));

+ 1 - 0
editor/plugins/animation_tree_editor_plugin.h

@@ -65,6 +65,7 @@ class AnimationTreeEditor : public VBoxContainer {
 	ObjectID current_root;
 
 	void _path_button_pressed(int p_path);
+	void _animation_list_changed();
 
 	static Vector<String> get_animation_list();
 

+ 3 - 0
scene/animation/animation_blend_tree.cpp

@@ -1175,6 +1175,7 @@ void AnimationNodeBlendTree::_tree_changed() {
 void AnimationNodeBlendTree::_node_changed(const StringName &p_node) {
 	ERR_FAIL_COND(!nodes.has(p_node));
 	nodes[p_node].connections.resize(nodes[p_node].node->get_input_count());
+	emit_signal(SNAME("node_changed"), p_node);
 }
 
 void AnimationNodeBlendTree::_bind_methods() {
@@ -1200,6 +1201,8 @@ void AnimationNodeBlendTree::_bind_methods() {
 	BIND_CONSTANT(CONNECTION_ERROR_NO_OUTPUT);
 	BIND_CONSTANT(CONNECTION_ERROR_SAME_NODE);
 	BIND_CONSTANT(CONNECTION_ERROR_CONNECTION_EXISTS);
+
+	ADD_SIGNAL(MethodInfo("node_changed", PropertyInfo(Variant::STRING_NAME, "node_name")));
 }
 
 void AnimationNodeBlendTree::_initialize_node_tree() {

+ 3 - 0
scene/animation/animation_player.cpp

@@ -1270,6 +1270,8 @@ void AnimationPlayer::_animation_set_cache_update() {
 		// If something was modified or removed, caches need to be cleared
 		clear_caches();
 	}
+
+	emit_signal(SNAME("animation_list_changed"));
 }
 
 void AnimationPlayer::_animation_added(const StringName &p_name, const StringName &p_library) {
@@ -2150,6 +2152,7 @@ void AnimationPlayer::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name")));
 	ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name")));
 	ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name")));
+	ADD_SIGNAL(MethodInfo("animation_list_changed"));
 	ADD_SIGNAL(MethodInfo("caches_cleared"));
 
 	BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);

+ 43 - 0
scene/animation/animation_tree.cpp

@@ -847,6 +847,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
 	return true;
 }
 
+void AnimationTree::_animation_player_changed() {
+	emit_signal(SNAME("animation_player_changed"));
+	_clear_caches();
+}
+
 void AnimationTree::_clear_caches() {
 	for (KeyValue<NodePath, TrackCache *> &K : track_cache) {
 		memdelete(K.value);
@@ -1738,6 +1743,7 @@ void AnimationTree::advance(real_t p_time) {
 void AnimationTree::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
+			_setup_animation_player();
 			if (last_animation_player.is_valid()) {
 				Object *player = ObjectDB::get_instance(last_animation_player);
 				if (player) {
@@ -1770,8 +1776,43 @@ void AnimationTree::_notification(int p_what) {
 	}
 }
 
+void AnimationTree::_setup_animation_player() {
+	if (!is_inside_tree()) {
+		return;
+	}
+
+	AnimationPlayer *new_player = nullptr;
+	if (!animation_player.is_empty()) {
+		new_player = Object::cast_to<AnimationPlayer>(get_node(animation_player));
+		if (new_player && !new_player->is_connected("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed))) {
+			new_player->connect("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed));
+		}
+	}
+
+	if (new_player) {
+		if (!last_animation_player.is_valid()) {
+			// Animation player set newly.
+			emit_signal(SNAME("animation_player_changed"));
+			return;
+		} else if (last_animation_player == new_player->get_instance_id()) {
+			// Animation player isn't changed.
+			return;
+		}
+	} else if (!last_animation_player.is_valid()) {
+		// Animation player is being empty.
+		return;
+	}
+
+	AnimationPlayer *old_player = Object::cast_to<AnimationPlayer>(ObjectDB::get_instance(last_animation_player));
+	if (old_player && old_player->is_connected("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed))) {
+		old_player->disconnect("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed));
+	}
+	emit_signal(SNAME("animation_player_changed"));
+}
+
 void AnimationTree::set_animation_player(const NodePath &p_player) {
 	animation_player = p_player;
+	_setup_animation_player();
 	update_configuration_warnings();
 }
 
@@ -2008,6 +2049,8 @@ void AnimationTree::_bind_methods() {
 	BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);
 	BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE);
 	BIND_ENUM_CONSTANT(ANIMATION_PROCESS_MANUAL);
+
+	ADD_SIGNAL(MethodInfo("animation_player_changed"));
 }
 
 AnimationTree::AnimationTree() {

+ 2 - 0
scene/animation/animation_tree.h

@@ -282,6 +282,8 @@ private:
 	bool cache_valid = false;
 	void _node_removed(Node *p_node);
 
+	void _setup_animation_player();
+	void _animation_player_changed();
 	void _clear_caches();
 	bool _update_caches(AnimationPlayer *player);
 	void _process_graph(double p_delta);