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 advance_on_start option to NodeAnimation to handle advance(0) for each NodeAnimation #94372

Merged
merged 1 commit into from
Nov 13, 2024
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
4 changes: 4 additions & 0 deletions doc/classes/AnimationNodeAnimation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
<link title="Third Person Shooter (TPS) Demo">https://godotengine.org/asset-library/asset/2710</link>
</tutorials>
<members>
<member name="advance_on_start" type="bool" setter="set_advance_on_start" getter="is_advance_on_start" default="false">
If [code]true[/code], on receiving a request to play an animation from the start, the first frame is not drawn, but only processed, and playback starts from the next frame.
See also the notes of [method AnimationPlayer.play].
</member>
<member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&amp;&quot;&quot;">
Animation to use as an output. It is one of the animations provided by [member AnimationTree.anim_player].
</member>
Expand Down
24 changes: 22 additions & 2 deletions scene/animation/animation_blend_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::process(const AnimationMixer

AnimationMixer::PlaybackInfo pi = p_playback_info;
if (p_playback_info.seeked) {
pi.delta = get_node_time_info().position - p_playback_info.time;
if (p_playback_info.is_external_seeking) {
pi.delta = get_node_time_info().position - p_playback_info.time;
}
} else {
pi.time = get_node_time_info().position + (backward ? -p_playback_info.delta : p_playback_info.delta);
}
Expand Down Expand Up @@ -140,6 +142,12 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe

// 1. Progress for AnimationNode.
bool will_end = Animation::is_greater_or_equal_approx(cur_time + cur_delta, cur_len);
bool is_started = p_seek && !p_is_external_seeking && Math::is_zero_approx(cur_time);

// 1. Progress for AnimationNode.
if (is_started && advance_on_start) {
cur_time = cur_delta;
}
if (cur_loop_mode != Animation::LOOP_NONE) {
if (cur_loop_mode == Animation::LOOP_LINEAR) {
if (!Math::is_zero_approx(cur_len)) {
Expand Down Expand Up @@ -232,7 +240,7 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
// We should use call_deferred since the track keys are still being processed.
if (process_state->tree && !p_test_only) {
// 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 && Math::is_zero_approx(cur_playback_time)) {
if (is_started) {
process_state->tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_started), animation);
}
// Finished.
Expand Down Expand Up @@ -282,6 +290,14 @@ bool AnimationNodeAnimation::is_backward() const {
return backward;
}

void AnimationNodeAnimation::set_advance_on_start(bool p_advance_on_start) {
advance_on_start = p_advance_on_start;
}

bool AnimationNodeAnimation::is_advance_on_start() const {
return advance_on_start;
}

void AnimationNodeAnimation::set_use_custom_timeline(bool p_use_custom_timeline) {
use_custom_timeline = p_use_custom_timeline;
notify_property_list_changed();
Expand Down Expand Up @@ -331,6 +347,9 @@ void AnimationNodeAnimation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_play_mode", "mode"), &AnimationNodeAnimation::set_play_mode);
ClassDB::bind_method(D_METHOD("get_play_mode"), &AnimationNodeAnimation::get_play_mode);

ClassDB::bind_method(D_METHOD("set_advance_on_start", "advance_on_start"), &AnimationNodeAnimation::set_advance_on_start);
ClassDB::bind_method(D_METHOD("is_advance_on_start"), &AnimationNodeAnimation::is_advance_on_start);

ClassDB::bind_method(D_METHOD("set_use_custom_timeline", "use_custom_timeline"), &AnimationNodeAnimation::set_use_custom_timeline);
ClassDB::bind_method(D_METHOD("is_using_custom_timeline"), &AnimationNodeAnimation::is_using_custom_timeline);

Expand All @@ -348,6 +367,7 @@ void AnimationNodeAnimation::_bind_methods() {

ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::INT, "play_mode", PROPERTY_HINT_ENUM, "Forward,Backward"), "set_play_mode", "get_play_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "advance_on_start"), "set_advance_on_start", "is_advance_on_start");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_custom_timeline"), "set_use_custom_timeline", "is_using_custom_timeline");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "timeline_length", PROPERTY_HINT_RANGE, "0.001,60,0.001,or_greater,or_less,hide_slider,suffix:s"), "set_timeline_length", "get_timeline_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stretch_time_scale"), "set_stretch_time_scale", "is_stretching_time_scale");
Expand Down
5 changes: 5 additions & 0 deletions scene/animation/animation_blend_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class AnimationNodeAnimation : public AnimationRootNode {

StringName animation;

bool advance_on_start = false;

bool use_custom_timeline = false;
double timeline_length = 1.0;
Animation::LoopMode loop_mode = Animation::LOOP_NONE;
Expand Down Expand Up @@ -72,6 +74,9 @@ class AnimationNodeAnimation : public AnimationRootNode {
void set_backward(bool p_backward);
bool is_backward() const;

void set_advance_on_start(bool p_advance_on_start);
bool is_advance_on_start() const;

void set_use_custom_timeline(bool p_use_custom_timeline);
bool is_using_custom_timeline() const;

Expand Down
4 changes: 3 additions & 1 deletion scene/animation/animation_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,9 @@ AnimationNode::NodeTimeInfo AnimationNode::process(const AnimationMixer::Playbac

AnimationMixer::PlaybackInfo pi = p_playback_info;
if (p_playback_info.seeked) {
pi.delta = get_node_time_info().position - p_playback_info.time;
if (p_playback_info.is_external_seeking) {
pi.delta = get_node_time_info().position - p_playback_info.time;
}
} else {
pi.time = get_node_time_info().position + p_playback_info.delta;
}
Expand Down
2 changes: 1 addition & 1 deletion scene/animation/animation_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class AnimationNode : public Resource {
if (Math::is_zero_approx(remain)) {
return 0;
}
return length - position;
return remain;
}
};

Expand Down