Merge pull request #65325 from TokageItLab/refactor-variant-for-anim
Move some static methods to `Animation` from `Variant` for refactoring `Animation` and `Tween`
This commit is contained in:
commit
a981a8061f
11 changed files with 495 additions and 870 deletions
|
@ -251,27 +251,6 @@ static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self)
|
|||
return self->booleanize();
|
||||
}
|
||||
|
||||
static void gdnative_variant_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) {
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
memnew_placement(r_dst, Variant);
|
||||
Variant::sub(*a, *b, *(Variant *)r_dst);
|
||||
}
|
||||
|
||||
static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
memnew_placement(r_dst, Variant);
|
||||
Variant::blend(*a, *b, p_c, *(Variant *)r_dst);
|
||||
}
|
||||
|
||||
static void gdnative_variant_interpolate(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
|
||||
const Variant *a = (const Variant *)p_a;
|
||||
const Variant *b = (const Variant *)p_b;
|
||||
memnew_placement(r_dst, Variant);
|
||||
Variant::interpolate(*a, *b, p_c, *(Variant *)r_dst);
|
||||
}
|
||||
|
||||
static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
|
||||
|
@ -970,9 +949,6 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
|
|||
gdni.variant_recursive_hash = gdnative_variant_recursive_hash;
|
||||
gdni.variant_hash_compare = gdnative_variant_hash_compare;
|
||||
gdni.variant_booleanize = gdnative_variant_booleanize;
|
||||
gdni.variant_sub = gdnative_variant_sub;
|
||||
gdni.variant_blend = gdnative_variant_blend;
|
||||
gdni.variant_interpolate = gdnative_variant_interpolate;
|
||||
gdni.variant_duplicate = gdnative_variant_duplicate;
|
||||
gdni.variant_stringify = gdnative_variant_stringify;
|
||||
|
||||
|
|
|
@ -427,9 +427,6 @@ typedef struct {
|
|||
GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count);
|
||||
GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other);
|
||||
GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self);
|
||||
void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst);
|
||||
void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
|
||||
void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
|
||||
void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep);
|
||||
void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret);
|
||||
|
||||
|
|
|
@ -552,9 +552,6 @@ public:
|
|||
void zero();
|
||||
Variant duplicate(bool p_deep = false) const;
|
||||
Variant recursive_duplicate(bool p_deep, int recursion_count) 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);
|
||||
|
||||
/* Built-In Methods */
|
||||
|
||||
|
|
|
@ -1911,572 +1911,6 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) 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 FLOAT: {
|
||||
double ra = a._data._float;
|
||||
double rb = b._data._float;
|
||||
r_dst = ra - rb;
|
||||
}
|
||||
return;
|
||||
case VECTOR2: {
|
||||
r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem);
|
||||
}
|
||||
return;
|
||||
case VECTOR2I: {
|
||||
int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
|
||||
r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby));
|
||||
}
|
||||
return;
|
||||
case RECT2: {
|
||||
const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
|
||||
const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
|
||||
r_dst = Rect2(ra->position - rb->position, ra->size - rb->size);
|
||||
}
|
||||
return;
|
||||
case RECT2I: {
|
||||
const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
|
||||
const Rect2i *rb = reinterpret_cast<const Rect2i *>(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<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem);
|
||||
}
|
||||
return;
|
||||
case VECTOR3I: {
|
||||
int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
|
||||
int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
|
||||
int32_t vbz = reinterpret_cast<const Vector3i *>(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<const ::AABB *>(a._data._mem);
|
||||
const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
|
||||
r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size);
|
||||
}
|
||||
return;
|
||||
case QUATERNION: {
|
||||
Quaternion empty_rot;
|
||||
const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
|
||||
const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
|
||||
r_dst = (*qb).inverse() * *qa;
|
||||
}
|
||||
return;
|
||||
case COLOR: {
|
||||
const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
|
||||
const Color *cb = reinterpret_cast<const Color *>(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()) {
|
||||
real_t va = a;
|
||||
real_t vb = b;
|
||||
r_dst = va + vb * c;
|
||||
} else {
|
||||
r_dst = a;
|
||||
}
|
||||
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 * c + 0.5);
|
||||
}
|
||||
return;
|
||||
case FLOAT: {
|
||||
double ra = a._data._float;
|
||||
double rb = b._data._float;
|
||||
r_dst = ra + rb * c;
|
||||
}
|
||||
return;
|
||||
case VECTOR2: {
|
||||
r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c;
|
||||
}
|
||||
return;
|
||||
case VECTOR2I: {
|
||||
int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
|
||||
r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
|
||||
}
|
||||
return;
|
||||
case RECT2: {
|
||||
const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
|
||||
const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
|
||||
r_dst = Rect2(ra->position + rb->position * c, ra->size + rb->size * c);
|
||||
}
|
||||
return;
|
||||
case RECT2I: {
|
||||
const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
|
||||
const Rect2i *rb = reinterpret_cast<const Rect2i *>(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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
|
||||
}
|
||||
return;
|
||||
case VECTOR3: {
|
||||
r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c;
|
||||
}
|
||||
return;
|
||||
case VECTOR3I: {
|
||||
int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
|
||||
int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
|
||||
int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
|
||||
r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
|
||||
}
|
||||
return;
|
||||
case AABB: {
|
||||
const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
|
||||
const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
|
||||
r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c);
|
||||
}
|
||||
return;
|
||||
case QUATERNION: {
|
||||
Quaternion empty_rot;
|
||||
const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
|
||||
const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
|
||||
r_dst = *qa * empty_rot.slerp(*qb, c);
|
||||
}
|
||||
return;
|
||||
case COLOR: {
|
||||
const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
|
||||
const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
|
||||
float new_r = ca->r + cb->r * c;
|
||||
float new_g = ca->g + cb->g * c;
|
||||
float new_b = ca->b + cb->b * c;
|
||||
float new_a = ca->a + cb->a * c;
|
||||
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 = c < 0.5 ? a : b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) {
|
||||
if (a.type != b.type) {
|
||||
if (a.is_num() && b.is_num()) {
|
||||
//not as efficient but..
|
||||
real_t va = a;
|
||||
real_t vb = b;
|
||||
r_dst = va + (vb - va) * c;
|
||||
|
||||
} else {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a.type) {
|
||||
case NIL: {
|
||||
r_dst = Variant();
|
||||
}
|
||||
return;
|
||||
case BOOL: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case INT: {
|
||||
int64_t va = a._data._int;
|
||||
int64_t vb = b._data._int;
|
||||
r_dst = int(va + (vb - va) * c);
|
||||
}
|
||||
return;
|
||||
case FLOAT: {
|
||||
real_t va = a._data._float;
|
||||
real_t vb = b._data._float;
|
||||
r_dst = va + (vb - va) * c;
|
||||
}
|
||||
return;
|
||||
case STRING: {
|
||||
//this is pretty funny and bizarre, but artists like to use it for typewriter effects
|
||||
String sa = *reinterpret_cast<const String *>(a._data._mem);
|
||||
String sb = *reinterpret_cast<const String *>(b._data._mem);
|
||||
String dst;
|
||||
int sa_len = sa.length();
|
||||
int sb_len = sb.length();
|
||||
int csize = sa_len + (sb_len - sa_len) * c;
|
||||
if (csize == 0) {
|
||||
r_dst = "";
|
||||
return;
|
||||
}
|
||||
dst.resize(csize + 1);
|
||||
dst[csize] = 0;
|
||||
int split = csize / 2;
|
||||
|
||||
for (int i = 0; i < csize; i++) {
|
||||
char32_t chr = ' ';
|
||||
|
||||
if (i < split) {
|
||||
if (i < sa.length()) {
|
||||
chr = sa[i];
|
||||
} else if (i < sb.length()) {
|
||||
chr = sb[i];
|
||||
}
|
||||
|
||||
} else {
|
||||
if (i < sb.length()) {
|
||||
chr = sb[i];
|
||||
} else if (i < sa.length()) {
|
||||
chr = sa[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[i] = chr;
|
||||
}
|
||||
|
||||
r_dst = dst;
|
||||
}
|
||||
return;
|
||||
case VECTOR2: {
|
||||
r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector2 *>(b._data._mem), c);
|
||||
}
|
||||
return;
|
||||
case VECTOR2I: {
|
||||
int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
|
||||
r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
|
||||
}
|
||||
return;
|
||||
|
||||
case RECT2: {
|
||||
r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c));
|
||||
}
|
||||
return;
|
||||
case RECT2I: {
|
||||
const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
|
||||
const Rect2i *rb = reinterpret_cast<const Rect2i *>(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 * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
|
||||
}
|
||||
return;
|
||||
|
||||
case VECTOR3: {
|
||||
r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector3 *>(b._data._mem), c);
|
||||
}
|
||||
return;
|
||||
case VECTOR3I: {
|
||||
int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
|
||||
int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
|
||||
int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
|
||||
int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
|
||||
int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
|
||||
int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
|
||||
r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
|
||||
}
|
||||
return;
|
||||
|
||||
case TRANSFORM2D: {
|
||||
r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c);
|
||||
}
|
||||
return;
|
||||
case PLANE: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case QUATERNION: {
|
||||
r_dst = reinterpret_cast<const Quaternion *>(a._data._mem)->slerp(*reinterpret_cast<const Quaternion *>(b._data._mem), c);
|
||||
}
|
||||
return;
|
||||
case AABB: {
|
||||
r_dst = ::AABB(a._data._aabb->position.lerp(b._data._aabb->position, c), a._data._aabb->size.lerp(b._data._aabb->size, c));
|
||||
}
|
||||
return;
|
||||
case BASIS: {
|
||||
r_dst = a._data._basis->lerp(*b._data._basis, c);
|
||||
}
|
||||
return;
|
||||
case TRANSFORM3D: {
|
||||
r_dst = a._data._transform3d->interpolate_with(*b._data._transform3d, c);
|
||||
}
|
||||
return;
|
||||
case COLOR: {
|
||||
r_dst = reinterpret_cast<const Color *>(a._data._mem)->lerp(*reinterpret_cast<const Color *>(b._data._mem), c);
|
||||
}
|
||||
return;
|
||||
case STRING_NAME: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case NODE_PATH: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case RID: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case OBJECT: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case DICTIONARY: {
|
||||
}
|
||||
return;
|
||||
case ARRAY: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case PACKED_BYTE_ARRAY: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case PACKED_INT32_ARRAY: {
|
||||
const Vector<int32_t> *arr_a = &PackedArrayRef<int32_t>::get_array(a._data.packed_array);
|
||||
const Vector<int32_t> *arr_b = &PackedArrayRef<int32_t>::get_array(b._data.packed_array);
|
||||
int32_t sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<int32_t> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
int32_t *vw = v.ptrw();
|
||||
const int32_t *ar = arr_a->ptr();
|
||||
const int32_t *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
Variant::interpolate(ar[i], br[i], c, va);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_INT64_ARRAY: {
|
||||
const Vector<int64_t> *arr_a = &PackedArrayRef<int64_t>::get_array(a._data.packed_array);
|
||||
const Vector<int64_t> *arr_b = &PackedArrayRef<int64_t>::get_array(b._data.packed_array);
|
||||
int64_t sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<int64_t> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
int64_t *vw = v.ptrw();
|
||||
const int64_t *ar = arr_a->ptr();
|
||||
const int64_t *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int64_t i = 0; i < sz; i++) {
|
||||
Variant::interpolate(ar[i], br[i], c, va);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_FLOAT32_ARRAY: {
|
||||
const Vector<float> *arr_a = &PackedArrayRef<float>::get_array(a._data.packed_array);
|
||||
const Vector<float> *arr_b = &PackedArrayRef<float>::get_array(b._data.packed_array);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<float> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
float *vw = v.ptrw();
|
||||
const float *ar = arr_a->ptr();
|
||||
const float *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int i = 0; i < sz; i++) {
|
||||
Variant::interpolate(ar[i], br[i], c, va);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_FLOAT64_ARRAY: {
|
||||
const Vector<double> *arr_a = &PackedArrayRef<double>::get_array(a._data.packed_array);
|
||||
const Vector<double> *arr_b = &PackedArrayRef<double>::get_array(b._data.packed_array);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<double> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
double *vw = v.ptrw();
|
||||
const double *ar = arr_a->ptr();
|
||||
const double *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int i = 0; i < sz; i++) {
|
||||
Variant::interpolate(ar[i], br[i], c, va);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_STRING_ARRAY: {
|
||||
r_dst = a;
|
||||
}
|
||||
return;
|
||||
case PACKED_VECTOR2_ARRAY: {
|
||||
const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array);
|
||||
const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<Vector2> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Vector2 *vw = v.ptrw();
|
||||
const Vector2 *ar = arr_a->ptr();
|
||||
const Vector2 *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_VECTOR3_ARRAY: {
|
||||
const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array);
|
||||
const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<Vector3> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Vector3 *vw = v.ptrw();
|
||||
const Vector3 *ar = arr_a->ptr();
|
||||
const Vector3 *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case PACKED_COLOR_ARRAY: {
|
||||
const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array);
|
||||
const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
r_dst = a;
|
||||
} else {
|
||||
Vector<Color> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Color *vw = v.ptrw();
|
||||
const Color *ar = arr_a->ptr();
|
||||
const Color *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
r_dst = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
default: {
|
||||
r_dst = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Variant::_register_variant_setters_getters() {
|
||||
register_named_setters_getters();
|
||||
register_indexed_setters_getters();
|
||||
|
|
|
@ -6050,10 +6050,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
real_t to_diff = fmod(b - a, Math_TAU);
|
||||
to_v = a + fmod(2.0 * to_diff, Math_TAU) - to_diff;
|
||||
}
|
||||
Variant delta_v;
|
||||
Variant::sub(to_v, from_v, delta_v);
|
||||
Variant delta_v = Animation::subtract_variant(to_v, from_v);
|
||||
double duration = to_t - from_t;
|
||||
double fixed_duration = duration - 0.01; // Prevent to overwrap keys...
|
||||
double fixed_duration = duration - UNIT_EPSILON; // Prevent to overwrap keys...
|
||||
for (double delta_t = dur_step; delta_t < fixed_duration; delta_t += dur_step) {
|
||||
Pair<real_t, Variant> keydata;
|
||||
keydata.first = from_t + delta_t;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1383,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) {
|
||||
|
@ -1703,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: {
|
||||
|
|
|
@ -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.
|
||||
|
@ -375,264 +376,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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -748,10 +499,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) {
|
||||
|
@ -973,7 +724,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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2317,9 +2317,7 @@ Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b,
|
|||
}
|
||||
|
||||
Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const {
|
||||
Variant dst;
|
||||
Variant::interpolate(p_a, p_b, p_c, dst);
|
||||
return dst;
|
||||
return interpolate_variant(p_a, p_b, p_c);
|
||||
}
|
||||
|
||||
real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const {
|
||||
|
@ -5563,6 +5561,466 @@ bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_in
|
|||
return false;
|
||||
}
|
||||
|
||||
// Helper math fuctions for Variant.
|
||||
Variant Animation::add_variant(const Variant &a, const Variant &b) {
|
||||
if (a.get_type() != b.get_type()) {
|
||||
return a;
|
||||
}
|
||||
|
||||
switch (a.get_type()) {
|
||||
case Variant::NIL: {
|
||||
return Variant();
|
||||
}
|
||||
case Variant::BOOL: {
|
||||
return (a.operator real_t()) + (b.operator real_t()); // It is cast for interpolation.
|
||||
}
|
||||
case Variant::RECT2: {
|
||||
const Rect2 ra = a.operator Rect2();
|
||||
const Rect2 rb = b.operator Rect2();
|
||||
return Rect2(ra.position + rb.position, ra.size + rb.size);
|
||||
}
|
||||
case Variant::RECT2I: {
|
||||
const Rect2i ra = a.operator Rect2i();
|
||||
const Rect2i rb = b.operator Rect2i();
|
||||
return Rect2i(ra.position + rb.position, ra.size + rb.size);
|
||||
}
|
||||
case Variant::PLANE: {
|
||||
const Plane pa = a.operator Plane();
|
||||
const Plane pb = b.operator Plane();
|
||||
return Plane(pa.normal + pb.normal, pa.d + pb.d);
|
||||
}
|
||||
case Variant::AABB: {
|
||||
const ::AABB aa = a.operator ::AABB();
|
||||
const ::AABB ab = b.operator ::AABB();
|
||||
return ::AABB(aa.position + ab.position, aa.size + ab.size);
|
||||
}
|
||||
case Variant::QUATERNION: {
|
||||
return (a.operator Quaternion()) * (b.operator Quaternion());
|
||||
}
|
||||
case Variant::TRANSFORM2D: {
|
||||
return (a.operator Transform2D()) * (b.operator Transform2D());
|
||||
}
|
||||
case Variant::TRANSFORM3D: {
|
||||
return (a.operator Transform3D()) * (b.operator Transform3D());
|
||||
}
|
||||
default: {
|
||||
return Variant::evaluate(Variant::OP_ADD, a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variant Animation::subtract_variant(const Variant &a, const Variant &b) {
|
||||
if (a.get_type() != b.get_type()) {
|
||||
return a;
|
||||
}
|
||||
|
||||
switch (a.get_type()) {
|
||||
case Variant::NIL: {
|
||||
return Variant();
|
||||
}
|
||||
case Variant::BOOL: {
|
||||
return (a.operator real_t()) - (b.operator real_t()); // It is cast for interpolation.
|
||||
}
|
||||
case Variant::RECT2: {
|
||||
const Rect2 ra = a.operator Rect2();
|
||||
const Rect2 rb = b.operator Rect2();
|
||||
return Rect2(ra.position - rb.position, ra.size - rb.size);
|
||||
}
|
||||
case Variant::RECT2I: {
|
||||
const Rect2i ra = a.operator Rect2i();
|
||||
const Rect2i rb = b.operator Rect2i();
|
||||
return Rect2i(ra.position - rb.position, ra.size - rb.size);
|
||||
}
|
||||
case Variant::PLANE: {
|
||||
const Plane pa = a.operator Plane();
|
||||
const Plane pb = b.operator Plane();
|
||||
return Plane(pa.normal - pb.normal, pa.d - pb.d);
|
||||
}
|
||||
case Variant::AABB: {
|
||||
const ::AABB aa = a.operator ::AABB();
|
||||
const ::AABB ab = b.operator ::AABB();
|
||||
return ::AABB(aa.position - ab.position, aa.size - ab.size);
|
||||
}
|
||||
case Variant::QUATERNION: {
|
||||
return (b.operator Quaternion()).inverse() * (a.operator Quaternion());
|
||||
}
|
||||
case Variant::TRANSFORM2D: {
|
||||
return (b.operator Transform2D()).inverse() * (a.operator Transform2D());
|
||||
}
|
||||
case Variant::TRANSFORM3D: {
|
||||
return (b.operator Transform3D()).inverse() * (a.operator Transform3D());
|
||||
}
|
||||
default: {
|
||||
return Variant::evaluate(Variant::OP_SUBTRACT, a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variant Animation::blend_variant(const Variant &a, const Variant &b, float c) {
|
||||
if (a.get_type() != b.get_type()) {
|
||||
if (a.is_num() && b.is_num()) {
|
||||
real_t va = a;
|
||||
real_t vb = b;
|
||||
return va + vb * c;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
switch (a.get_type()) {
|
||||
case Variant::NIL: {
|
||||
return Variant();
|
||||
}
|
||||
case Variant::INT: {
|
||||
return int((a.operator int64_t()) + (b.operator int64_t()) * c + 0.5);
|
||||
}
|
||||
case Variant::FLOAT: {
|
||||
return (a.operator double()) + (b.operator double()) * c;
|
||||
}
|
||||
case Variant::VECTOR2: {
|
||||
return (a.operator Vector2()) + (b.operator Vector2()) * c;
|
||||
}
|
||||
case Variant::VECTOR2I: {
|
||||
const Vector2i va = a.operator Vector2i();
|
||||
const Vector2i vb = b.operator Vector2i();
|
||||
return Vector2i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5));
|
||||
}
|
||||
case Variant::RECT2: {
|
||||
const Rect2 ra = a.operator Rect2();
|
||||
const Rect2 rb = b.operator Rect2();
|
||||
return Rect2(ra.position + rb.position * c, ra.size + rb.size * c);
|
||||
}
|
||||
case Variant::RECT2I: {
|
||||
const Rect2i ra = a.operator Rect2i();
|
||||
const Rect2i rb = b.operator Rect2i();
|
||||
return Rect2i(int32_t(ra.position.x + rb.position.x * c + 0.5), int32_t(ra.position.y + rb.position.y * c + 0.5), int32_t(ra.size.x + rb.size.x * c + 0.5), int32_t(ra.size.y + rb.size.y * c + 0.5));
|
||||
}
|
||||
case Variant::VECTOR3: {
|
||||
return (a.operator Vector3()) + (b.operator Vector3()) * c;
|
||||
}
|
||||
case Variant::VECTOR3I: {
|
||||
const Vector3i va = a.operator Vector3i();
|
||||
const Vector3i vb = b.operator Vector3i();
|
||||
return Vector3i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5));
|
||||
}
|
||||
case Variant::VECTOR4: {
|
||||
return (a.operator Vector4()) + (b.operator Vector4()) * c;
|
||||
}
|
||||
case Variant::VECTOR4I: {
|
||||
const Vector4i va = a.operator Vector4i();
|
||||
const Vector4i vb = b.operator Vector4i();
|
||||
return Vector4i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5), int32_t(va.w + vb.w * c + 0.5));
|
||||
}
|
||||
case Variant::PLANE: {
|
||||
const Plane pa = a.operator Plane();
|
||||
const Plane pb = b.operator Plane();
|
||||
return Plane(pa.normal + pb.normal * c, pa.d + pb.d * c);
|
||||
}
|
||||
case Variant::COLOR: {
|
||||
return (a.operator Color()) + (b.operator Color()) * c;
|
||||
}
|
||||
case Variant::AABB: {
|
||||
const ::AABB aa = a.operator ::AABB();
|
||||
const ::AABB ab = b.operator ::AABB();
|
||||
return ::AABB(aa.position + ab.position * c, aa.size + ab.size * c);
|
||||
}
|
||||
case Variant::BASIS: {
|
||||
return (a.operator Basis()) + (b.operator Basis()) * c;
|
||||
}
|
||||
case Variant::QUATERNION: {
|
||||
return (a.operator Quaternion()) * Quaternion().slerp((b.operator Quaternion()), c);
|
||||
}
|
||||
case Variant::TRANSFORM2D: {
|
||||
return (a.operator Transform2D()) * Transform2D().interpolate_with((b.operator Transform2D()), c);
|
||||
}
|
||||
case Variant::TRANSFORM3D: {
|
||||
return (a.operator Transform3D()) * Transform3D().interpolate_with((b.operator Transform3D()), c);
|
||||
}
|
||||
default: {
|
||||
return c < 0.5 ? a : b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float c) {
|
||||
if (a.get_type() != b.get_type()) {
|
||||
if (a.is_num() && b.is_num()) {
|
||||
real_t va = a;
|
||||
real_t vb = b;
|
||||
return va + (vb - va) * c;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
switch (a.get_type()) {
|
||||
case Variant::NIL: {
|
||||
return Variant();
|
||||
}
|
||||
case Variant::INT: {
|
||||
const int64_t va = a.operator int64_t();
|
||||
return int(va + ((b.operator int64_t()) - va) * c);
|
||||
}
|
||||
case Variant::FLOAT: {
|
||||
const real_t va = a.operator real_t();
|
||||
return va + ((b.operator real_t()) - va) * c;
|
||||
}
|
||||
case Variant::VECTOR2: {
|
||||
return (a.operator Vector2()).lerp(b.operator Vector2(), c);
|
||||
}
|
||||
case Variant::VECTOR2I: {
|
||||
const Vector2i va = a.operator Vector2i();
|
||||
const Vector2i vb = b.operator Vector2i();
|
||||
return Vector2i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c));
|
||||
}
|
||||
case Variant::RECT2: {
|
||||
const Rect2 ra = a.operator Rect2();
|
||||
const Rect2 rb = b.operator Rect2();
|
||||
return Rect2(ra.position.lerp(rb.position, c), ra.size.lerp(rb.size, c));
|
||||
}
|
||||
case Variant::RECT2I: {
|
||||
const Rect2i ra = a.operator Rect2i();
|
||||
const Rect2i rb = b.operator Rect2i();
|
||||
return Rect2i(int32_t(ra.position.x + (rb.position.x - ra.position.x) * c), int32_t(ra.position.y + (rb.position.y - ra.position.y) * c), int32_t(ra.size.x + (rb.size.x - ra.size.x) * c), int32_t(ra.size.y + (rb.size.y - ra.size.y) * c));
|
||||
}
|
||||
case Variant::VECTOR3: {
|
||||
return (a.operator Vector3()).lerp(b.operator Vector3(), c);
|
||||
}
|
||||
case Variant::VECTOR3I: {
|
||||
const Vector3i va = a.operator Vector3i();
|
||||
const Vector3i vb = b.operator Vector3i();
|
||||
return Vector3i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c));
|
||||
}
|
||||
case Variant::VECTOR4: {
|
||||
return (a.operator Vector4()).lerp(b.operator Vector4(), c);
|
||||
}
|
||||
case Variant::VECTOR4I: {
|
||||
const Vector4i va = a.operator Vector4i();
|
||||
const Vector4i vb = b.operator Vector4i();
|
||||
return Vector4i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c), int32_t(va.w + (vb.w - va.w) * c));
|
||||
}
|
||||
case Variant::PLANE: {
|
||||
const Plane pa = a.operator Plane();
|
||||
const Plane pb = b.operator Plane();
|
||||
return Plane(pa.normal.lerp(pb.normal, c), pa.d + (pb.d - pa.d) * c);
|
||||
}
|
||||
case Variant::COLOR: {
|
||||
return (a.operator Color()).lerp(b.operator Color(), c);
|
||||
}
|
||||
case Variant::AABB: {
|
||||
const ::AABB aa = a.operator ::AABB();
|
||||
const ::AABB ab = b.operator ::AABB();
|
||||
return ::AABB(aa.position.lerp(ab.position, c), aa.size.lerp(ab.size, c));
|
||||
}
|
||||
case Variant::BASIS: {
|
||||
return (a.operator Basis()).lerp(b.operator Basis(), c);
|
||||
}
|
||||
case Variant::QUATERNION: {
|
||||
return (a.operator Quaternion()).slerp(b.operator Quaternion(), c);
|
||||
}
|
||||
case Variant::TRANSFORM2D: {
|
||||
return (a.operator Transform2D()).interpolate_with(b.operator Transform2D(), c);
|
||||
}
|
||||
case Variant::TRANSFORM3D: {
|
||||
return (a.operator Transform3D()).interpolate_with(b.operator Transform3D(), c);
|
||||
}
|
||||
case Variant::STRING: {
|
||||
// This is pretty funny and bizarre, but artists like to use it for typewriter effects.
|
||||
const String sa = a.operator String();
|
||||
const String sb = b.operator String();
|
||||
String dst;
|
||||
int sa_len = sa.length();
|
||||
int sb_len = sb.length();
|
||||
int csize = sa_len + (sb_len - sa_len) * c;
|
||||
if (csize == 0) {
|
||||
return "";
|
||||
}
|
||||
dst.resize(csize + 1);
|
||||
dst[csize] = 0;
|
||||
int split = csize / 2;
|
||||
|
||||
for (int i = 0; i < csize; i++) {
|
||||
char32_t chr = ' ';
|
||||
|
||||
if (i < split) {
|
||||
if (i < sa.length()) {
|
||||
chr = sa[i];
|
||||
} else if (i < sb.length()) {
|
||||
chr = sb[i];
|
||||
}
|
||||
|
||||
} else {
|
||||
if (i < sb.length()) {
|
||||
chr = sb[i];
|
||||
} else if (i < sa.length()) {
|
||||
chr = sa[i];
|
||||
}
|
||||
}
|
||||
|
||||
dst[i] = chr;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
case Variant::PACKED_INT32_ARRAY: {
|
||||
const Vector<int32_t> *arr_a = Object::cast_to<Vector<int32_t>>(a);
|
||||
const Vector<int32_t> *arr_b = Object::cast_to<Vector<int32_t>>(b);
|
||||
int32_t sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<int32_t> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
int32_t *vw = v.ptrw();
|
||||
const int32_t *ar = arr_a->ptr();
|
||||
const int32_t *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
va = interpolate_variant(ar[i], br[i], c);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_INT64_ARRAY: {
|
||||
const Vector<int64_t> *arr_a = Object::cast_to<Vector<int64_t>>(a);
|
||||
const Vector<int64_t> *arr_b = Object::cast_to<Vector<int64_t>>(b);
|
||||
int64_t sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<int64_t> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
int64_t *vw = v.ptrw();
|
||||
const int64_t *ar = arr_a->ptr();
|
||||
const int64_t *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int64_t i = 0; i < sz; i++) {
|
||||
va = interpolate_variant(ar[i], br[i], c);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_FLOAT32_ARRAY: {
|
||||
const Vector<float> *arr_a = Object::cast_to<Vector<float>>(a);
|
||||
const Vector<float> *arr_b = Object::cast_to<Vector<float>>(b);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<float> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
float *vw = v.ptrw();
|
||||
const float *ar = arr_a->ptr();
|
||||
const float *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int i = 0; i < sz; i++) {
|
||||
va = interpolate_variant(ar[i], br[i], c);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_FLOAT64_ARRAY: {
|
||||
const Vector<double> *arr_a = Object::cast_to<Vector<double>>(a);
|
||||
const Vector<double> *arr_b = Object::cast_to<Vector<double>>(b);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<double> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
double *vw = v.ptrw();
|
||||
const double *ar = arr_a->ptr();
|
||||
const double *br = arr_b->ptr();
|
||||
|
||||
Variant va;
|
||||
for (int i = 0; i < sz; i++) {
|
||||
va = interpolate_variant(ar[i], br[i], c);
|
||||
vw[i] = va;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_VECTOR2_ARRAY: {
|
||||
const Vector<Vector2> *arr_a = Object::cast_to<Vector<Vector2>>(a);
|
||||
const Vector<Vector2> *arr_b = Object::cast_to<Vector<Vector2>>(b);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<Vector2> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Vector2 *vw = v.ptrw();
|
||||
const Vector2 *ar = arr_a->ptr();
|
||||
const Vector2 *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_VECTOR3_ARRAY: {
|
||||
const Vector<Vector3> *arr_a = Object::cast_to<Vector<Vector3>>(a);
|
||||
const Vector<Vector3> *arr_b = Object::cast_to<Vector<Vector3>>(b);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<Vector3> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Vector3 *vw = v.ptrw();
|
||||
const Vector3 *ar = arr_a->ptr();
|
||||
const Vector3 *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_COLOR_ARRAY: {
|
||||
const Vector<Color> *arr_a = Object::cast_to<Vector<Color>>(a);
|
||||
const Vector<Color> *arr_b = Object::cast_to<Vector<Color>>(b);
|
||||
int sz = arr_a->size();
|
||||
if (sz == 0 || arr_b->size() != sz) {
|
||||
return a;
|
||||
} else {
|
||||
Vector<Color> v;
|
||||
v.resize(sz);
|
||||
{
|
||||
Color *vw = v.ptrw();
|
||||
const Color *ar = arr_a->ptr();
|
||||
const Color *br = arr_b->ptr();
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
vw[i] = ar[i].lerp(br[i], c);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return c < 0.5 ? a : b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Animation::Animation() {}
|
||||
|
||||
Animation::~Animation() {
|
||||
|
|
|
@ -496,6 +496,12 @@ public:
|
|||
void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3);
|
||||
void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests
|
||||
|
||||
// Helper math fuctions for Variant.
|
||||
static Variant add_variant(const Variant &a, const Variant &b);
|
||||
static Variant subtract_variant(const Variant &a, const Variant &b);
|
||||
static Variant blend_variant(const Variant &a, const Variant &b, float c);
|
||||
static Variant interpolate_variant(const Variant &a, const Variant &b, float c);
|
||||
|
||||
Animation();
|
||||
~Animation();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue