diff options
author | Silc Renew <tokage.it.lab@gmail.com> | 2022-05-05 03:53:48 +0900 |
---|---|---|
committer | Silc 'Tokage' Renew <tokage.it.lab@gmail.com> | 2022-05-09 08:28:32 +0900 |
commit | ba8398f27081f2b33accf08e26044c0a9d8a66cb (patch) | |
tree | 0d0f77c9b66aec8b8bdb67cdcc0cbf9e12c8432f | |
parent | 943b50995292d98d9bc2e45ff04eaf0a716cea28 (diff) |
Fixed delta & Implement selection of whether or not to seek root
-rw-r--r-- | doc/classes/AnimationNode.xml | 20 | ||||
-rw-r--r-- | doc/classes/AnimationNodeOneShot.xml | 4 | ||||
-rw-r--r-- | editor/animation_track_editor.cpp | 18 | ||||
-rw-r--r-- | editor/animation_track_editor.h | 8 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/animation_player_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_1d.cpp | 6 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_1d.h | 2 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_2d.cpp | 12 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_2d.h | 2 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 88 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.h | 26 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.cpp | 18 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.h | 4 | ||||
-rw-r--r-- | scene/animation/animation_player.cpp | 14 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 62 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 15 |
17 files changed, 155 insertions, 148 deletions
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml index 99d21706ee..9026aa6a34 100644 --- a/doc/classes/AnimationNode.xml +++ b/doc/classes/AnimationNode.xml @@ -53,6 +53,7 @@ <return type="float" /> <argument index="0" name="time" type="float" /> <argument index="1" name="seek" type="bool" /> + <argument index="2" name="seek_root" type="bool" /> <description> User-defined callback called when a custom node is processed. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute. Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions. You can also use [method get_parameter] and [method set_parameter] to modify local memory. @@ -72,8 +73,9 @@ <argument index="1" name="time" type="float" /> <argument index="2" name="delta" type="float" /> <argument index="3" name="seeked" type="bool" /> - <argument index="4" name="blend" type="float" /> - <argument index="5" name="pingponged" type="int" default="0" /> + <argument index="4" name="seek_root" type="bool" /> + <argument index="5" name="blend" type="float" /> + <argument index="6" name="pingponged" type="int" default="0" /> <description> Blend an animation by [code]blend[/code] amount (name must be valid in the linked [AnimationPlayer]). A [code]time[/code] and [code]delta[/code] may be passed, as well as whether [code]seek[/code] happened. </description> @@ -83,9 +85,10 @@ <argument index="0" name="input_index" type="int" /> <argument index="1" name="time" type="float" /> <argument index="2" name="seek" type="bool" /> - <argument index="3" name="blend" type="float" /> - <argument index="4" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> - <argument index="5" name="optimize" type="bool" default="true" /> + <argument index="3" name="seek_root" type="bool" /> + <argument index="4" name="blend" type="float" /> + <argument index="5" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> + <argument index="6" name="optimize" type="bool" default="true" /> <description> Blend an input. This is only useful for nodes created for an [AnimationNodeBlendTree]. The [code]time[/code] parameter is a relative delta, unless [code]seek[/code] is [code]true[/code], in which case it is absolute. A filter mode may be optionally passed (see [enum FilterAction] for options). </description> @@ -96,9 +99,10 @@ <argument index="1" name="node" type="AnimationNode" /> <argument index="2" name="time" type="float" /> <argument index="3" name="seek" type="bool" /> - <argument index="4" name="blend" type="float" /> - <argument index="5" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> - <argument index="6" name="optimize" type="bool" default="true" /> + <argument index="4" name="seek_root" type="bool" /> + <argument index="5" name="blend" type="float" /> + <argument index="6" name="filter" type="int" enum="AnimationNode.FilterAction" default="0" /> + <argument index="7" name="optimize" type="bool" default="true" /> <description> Blend another animation node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition. </description> diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml index 727a09e110..de2414cd43 100644 --- a/doc/classes/AnimationNodeOneShot.xml +++ b/doc/classes/AnimationNodeOneShot.xml @@ -20,9 +20,9 @@ <member name="autorestart_random_delay" type="float" setter="set_autorestart_random_delay" getter="get_autorestart_random_delay" default="0.0"> If [member autorestart] is [code]true[/code], a random additional delay (in seconds) between 0 and this value will be added to [member autorestart_delay]. </member> - <member name="fadein_time" type="float" setter="set_fadein_time" getter="get_fadein_time" default="0.1"> + <member name="fadein_time" type="float" setter="set_fadein_time" getter="get_fadein_time" default="0.0"> </member> - <member name="fadeout_time" type="float" setter="set_fadeout_time" getter="get_fadeout_time" default="0.1"> + <member name="fadeout_time" type="float" setter="set_fadeout_time" getter="get_fadeout_time" default="0.0"> </member> <member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0"> </member> diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index c425613262..a1f4cb2282 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1417,14 +1417,14 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) { void AnimationTimelineEdit::_anim_loop_pressed() { undo_redo->create_action(TTR("Change Animation Loop")); switch (animation->get_loop_mode()) { - case Animation::LoopMode::LOOP_NONE: { - undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_LINEAR); + case Animation::LOOP_NONE: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LOOP_LINEAR); } break; - case Animation::LoopMode::LOOP_LINEAR: { - undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_PINGPONG); + case Animation::LOOP_LINEAR: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LOOP_PINGPONG); } break; - case Animation::LoopMode::LOOP_PINGPONG: { - undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_NONE); + case Animation::LOOP_PINGPONG: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LOOP_NONE); } break; default: break; @@ -1724,15 +1724,15 @@ void AnimationTimelineEdit::update_values() { } switch (animation->get_loop_mode()) { - case Animation::LoopMode::LOOP_NONE: { + case Animation::LOOP_NONE: { loop->set_icon(get_theme_icon(SNAME("Loop"), SNAME("EditorIcons"))); loop->set_pressed(false); } break; - case Animation::LoopMode::LOOP_LINEAR: { + case Animation::LOOP_LINEAR: { loop->set_icon(get_theme_icon(SNAME("Loop"), SNAME("EditorIcons"))); loop->set_pressed(true); } break; - case Animation::LoopMode::LOOP_PINGPONG: { + case Animation::LOOP_PINGPONG: { loop->set_icon(get_theme_icon(SNAME("PingPongLoop"), SNAME("EditorIcons"))); loop->set_pressed(true); } break; diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index bd66a4b2df..1b8f5e678f 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -478,10 +478,10 @@ class AnimationTrackEditor : public VBoxContainer { struct TrackClipboard { NodePath full_path; NodePath base_path; - Animation::TrackType track_type = Animation::TrackType::TYPE_ANIMATION; - Animation::InterpolationType interp_type = Animation::InterpolationType::INTERPOLATION_CUBIC; - Animation::UpdateMode update_mode = Animation::UpdateMode::UPDATE_CAPTURE; - Animation::LoopMode loop_mode = Animation::LoopMode::LOOP_LINEAR; + Animation::TrackType track_type = Animation::TYPE_ANIMATION; + Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC; + Animation::UpdateMode update_mode = Animation::UPDATE_CAPTURE; + Animation::LoopMode loop_mode = Animation::LOOP_LINEAR; bool loop_wrap = false; bool enabled = false; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 06a84ff23c..7e9d581ae8 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -466,7 +466,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I static const char *loop_strings[loop_string_count] = { "loop_mode", "loop", "cycle" }; for (int i = 0; i < loop_string_count; i++) { if (_teststr(animname, loop_strings[i])) { - anim->set_loop_mode(Animation::LoopMode::LOOP_LINEAR); + anim->set_loop_mode(Animation::LOOP_LINEAR); animname = _fixstr(animname, loop_strings[i]); Ref<AnimationLibrary> library = ap->get_animation_library(ap->find_animation_library(anim)); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 581dab84b4..57cf13d298 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1338,7 +1338,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { float pos = cpos + step_off * anim->get_step(); - bool valid = anim->get_loop_mode() != Animation::LoopMode::LOOP_NONE || (pos >= 0 && pos <= anim->get_length()); + bool valid = anim->get_loop_mode() != Animation::LOOP_NONE || (pos >= 0 && pos <= anim->get_length()); onion.captures_valid.write[cidx] = valid; if (valid) { player->seek(pos, true); diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index 849316c568..594f98410e 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -219,14 +219,14 @@ void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<Animatio } } -double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek) { +double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_seek_root) { if (blend_points_used == 0) { return 0.0; } if (blend_points_used == 1) { // only one point available, just play that animation - return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, 1.0, FILTER_IGNORE, false); + return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); } double blend_pos = get_parameter(blend_position); @@ -295,7 +295,7 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek) { double max_time_remaining = 0.0; for (int i = 0; i < blend_points_used; i++) { - double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, weights[i], FILTER_IGNORE, false); + double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, false); max_time_remaining = MAX(max_time_remaining, remaining); } diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h index 7038cece06..b2075c8c93 100644 --- a/scene/animation/animation_blend_space_1d.h +++ b/scene/animation/animation_blend_space_1d.h @@ -93,7 +93,7 @@ public: void set_value_label(const String &p_label); String get_value_label() const; - double process(double p_time, bool p_seek) override; + double process(double p_time, bool p_seek, bool p_seek_root) override; String get_caption() const override; Ref<AnimationNode> get_child_by_name(const StringName &p_name) override; diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index a3aa3f6cc8..acdce2d7de 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -432,7 +432,7 @@ void AnimationNodeBlendSpace2D::_blend_triangle(const Vector2 &p_pos, const Vect r_weights[2] = w; } -double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) { +double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_seek_root) { _update_triangles(); Vector2 blend_pos = get_parameter(blend_position); @@ -502,7 +502,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) { for (int j = 0; j < 3; j++) { if (i == triangle_points[j]) { //blend with the given weight - double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false); + double t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, blend_weights[j], FILTER_IGNORE, false); if (first || t < mind) { mind = t; first = false; @@ -514,7 +514,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) { if (!found) { //ignore - blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false); + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, false); } } } else { @@ -539,16 +539,16 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) { na_n->set_backward(na_c->is_backward()); } //see how much animation remains - from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false); + from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, p_seek_root, 0.0, FILTER_IGNORE, false); } - mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false); + mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 1.0, FILTER_IGNORE, false); length_internal = from + mind; closest = new_closest; } else { - mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, 1.0, FILTER_IGNORE, false); + mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); } } diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h index 1356656bf8..01f53ed25a 100644 --- a/scene/animation/animation_blend_space_2d.h +++ b/scene/animation/animation_blend_space_2d.h @@ -126,7 +126,7 @@ public: void set_y_label(const String &p_label); String get_y_label() const; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; virtual String get_caption() const override; Vector2 get_closest_point(const Vector2 &p_point); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 433f21f91f..3de3ab256e 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -64,7 +64,7 @@ void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const { } } -double AnimationNodeAnimation::process(double p_time, bool p_seek) { +double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_seek_root) { AnimationPlayer *ap = state->player; ERR_FAIL_COND_V(!ap, 0); @@ -101,8 +101,8 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek) { } } - if (anim->get_loop_mode() == Animation::LoopMode::LOOP_PINGPONG) { - if (anim_size) { + if (anim->get_loop_mode() == Animation::LOOP_PINGPONG) { + if (!Math::is_zero_approx(anim_size)) { if ((int)Math::floor(abs(time - prev_time) / anim_size) % 2 == 0) { if (prev_time > 0 && time <= 0) { backward = !backward; @@ -116,22 +116,24 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek) { time = Math::pingpong(time, anim_size); } } else { - if (anim->get_loop_mode() == Animation::LoopMode::LOOP_LINEAR) { - if (anim_size) { + if (anim->get_loop_mode() == Animation::LOOP_LINEAR) { + if (!Math::is_zero_approx(anim_size)) { time = Math::fposmod(time, anim_size); } } else if (time < 0) { + step += time; time = 0; } else if (time > anim_size) { + step += anim_size - time; time = anim_size; } backward = false; } if (play_mode == PLAY_MODE_FORWARD) { - blend_animation(animation, time, step, p_seek, 1.0, pingponged); + blend_animation(animation, time, step, p_seek, p_seek_root, 1.0, pingponged); } else { - blend_animation(animation, anim_size - time, -step, p_seek, 1.0, pingponged); + blend_animation(animation, anim_size - time, -step, p_seek, p_seek_root, 1.0, pingponged); } set_parameter(this->time, time); @@ -251,7 +253,7 @@ bool AnimationNodeOneShot::has_filter() const { return true; } -double AnimationNodeOneShot::process(double p_time, bool p_seek) { +double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_root) { bool active = get_parameter(this->active); bool prev_active = get_parameter(this->prev_active); double time = get_parameter(this->time); @@ -274,7 +276,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek) { } if (!active) { - return blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); + return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); } } @@ -311,12 +313,12 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek) { double main_rem; if (mix == MIX_MODE_ADD) { - main_rem = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); + main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); } else { - main_rem = blend_input(0, p_time, p_seek, 1.0 - blend, FILTER_BLEND, !sync); + main_rem = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_BLEND, !sync); } - double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, blend, FILTER_PASS, false); + double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, false); if (do_start) { remaining = os_rem; @@ -420,10 +422,10 @@ bool AnimationNodeAdd2::has_filter() const { return true; } -double AnimationNodeAdd2::process(double p_time, bool p_seek) { +double AnimationNodeAdd2::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(add_amount); - double rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); - blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); + blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync); return rem0; } @@ -466,11 +468,11 @@ bool AnimationNodeAdd3::has_filter() const { return true; } -double AnimationNodeAdd3::process(double p_time, bool p_seek) { +double AnimationNodeAdd3::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(add_amount); - blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_PASS, !sync); - double rem0 = blend_input(1, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); - blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_PASS, !sync); + blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_PASS, !sync); + double rem0 = blend_input(1, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); + blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_PASS, !sync); return rem0; } @@ -502,11 +504,11 @@ String AnimationNodeBlend2::get_caption() const { return "Blend2"; } -double AnimationNodeBlend2::process(double p_time, bool p_seek) { +double AnimationNodeBlend2::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(blend_amount); - double rem0 = blend_input(0, p_time, p_seek, 1.0 - amount, FILTER_BLEND, !sync); - double rem1 = blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, 1.0 - amount, FILTER_BLEND, !sync); + double rem1 = blend_input(1, p_time, p_seek, p_seek_root, amount, FILTER_PASS, !sync); return amount > 0.5 ? rem1 : rem0; //hacky but good enough } @@ -557,11 +559,11 @@ bool AnimationNodeBlend3::is_using_sync() const { return sync; } -double AnimationNodeBlend3::process(double p_time, bool p_seek) { +double AnimationNodeBlend3::process(double p_time, bool p_seek, bool p_seek_root) { double amount = get_parameter(blend_amount); - double rem0 = blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_IGNORE, !sync); - double rem1 = blend_input(1, p_time, p_seek, 1.0 - ABS(amount), FILTER_IGNORE, !sync); - double rem2 = blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_IGNORE, !sync); + double rem0 = blend_input(0, p_time, p_seek, p_seek_root, MAX(0, -amount), FILTER_IGNORE, !sync); + double rem1 = blend_input(1, p_time, p_seek, p_seek_root, 1.0 - ABS(amount), FILTER_IGNORE, !sync); + double rem2 = blend_input(2, p_time, p_seek, p_seek_root, MAX(0, amount), FILTER_IGNORE, !sync); return amount > 0.5 ? rem2 : (amount < -0.5 ? rem0 : rem1); //hacky but good enough } @@ -595,12 +597,12 @@ String AnimationNodeTimeScale::get_caption() const { return "TimeScale"; } -double AnimationNodeTimeScale::process(double p_time, bool p_seek) { +double AnimationNodeTimeScale::process(double p_time, bool p_seek, bool p_seek_root) { double scale = get_parameter(this->scale); if (p_seek) { - return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false); } else { - return blend_input(0, p_time * scale, false, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, false); } } @@ -625,16 +627,16 @@ String AnimationNodeTimeSeek::get_caption() const { return "Seek"; } -double AnimationNodeTimeSeek::process(double p_time, bool p_seek) { +double AnimationNodeTimeSeek::process(double p_time, bool p_seek, bool p_seek_root) { double seek_pos = get_parameter(this->seek_pos); if (p_seek) { - return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, false); } else if (seek_pos >= 0) { - double ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false); + double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, false); set_parameter(this->seek_pos, -1.0); //reset return ret; } else { - return blend_input(0, p_time, false, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, false); } } @@ -726,7 +728,7 @@ float AnimationNodeTransition::get_cross_fade_time() const { return xfade; } -double AnimationNodeTransition::process(double p_time, bool p_seek) { +double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_root) { int current = get_parameter(this->current); int prev = get_parameter(this->prev); int prev_current = get_parameter(this->prev_current); @@ -754,7 +756,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek) { if (prev < 0) { // process current animation, check for transition - rem = blend_input(current, p_time, p_seek, 1.0, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); if (p_seek) { time = p_time; @@ -772,16 +774,16 @@ double AnimationNodeTransition::process(double p_time, bool p_seek) { if (!p_seek && switched) { //just switched, seek to start of current - rem = blend_input(current, 0, true, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); } else { - rem = blend_input(current, p_time, p_seek, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); } if (p_seek) { // don't seek prev animation - blend_input(prev, 0, false, blend, FILTER_IGNORE, false); + blend_input(prev, 0, false, p_seek_root, blend, FILTER_IGNORE, false); time = p_time; } else { - blend_input(prev, p_time, false, blend, FILTER_IGNORE, false); + blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, false); time += p_time; prev_xfading -= p_time; if (prev_xfading < 0) { @@ -844,8 +846,8 @@ String AnimationNodeOutput::get_caption() const { return "Output"; } -double AnimationNodeOutput::process(double p_time, bool p_seek) { - return blend_input(0, p_time, p_seek, 1.0); +double AnimationNodeOutput::process(double p_time, bool p_seek, bool p_seek_root) { + return blend_input(0, p_time, p_seek, p_seek_root, 1.0); } AnimationNodeOutput::AnimationNodeOutput() { @@ -1057,9 +1059,9 @@ String AnimationNodeBlendTree::get_caption() const { return "BlendTree"; } -double AnimationNodeBlendTree::process(double p_time, bool p_seek) { +double AnimationNodeBlendTree::process(double p_time, bool p_seek, bool p_seek_root) { Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node; - return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, 1.0); + return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0); } void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 2acacd7396..09971a61c0 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -53,7 +53,7 @@ public: static Vector<String> (*get_editable_animation_list)(); virtual String get_caption() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; void set_animation(const StringName &p_name); StringName get_animation() const; @@ -87,8 +87,8 @@ public: }; private: - float fade_in = 0.1; - float fade_out = 0.1; + float fade_in = 0.0; + float fade_out = 0.0; bool autorestart = false; float autorestart_delay = 1.0; @@ -138,7 +138,7 @@ public: bool is_using_sync() const; virtual bool has_filter() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeOneShot(); }; @@ -164,7 +164,7 @@ public: bool is_using_sync() const; virtual bool has_filter() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd2(); }; @@ -188,7 +188,7 @@ public: bool is_using_sync() const; virtual bool has_filter() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd3(); }; @@ -207,7 +207,7 @@ public: virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; virtual String get_caption() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; void set_use_sync(bool p_sync); bool is_using_sync() const; @@ -234,7 +234,7 @@ public: void set_use_sync(bool p_sync); bool is_using_sync() const; - double process(double p_time, bool p_seek) override; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeBlend3(); }; @@ -252,7 +252,7 @@ public: virtual String get_caption() const override; - double process(double p_time, bool p_seek) override; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeTimeScale(); }; @@ -271,7 +271,7 @@ public: virtual String get_caption() const override; - double process(double p_time, bool p_seek) override; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeTimeSeek(); }; @@ -329,7 +329,7 @@ public: void set_cross_fade_time(float p_fade); float get_cross_fade_time() const; - double process(double p_time, bool p_seek) override; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeTransition(); }; @@ -339,7 +339,7 @@ class AnimationNodeOutput : public AnimationNode { public: virtual String get_caption() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeOutput(); }; @@ -408,7 +408,7 @@ public: void get_node_connections(List<NodeConnection> *r_connections) const; virtual String get_caption() const override; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; void get_node_list(List<StringName> *r_list); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index b3cae4f5b5..8ac195aabe 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -292,7 +292,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta return true; } -double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek) { +double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root) { //if not playing and it can restart, then restart if (!playing && start_request == StringName()) { if (!stop_request && p_state_machine->start_node) { @@ -356,7 +356,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s current = p_state_machine->start_node; } - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, 1.0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 1.0, AnimationNode::FILTER_IGNORE, false); pos_current = 0; } @@ -381,10 +381,10 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } } - float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, fade_blend, AnimationNode::FILTER_IGNORE, false); + float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, false); if (fading_from != StringName()) { - p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, false); + p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_seek_root, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, false); } //guess playback position @@ -538,12 +538,12 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } current = next; if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) { - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, 0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); pos_current = MIN(pos_current, len_current); - p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, 0, AnimationNode::FILTER_IGNORE, false); + p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); } else { - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, 0, AnimationNode::FILTER_IGNORE, false); + len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, false); pos_current = 0; } @@ -1071,11 +1071,11 @@ Vector2 AnimationNodeStateMachine::get_graph_offset() const { return graph_offset; } -double AnimationNodeStateMachine::process(double p_time, bool p_seek) { +double AnimationNodeStateMachine::process(double p_time, bool p_seek, bool p_seek_root) { Ref<AnimationNodeStateMachinePlayback> playback = get_parameter(this->playback); ERR_FAIL_COND_V(playback.is_null(), 0.0); - return playback->process(this, p_time, p_seek); + return playback->process(this, p_time, p_seek, p_seek_root); } String AnimationNodeStateMachine::get_caption() const { diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index 39a84358fb..ec56c2606a 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -120,7 +120,7 @@ class AnimationNodeStateMachinePlayback : public Resource { bool _travel(AnimationNodeStateMachine *p_state_machine, const StringName &p_travel); - double process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek); + double process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root); bool _check_advance_condition(const Ref<AnimationNodeStateMachine> p_state_machine, const Ref<AnimationNodeStateMachineTransition> p_transition) const; @@ -226,7 +226,7 @@ public: void set_graph_offset(const Vector2 &p_offset); Vector2 get_graph_offset() const; - virtual double process(double p_time, bool p_seek) override; + virtual double process(double p_time, bool p_seek, bool p_seek_root) override; virtual String get_caption() const override; virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 081e6e809a..b498837847 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -832,7 +832,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double nc->audio_start = p_time; } } else if (nc->audio_playing) { - bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE; + bool loop = a->get_loop_mode() != Animation::LOOP_NONE; bool stop = false; @@ -883,15 +883,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double double at_anim_pos = 0.0; switch (anim->get_loop_mode()) { - case Animation::LoopMode::LOOP_NONE: { + case Animation::LOOP_NONE: { at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end } break; - case Animation::LoopMode::LOOP_LINEAR: { + case Animation::LOOP_LINEAR: { at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop } break; - case Animation::LoopMode::LOOP_PINGPONG: { + case Animation::LOOP_PINGPONG: { at_anim_pos = Math::pingpong(p_time - pos, (double)anim->get_length()); } break; @@ -944,7 +944,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, int pingponged = 0; switch (cd.from->animation->get_loop_mode()) { - case Animation::LoopMode::LOOP_NONE: { + case Animation::LOOP_NONE: { if (next_pos < 0) { next_pos = 0; } else if (next_pos > len) { @@ -969,7 +969,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, } } break; - case Animation::LoopMode::LOOP_LINEAR: { + case Animation::LOOP_LINEAR: { double looped_next_pos = Math::fposmod(next_pos, (double)len); if (looped_next_pos == 0 && next_pos != 0) { // Loop multiples of the length to it, rather than 0 @@ -980,7 +980,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, } } break; - case Animation::LoopMode::LOOP_PINGPONG: { + case Animation::LOOP_PINGPONG: { if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) { if (next_pos < 0 && cd.pos >= 0) { cd.speed_scale *= -1.0; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index b0590bc2bd..41d24fbfdf 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -88,7 +88,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) { } } -void AnimationNode::blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, real_t p_blend, int p_pingponged) { +void AnimationNode::blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_seek_root, real_t p_blend, int p_pingponged) { ERR_FAIL_COND(!state); ERR_FAIL_COND(!state->player->has_animation(p_animation)); @@ -115,17 +115,18 @@ void AnimationNode::blend_animation(const StringName &p_animation, double p_time anim_state.animation = animation; anim_state.seeked = p_seeked; anim_state.pingponged = p_pingponged; + anim_state.seek_root = p_seek_root; state->animation_states.push_back(anim_state); } -double AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, const Vector<StringName> &p_connections) { +double AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_seek_root, const Vector<StringName> &p_connections) { base_path = p_base_path; parent = p_parent; connections = p_connections; state = p_state; - double t = process(p_time, p_seek); + double t = process(p_time, p_seek, p_seek_root); state = nullptr; parent = nullptr; @@ -144,7 +145,7 @@ void AnimationNode::make_invalid(const String &p_reason) { state->invalid_reasons += String::utf8("• ") + p_reason; } -double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize) { +double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) { ERR_FAIL_INDEX_V(p_input, inputs.size(), 0); ERR_FAIL_COND_V(!state, 0); @@ -163,7 +164,7 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, real_ //inputs.write[p_input].last_pass = state->last_pass; real_t activity = 0.0; - double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity); + double ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize, &activity); Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path); @@ -174,11 +175,11 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, real_ return ret; } -double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize) { - return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_blend, p_filter, p_optimize); +double AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize) { + return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_optimize); } -double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize, real_t *r_max) { +double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter, bool p_optimize, real_t *r_max) { ERR_FAIL_COND_V(!p_node.is_valid(), 0); ERR_FAIL_COND_V(!state, 0); @@ -287,9 +288,9 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri } if (!p_seek && p_optimize && !any_valid) { - return p_node->_pre_process(new_path, new_parent, state, 0, p_seek, p_connections); + return p_node->_pre_process(new_path, new_parent, state, 0, p_seek, p_seek_root, p_connections); } - return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_connections); + return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_seek_root, p_connections); } int AnimationNode::get_input_count() const { @@ -333,9 +334,9 @@ void AnimationNode::remove_input(int p_index) { emit_changed(); } -double AnimationNode::process(double p_time, bool p_seek) { +double AnimationNode::process(double p_time, bool p_seek, bool p_seek_root) { double ret; - if (GDVIRTUAL_CALL(_process, p_time, p_seek, ret)) { + if (GDVIRTUAL_CALL(_process, p_time, p_seek, p_seek_root, ret)) { return ret; } @@ -420,9 +421,9 @@ void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters); ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters); - ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "seek_root", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_parameter", "name", "value"), &AnimationNode::set_parameter); ClassDB::bind_method(D_METHOD("get_parameter", "name"), &AnimationNode::get_parameter); @@ -434,7 +435,7 @@ void AnimationNode::_bind_methods() { GDVIRTUAL_BIND(_get_parameter_list); GDVIRTUAL_BIND(_get_child_by_name, "name"); GDVIRTUAL_BIND(_get_parameter_default_value, "parameter"); - GDVIRTUAL_BIND(_process, "time", "seek"); + GDVIRTUAL_BIND(_process, "time", "seek", "seek_root"); GDVIRTUAL_BIND(_get_caption); GDVIRTUAL_BIND(_has_filter); @@ -864,7 +865,6 @@ void AnimationTree::_process_graph(double p_delta) { _update_properties(); //if properties need updating, update them //check all tracks, see if they need modification - root_motion_transform = Transform3D(); if (!root.is_valid()) { @@ -943,11 +943,11 @@ void AnimationTree::_process_graph(double p_delta) { { if (started) { //if started, seek - root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, nullptr, &state, 0, true, Vector<StringName>()); + root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, nullptr, &state, 0, true, false, Vector<StringName>()); started = false; } - root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, nullptr, &state, p_delta, false, Vector<StringName>()); + root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path, nullptr, &state, p_delta, false, false, Vector<StringName>()); } if (!state.valid) { @@ -967,6 +967,7 @@ void AnimationTree::_process_graph(double p_delta) { int pingponged = as.pingponged; #ifndef _3D_DISABLED bool backward = signbit(delta); + bool calc_root = !seeked || as.seek_root; #endif // _3D_DISABLED for (int i = 0; i < a->get_track_count(); i++) { @@ -995,7 +996,7 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_POSITION_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (track->root_motion) { + if (track->root_motion && calc_root) { if (t->process_pass != process_pass) { t->process_pass = process_pass; t->loc = Vector3(0, 0, 0); @@ -1057,7 +1058,7 @@ void AnimationTree::_process_graph(double p_delta) { } a->position_track_interpolate(i, 0, &loc[1]); t->loc += (loc[1] - loc[0]) * blend; - prev_time = 0; + prev_time = (double)a->get_length(); } } @@ -1091,7 +1092,7 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_ROTATION_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (track->root_motion) { + if (track->root_motion && calc_root) { if (t->process_pass != process_pass) { t->process_pass = process_pass; t->loc = Vector3(0, 0, 0); @@ -1153,7 +1154,7 @@ void AnimationTree::_process_graph(double p_delta) { } a->rotation_track_interpolate(i, 0, &rot[1]); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); - prev_time = 0; + prev_time = (double)a->get_length(); } } @@ -1187,7 +1188,7 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_SCALE_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (track->root_motion) { + if (track->root_motion && calc_root) { if (t->process_pass != process_pass) { t->process_pass = process_pass; t->loc = Vector3(0, 0, 0); @@ -1249,7 +1250,7 @@ void AnimationTree::_process_graph(double p_delta) { } a->scale_track_interpolate(i, 0, &scale[1]); t->scale += (scale[1] - scale[0]) * blend; - prev_time = 0; + prev_time = (double)a->get_length(); } } @@ -1306,8 +1307,7 @@ void AnimationTree::_process_graph(double p_delta) { Animation::UpdateMode update_mode = a->value_track_get_update_mode(i); - if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { //delta == 0 means seek - + if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { Variant value = a->value_track_interpolate(i, time); if (value == Variant()) { @@ -1448,7 +1448,7 @@ void AnimationTree::_process_graph(double p_delta) { t->start = time; } } else if (t->playing) { - bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE; + bool loop = a->get_loop_mode() != Animation::LOOP_NONE; bool stop = false; @@ -1517,13 +1517,13 @@ void AnimationTree::_process_graph(double p_delta) { double at_anim_pos = 0.0; switch (anim->get_loop_mode()) { - case Animation::LoopMode::LOOP_NONE: { + case Animation::LOOP_NONE: { at_anim_pos = MAX((double)anim->get_length(), time - pos); //seek to end } break; - case Animation::LoopMode::LOOP_LINEAR: { + case Animation::LOOP_LINEAR: { at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop } break; - case Animation::LoopMode::LOOP_PINGPONG: { + case Animation::LOOP_PINGPONG: { at_anim_pos = Math::pingpong(time - pos, (double)a->get_length()); } break; default: diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 3f09bf7f4b..785c2d9c64 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -68,6 +68,7 @@ public: const Vector<real_t> *track_blends = nullptr; real_t blend = 0.0; bool seeked = false; + bool seek_root = false; int pingponged = 0; }; @@ -85,7 +86,7 @@ public: Vector<real_t> blends; State *state = nullptr; - double _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, const Vector<StringName> &p_connections); + double _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, double p_time, bool p_seek, bool p_seek_root, const Vector<StringName> &p_connections); //all this is temporary StringName base_path; @@ -98,12 +99,12 @@ public: Array _get_filters() const; void _set_filters(const Array &p_filters); friend class AnimationNodeBlendTree; - double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr); + double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr); protected: - void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, real_t p_blend, int p_pingponged = 0); - double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); - double blend_input(int p_input, double p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); + void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_seek_root, real_t p_blend, int p_pingponged = 0); + double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); + double blend_input(int p_input, double p_time, bool p_seek, bool p_seek_root, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); void make_invalid(const String &p_reason); @@ -115,7 +116,7 @@ protected: GDVIRTUAL0RC(Array, _get_parameter_list) GDVIRTUAL1RC(Ref<AnimationNode>, _get_child_by_name, StringName) GDVIRTUAL1RC(Variant, _get_parameter_default_value, StringName) - GDVIRTUAL2RC(double, _process, double, bool) + GDVIRTUAL3RC(double, _process, double, bool, bool) GDVIRTUAL0RC(String, _get_caption) GDVIRTUAL0RC(bool, _has_filter) @@ -133,7 +134,7 @@ public: virtual void get_child_nodes(List<ChildNode> *r_child_nodes); - virtual double process(double p_time, bool p_seek); + virtual double process(double p_time, bool p_seek, bool p_seek_root); virtual String get_caption() const; int get_input_count() const; |