diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/animation.cpp | 464 | ||||
-rw-r--r-- | scene/resources/animation.h | 6 | ||||
-rw-r--r-- | scene/resources/material.cpp | 30 | ||||
-rw-r--r-- | scene/resources/material.h | 11 |
4 files changed, 483 insertions, 28 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() { diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 46a88df130..112a6c28aa 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -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(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e47bfef576..c1e30dd93c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -257,23 +257,25 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { groups[last_group][last_subgroup].push_back(info); } - // Sort groups alphabetically. - List<UniformProp> props; + List<String> group_names; for (HashMap<String, HashMap<String, List<PropertyInfo>>>::Iterator group = groups.begin(); group; ++group) { - for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = group->value.begin(); subgroup; ++subgroup) { - for (List<PropertyInfo>::Element *item = subgroup->value.front(); item; item = item->next()) { - if (subgroup->key == "<None>") { - props.push_back({ group->key, item->get() }); - } else { - props.push_back({ group->key + "::" + subgroup->key, item->get() }); - } - } - } + group_names.push_back(group->key); } - props.sort_custom<UniformPropComparator>(); + group_names.sort(); - for (List<UniformProp>::Element *E = props.front(); E; E = E->next()) { - p_list->push_back(E->get().info); + for (const String &group_name : group_names) { + List<String> subgroup_names; + HashMap<String, List<PropertyInfo>> &subgroups = groups[group_name]; + for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = subgroups.begin(); subgroup; ++subgroup) { + subgroup_names.push_back(subgroup->key); + } + subgroup_names.sort(); + for (const String &subgroup_name : subgroup_names) { + List<PropertyInfo> &prop_infos = subgroups[subgroup_name]; + for (List<PropertyInfo>::Element *item = prop_infos.front(); item; item = item->next()) { + p_list->push_back(item->get()); + } + } } } } diff --git a/scene/resources/material.h b/scene/resources/material.h index 6c81293ee3..dd9589c577 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -84,17 +84,6 @@ class ShaderMaterial : public Material { HashMap<StringName, Variant> param_cache; - struct UniformProp { - String str; - PropertyInfo info; - }; - - struct UniformPropComparator { - bool operator()(const UniformProp &p_a, const UniformProp &p_b) const { - return p_a.str.naturalnocasecmp_to(p_b.str) < 0; - } - }; - protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; |