diff options
Diffstat (limited to 'scene/animation')
-rw-r--r-- | scene/animation/animation_blend_space_1d.cpp | 27 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_1d.h | 5 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_2d.cpp | 33 | ||||
-rw-r--r-- | scene/animation/animation_blend_space_2d.h | 5 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 163 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.h | 64 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.cpp | 48 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.h | 2 | ||||
-rw-r--r-- | scene/animation/animation_player.cpp | 79 | ||||
-rw-r--r-- | scene/animation/animation_player.h | 11 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 64 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 14 | ||||
-rw-r--r-- | scene/animation/easing_equations.h | 2 | ||||
-rw-r--r-- | scene/animation/tween.cpp | 15 | ||||
-rw-r--r-- | scene/animation/tween.h | 2 |
15 files changed, 330 insertions, 204 deletions
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index 594f98410e..b42e426f51 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -78,6 +78,9 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label); ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label); + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync); + ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point); for (int i = 0; i < MAX_BLEND_POINTS; i++) { @@ -89,6 +92,7 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync"); } void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) { @@ -117,7 +121,7 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_ blend_points[p_at_index].node = p_node; blend_points[p_at_index].position = p_position; - blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); blend_points_used++; emit_signal(SNAME("tree_changed")); @@ -138,7 +142,7 @@ void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<Anim } blend_points[p_point].node = p_node; - blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace1D::_tree_changed), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -211,6 +215,14 @@ String AnimationNodeBlendSpace1D::get_value_label() const { return value_label; } +void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeBlendSpace1D::is_using_sync() const { + return sync; +} + void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node) { if (p_index == blend_points_used) { add_blend_point(p_node, 0); @@ -226,7 +238,7 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see 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, p_seek_root, 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, true); } double blend_pos = get_parameter(blend_position); @@ -295,9 +307,12 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_see 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, p_seek_root, weights[i], FILTER_IGNORE, false); - - max_time_remaining = MAX(max_time_remaining, remaining); + if (i == point_lower || i == point_higher) { + double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, weights[i], FILTER_IGNORE, true); + max_time_remaining = MAX(max_time_remaining, remaining); + } else { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } } return max_time_remaining; diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h index b2075c8c93..346e8a3a2f 100644 --- a/scene/animation/animation_blend_space_1d.h +++ b/scene/animation/animation_blend_space_1d.h @@ -63,6 +63,8 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode { StringName blend_position = "blend_position"; protected: + bool sync = false; + virtual void _validate_property(PropertyInfo &property) const override; static void _bind_methods(); @@ -93,6 +95,9 @@ public: void set_value_label(const String &p_label); String get_value_label() const; + void set_use_sync(bool p_sync); + bool is_using_sync() const; + double process(double p_time, bool p_seek, bool p_seek_root) override; String get_caption() const override; diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index acdce2d7de..6b5851a977 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -80,7 +80,7 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_ blend_points[p_at_index].node = p_node; blend_points[p_at_index].position = p_position; - blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_at_index].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED); blend_points_used++; _queue_auto_triangles(); @@ -102,7 +102,7 @@ void AnimationNodeBlendSpace2D::set_blend_point_node(int p_point, const Ref<Anim blend_points[p_point].node->disconnect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed)); } blend_points[p_point].node = p_node; - blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + blend_points[p_point].node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendSpace2D::_tree_changed), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -502,7 +502,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see 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, p_seek_root, 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, true); if (first || t < mind) { mind = t; first = false; @@ -513,8 +513,7 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see } if (!found) { - //ignore - blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, false); + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); } } } else { @@ -539,16 +538,22 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek, bool p_see 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, p_seek_root, 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, true); } - mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_seek_root, 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, true); length_internal = from + mind; closest = new_closest; } else { - mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, p_seek_root, 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, true); + } + + for (int i = 0; i < blend_points_used; i++) { + if (i != closest) { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } } } @@ -604,6 +609,14 @@ AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode() return blend_mode; } +void AnimationNodeBlendSpace2D::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeBlendSpace2D::is_using_sync() const { + return sync; +} + void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("set_blend_point_position", "point", "pos"), &AnimationNodeBlendSpace2D::set_blend_point_position); @@ -644,6 +657,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode); ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace2D::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace2D::is_using_sync); + ClassDB::bind_method(D_METHOD("_update_triangles"), &AnimationNodeBlendSpace2D::_update_triangles); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_triangles", "get_auto_triangles"); @@ -661,6 +677,7 @@ void AnimationNodeBlendSpace2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_x_label", "get_x_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_y_label", "get_y_label"); ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync"); ADD_SIGNAL(MethodInfo("triangles_updated")); BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED); diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h index 01f53ed25a..689b96e356 100644 --- a/scene/animation/animation_blend_space_2d.h +++ b/scene/animation/animation_blend_space_2d.h @@ -88,6 +88,8 @@ protected: void _tree_changed(); protected: + bool sync = false; + virtual void _validate_property(PropertyInfo &property) const override; static void _bind_methods(); @@ -137,6 +139,9 @@ public: void set_blend_mode(BlendMode p_blend_mode); BlendMode get_blend_mode() const; + void set_use_sync(bool p_sync); + bool is_using_sync() const; + virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override; AnimationNodeBlendSpace2D(); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 4f6975deb1..fe2fb1b7a1 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -179,6 +179,26 @@ AnimationNodeAnimation::AnimationNodeAnimation() { //////////////////////////////////////////////////////// +void AnimationNodeSync::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeSync::set_use_sync); + ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeSync::is_using_sync); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); +} + +void AnimationNodeSync::set_use_sync(bool p_sync) { + sync = p_sync; +} + +bool AnimationNodeSync::is_using_sync() const { + return sync; +} + +AnimationNodeSync::AnimationNodeSync() { +} + +//////////////////////////////////////////////////////// + void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const { r_list->push_back(PropertyInfo(Variant::BOOL, active)); r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); @@ -276,7 +296,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo } if (!active) { - return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, !sync); + return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, sync); } } @@ -313,12 +333,12 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo double main_rem; if (mix == MIX_MODE_ADD) { - main_rem = blend_input(0, p_time, p_seek, p_seek_root, 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, p_seek_root, 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, p_seek_root, blend, FILTER_PASS, false); + double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, p_seek_root, blend, FILTER_PASS, true); if (do_start) { remaining = os_rem; @@ -343,14 +363,6 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_seek_roo return MAX(main_rem, remaining); } -void AnimationNodeOneShot::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeOneShot::is_using_sync() const { - return sync; -} - void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_fadein_time", "time"), &AnimationNodeOneShot::set_fadein_time); ClassDB::bind_method(D_METHOD("get_fadein_time"), &AnimationNodeOneShot::get_fadein_time); @@ -370,9 +382,6 @@ void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mix_mode", "mode"), &AnimationNodeOneShot::set_mix_mode); ClassDB::bind_method(D_METHOD("get_mix_mode"), &AnimationNodeOneShot::get_mix_mode); - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_fadein_time", "get_fadein_time"); @@ -384,9 +393,6 @@ void AnimationNodeOneShot::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_delay", "get_autorestart_delay"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "autorestart_random_delay", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater,suffix:s"), "set_autorestart_random_delay", "get_autorestart_random_delay"); - ADD_GROUP("", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); - BIND_ENUM_CONSTANT(MIX_MODE_BLEND); BIND_ENUM_CONSTANT(MIX_MODE_ADD); } @@ -410,31 +416,19 @@ String AnimationNodeAdd2::get_caption() const { return "Add2"; } -void AnimationNodeAdd2::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeAdd2::is_using_sync() const { - return sync; -} - bool AnimationNodeAdd2::has_filter() const { return true; } 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, p_seek_root, 1.0, FILTER_IGNORE, !sync); - blend_input(1, p_time, p_seek, p_seek_root, 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; } void AnimationNodeAdd2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd2::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd2::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd2::AnimationNodeAdd2() { @@ -456,32 +450,20 @@ String AnimationNodeAdd3::get_caption() const { return "Add3"; } -void AnimationNodeAdd3::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeAdd3::is_using_sync() const { - return sync; -} - bool AnimationNodeAdd3::has_filter() const { return true; } 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, 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); + 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; } void AnimationNodeAdd3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd3::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd3::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeAdd3::AnimationNodeAdd3() { @@ -507,29 +489,17 @@ String AnimationNodeBlend2::get_caption() const { 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, 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); + 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 } -void AnimationNodeBlend2::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeBlend2::is_using_sync() const { - return sync; -} - bool AnimationNodeBlend2::has_filter() const { return true; } void AnimationNodeBlend2::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend2::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend2::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend2::AnimationNodeBlend2() { @@ -551,35 +521,22 @@ String AnimationNodeBlend3::get_caption() const { return "Blend3"; } -void AnimationNodeBlend3::set_use_sync(bool p_sync) { - sync = p_sync; -} - -bool AnimationNodeBlend3::is_using_sync() const { - return sync; -} - 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, 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); + 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 } void AnimationNodeBlend3::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend3::set_use_sync); - ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend3::is_using_sync); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync"); } AnimationNodeBlend3::AnimationNodeBlend3() { add_input("-blend"); add_input("in"); add_input("+blend"); - sync = false; } ///////////////////////////////// @@ -599,9 +556,9 @@ String AnimationNodeTimeScale::get_caption() const { 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, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true); } else { - return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time * scale, false, p_seek_root, 1.0, FILTER_IGNORE, true); } } @@ -629,13 +586,13 @@ String AnimationNodeTimeSeek::get_caption() const { 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, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, true, p_seek_root, 1.0, FILTER_IGNORE, true); } else if (seek_pos >= 0) { - double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, false); + double ret = blend_input(0, seek_pos, true, true, 1.0, FILTER_IGNORE, true); set_parameter(this->seek_pos, -1.0); //reset return ret; } else { - return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, false); + return blend_input(0, p_time, false, p_seek_root, 1.0, FILTER_IGNORE, true); } } @@ -727,6 +684,14 @@ float AnimationNodeTransition::get_cross_fade_time() const { return xfade; } +void AnimationNodeTransition::set_from_start(bool p_from_start) { + from_start = p_from_start; +} + +bool AnimationNodeTransition::is_from_start() const { + return from_start; +} + 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); @@ -753,9 +718,15 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_ double rem = 0.0; + for (int i = 0; i < enabled_inputs; i++) { + if (i != current && i != prev) { + blend_input(i, p_time, p_seek, p_seek_root, 0, FILTER_IGNORE, sync); + } + } + if (prev < 0) { // process current animation, check for transition - rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); if (p_seek) { time = p_time; @@ -771,18 +742,18 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_ float blend = xfade == 0 ? 0 : (prev_xfading / xfade); - if (!p_seek && switched) { //just switched, seek to start of current + if (from_start && !p_seek && switched) { //just switched, seek to start of current - rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, 0, true, p_seek_root, 1.0 - blend, FILTER_IGNORE, true); } else { - rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, false); + rem = blend_input(current, p_time, p_seek, p_seek_root, 1.0 - blend, FILTER_IGNORE, true); } - if (p_seek) { // don't seek prev animation - blend_input(prev, 0, false, p_seek_root, blend, FILTER_IGNORE, false); + if (p_seek) { + blend_input(prev, p_time, true, p_seek_root, blend, FILTER_IGNORE, true); time = p_time; } else { - blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, false); + blend_input(prev, p_time, false, p_seek_root, blend, FILTER_IGNORE, true); time += p_time; prev_xfading -= p_time; if (prev_xfading < 0) { @@ -824,8 +795,12 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time); ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time); + ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start); + ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start); + ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_cross_fade_time", "get_cross_fade_time"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start"); for (int i = 0; i < MAX_INPUTS; i++) { ADD_PROPERTYI(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_input_caption", "get_input_caption", i); @@ -846,7 +821,7 @@ String AnimationNodeOutput::get_caption() const { } 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); + return blend_input(0, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); } AnimationNodeOutput::AnimationNodeOutput() { @@ -869,8 +844,8 @@ void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNod emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); - p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_name), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeBlendTree::_tree_changed), CONNECT_REFERENCE_COUNTED); + p_node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_name), CONNECT_REFERENCE_COUNTED); } Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) const { @@ -970,7 +945,7 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN } } //connection must be done with new name - nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed), varray(p_new_name), CONNECT_REFERENCE_COUNTED); + nodes[p_new_name].node->connect("changed", callable_mp(this, &AnimationNodeBlendTree::_node_changed).bind(p_new_name), CONNECT_REFERENCE_COUNTED); emit_signal(SNAME("tree_changed")); } @@ -1060,7 +1035,7 @@ String AnimationNodeBlendTree::get_caption() const { 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, p_seek_root, 1.0); + return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, p_seek_root, 1.0, FILTER_IGNORE, true); } 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 0a2305b8d6..d35ff04f30 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -77,8 +77,23 @@ private: VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode) -class AnimationNodeOneShot : public AnimationNode { - GDCLASS(AnimationNodeOneShot, AnimationNode); +class AnimationNodeSync : public AnimationNode { + GDCLASS(AnimationNodeSync, AnimationNode); + +protected: + bool sync = false; + + static void _bind_methods(); + +public: + void set_use_sync(bool p_sync); + bool is_using_sync() const; + + AnimationNodeSync(); +}; + +class AnimationNodeOneShot : public AnimationNodeSync { + GDCLASS(AnimationNodeOneShot, AnimationNodeSync); public: enum MixMode { @@ -95,8 +110,6 @@ private: float autorestart_random_delay = 0.0; MixMode mix = MIX_MODE_BLEND; - bool sync = false; - /* bool active; bool do_start; float time; @@ -134,9 +147,6 @@ public: void set_mix_mode(MixMode p_mix); MixMode get_mix_mode() const; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; @@ -145,11 +155,10 @@ public: VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode) -class AnimationNodeAdd2 : public AnimationNode { - GDCLASS(AnimationNodeAdd2, AnimationNode); +class AnimationNodeAdd2 : public AnimationNodeSync { + GDCLASS(AnimationNodeAdd2, AnimationNodeSync); StringName add_amount = PNAME("add_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -160,20 +169,16 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd2(); }; -class AnimationNodeAdd3 : public AnimationNode { - GDCLASS(AnimationNodeAdd3, AnimationNode); +class AnimationNodeAdd3 : public AnimationNodeSync { + GDCLASS(AnimationNodeAdd3, AnimationNodeSync); StringName add_amount = PNAME("add_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -184,20 +189,16 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - virtual bool has_filter() const override; virtual double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeAdd3(); }; -class AnimationNodeBlend2 : public AnimationNode { - GDCLASS(AnimationNodeBlend2, AnimationNode); +class AnimationNodeBlend2 : public AnimationNodeSync { + GDCLASS(AnimationNodeBlend2, AnimationNodeSync); StringName blend_amount = PNAME("blend_amount"); - bool sync = false; protected: static void _bind_methods(); @@ -209,18 +210,14 @@ public: virtual String get_caption() const 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; - virtual bool has_filter() const override; AnimationNodeBlend2(); }; -class AnimationNodeBlend3 : public AnimationNode { - GDCLASS(AnimationNodeBlend3, AnimationNode); +class AnimationNodeBlend3 : public AnimationNodeSync { + GDCLASS(AnimationNodeBlend3, AnimationNodeSync); StringName blend_amount = PNAME("blend_amount"); - bool sync; protected: static void _bind_methods(); @@ -231,9 +228,6 @@ public: virtual String get_caption() const override; - void set_use_sync(bool p_sync); - bool is_using_sync() const; - double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeBlend3(); }; @@ -276,8 +270,8 @@ public: AnimationNodeTimeSeek(); }; -class AnimationNodeTransition : public AnimationNode { - GDCLASS(AnimationNodeTransition, AnimationNode); +class AnimationNodeTransition : public AnimationNodeSync { + GDCLASS(AnimationNodeTransition, AnimationNodeSync); enum { MAX_INPUTS = 32 @@ -304,6 +298,7 @@ class AnimationNodeTransition : public AnimationNode { StringName prev_current = "prev_current"; float xfade = 0.0; + bool from_start = true; void _update_inputs(); @@ -329,6 +324,9 @@ public: void set_cross_fade_time(float p_fade); float get_cross_fade_time() const; + void set_from_start(bool p_from_start); + bool is_from_start() const; + double process(double p_time, bool p_seek, bool p_seek_root) override; AnimationNodeTransition(); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 2ee7f4fa43..793967d9ad 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -395,7 +395,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, p_seek_root, 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, true); pos_current = 0; } @@ -420,10 +420,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, p_seek_root, 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, true); if (fading_from != StringName()) { - 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); + 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, true); } //guess playback position @@ -577,12 +577,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, p_seek_root, 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, true); pos_current = MIN(pos_current, len_current); - p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_seek_root, 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, true); } else { - len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 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, true); pos_current = 0; } @@ -630,7 +630,7 @@ bool AnimationNodeStateMachinePlayback::_check_advance_condition(const Ref<Anima Node *expression_base = tree_base->get_node_or_null(advance_expression_base_node_path); if (expression_base) { Ref<Expression> exp = transition->expression; - bool ret = exp->execute(Array(), tree_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls. + bool ret = exp->execute(Array(), expression_base, false, Engine::get_singleton()->is_editor_hint()); // Avoids allowing the user to crash the system with an expression by only allowing const calls. if (!exp->has_execute_failed()) { if (ret) { return true; @@ -723,7 +723,7 @@ void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<Animation emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<AnimationNode> p_node) { @@ -743,7 +743,7 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<Anima emit_changed(); emit_signal(SNAME("tree_changed")); - p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } bool AnimationNodeStateMachine::can_edit_node(const StringName &p_name) const { @@ -830,20 +830,12 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri anodesm->state_machine_name = p_new_name; } - for (int i = 0; i < transitions.size(); i++) { - if (transitions[i].local_from == p_name) { - _rename_transition(transitions[i].from, String(transitions[i].from).replace_first(p_name, p_new_name)); - } - - if (transitions[i].local_to == p_name) { - _rename_transition(transitions[i].to, String(transitions[i].to).replace_first(p_name, p_new_name)); - } - } + _rename_transitions(p_name, p_new_name); emit_signal("tree_changed"); } -void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, const StringName &p_new_name) { +void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, const StringName &p_new_name) { if (updating_transitions) { return; } @@ -854,12 +846,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].to).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_from == p_name) { + transitions.write[i].local_from = p_new_name; + } + transitions.write[i].from = p_new_name; } @@ -867,12 +863,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].from).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_to == p_name) { + transitions.write[i].local_to = p_new_name; + } + transitions.write[i].to = p_new_name; } @@ -1032,7 +1032,7 @@ void AnimationNodeStateMachine::add_transition(const StringName &p_from, const S tr.local_to = local_to; tr.transition = p_transition; - tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), varray(), CONNECT_REFERENCE_COUNTED); + tr.transition->connect("advance_condition_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); transitions.push_back(tr); diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index d4e58ca3d3..ead914db7a 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -185,7 +185,7 @@ private: void _tree_changed(); void _remove_transition(const Ref<AnimationNodeStateMachineTransition> p_transition); - void _rename_transition(const StringName &p_name, const StringName &p_new_name); + void _rename_transitions(const StringName &p_name, const StringName &p_new_name); bool _can_connect(const StringName &p_name, Vector<AnimationNodeStateMachine *> p_parents = Vector<AnimationNodeStateMachine *>()); StringName _get_shortest_path(const StringName &p_path) const; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 2e87dbf9da..636c9e26a5 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -64,7 +64,7 @@ void AnimatedValuesBackup::restore() const { if (arr.size() == 3) { Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]); Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]); - Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[0]); + Object::cast_to<Skeleton3D>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]); } } } @@ -325,7 +325,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov { if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) { - child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed), make_binds(child), CONNECT_ONESHOT); + child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONESHOT); } } @@ -370,6 +370,10 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov node_cache->node_3d = nullptr; ERR_CONTINUE(node_cache->bone_idx < 0); } + Transform3D rest = node_cache->skeleton->get_bone_rest(bone_idx); + node_cache->init_loc = rest.origin; + node_cache->init_rot = rest.basis.get_rotation_quaternion(); + node_cache->init_scale = rest.basis.get_scale(); } else { // no property, just use spatialnode node_cache->skeleton = nullptr; @@ -450,6 +454,23 @@ static void _call_object(Object *p_object, const StringName &p_method, const Vec } } +Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { + switch (p_anim->track_get_type(p_track)) { +#ifndef _3D_DISABLED + case Animation::TYPE_POSITION_3D: { + if (p_object_idx >= 0) { + const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object); + return Vector3(p_value) * skel->get_motion_scale(); + } + return p_value; + } break; +#endif // _3D_DISABLED + default: { + } break; + } + return p_value; +} + void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); @@ -494,14 +515,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + loc = _post_process_key_value(a, i, loc, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; nc->loc_accum = loc; - nc->rot_accum = Quaternion(); - nc->scale_accum = Vector3(); + nc->rot_accum = nc->init_rot; + nc->scale_accum = nc->init_scale; } else { nc->loc_accum = nc->loc_accum.lerp(loc, p_interp); } @@ -521,14 +543,15 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + rot = _post_process_key_value(a, i, rot, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; - nc->loc_accum = Vector3(); + nc->loc_accum = nc->init_loc; nc->rot_accum = rot; - nc->scale_accum = Vector3(); + nc->scale_accum = nc->init_scale; } else { nc->rot_accum = nc->rot_accum.slerp(rot, p_interp); } @@ -548,13 +571,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + scale = _post_process_key_value(a, i, scale, nc->node_3d, nc->bone_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); cache_update[cache_update_size++] = nc; nc->accum_pass = accum_pass; - nc->loc_accum = Vector3(); - nc->rot_accum = Quaternion(); + nc->loc_accum = nc->init_loc; + nc->rot_accum = nc->init_rot; nc->scale_accum = scale; } else { nc->scale_accum = nc->scale_accum.lerp(scale, p_interp); @@ -575,6 +599,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (err != OK) { continue; } + blend = _post_process_key_value(a, i, blend, nc->node_blend_shape, nc->blend_shape_idx); if (nc->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX); @@ -627,9 +652,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (p_time < first_key_time) { double c = Math::ease(p_time / first_key_time, transition); Variant first_value = a->track_get_key_value(i, first_key); + first_value = _post_process_key_value(a, i, first_value, nc->node); Variant interp_value; Variant::interpolate(pa->capture, first_value, c, interp_value); - if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); cache_update_prop[cache_update_prop_size++] = pa; @@ -649,6 +674,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (value == Variant()) { continue; } + value = _post_process_key_value(a, i, value, nc->node); if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); @@ -665,6 +691,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double for (int &F : indices) { Variant value = a->track_get_key_value(i, F); + value = _post_process_key_value(a, i, value, nc->node); switch (pa->special) { case SP_NONE: { bool valid; @@ -749,6 +776,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double TrackNodeCache::BezierAnim *ba = &E->value; real_t bezier = a->bezier_track_interpolate(i, p_time); + bezier = _post_process_key_value(a, i, bezier, nc->node); if (ba->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX); cache_update_bezier[cache_update_bezier_size++] = ba; @@ -1173,11 +1201,15 @@ void AnimationPlayer::_animation_process(double p_delta) { emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name); } } else { - //stop(); playing = false; _set_process(false); if (end_notify) { emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned); + + if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) { + print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path())); + get_tree()->quit(); + } } } end_reached = false; @@ -1345,9 +1377,9 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref animation_libraries.insert(insert_pos, ald); - ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name)); - ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name)); - ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_name)); + ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); + ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); + ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name)); _animation_set_cache_update(); @@ -1385,7 +1417,7 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) { } void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) { - Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED); + Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED); } void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) { @@ -1411,9 +1443,9 @@ void AnimationPlayer::rename_animation_library(const StringName &p_name, const S animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added)); animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed)); - animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name)); - animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name)); - animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_new_name)); for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) { StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key)); @@ -1864,6 +1896,14 @@ AnimationPlayer::AnimationMethodCallMode AnimationPlayer::get_method_call_mode() return method_call_mode; } +void AnimationPlayer::set_movie_quit_on_finish_enabled(bool p_enabled) { + movie_quit_on_finish = p_enabled; +} + +bool AnimationPlayer::is_movie_quit_on_finish_enabled() const { + return movie_quit_on_finish; +} + void AnimationPlayer::_set_process(bool p_process, bool p_force) { if (processing == p_process && !p_force) { return; @@ -2084,6 +2124,9 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode); ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode); + ClassDB::bind_method(D_METHOD("set_movie_quit_on_finish_enabled"), &AnimationPlayer::set_movie_quit_on_finish_enabled); + ClassDB::bind_method(D_METHOD("is_movie_quit_on_finish_enabled"), &AnimationPlayer::is_movie_quit_on_finish_enabled); + ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position); ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length); @@ -2105,6 +2148,8 @@ void AnimationPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "method_call_mode", PROPERTY_HINT_ENUM, "Deferred,Immediate"), "set_method_call_mode", "get_method_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled"); + ADD_SIGNAL(MethodInfo("animation_finished", PropertyInfo(Variant::STRING_NAME, "anim_name"))); ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name"))); ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name"))); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index d3eb37a345..b6d8dab1ed 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -109,6 +109,9 @@ private: bool loc_used = false; bool rot_used = false; bool scale_used = false; + Vector3 init_loc = Vector3(0, 0, 0); + Quaternion init_rot = Quaternion(0, 0, 0, 1); + Vector3 init_scale = Vector3(1, 1, 1); Vector3 loc_accum; Quaternion rot_accum; @@ -259,6 +262,7 @@ private: bool reset_on_save = true; AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE; AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED; + bool movie_quit_on_finish = false; bool processing = false; bool active = true; @@ -313,6 +317,8 @@ protected: static void _bind_methods(); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); + public: StringName find_animation(const Ref<Animation> &p_animation) const; StringName find_animation_library(const Ref<Animation> &p_animation) const; @@ -368,6 +374,9 @@ public: void set_method_call_mode(AnimationMethodCallMode p_mode); AnimationMethodCallMode get_method_call_mode() const; + void set_movie_quit_on_finish_enabled(bool p_enabled); + bool is_movie_quit_on_finish_enabled() const; + void seek(double p_time, bool p_update = false); void seek_delta(double p_time, float p_delta); float get_current_animation_position() const; @@ -395,4 +404,4 @@ public: VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback); VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode); -#endif +#endif // ANIMATION_PLAYER_H diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 8c8822ac3f..14cf64afad 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -150,7 +150,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, bool p_seek_root, 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_sync) { ERR_FAIL_INDEX_V(p_input, inputs.size(), 0); ERR_FAIL_COND_V(!state, 0); @@ -169,7 +169,7 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool //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_seek_root, 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_sync, &activity); Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path); @@ -180,11 +180,11 @@ double AnimationNode::blend_input(int p_input, double p_time, bool p_seek, bool return ret; } -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_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_sync) { + return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_seek_root, p_blend, p_filter, p_sync); } -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) { +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_sync, real_t *r_max) { ERR_FAIL_COND_V(!p_node.is_valid(), 0); ERR_FAIL_COND_V(!state, 0); @@ -292,9 +292,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri } // If tracks for blending don't exist for one of the animations, Rest or RESET animation is blended as init animation instead. - // Then, blend weight is 0 means that the init animation blend weight is 1. + // Then blend weight is 0 means that the init animation blend weight is 1. + // In that case, processing only the animation with the lacking track will not process the lacking track, and will not properly apply the Reset value. + // This means that all tracks which the animations in the branch that may be blended have must be processed. // Therefore, the blending process must be executed even if the blend weight is 0. - if (!p_seek && p_optimize && !any_valid) { + if (!p_seek && !p_sync && !any_valid) { 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_seek_root, p_connections); @@ -428,8 +430,8 @@ void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters); 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("blend_node", "name", "node", "time", "seek", "seek_root", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "seek_root", "blend", "filter", "sync"), &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); @@ -587,7 +589,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } if (!child->is_connected("tree_exited", callable_mp(this, &AnimationTree::_node_removed))) { - child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed), varray(child)); + child->connect("tree_exited", callable_mp(this, &AnimationTree::_node_removed).bind(child)); } switch (track_type) { @@ -1052,7 +1054,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, (double)a->get_length(), &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = 0; } @@ -1062,7 +1066,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, 0, &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = (double)a->get_length(); } @@ -1072,8 +1078,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc[0] = _post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, time, &loc[1]); + loc[1] = _post_process_key_value(a, i, loc[1], t->object, t->bone_idx); t->loc += (loc[1] - loc[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); @@ -1090,6 +1098,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + loc = _post_process_key_value(a, i, loc, t->object, t->bone_idx); t->loc += (loc - t->init_loc) * blend; } @@ -1148,7 +1157,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); + rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } @@ -1158,6 +1169,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, 0, &rot[1]); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = (double)a->get_length(); @@ -1168,8 +1180,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot[0] = _post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, time, &rot[1]); + rot[1] = _post_process_key_value(a, i, rot[1], t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = !backward ? 0 : (double)a->get_length(); @@ -1186,6 +1200,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + rot = _post_process_key_value(a, i, rot, t->object, t->bone_idx); t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized(); } @@ -1244,8 +1259,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]); t->scale += (scale[1] - scale[0]) * blend; + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); prev_time = 0; } } else { @@ -1254,7 +1271,9 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, 0, &scale[1]); + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); t->scale += (scale[1] - scale[0]) * blend; prev_time = (double)a->get_length(); } @@ -1264,8 +1283,10 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale[0] = _post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, time, &scale[1]); + scale[1] = _post_process_key_value(a, i, scale[1], t->object, t->bone_idx); t->scale += (scale[1] - scale[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); @@ -1282,6 +1303,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + scale = _post_process_key_value(a, i, scale, t->object, t->bone_idx); t->scale += (scale - t->init_scale) * blend; } @@ -1304,6 +1326,7 @@ void AnimationTree::_process_graph(double p_delta) { if (err != OK) { continue; } + value = _post_process_key_value(a, i, value, t->object, t->shape_index); t->value += (value - t->init_value) * blend; #endif // _3D_DISABLED @@ -1315,6 +1338,7 @@ void AnimationTree::_process_graph(double p_delta) { if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { Variant value = a->value_track_interpolate(i, time); + value = _post_process_key_value(a, i, value, t->object); if (value == Variant()) { continue; @@ -1342,12 +1366,14 @@ void AnimationTree::_process_graph(double p_delta) { continue; } Variant value = a->track_get_key_value(i, idx); + value = _post_process_key_value(a, i, value, t->object); t->object->set_indexed(t->subpath, value); } else { List<int> indices; a->value_track_get_key_indices(i, time, delta, &indices, pingponged); for (int &F : indices) { Variant value = a->track_get_key_value(i, F); + value = _post_process_key_value(a, i, value, t->object); t->object->set_indexed(t->subpath, value); } } @@ -1386,6 +1412,7 @@ void AnimationTree::_process_graph(double p_delta) { TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); real_t bezier = a->bezier_track_interpolate(i, time); + bezier = _post_process_key_value(a, i, bezier, t->object); if (t->process_pass != process_pass) { t->process_pass = process_pass; @@ -1661,6 +1688,23 @@ void AnimationTree::_process_graph(double p_delta) { } } +Variant AnimationTree::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx) { + switch (p_anim->track_get_type(p_track)) { +#ifndef _3D_DISABLED + case Animation::TYPE_POSITION_3D: { + if (p_object_idx >= 0) { + const Skeleton3D *skel = Object::cast_to<Skeleton3D>(p_object); + return Vector3(p_value) * skel->get_motion_scale(); + } + return p_value; + } break; +#endif // _3D_DISABLED + default: { + } break; + } + return p_value; +} + void AnimationTree::advance(real_t p_time) { _process_graph(p_time); } diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 0bfe615c9b..99851d140e 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ANIMATION_GRAPH_PLAYER_H -#define ANIMATION_GRAPH_PLAYER_H +#ifndef ANIMATION_TREE_H +#define ANIMATION_TREE_H #include "animation_player.h" #include "scene/3d/node_3d.h" @@ -99,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, bool p_seek_root, 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_sync = true, real_t *r_max = nullptr); protected: 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); + 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_sync = 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_sync = true); void make_invalid(const String &p_reason); AnimationTree *get_animation_tree() const; @@ -321,6 +321,8 @@ protected: void _notification(int p_what); static void _bind_methods(); + virtual Variant _post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, const Object *p_object, int p_object_idx = -1); + public: void set_tree_root(const Ref<AnimationNode> &p_root); Ref<AnimationNode> get_tree_root() const; @@ -359,4 +361,4 @@ public: VARIANT_ENUM_CAST(AnimationTree::AnimationProcessCallback) -#endif // ANIMATION_GRAPH_PLAYER_H +#endif // ANIMATION_TREE_H diff --git a/scene/animation/easing_equations.h b/scene/animation/easing_equations.h index 6d246c7a93..094829e406 100644 --- a/scene/animation/easing_equations.h +++ b/scene/animation/easing_equations.h @@ -402,4 +402,4 @@ static real_t out_in(real_t t, real_t b, real_t c, real_t d) { } }; // namespace back -#endif +#endif // EASING_EQUATIONS_H diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 5457da472f..dbc71cd9e7 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -464,6 +464,17 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f APPLY_EQUATION(columns[2][1]); return r; } + case Variant::VECTOR4: { + Vector4 i = p_initial_val; + Vector4 d = p_delta_val; + Vector4 r; + + APPLY_EQUATION(x); + APPLY_EQUATION(y); + APPLY_EQUATION(z); + APPLY_EQUATION(w); + return r; + } case Variant::QUATERNION: { Quaternion i = p_initial_val; @@ -853,7 +864,7 @@ bool CallbackTweener::step(float &r_delta) { if (elapsed_time >= delay) { Variant result; Callable::CallError ce; - callback.call(nullptr, 0, result, ce); + callback.callp(nullptr, 0, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce)); } @@ -924,7 +935,7 @@ bool MethodTweener::step(float &r_delta) { Variant result; Callable::CallError ce; - callback.call(argptr, 1, result, ce); + callback.callp(argptr, 1, result, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce)); } diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 40268405cf..b57ec2e5e7 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -283,4 +283,4 @@ private: Callable callback; }; -#endif +#endif // TWEEN_H |