Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add animation_started/finished signals to AnimationTree and fix time accuracy in StateMachine #70278

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions doc/classes/AnimationTree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
13 changes: 13 additions & 0 deletions scene/animation/animation_blend_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 6 additions & 5 deletions scene/animation/animation_node_state_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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();
}
}
Expand All @@ -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.
}
Expand All @@ -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()) {
Expand Down
4 changes: 2 additions & 2 deletions scene/animation/animation_node_state_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion scene/animation/animation_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down