diff options
Diffstat (limited to 'scene/animation')
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 9 | ||||
-rw-r--r-- | scene/animation/animation_node_state_machine.cpp | 61 | ||||
-rw-r--r-- | scene/animation/animation_player.cpp | 12 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 62 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 4 | ||||
-rw-r--r-- | scene/animation/tween.cpp | 285 | ||||
-rw-r--r-- | scene/animation/tween.h | 1 |
7 files changed, 124 insertions, 310 deletions
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 61f068408c..1efbaacb3b 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -542,7 +542,7 @@ AnimationNodeBlend3::AnimationNodeBlend3() { ///////////////////////////////// void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const { - r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "-32,32,0.01,or_lesser,or_greater")); + r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "-32,32,0.01,or_less,or_greater")); } Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const { @@ -750,7 +750,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_ float blend = xfade_time == 0 ? 0 : (prev_xfading / xfade_time); if (xfade_curve.is_valid()) { - blend = xfade_curve->interpolate(blend); + blend = xfade_curve->sample(blend); } if (from_start && !p_seek && switched) { //just switched, seek to start of current @@ -810,7 +810,7 @@ void AnimationNodeTransition::_bind_methods() { 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::INT, "enabled_inputs", 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_xfade_time", "get_xfade_time"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start"); @@ -1175,6 +1175,7 @@ void AnimationNodeBlendTree::_tree_changed() { void AnimationNodeBlendTree::_node_changed(const StringName &p_node) { ERR_FAIL_COND(!nodes.has(p_node)); nodes[p_node].connections.resize(nodes[p_node].node->get_input_count()); + emit_signal(SNAME("node_changed"), p_node); } void AnimationNodeBlendTree::_bind_methods() { @@ -1200,6 +1201,8 @@ void AnimationNodeBlendTree::_bind_methods() { BIND_CONSTANT(CONNECTION_ERROR_NO_OUTPUT); BIND_CONSTANT(CONNECTION_ERROR_SAME_NODE); BIND_CONSTANT(CONNECTION_ERROR_CONNECTION_EXISTS); + + ADD_SIGNAL(MethodInfo("node_changed", PropertyInfo(Variant::STRING_NAME, "node_name"))); } void AnimationNodeBlendTree::_initialize_node_tree() { diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index afb52de307..49a59de9b2 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -344,6 +344,15 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta } double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root) { + if (p_time == -1) { + Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node; + if (anodesm.is_valid()) { + p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true); + } + playing = false; + return 0; + } + //if not playing and it can restart, then restart if (!playing && start_request == StringName()) { if (!stop_request && p_state_machine->start_node) { @@ -433,7 +442,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } if (current_curve.is_valid()) { - fade_blend = current_curve->interpolate(fade_blend); + fade_blend = current_curve->sample(fade_blend); } float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true); @@ -491,7 +500,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s // handles start_node: if previous state machine is pointing to a node inside the current state machine, starts the current machine from start_node to prev_local_to if (p_state_machine->start_node == current && p_state_machine->transitions[i].local_from == current) { if (p_state_machine->prev_state_machine != nullptr) { - Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter("playback"); + Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter(p_state_machine->playback); if (prev_playback.is_valid()) { StringName prev_local_to = String(prev_playback->current_transition.next).replace_first(String(p_state_machine->state_machine_name) + "/", ""); @@ -530,7 +539,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s AnimationNodeStateMachine *prev_state_machine = p_state_machine->prev_state_machine; if (prev_state_machine != nullptr) { - Ref<AnimationNodeStateMachinePlayback> prev_playback = prev_state_machine->get_parameter("playback"); + Ref<AnimationNodeStateMachinePlayback> prev_playback = prev_state_machine->get_parameter(p_state_machine->playback); if (prev_playback.is_valid()) { if (next_xfade) { @@ -578,7 +587,6 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } if (goto_next) { //end_loop should be used because fade time may be too small or zero and animation may have looped - if (next_xfade) { //time to fade, baby fading_from = current; @@ -592,7 +600,16 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s if (path.size()) { //if it came from path, remove path path.remove_at(0); } + + { // if the current node is a state machine, update the "playing" variable to false by passing -1 in p_time + Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node; + if (anodesm.is_valid()) { + p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true); + } + } + 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, true); pos_current = MIN(pos_current, len_current); @@ -607,15 +624,16 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s } } - // time left must always be 1 because the end node don't length to compute - if (p_state_machine->end_node != current) { - rem = 1; + if (current != p_state_machine->end_node) { + rem = 1; // the time remaining must always be 1 because there is no way to predict how long it takes for the entire state machine to complete } else { - Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter("playback"); + if (p_state_machine->prev_state_machine != nullptr) { + Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter(p_state_machine->playback); - if (prev_playback.is_valid()) { - prev_playback->current_transition = current_transition; - prev_playback->force_auto_advance = true; + if (prev_playback.is_valid()) { + prev_playback->current_transition = current_transition; + prev_playback->force_auto_advance = true; + } } } @@ -690,23 +708,6 @@ void AnimationNodeStateMachine::get_parameter_list(List<PropertyInfo> *r_list) c for (const StringName &E : advance_conditions) { r_list->push_back(PropertyInfo(Variant::BOOL, E)); } - - // for (const KeyValue<StringName, State> &E : states) { - // if (E->node == ansm) { - // for (int i = 0; i < E->node->transitions.size(); i++) { - // StringName ac = E->node->transitions[i].transition->get_advance_condition_name(); - // if (ac != StringName() && advance_conditions.find(ac) == nullptr) { - // advance_conditions.push_back(ac); - // } - // } - - // advance_conditions.sort_custom<StringName::AlphCompare>(); - - // for (const StringName &E : advance_conditions) { - // r_list->push_back(PropertyInfo(Variant::BOOL, E)); - // } - // } - // } } Variant AnimationNodeStateMachine::get_parameter_default_value(const StringName &p_parameter) const { @@ -900,10 +901,6 @@ void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, co void AnimationNodeStateMachine::get_node_list(List<StringName> *r_nodes) const { List<StringName> nodes; for (const KeyValue<StringName, State> &E : states) { - if (E.key == end_node && prev_state_machine == nullptr) { - continue; - } - nodes.push_back(E.key); } nodes.sort_custom<StringName::AlphCompare>(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 073f61bfdd..ce9406883d 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -323,7 +323,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov #endif // _3D_DISABLED if (!child->is_connected("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed))) { - child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONESHOT); + child->connect("tree_exiting", callable_mp(this, &AnimationPlayer::_node_removed).bind(child), CONNECT_ONE_SHOT); } TrackNodeCacheKey key; @@ -650,15 +650,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double 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); + Variant interp_value = Animation::interpolate_variant(pa->capture, first_value, c); if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); cache_update_prop[cache_update_prop_size++] = pa; pa->value_accum = interp_value; pa->accum_pass = accum_pass; } else { - Variant::interpolate(pa->value_accum, interp_value, p_interp, pa->value_accum); + pa->value_accum = Animation::interpolate_variant(pa->value_accum, interp_value, p_interp); } continue; //handled @@ -679,7 +678,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double pa->value_accum = value; pa->accum_pass = accum_pass; } else { - Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum); + pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp); } } else if (p_is_current && p_delta != 0) { @@ -1270,6 +1269,8 @@ void AnimationPlayer::_animation_set_cache_update() { // If something was modified or removed, caches need to be cleared clear_caches(); } + + emit_signal(SNAME("animation_list_changed")); } void AnimationPlayer::_animation_added(const StringName &p_name, const StringName &p_library) { @@ -2150,6 +2151,7 @@ void AnimationPlayer::_bind_methods() { 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"))); + ADD_SIGNAL(MethodInfo("animation_list_changed")); ADD_SIGNAL(MethodInfo("caches_cleared")); BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index d06324f0aa..bcd52082af 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -847,6 +847,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { return true; } +void AnimationTree::_animation_player_changed() { + emit_signal(SNAME("animation_player_changed")); + _clear_caches(); +} + void AnimationTree::_clear_caches() { for (KeyValue<NodePath, TrackCache *> &K : track_cache) { memdelete(K.value); @@ -1378,8 +1383,13 @@ void AnimationTree::_process_graph(double p_delta) { } t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math_TAU); } else { - Variant::sub(value, t->init_value, value); - Variant::blend(t->value, value, blend, t->value); + if (t->init_value.get_type() == Variant::BOOL) { + value = Animation::subtract_variant(value.operator real_t(), t->init_value.operator real_t()); + t->value = Animation::blend_variant(t->value.operator real_t(), value.operator real_t(), blend); + } else { + value = Animation::subtract_variant(value, t->init_value); + t->value = Animation::blend_variant(t->value, value, blend); + } } } else { if (blend < CMP_EPSILON) { @@ -1698,7 +1708,11 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_VALUE: { TrackCacheValue *t = static_cast<TrackCacheValue *>(track); - t->object->set_indexed(t->subpath, t->value); + if (t->init_value.get_type() == Variant::BOOL) { + t->object->set_indexed(t->subpath, t->value.operator real_t() >= 0.5); + } else { + t->object->set_indexed(t->subpath, t->value); + } } break; case Animation::TYPE_BEZIER: { @@ -1738,6 +1752,7 @@ void AnimationTree::advance(real_t p_time) { void AnimationTree::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + _setup_animation_player(); if (last_animation_player.is_valid()) { Object *player = ObjectDB::get_instance(last_animation_player); if (player) { @@ -1770,8 +1785,43 @@ void AnimationTree::_notification(int p_what) { } } +void AnimationTree::_setup_animation_player() { + if (!is_inside_tree()) { + return; + } + + AnimationPlayer *new_player = nullptr; + if (!animation_player.is_empty()) { + new_player = Object::cast_to<AnimationPlayer>(get_node(animation_player)); + if (new_player && !new_player->is_connected("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed))) { + new_player->connect("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed)); + } + } + + if (new_player) { + if (!last_animation_player.is_valid()) { + // Animation player set newly. + emit_signal(SNAME("animation_player_changed")); + return; + } else if (last_animation_player == new_player->get_instance_id()) { + // Animation player isn't changed. + return; + } + } else if (!last_animation_player.is_valid()) { + // Animation player is being empty. + return; + } + + AnimationPlayer *old_player = Object::cast_to<AnimationPlayer>(ObjectDB::get_instance(last_animation_player)); + if (old_player && old_player->is_connected("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed))) { + old_player->disconnect("animation_list_changed", callable_mp(this, &AnimationTree::_animation_player_changed)); + } + emit_signal(SNAME("animation_player_changed")); +} + void AnimationTree::set_animation_player(const NodePath &p_player) { animation_player = p_player; + _setup_animation_player(); update_configuration_warnings(); } @@ -1799,8 +1849,8 @@ uint64_t AnimationTree::get_last_process_pass() const { return process_pass; } -TypedArray<String> AnimationTree::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray AnimationTree::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!root.is_valid()) { warnings.push_back(RTR("No root AnimationNode for the graph is set.")); @@ -2008,6 +2058,8 @@ void AnimationTree::_bind_methods() { BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS); BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE); BIND_ENUM_CONSTANT(ANIMATION_PROCESS_MANUAL); + + ADD_SIGNAL(MethodInfo("animation_player_changed")); } AnimationTree::AnimationTree() { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index ee0c0303dc..fc31c52bc6 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -282,6 +282,8 @@ private: bool cache_valid = false; void _node_removed(Node *p_node); + void _setup_animation_player(); + void _animation_player_changed(); void _clear_caches(); bool _update_caches(AnimationPlayer *player); void _process_graph(double p_delta); @@ -340,7 +342,7 @@ public: void set_advance_expression_base_node(const NodePath &p_advance_expression_base_node); NodePath get_advance_expression_base_node() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; bool is_state_invalid() const; String get_invalid_state_reason() const; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 7d9f83b7a2..b02f1959b7 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -32,6 +32,7 @@ #include "scene/animation/easing_equations.h" #include "scene/main/node.h" +#include "scene/resources/animation.h" Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = { { &linear::in, &linear::in, &linear::in, &linear::in }, // Linear is the same for each easing. @@ -75,10 +76,17 @@ Ref<PropertyTweener> Tween::tween_property(Object *p_target, NodePath p_property ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree."); ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first."); -#ifdef DEBUG_ENABLED Variant::Type property_type = p_target->get_indexed(p_property.get_as_property_path().get_subnames()).get_type(); - ERR_FAIL_COND_V_MSG(property_type != p_to.get_type(), Ref<PropertyTweener>(), "Type mismatch between property and final value: " + Variant::get_type_name(property_type) + " and " + Variant::get_type_name(p_to.get_type())); -#endif + if (property_type != p_to.get_type()) { + // Cast p_to between floats and ints to avoid minor annoyances. + if (property_type == Variant::FLOAT && p_to.get_type() == Variant::INT) { + p_to = float(p_to); + } else if (property_type == Variant::INT && p_to.get_type() == Variant::FLOAT) { + p_to = int(p_to); + } else { + ERR_FAIL_V_MSG(Ref<PropertyTweener>(), "Type mismatch between property and final value: " + Variant::get_type_name(property_type) + " and " + Variant::get_type_name(p_to.get_type())); + } + } Ref<PropertyTweener> tweener = memnew(PropertyTweener(p_target, p_property, p_to, p_duration)); append(tweener); @@ -307,6 +315,7 @@ bool Tween::step(float p_delta) { running = false; dead = true; emit_signal(SNAME("finished")); + break; } else { emit_signal(SNAME("loop_finished"), loops_done); current_step = 0; @@ -368,264 +377,14 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f ERR_FAIL_INDEX_V(p_trans, TransitionType::TRANS_MAX, Variant()); ERR_FAIL_INDEX_V(p_ease, EaseType::EASE_MAX, Variant()); -// Helper macro to run equation on sub-elements of the value (e.g. x and y of Vector2). -#define APPLY_EQUATION(element) \ - r.element = run_equation(p_trans, p_ease, p_time, i.element, d.element, p_duration); - - switch (p_initial_val.get_type()) { - case Variant::BOOL: { - return (run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration)) >= 0.5; - } - - case Variant::INT: { - return (int)run_equation(p_trans, p_ease, p_time, (int)p_initial_val, (int)p_delta_val, p_duration); - } - - case Variant::FLOAT: { - return run_equation(p_trans, p_ease, p_time, (real_t)p_initial_val, (real_t)p_delta_val, p_duration); - } - - case Variant::VECTOR2: { - Vector2 i = p_initial_val; - Vector2 d = p_delta_val; - Vector2 r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - return r; - } - - case Variant::VECTOR2I: { - Vector2i i = p_initial_val; - Vector2i d = p_delta_val; - Vector2i r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - return r; - } - - case Variant::RECT2: { - Rect2 i = p_initial_val; - Rect2 d = p_delta_val; - Rect2 r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - return r; - } - - case Variant::RECT2I: { - Rect2i i = p_initial_val; - Rect2i d = p_delta_val; - Rect2i r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - return r; - } - - case Variant::VECTOR3: { - Vector3 i = p_initial_val; - Vector3 d = p_delta_val; - Vector3 r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - APPLY_EQUATION(z); - return r; - } - - case Variant::VECTOR3I: { - Vector3i i = p_initial_val; - Vector3i d = p_delta_val; - Vector3i r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - APPLY_EQUATION(z); - return r; - } - - case Variant::TRANSFORM2D: { - Transform2D i = p_initial_val; - Transform2D d = p_delta_val; - Transform2D r; - - APPLY_EQUATION(columns[0][0]); - APPLY_EQUATION(columns[0][1]); - APPLY_EQUATION(columns[1][0]); - APPLY_EQUATION(columns[1][1]); - APPLY_EQUATION(columns[2][0]); - 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; - Quaternion d = p_delta_val; - Quaternion r = i * d; - r = i.slerp(r, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration)); - return r; - } - - case Variant::AABB: { - AABB i = p_initial_val; - AABB d = p_delta_val; - AABB r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(position.z); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - APPLY_EQUATION(size.z); - return r; - } - - case Variant::BASIS: { - Basis i = p_initial_val; - Basis d = p_delta_val; - Basis r; - - APPLY_EQUATION(rows[0][0]); - APPLY_EQUATION(rows[0][1]); - APPLY_EQUATION(rows[0][2]); - APPLY_EQUATION(rows[1][0]); - APPLY_EQUATION(rows[1][1]); - APPLY_EQUATION(rows[1][2]); - APPLY_EQUATION(rows[2][0]); - APPLY_EQUATION(rows[2][1]); - APPLY_EQUATION(rows[2][2]); - return r; - } - - case Variant::TRANSFORM3D: { - Transform3D i = p_initial_val; - Transform3D d = p_delta_val; - Transform3D r; - - APPLY_EQUATION(basis.rows[0][0]); - APPLY_EQUATION(basis.rows[0][1]); - APPLY_EQUATION(basis.rows[0][2]); - APPLY_EQUATION(basis.rows[1][0]); - APPLY_EQUATION(basis.rows[1][1]); - APPLY_EQUATION(basis.rows[1][2]); - APPLY_EQUATION(basis.rows[2][0]); - APPLY_EQUATION(basis.rows[2][1]); - APPLY_EQUATION(basis.rows[2][2]); - APPLY_EQUATION(origin.x); - APPLY_EQUATION(origin.y); - APPLY_EQUATION(origin.z); - return r; - } - - case Variant::COLOR: { - Color i = p_initial_val; - Color d = p_delta_val; - Color r; - - APPLY_EQUATION(r); - APPLY_EQUATION(g); - APPLY_EQUATION(b); - APPLY_EQUATION(a); - return r; - } - - default: { - return p_initial_val; - } - }; -#undef APPLY_EQUATION -} - -Variant Tween::calculate_delta_value(Variant p_intial_val, Variant p_final_val) { - ERR_FAIL_COND_V_MSG(p_intial_val.get_type() != p_final_val.get_type(), p_intial_val, "Type mismatch between initial and final value: " + Variant::get_type_name(p_intial_val.get_type()) + " and " + Variant::get_type_name(p_final_val.get_type())); - - switch (p_intial_val.get_type()) { - case Variant::BOOL: { - return (int)p_final_val - (int)p_intial_val; - } - - case Variant::RECT2: { - Rect2 i = p_intial_val; - Rect2 f = p_final_val; - return Rect2(f.position - i.position, f.size - i.size); - } - - case Variant::RECT2I: { - Rect2i i = p_intial_val; - Rect2i f = p_final_val; - return Rect2i(f.position - i.position, f.size - i.size); - } - - case Variant::TRANSFORM2D: { - Transform2D i = p_intial_val; - Transform2D f = p_final_val; - return Transform2D(f.columns[0][0] - i.columns[0][0], - f.columns[0][1] - i.columns[0][1], - f.columns[1][0] - i.columns[1][0], - f.columns[1][1] - i.columns[1][1], - f.columns[2][0] - i.columns[2][0], - f.columns[2][1] - i.columns[2][1]); - } - - case Variant::AABB: { - AABB i = p_intial_val; - AABB f = p_final_val; - return AABB(f.position - i.position, f.size - i.size); - } - - case Variant::BASIS: { - Basis i = p_intial_val; - Basis f = p_final_val; - return Basis(f.rows[0][0] - i.rows[0][0], - f.rows[0][1] - i.rows[0][1], - f.rows[0][2] - i.rows[0][2], - f.rows[1][0] - i.rows[1][0], - f.rows[1][1] - i.rows[1][1], - f.rows[1][2] - i.rows[1][2], - f.rows[2][0] - i.rows[2][0], - f.rows[2][1] - i.rows[2][1], - f.rows[2][2] - i.rows[2][2]); - } - - case Variant::TRANSFORM3D: { - Transform3D i = p_intial_val; - Transform3D f = p_final_val; - return Transform3D(f.basis.rows[0][0] - i.basis.rows[0][0], - f.basis.rows[0][1] - i.basis.rows[0][1], - f.basis.rows[0][2] - i.basis.rows[0][2], - f.basis.rows[1][0] - i.basis.rows[1][0], - f.basis.rows[1][1] - i.basis.rows[1][1], - f.basis.rows[1][2] - i.basis.rows[1][2], - f.basis.rows[2][0] - i.basis.rows[2][0], - f.basis.rows[2][1] - i.basis.rows[2][1], - f.basis.rows[2][2] - i.basis.rows[2][2], - f.origin.x - i.origin.x, - f.origin.y - i.origin.y, - f.origin.z - i.origin.z); - } + // Special case for bool. + if (p_initial_val.get_type() == Variant::BOOL) { + return run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration) >= 0.5; + } - default: { - return Variant::evaluate(Variant::OP_SUBTRACT, p_final_val, p_intial_val); - } - }; + Variant ret = Animation::add_variant(p_initial_val, p_delta_val); + ret = Animation::interpolate_variant(p_initial_val, ret, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration)); + return ret; } void Tween::_bind_methods() { @@ -741,10 +500,10 @@ void PropertyTweener::start() { } if (relative) { - final_val = Variant::evaluate(Variant::Operator::OP_ADD, initial_val, base_final_val); + final_val = Animation::add_variant(initial_val, base_final_val); } - delta_val = tween->calculate_delta_value(initial_val, final_val); + delta_val = Animation::subtract_variant(final_val, initial_val); } bool PropertyTweener::step(float &r_delta) { @@ -966,7 +725,7 @@ void MethodTweener::_bind_methods() { MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration) { callback = p_callback; initial_val = p_from; - delta_val = tween->calculate_delta_value(p_from, p_to); + delta_val = Animation::subtract_variant(p_to, p_from); final_val = p_to; duration = p_duration; } diff --git a/scene/animation/tween.h b/scene/animation/tween.h index b57ec2e5e7..da7a8b5d71 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -164,7 +164,6 @@ public: static real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d); static Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease); - Variant calculate_delta_value(Variant p_intial_val, Variant p_final_val); bool step(float p_delta); bool can_process(bool p_tree_paused) const; |