Skip to content

Document list of types supported by Tween and Animation interpolation #107972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Calinou
Copy link
Member

@Calinou Calinou commented Jun 25, 2025

Interpolation uses this method behind the scenes:

Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float c, bool p_snap_array_element) {
if (a.get_type() != b.get_type()) {
if (a.is_num() && b.is_num()) {
return interpolate_variant(cast_to_blendwise(a), cast_to_blendwise(b), c);
} else if (!a.is_array()) {
return a;
}
}
switch (a.get_type()) {
case Variant::NIL: {
return Variant();
} break;
case Variant::FLOAT: {
return Math::lerp(a.operator double(), b.operator double(), (double)c);
} break;
case Variant::VECTOR2: {
return (a.operator Vector2()).lerp(b.operator Vector2(), c);
} break;
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));
} break;
case Variant::VECTOR3: {
return (a.operator Vector3()).lerp(b.operator Vector3(), c);
} break;
case Variant::VECTOR4: {
return (a.operator Vector4()).lerp(b.operator Vector4(), c);
} break;
case Variant::PLANE: {
const Plane pa = a.operator Plane();
const Plane pb = b.operator Plane();
return Plane(pa.normal.lerp(pb.normal, c), Math::lerp((double)pa.d, (double)pb.d, (double)c));
} break;
case Variant::COLOR: {
return (a.operator Color()).lerp(b.operator Color(), c);
} break;
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));
} break;
case Variant::BASIS: {
return (a.operator Basis()).lerp(b.operator Basis(), c);
} break;
case Variant::QUATERNION: {
return (a.operator Quaternion()).slerp(b.operator Quaternion(), c);
} break;
case Variant::TRANSFORM2D: {
return (a.operator Transform2D()).interpolate_with(b.operator Transform2D(), c);
} break;
case Variant::TRANSFORM3D: {
return (a.operator Transform3D()).interpolate_with(b.operator Transform3D(), c);
} break;
case Variant::BOOL:
case Variant::INT:
case Variant::RECT2I:
case Variant::VECTOR2I:
case Variant::VECTOR3I:
case Variant::VECTOR4I:
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY: {
// Fallback the interpolatable value which needs casting.
return cast_from_blendwise(interpolate_variant(cast_to_blendwise(a), cast_to_blendwise(b), c), a.get_type());
} break;
case Variant::STRING:
case Variant::STRING_NAME: {
Array arr_a = cast_to_blendwise(a);
Array arr_b = cast_to_blendwise(b);
int min_size = arr_a.size();
int max_size = arr_b.size();
bool is_a_larger = inform_variant_array(min_size, max_size);
int mid_size = interpolate_variant(arr_a.size(), arr_b.size(), c);
if (is_a_larger) {
arr_a.resize(mid_size);
} else {
arr_b.resize(mid_size);
}
return cast_from_blendwise(interpolate_variant(arr_a, arr_b, c, true), a.get_type());
} break;
case Variant::PACKED_BYTE_ARRAY: {
// Skip.
} break;
default: {
if (a.is_array()) {
const Array arr_a = a.operator Array();
const Array arr_b = b.operator Array();
int min_size = arr_a.size();
int max_size = arr_b.size();
bool is_a_larger = inform_variant_array(min_size, max_size);
Array result;
result.set_typed(MAX(arr_a.get_typed_builtin(), arr_b.get_typed_builtin()), StringName(), Variant());
result.resize(min_size);
int i = 0;
for (; i < min_size; i++) {
result[i] = interpolate_variant(arr_a[i], arr_b[i], c);
}
if (min_size != max_size) {
// Process with last element of the lesser array.
// This is pretty funny and bizarre, but artists like to use it for polygon animation.
Variant lesser_last;
if (is_a_larger && !Math::is_equal_approx(c, 1.0f)) {
result.resize(max_size);
if (p_snap_array_element) {
c = 0;
}
if (i > 0) {
lesser_last = arr_b[i - 1];
} else {
Variant vz = arr_a[i];
vz.zero();
lesser_last = vz;
}
for (; i < max_size; i++) {
result[i] = interpolate_variant(arr_a[i], lesser_last, c);
}
} else if (!is_a_larger && !Math::is_zero_approx(c)) {
result.resize(max_size);
if (p_snap_array_element) {
c = 1;
}
if (i > 0) {
lesser_last = arr_a[i - 1];
} else {
Variant vz = arr_b[i];
vz.zero();
lesser_last = vz;
}
for (; i < max_size; i++) {
result[i] = interpolate_variant(lesser_last, arr_b[i], c);
}
}
}
return result;
}
} break;
}
return c < 0.5 ? a : b;
}

@Calinou Calinou added this to the 4.5 milestone Jun 25, 2025
@Calinou Calinou requested a review from a team as a code owner June 25, 2025 12:27
@Calinou Calinou added enhancement documentation cherrypick:4.4 Considered for cherry-picking into a future 4.4.x release labels Jun 25, 2025
@Calinou Calinou force-pushed the doc-tween-supported-interpolation-types branch from 81e2a55 to ede4497 Compare June 26, 2025 13:48
Copy link
Member

@Mickeon Mickeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these should be three separate lines, and the additional remarks on both strings and arrays sound like notes, but I have no suggestions at the moment.

@Calinou Calinou force-pushed the doc-tween-supported-interpolation-types branch from ede4497 to 1c75290 Compare June 26, 2025 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cherrypick:4.4 Considered for cherry-picking into a future 4.4.x release documentation enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants