diff --git a/core/variant.h b/core/variant.h index 480a51cba..7e0cf206b 100644 --- a/core/variant.h +++ b/core/variant.h @@ -386,6 +386,7 @@ public: Variant duplicate(bool deep = false) const; static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst); static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); + static void sub(const Variant &a, const Variant &b, Variant &r_dst); struct CallError { enum Error { diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 967cdc8a6..722bc9131 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -4530,6 +4530,110 @@ Variant Variant::duplicate(bool deep) const { } } +void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) { + if (a.type != b.type) { + return; + } + + switch (a.type) { + case NIL: { + r_dst = Variant(); + } + return; + case INT: { + int64_t va = a._data._int; + int64_t vb = b._data._int; + r_dst = int(va - vb); + } + return; + case REAL: { + real_t ra = a._data._real; + real_t rb = b._data._real; + r_dst = ra - rb; + } + return; + case VECTOR2: { + r_dst = *reinterpret_cast(a._data._mem) - *reinterpret_cast(b._data._mem); + } + return; + case VECTOR2I: { + int32_t vax = reinterpret_cast(a._data._mem)->x; + int32_t vbx = reinterpret_cast(b._data._mem)->x; + int32_t vay = reinterpret_cast(a._data._mem)->y; + int32_t vby = reinterpret_cast(b._data._mem)->y; + r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby)); + } + return; + case RECT2: { + const Rect2 *ra = reinterpret_cast(a._data._mem); + const Rect2 *rb = reinterpret_cast(b._data._mem); + r_dst = Rect2(ra->position - rb->position, ra->size - rb->size); + } + return; + case RECT2I: { + const Rect2i *ra = reinterpret_cast(a._data._mem); + const Rect2i *rb = reinterpret_cast(b._data._mem); + + int32_t vax = ra->position.x; + int32_t vay = ra->position.y; + int32_t vbx = ra->size.x; + int32_t vby = ra->size.y; + int32_t vcx = rb->position.x; + int32_t vcy = rb->position.y; + int32_t vdx = rb->size.x; + int32_t vdy = rb->size.y; + + r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy)); + } + return; + case VECTOR3: { + r_dst = *reinterpret_cast(a._data._mem) - *reinterpret_cast(b._data._mem); + } + return; + case VECTOR3I: { + int32_t vax = reinterpret_cast(a._data._mem)->x; + int32_t vbx = reinterpret_cast(b._data._mem)->x; + int32_t vay = reinterpret_cast(a._data._mem)->y; + int32_t vby = reinterpret_cast(b._data._mem)->y; + int32_t vaz = reinterpret_cast(a._data._mem)->z; + int32_t vbz = reinterpret_cast(b._data._mem)->z; + r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz)); + } + return; + case AABB: { + const ::AABB *ra = reinterpret_cast(a._data._mem); + const ::AABB *rb = reinterpret_cast(b._data._mem); + r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size); + } + return; + case QUAT: { + Quat empty_rot; + const Quat *qa = reinterpret_cast(a._data._mem); + const Quat *qb = reinterpret_cast(b._data._mem); + r_dst = (*qb).inverse() * *qa; + } + return; + case COLOR: { + const Color *ca = reinterpret_cast(a._data._mem); + const Color *cb = reinterpret_cast(b._data._mem); + float new_r = ca->r - cb->r; + float new_g = ca->g - cb->g; + float new_b = ca->b - cb->b; + float new_a = ca->a - cb->a; + new_r = new_r > 1.0 ? 1.0 : new_r; + new_g = new_g > 1.0 ? 1.0 : new_g; + new_b = new_b > 1.0 ? 1.0 : new_b; + new_a = new_a > 1.0 ? 1.0 : new_a; + r_dst = Color(new_r, new_g, new_b, new_a); + } + return; + default: { + r_dst = a; + } + return; + } +} + void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) { if (a.type != b.type) { if (a.is_num() && b.is_num()) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 9d22ea87b..570b8d599 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -538,6 +538,12 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List sname; player->get_animation_list(&sname); + Ref reset_anim; + bool has_reset_anim = player->has_animation("RESET"); + if (has_reset_anim) { + reset_anim = player->get_animation("RESET"); + } + for (List::Element *E = sname.front(); E; E = E->next()) { Ref anim = player->get_animation(E->get()); for (int i = 0; i < anim->get_track_count(); i++) { @@ -591,6 +597,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track = track_value; + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_value->init_value = reset_anim->track_get_key_value(rt, 0); + } + } + } break; case Animation::TYPE_POSITION_3D: case Animation::TYPE_ROTATION_3D: @@ -645,6 +658,26 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { default: { } } + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + switch (track_type) { + case Animation::TYPE_POSITION_3D: { + track_xform->init_loc = reset_anim->track_get_key_value(rt, 0); + } break; + case Animation::TYPE_ROTATION_3D: { + track_xform->ref_rot = reset_anim->track_get_key_value(rt, 0); + track_xform->init_rot = track_xform->ref_rot.log(); + } break; + case Animation::TYPE_SCALE_3D: { + track_xform->init_scale = reset_anim->track_get_key_value(rt, 0); + } break; + default: { + } + } + } + } #endif } break; case Animation::TYPE_METHOD: { @@ -674,6 +707,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_bezier->object_id = track_bezier->object->get_instance_id(); track = track_bezier; + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_bezier->init_value = reset_anim->track_get_key_value(rt, 0); + } + } } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *track_audio = memnew(TrackCacheAudio); @@ -1116,10 +1156,16 @@ void AnimationTree::_process_graph(float p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = value; - t->value.zero(); + + if (!t->init_value) { + t->init_value = value; + t->init_value.zero(); + } else { + t->value = t->init_value; + } } + Variant::sub(value, t->init_value, value); Variant::blend(t->value, value, blend, t->value); } else { @@ -1180,10 +1226,10 @@ void AnimationTree::_process_graph(float p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = 0; + t->value = t->init_value; } - t->value += bezier * blend; + t->value += (bezier - t->init_value) * blend; } break; case Animation::TYPE_AUDIO: { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 32a014fa7..b49135418 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -215,6 +215,7 @@ private: }; struct TrackCacheValue : public TrackCache { + Variant init_value; Variant value; Vector subpath; TrackCacheValue() { type = Animation::TYPE_VALUE; } @@ -225,11 +226,13 @@ private: }; struct TrackCacheBezier : public TrackCache { + real_t init_value; float value; Vector subpath; TrackCacheBezier() { type = Animation::TYPE_BEZIER; value = 0; + init_value = 0.0; } };