Fix redraw timing in AnimationBlendTreeEditor

This commit is contained in:
Silc Renew 2022-09-01 23:00:55 +09:00
parent 0c221f0284
commit cff95e54e0
11 changed files with 124 additions and 23 deletions

View file

@ -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.

View file

@ -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>

View file

@ -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]).

View file

@ -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) {
String prev_name = blend_tree->get_node_name(p_node);
ERR_FAIL_COND(prev_name.is_empty());
@ -936,8 +947,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);
@ -975,7 +986,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) {
@ -992,6 +1003,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));
}
@ -1004,9 +1016,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);

View file

@ -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();
};

View file

@ -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));

View file

@ -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();

View file

@ -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() {

View file

@ -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);

View file

@ -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() {

View file

@ -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);