diff options
Diffstat (limited to 'scene/animation/animation_blend_tree.cpp')
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 156 |
1 files changed, 102 insertions, 54 deletions
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index d11387902a..d6c5d0b51c 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -30,6 +30,7 @@ #include "animation_blend_tree.h" +#include "scene/resources/animation.h" #include "scene/scene_string_names.h" void AnimationNodeAnimation::set_animation(const StringName &p_name) { @@ -83,30 +84,55 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek) { } Ref<Animation> anim = ap->get_animation(animation); - - double step; + double anim_size = (double)anim->get_length(); + double step = 0.0; + double prev_time = time; + int pingponged = 0; + bool current_backward = signbit(p_time); if (p_seek) { + step = p_time - time; time = p_time; - step = 0; } else { - time = MAX(0, time + p_time); - step = p_time; + p_time *= backward ? -1.0 : 1.0; + if (!(time == anim_size && !current_backward) && !(time == 0 && current_backward)) { + time = time + p_time; + step = p_time; + } } - double anim_size = anim->get_length(); - - if (anim->has_loop()) { + if (anim->get_loop_mode() == Animation::LoopMode::LOOP_PINGPONG) { if (anim_size) { - time = Math::fposmod(time, anim_size); + if ((int)Math::floor(abs(time - prev_time) / anim_size) % 2 == 0) { + if (prev_time > 0 && time <= 0) { + backward = !backward; + pingponged = -1; + } + if (prev_time < anim_size && time >= anim_size) { + backward = !backward; + pingponged = 1; + } + } + time = Math::pingpong(time, anim_size); } - - } else if (time > anim_size) { - time = anim_size; + } else { + if (anim->get_loop_mode() == Animation::LoopMode::LOOP_LINEAR) { + if (anim_size) { + time = Math::fposmod(time, anim_size); + } + } else if (time < 0) { + time = 0; + } else if (time > anim_size) { + time = anim_size; + } + backward = false; } - blend_animation(animation, time, step, p_seek, 1.0); - + if (play_mode == PLAY_MODE_FORWARD) { + blend_animation(animation, time, step, p_seek, 1.0, pingponged); + } else { + blend_animation(animation, anim_size - time, -step, p_seek, 1.0, pingponged); + } set_parameter(this->time, time); return anim_size - time; @@ -116,11 +142,34 @@ String AnimationNodeAnimation::get_caption() const { return "Animation"; } +void AnimationNodeAnimation::set_play_mode(PlayMode p_play_mode) { + play_mode = p_play_mode; +} + +AnimationNodeAnimation::PlayMode AnimationNodeAnimation::get_play_mode() const { + return play_mode; +} + +void AnimationNodeAnimation::set_backward(bool p_backward) { + backward = p_backward; +} + +bool AnimationNodeAnimation::is_backward() const { + return backward; +} + void AnimationNodeAnimation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation", "name"), &AnimationNodeAnimation::set_animation); ClassDB::bind_method(D_METHOD("get_animation"), &AnimationNodeAnimation::get_animation); + ClassDB::bind_method(D_METHOD("set_play_mode", "mode"), &AnimationNodeAnimation::set_play_mode); + ClassDB::bind_method(D_METHOD("get_play_mode"), &AnimationNodeAnimation::get_play_mode); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "play_mode", PROPERTY_HINT_ENUM, "Forward,Backward"), "set_play_mode", "get_play_mode"); + + BIND_ENUM_CONSTANT(PLAY_MODE_FORWARD); + BIND_ENUM_CONSTANT(PLAY_MODE_BACKWARD); } AnimationNodeAnimation::AnimationNodeAnimation() { @@ -248,27 +297,26 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek) { if (fade_in > 0) { blend = time / fade_in; } else { - blend = 0; //wtf + blend = 0; } - - } else if (!do_start && remaining < fade_out) { - if (fade_out) { + } else if (!do_start && remaining <= fade_out) { + if (fade_out > 0) { blend = (remaining / fade_out); } else { - blend = 1.0; + blend = 0; } } else { blend = 1.0; } - float main_rem; + double main_rem; if (mix == MIX_MODE_ADD) { main_rem = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); } else { main_rem = blend_input(0, p_time, p_seek, 1.0 - blend, FILTER_BLEND, !sync); } - float 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, blend, FILTER_PASS, false); if (do_start) { remaining = os_rem; @@ -534,7 +582,7 @@ AnimationNodeBlend3::AnimationNodeBlend3() { ///////////////////////////////// void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const { - r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "0,32,0.01,or_greater")); + r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "-32,32,0.01,or_lesser,or_greater")); } Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const { @@ -718,7 +766,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek) { } else { // cross-fading from prev to current - float blend = xfade ? (prev_xfading / xfade) : 1; + float blend = xfade == 0 ? 0 : (prev_xfading / xfade); if (!p_seek && switched) { //just switched, seek to start of current @@ -829,9 +877,9 @@ Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) co } StringName AnimationNodeBlendTree::get_node_name(const Ref<AnimationNode> &p_node) const { - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - if (E->get().node == p_node) { - return E->key(); + for (const KeyValue<StringName, Node> &E : nodes) { + if (E.value.node == p_node) { + return E.key; } } @@ -851,8 +899,8 @@ Vector2 AnimationNodeBlendTree::get_node_position(const StringName &p_node) cons void AnimationNodeBlendTree::get_child_nodes(List<ChildNode> *r_child_nodes) { Vector<StringName> ns; - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - ns.push_back(E->key()); + for (const KeyValue<StringName, Node> &E : nodes) { + ns.push_back(E.key); } ns.sort_custom<StringName::AlphCompare>(); @@ -887,10 +935,10 @@ void AnimationNodeBlendTree::remove_node(const StringName &p_name) { nodes.erase(p_name); //erase connections to name - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().connections.size(); i++) { - if (E->get().connections[i] == p_name) { - E->get().connections.write[i] = StringName(); + for (KeyValue<StringName, Node> &E : nodes) { + for (int i = 0; i < E.value.connections.size(); i++) { + if (E.value.connections[i] == p_name) { + E.value.connections.write[i] = StringName(); } } } @@ -911,10 +959,10 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN nodes.erase(p_name); //rename connections - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().connections.size(); i++) { - if (E->get().connections[i] == p_name) { - E->get().connections.write[i] = p_new_name; + for (KeyValue<StringName, Node> &E : nodes) { + for (int i = 0; i < E.value.connections.size(); i++) { + if (E.value.connections[i] == p_name) { + E.value.connections.write[i] = p_new_name; } } } @@ -933,9 +981,9 @@ void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_ Ref<AnimationNode> input = nodes[p_input_node].node; ERR_FAIL_INDEX(p_input_index, nodes[p_input_node].connections.size()); - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().connections.size(); i++) { - StringName output = E->get().connections[i]; + for (KeyValue<StringName, Node> &E : nodes) { + for (int i = 0; i < E.value.connections.size(); i++) { + StringName output = E.value.connections[i]; ERR_FAIL_COND(output == p_output_node); } } @@ -977,9 +1025,9 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node return CONNECTION_ERROR_CONNECTION_EXISTS; } - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().connections.size(); i++) { - StringName output = E->get().connections[i]; + for (const KeyValue<StringName, Node> &E : nodes) { + for (int i = 0; i < E.value.connections.size(); i++) { + const StringName output = E.value.connections[i]; if (output == p_output_node) { return CONNECTION_ERROR_CONNECTION_EXISTS; } @@ -989,12 +1037,12 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node } void AnimationNodeBlendTree::get_node_connections(List<NodeConnection> *r_connections) const { - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - for (int i = 0; i < E->get().connections.size(); i++) { - StringName output = E->get().connections[i]; + for (const KeyValue<StringName, Node> &E : nodes) { + for (int i = 0; i < E.value.connections.size(); i++) { + const StringName output = E.value.connections[i]; if (output != StringName()) { NodeConnection nc; - nc.input_node = E->key(); + nc.input_node = E.key; nc.input_index = i; nc.output_node = output; r_connections->push_back(nc); @@ -1013,8 +1061,8 @@ double AnimationNodeBlendTree::process(double p_time, bool p_seek) { } void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) { - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - r_list->push_back(E->key()); + for (const KeyValue<StringName, Node> &E : nodes) { + r_list->push_back(E.key); } } @@ -1105,20 +1153,20 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) const { List<StringName> names; - for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) { - names.push_back(E->key()); + for (const KeyValue<StringName, Node> &E : nodes) { + names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); for (const StringName &E : names) { String name = E; if (name != "output") { - p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NO_EDITOR)); } - p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } - p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } void AnimationNodeBlendTree::reset_state() { @@ -1153,7 +1201,7 @@ void AnimationNodeBlendTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeBlendTree::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeBlendTree::get_graph_offset); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset"); BIND_CONSTANT(CONNECTION_OK); BIND_CONSTANT(CONNECTION_ERROR_NO_INPUT); |