diff options
-rw-r--r-- | doc/classes/AnimationTree.xml | 14 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 13 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.cpp | 11 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.h | 4 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 5 |
5 files changed, 39 insertions, 8 deletions
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml index 21f4b37741..a17a727d7e 100644 --- a/doc/classes/AnimationTree.xml +++ b/doc/classes/AnimationTree.xml @@ -111,11 +111,25 @@ </member> </members> <signals> + <signal name="animation_finished"> + <param index="0" name="anim_name" type="StringName" /> + <description> + Notifies when an animation finished playing. + [b]Note:[/b] This signal is not emitted if an animation is looping or aborted. Also be aware of the possibility of unseen playback by sync and xfade. + </description> + </signal> <signal name="animation_player_changed"> <description> Emitted when the [member anim_player] is changed. </description> </signal> + <signal name="animation_started"> + <param index="0" name="anim_name" type="StringName" /> + <description> + Notifies when an animation starts playing. + [b]Note:[/b] This signal is not emitted if an animation is looping or playbacked from the middle. Also be aware of the possibility of unseen playback by sync and xfade. + </description> + </signal> </signals> <constants> <constant name="ANIMATION_PROCESS_PHYSICS" value="0" enum="AnimationProcessCallback"> diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index d10b271b79..26261d6da5 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -144,6 +144,19 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_is_ext } } } + + // Emit start & finish signal. Internally, the detections are the same for backward. + // We should use call_deferred since the track keys are still being prosessed. + if (state->tree) { + // AnimationTree uses seek to 0 "internally" to process the first key of the animation, which is used as the start detection. + if (p_seek && !p_is_external_seeking && cur_time == 0) { + state->tree->call_deferred(SNAME("emit_signal"), "animation_started", animation); + } + // Finished. + if (prev_time < anim_size && cur_time >= anim_size) { + state->tree->call_deferred(SNAME("emit_signal"), "animation_finished", animation); + } + } } if (play_mode == PLAY_MODE_FORWARD) { diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 293e04eb1f..4be5ed11dd 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -379,6 +379,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s // can't travel, then teleport path.clear(); current = start_request; + play_start = true; } start_request = StringName(); //clear start request } @@ -424,7 +425,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s fading_pos += p_time; } fade_blend = MIN(1.0, fading_pos / fading_time); - if (fade_blend >= 1.0) { + if (fade_blend > 1.0) { fading_from = StringName(); } } @@ -433,9 +434,9 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s if (current_curve.is_valid()) { fade_blend = current_curve->sample(fade_blend); } - float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend) ? CMP_EPSILON : fade_blend, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge. + double rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend) ? CMP_EPSILON : fade_blend, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge. - float fade_blend_inv = 1.0 - fade_blend; + double fade_blend_inv = 1.0 - fade_blend; if (fading_from != StringName()) { p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend_inv) ? CMP_EPSILON : fade_blend_inv, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge. } @@ -446,14 +447,14 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } { //advance and loop check - float next_pos = len_current - rem; + double next_pos = len_current - rem; end_loop = next_pos < pos_current; pos_current = next_pos; //looped } //find next StringName next; - float next_xfade = 0.0; + double next_xfade = 0.0; AnimationNodeStateMachineTransition::SwitchMode switch_mode = AnimationNodeStateMachineTransition::SWITCH_MODE_IMMEDIATE; if (path.size()) { diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index 0dfe5a3a43..e52ff23d7e 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -111,8 +111,8 @@ class AnimationNodeStateMachinePlayback : public Resource { StringName next; }; - float len_current = 0.0; - float pos_current = 0.0; + double len_current = 0.0; + double pos_current = 0.0; bool end_loop = false; StringName current; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index b06a21dea9..c9bfbf664a 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -432,7 +432,6 @@ void AnimationNode::_bind_methods() { GDVIRTUAL_BIND(_has_filter); ADD_SIGNAL(MethodInfo("removed_from_graph")); - ADD_SIGNAL(MethodInfo("tree_changed")); BIND_ENUM_CONSTANT(FILTER_IGNORE); @@ -2037,6 +2036,10 @@ void AnimationTree::_bind_methods() { BIND_ENUM_CONSTANT(ANIMATION_PROCESS_MANUAL); ADD_SIGNAL(MethodInfo("animation_player_changed")); + + // Signals from AnimationNodes. + ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name"))); + ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name"))); } AnimationTree::AnimationTree() { |