From 4525181c2dc959609302d8977b5ed6b390f0cfc8 Mon Sep 17 00:00:00 2001 From: Silc Renew Date: Tue, 31 Jan 2023 21:17:29 +0900 Subject: [PATCH] Make restart in NodeStateMachine / NodeTransition optional --- doc/classes/AnimationNodeStateMachine.xml | 5 +++ doc/classes/AnimationNodeTransition.xml | 3 ++ scene/animation/animation_blend_tree.cpp | 32 +++++++++++++------ scene/animation/animation_blend_tree.h | 4 +++ .../animation_node_state_machine.cpp | 15 ++++++++- .../animation/animation_node_state_machine.h | 4 +++ 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/doc/classes/AnimationNodeStateMachine.xml b/doc/classes/AnimationNodeStateMachine.xml index 0fb789875fc..95891a9061a 100644 --- a/doc/classes/AnimationNodeStateMachine.xml +++ b/doc/classes/AnimationNodeStateMachine.xml @@ -161,4 +161,9 @@ + + + If [code]true[/code], allows teleport to the self state with [method AnimationNodeStateMachinePlayback.travel]. When the reset option is enabled in [method AnimationNodeStateMachinePlayback.travel], the animation is restarted. If [code]false[/code], nothing happens on the teleportation to the self state. + + diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml index a067b0a9bad..bc3e5716ddd 100644 --- a/doc/classes/AnimationNodeTransition.xml +++ b/doc/classes/AnimationNodeTransition.xml @@ -44,6 +44,9 @@ + + If [code]true[/code], allows transition to the self state. When the reset option is enabled in input, the animation is restarted. If [code]false[/code], nothing happens on the transition to the self state. + The number of enabled input ports for this node. diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 45f4f690b96..797999625b4 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -800,6 +800,14 @@ Ref AnimationNodeTransition::get_xfade_curve() const { return xfade_curve; } +void AnimationNodeTransition::set_allow_transition_to_self(bool p_enable) { + allow_transition_to_self = p_enable; +} + +bool AnimationNodeTransition::is_allow_transition_to_self() const { + return allow_transition_to_self; +} + double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_external_seeking) { String cur_transition_request = get_parameter(transition_request); int cur_current_index = get_parameter(current_index); @@ -815,20 +823,22 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex int new_idx = find_input(cur_transition_request); if (new_idx >= 0) { if (cur_current_index == new_idx) { - // Transition to same state. - restart = input_data[cur_current_index].reset; - cur_prev_xfading = 0; - set_parameter(prev_xfading, 0); - cur_prev_index = -1; - set_parameter(prev_index, -1); + if (allow_transition_to_self) { + // Transition to same state. + restart = input_data[cur_current_index].reset; + cur_prev_xfading = 0; + set_parameter(prev_xfading, 0); + cur_prev_index = -1; + set_parameter(prev_index, -1); + } } else { switched = true; cur_prev_index = cur_current_index; set_parameter(prev_index, cur_current_index); + cur_current_index = new_idx; + set_parameter(current_index, cur_current_index); + set_parameter(current_state, cur_transition_request); } - cur_current_index = new_idx; - set_parameter(current_index, cur_current_index); - set_parameter(current_state, cur_transition_request); } else { ERR_PRINT("No such input: '" + cur_transition_request + "'"); } @@ -932,8 +942,12 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeTransition::set_xfade_curve); ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeTransition::get_xfade_curve); + ClassDB::bind_method(D_METHOD("set_allow_transition_to_self", "enable"), &AnimationNodeTransition::set_allow_transition_to_self); + ClassDB::bind_method(D_METHOD("is_allow_transition_to_self"), &AnimationNodeTransition::is_allow_transition_to_self); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_transition_to_self"), "set_allow_transition_to_self", "is_allow_transition_to_self"); ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, "Inputs,input_"), "set_input_count", "get_input_count"); } diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 3c27edbf70c..20f8e9b1903 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -294,6 +294,7 @@ class AnimationNodeTransition : public AnimationNodeSync { double xfade_time = 0.0; Ref xfade_curve; + bool allow_transition_to_self = false; protected: bool _get(const StringName &p_path, Variant &r_ret) const; @@ -325,6 +326,9 @@ public: void set_xfade_curve(const Ref &p_curve); Ref get_xfade_curve() const; + void set_allow_transition_to_self(bool p_enable); + bool is_allow_transition_to_self() const; + double process(double p_time, bool p_seek, bool p_is_external_seeking) override; AnimationNodeTransition(); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 7fb831b3b20..ec28a5cca1b 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -252,7 +252,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta path.clear(); //a new one will be needed if (current == p_travel) { - return false; // Will teleport oneself (restart). + return !p_state_machine->is_allow_transition_to_self(); } Vector2 current_pos = p_state_machine->states[current].position; @@ -813,6 +813,14 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Refconnect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } +void AnimationNodeStateMachine::set_allow_transition_to_self(bool p_enable) { + allow_transition_to_self = p_enable; +} + +bool AnimationNodeStateMachine::is_allow_transition_to_self() const { + return allow_transition_to_self; +} + bool AnimationNodeStateMachine::can_edit_node(const StringName &p_name) const { if (states.has(p_name)) { return !(states[p_name].node->is_class("AnimationNodeStartState") || states[p_name].node->is_class("AnimationNodeEndState")); @@ -1383,6 +1391,11 @@ void AnimationNodeStateMachine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeStateMachine::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeStateMachine::get_graph_offset); + + ClassDB::bind_method(D_METHOD("set_allow_transition_to_self", "enable"), &AnimationNodeStateMachine::set_allow_transition_to_self); + ClassDB::bind_method(D_METHOD("is_allow_transition_to_self"), &AnimationNodeStateMachine::is_allow_transition_to_self); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_transition_to_self"), "set_allow_transition_to_self", "is_allow_transition_to_self"); } AnimationNodeStateMachine::AnimationNodeStateMachine() { diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index cf4d850aa66..5c2a4d6264c 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -188,6 +188,7 @@ private: }; HashMap states; + bool allow_transition_to_self = false; struct Transition { StringName from; @@ -254,6 +255,9 @@ public: void remove_transition_by_index(const int p_transition); void remove_transition(const StringName &p_from, const StringName &p_to); + void set_allow_transition_to_self(bool p_enable); + bool is_allow_transition_to_self() const; + bool can_edit_node(const StringName &p_name) const; AnimationNodeStateMachine *get_prev_state_machine() const;