diff options
Diffstat (limited to 'scene/resources/animation.cpp')
| -rw-r--r-- | scene/resources/animation.cpp | 464 | 
1 files changed, 461 insertions, 3 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 9d5bc18c96..4f16f75389 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -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() {  |