diff options
Diffstat (limited to 'scene/resources')
26 files changed, 722 insertions, 209 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 9d5bc18c96..f2ac1c2e58 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2102,11 +2102,9 @@ bool Animation::track_is_compressed(int p_track) const { return bst->compressed_track >= 0; } break; default: { - return false; //animation does not really use transitions + return false; // Animation does not really use transitions. } break; } - - ERR_FAIL_V(false); } void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p_value) { @@ -2317,9 +2315,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 +5559,466 @@ bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_in return false; } +// Helper math functions 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..49c8fa4c22 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 functions 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/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index a87c8272ea..26204583ef 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -33,7 +33,7 @@ #include "core/io/file_access.h" #include "core/io/marshalls.h" -void AudioStreamPlaybackWAV::start(float p_from_pos) { +void AudioStreamPlaybackWAV::start(double p_from_pos) { if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) { //no seeking in IMA_ADPCM for (int i = 0; i < 2; i++) { @@ -67,16 +67,16 @@ int AudioStreamPlaybackWAV::get_loop_count() const { return 0; } -float AudioStreamPlaybackWAV::get_playback_position() const { +double AudioStreamPlaybackWAV::get_playback_position() const { return float(offset >> MIX_FRAC_BITS) / base->mix_rate; } -void AudioStreamPlaybackWAV::seek(float p_time) { +void AudioStreamPlaybackWAV::seek(double p_time) { if (base->format == AudioStreamWAV::FORMAT_IMA_ADPCM) { return; //no seeking in ima-adpcm } - float max = base->get_length(); + double max = base->get_length(); if (p_time < 0) { p_time = 0; } else if (p_time >= max) { @@ -180,7 +180,7 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, final_r = p_src[pos + 1]; } - if (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ + if constexpr (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ final <<= 8; if (is_stereo) { final_r <<= 8; @@ -194,7 +194,7 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, next = p_src[pos + 1]; } - if (sizeof(Depth) == 1) { + if constexpr (sizeof(Depth) == 1) { next <<= 8; if (is_stereo) { next_r <<= 8; @@ -463,7 +463,7 @@ bool AudioStreamWAV::is_stereo() const { return stereo; } -float AudioStreamWAV::get_length() const { +double AudioStreamWAV::get_length() const { int len = data_bytes; switch (format) { case AudioStreamWAV::FORMAT_8_BITS: @@ -481,7 +481,7 @@ float AudioStreamWAV::get_length() const { len /= 2; } - return float(len) / mix_rate; + return double(len) / mix_rate; } bool AudioStreamWAV::is_monophonic() const { diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h index d800388d96..d0edc52031 100644 --- a/scene/resources/audio_stream_wav.h +++ b/scene/resources/audio_stream_wav.h @@ -64,14 +64,14 @@ class AudioStreamPlaybackWAV : public AudioStreamPlayback { void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm); public: - virtual void start(float p_from_pos = 0.0) override; + virtual void start(double p_from_pos = 0.0) override; virtual void stop() override; virtual bool is_playing() const override; virtual int get_loop_count() const override; //times it looped - virtual float get_playback_position() const override; - virtual void seek(float p_time) override; + virtual double get_playback_position() const override; + virtual void seek(double p_time) override; virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; @@ -137,7 +137,7 @@ public: void set_stereo(bool p_enable); bool is_stereo() const; - virtual float get_length() const override; //if supported, otherwise return 0 + virtual double get_length() const override; //if supported, otherwise return 0 virtual bool is_monophonic() const override; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 869d582935..f03e3813cc 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -43,6 +43,8 @@ #include "modules/svg/image_loader_svg.h" #endif +static const int default_font_size = 16; + static float scale = 1.0; static const int default_margin = 4; diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 003934ce90..5243bcefa7 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -33,8 +33,6 @@ #include "scene/resources/theme.h" -const int default_font_size = 16; - void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); diff --git a/scene/resources/fog_material.cpp b/scene/resources/fog_material.cpp index 0395ed0346..46b44d681f 100644 --- a/scene/resources/fog_material.cpp +++ b/scene/resources/fog_material.cpp @@ -122,7 +122,7 @@ void FogMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_density_texture", "density_texture"), &FogMaterial::set_density_texture); ClassDB::bind_method(D_METHOD("get_density_texture"), &FogMaterial::get_density_texture); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "density", PROPERTY_HINT_RANGE, "0.0,16.0,0.0001,or_greater,or_less"), "set_density", "get_density"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "density", PROPERTY_HINT_RANGE, "-8.0,8.0,0.0001,or_greater,or_less"), "set_density", "get_density"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo", PROPERTY_HINT_COLOR_NO_ALPHA), "set_albedo", "get_albedo"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height_falloff", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_height_falloff", "get_height_falloff"); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 189d8d5502..6a278f1f39 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -127,16 +127,18 @@ void Font::_invalidate_rids() { } bool Font::_is_cyclic(const Ref<Font> &p_f, int p_depth) const { - ERR_FAIL_COND_V(p_depth > MAX_FALLBACK_DEPTH, false); + ERR_FAIL_COND_V(p_depth > MAX_FALLBACK_DEPTH, true); if (p_f.is_null()) { return false; } + if (p_f == this) { + return true; + } for (int i = 0; i < p_f->fallbacks.size(); i++) { const Ref<Font> &f = p_f->fallbacks[i]; - if (f == this) { + if (_is_cyclic(f, p_depth + 1)) { return true; } - return _is_cyclic(f, p_depth + 1); } return false; } @@ -147,7 +149,10 @@ void Font::reset_state() { // Fallbacks. void Font::set_fallbacks(const TypedArray<Font> &p_fallbacks) { - ERR_FAIL_COND(_is_cyclic(this, 0)); + for (int i = 0; i < p_fallbacks.size(); i++) { + const Ref<Font> &f = p_fallbacks[i]; + ERR_FAIL_COND_MSG(_is_cyclic(f, 0), "Cyclic font fallback."); + } for (int i = 0; i < fallbacks.size(); i++) { Ref<Font> f = fallbacks[i]; if (f.is_valid()) { @@ -259,7 +264,7 @@ Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignmen hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); } hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -272,13 +277,15 @@ Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignmen buffer->set_direction(p_direction); buffer->set_orientation(p_orientation); buffer->add_string(p_text, Ref<Font>(this), p_font_size); - if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - buffer->set_horizontal_alignment(p_alignment); - buffer->set_width(p_width); - buffer->set_flags(p_jst_flags); - } cache.insert(hash, buffer); } + + buffer->set_width(p_width); + buffer->set_horizontal_alignment(p_alignment); + if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { + buffer->set_flags(p_jst_flags); + } + return buffer->get_size(); } @@ -286,8 +293,8 @@ Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -316,7 +323,7 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); } hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -352,8 +359,8 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -389,7 +396,7 @@ void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const Str hash = hash_djb2_one_64(p_font_size, hash); if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); } hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -425,8 +432,8 @@ void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, uint64_t hash = p_text.hash64(); hash = hash_djb2_one_64(p_font_size, hash); hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator uint32_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator uint32_t(), hash); + hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); + hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); hash = hash_djb2_one_64(p_direction, hash); hash = hash_djb2_one_64(p_orientation, hash); @@ -554,7 +561,6 @@ Font::Font() { } Font::~Font() { - reset_state(); } /*************************************************************************/ @@ -2433,11 +2439,10 @@ int32_t FontFile::get_glyph_index(int p_size, char32_t p_char, char32_t p_variat } FontFile::FontFile() { - /* NOP */ } FontFile::~FontFile() { - reset_state(); + _clear_cache(); } /*************************************************************************/ @@ -2688,7 +2693,6 @@ FontVariation::FontVariation() { } FontVariation::~FontVariation() { - reset_state(); } /*************************************************************************/ @@ -3081,5 +3085,4 @@ SystemFont::SystemFont() { } SystemFont::~SystemFont() { - reset_state(); } diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 0afca95de0..de3d502102 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -254,7 +254,20 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma mesh.unref(); } -void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle) { +#define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \ + Vector3 transformed_vert = Vector3(); \ + for (unsigned int weight_idx = 0; weight_idx < bone_count; weight_idx++) { \ + int bone_idx = bone_array[vert_idx * bone_count + weight_idx]; \ + float w = weight_array[vert_idx * bone_count + weight_idx]; \ + if (w < FLT_EPSILON) { \ + continue; \ + } \ + ERR_FAIL_INDEX(bone_idx, static_cast<int>(transform_array.size())); \ + transformed_vert += transform_array[bone_idx].xform(read_array[vert_idx]) * w; \ + } \ + write_array[vert_idx] = transformed_vert; + +void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_bone_transform_array) { if (!SurfaceTool::simplify_scale_func) { return; } @@ -265,6 +278,12 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli return; } + LocalVector<Transform3D> bone_transform_vector; + for (int i = 0; i < p_bone_transform_array.size(); i++) { + ERR_FAIL_COND(p_bone_transform_array[i].get_type() != Variant::TRANSFORM3D); + bone_transform_vector.push_back(p_bone_transform_array[i]); + } + for (int i = 0; i < surfaces.size(); i++) { if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { continue; @@ -276,6 +295,8 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli Vector<Vector3> normals = surfaces[i].arrays[RS::ARRAY_NORMAL]; Vector<Vector2> uvs = surfaces[i].arrays[RS::ARRAY_TEX_UV]; Vector<Vector2> uv2s = surfaces[i].arrays[RS::ARRAY_TEX_UV2]; + Vector<int> bones = surfaces[i].arrays[RS::ARRAY_BONES]; + Vector<float> weights = surfaces[i].arrays[RS::ARRAY_WEIGHTS]; unsigned int index_count = indices.size(); unsigned int vertex_count = vertices.size(); @@ -301,6 +322,22 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } + if (bones.size() > 0 && weights.size() && bone_transform_vector.size() > 0) { + Vector3 *vertices_ptrw = vertices.ptrw(); + + // Apply bone transforms to regular surface. + unsigned int bone_weight_length = surfaces[i].flags & Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS ? 8 : 4; + + const int *bo = bones.ptr(); + const float *we = weights.ptr(); + + for (unsigned int j = 0; j < vertex_count; j++) { + VERTEX_SKIN_FUNC(bone_weight_length, j, vertices_ptr, vertices_ptrw, bone_transform_vector, bo, we) + } + + vertices_ptr = vertices.ptr(); + } + float normal_merge_threshold = Math::cos(Math::deg_to_rad(p_normal_merge_angle)); float normal_pre_split_threshold = Math::cos(Math::deg_to_rad(MIN(180.0f, p_normal_split_angle * 2.0f))); float normal_split_threshold = Math::cos(Math::deg_to_rad(p_normal_split_angle)); @@ -1246,7 +1283,7 @@ void ImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &ImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &ImporterMesh::set_surface_material); - ClassDB::bind_method(D_METHOD("generate_lods", "normal_merge_angle", "normal_split_angle"), &ImporterMesh::generate_lods); + ClassDB::bind_method(D_METHOD("generate_lods", "normal_merge_angle", "normal_split_angle", "bone_transform_array"), &ImporterMesh::generate_lods); ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &ImporterMesh::get_mesh, DEFVAL(Ref<ArrayMesh>())); ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear); diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h index dce2638c19..088a77edd1 100644 --- a/scene/resources/importer_mesh.h +++ b/scene/resources/importer_mesh.h @@ -112,7 +112,7 @@ public: void set_surface_material(int p_surface, const Ref<Material> &p_material); - void generate_lods(float p_normal_merge_angle, float p_normal_split_angle); + void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array); void create_shadow_mesh(); Ref<ImporterMesh> get_shadow_mesh() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 448ff74a53..838927e34f 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -156,17 +156,7 @@ Material::~Material() { bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { if (shader.is_valid()) { - StringName pr = shader->remap_uniform(p_name); - if (!pr) { - String n = p_name; - if (n.find("shader_parameter/") == 0) { //backwards compatibility - pr = n.replace_first("shader_parameter/", ""); - } else if (n.find("shader_uniform/") == 0) { //backwards compatibility - pr = n.replace_first("shader_uniform/", ""); - } else if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - } + StringName pr = shader->remap_parameter(p_name); if (pr) { set_shader_parameter(pr, p_value); return true; @@ -178,25 +168,9 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { if (shader.is_valid()) { - StringName pr = shader->remap_uniform(p_name); - if (!pr) { - String n = p_name; - if (n.find("shader_parameter/") == 0) { //backwards compatibility - pr = n.replace_first("shader_parameter/", ""); - } else if (n.find("shader_uniform/") == 0) { //backwards compatibility - pr = n.replace_first("shader_uniform/", ""); - } else if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - } - + StringName pr = shader->remap_parameter(p_name); if (pr) { - HashMap<StringName, Variant>::ConstIterator E = param_cache.find(pr); - if (E) { - r_ret = E->value; - } else { - r_ret = Variant(); - } + r_ret = get_shader_parameter(pr); return true; } } @@ -238,6 +212,7 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { PropertyInfo info; info.usage = PROPERTY_USAGE_GROUP; info.name = last_group.capitalize(); + info.hint_string = "shader_parameter/"; List<PropertyInfo> none_subgroup; none_subgroup.push_back(info); @@ -252,6 +227,7 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { PropertyInfo info; info.usage = PROPERTY_USAGE_SUBGROUP; info.name = last_subgroup.capitalize(); + info.hint_string = "shader_parameter/"; List<PropertyInfo> subgroup; subgroup.push_back(info); @@ -271,39 +247,42 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { PropertyInfo info; info.usage = PROPERTY_USAGE_GROUP; - info.name = "Shader Param"; + info.name = "Shader Parameters"; + info.hint_string = "shader_parameter/"; groups["<None>"]["<None>"].push_back(info); } PropertyInfo info = E->get(); - info.name = info.name; + info.name = "shader_parameter/" + info.name; 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()); + } + } } } } bool ShaderMaterial::_property_can_revert(const StringName &p_name) const { if (shader.is_valid()) { - StringName pr = shader->remap_uniform(p_name); + StringName pr = shader->remap_parameter(p_name); if (pr) { Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), pr); Variant current_value; @@ -316,7 +295,7 @@ bool ShaderMaterial::_property_can_revert(const StringName &p_name) const { bool ShaderMaterial::_property_get_revert(const StringName &p_name, Variant &r_property) const { if (shader.is_valid()) { - StringName pr = shader->remap_uniform(p_name); + StringName pr = shader->remap_parameter(p_name); if (pr) { r_property = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), pr); return true; @@ -924,6 +903,7 @@ void BaseMaterial3D::_update_shader() { if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; } + code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; } break; case BILLBOARD_FIXED_Y: { code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);\n"; @@ -931,6 +911,7 @@ void BaseMaterial3D::_update_shader() { if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; } + code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; } break; case BILLBOARD_PARTICLES: { //make billboard @@ -939,6 +920,8 @@ void BaseMaterial3D::_update_shader() { code += " mat_world = mat_world * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; //set modelview code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat_world;\n"; + //set modelview normal + code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; //handle animation code += " float h_frames = float(particles_anim_h_frames);\n"; @@ -949,7 +932,7 @@ void BaseMaterial3D::_update_shader() { code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; code += " } else {\n"; code += " particle_frame = mod(particle_frame, particle_total_frames);\n"; - code += " }"; + code += " }\n"; code += " UV /= vec2(h_frames, v_frames);\n"; code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; } break; @@ -3140,8 +3123,6 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value) WARN_PRINT("Godot 3.x SpatialMaterial remapped parameter not found: " + String(p_name)); return true; } - - return false; } #endif // DISABLE_DEPRECATED 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; diff --git a/scene/resources/particle_process_material.h b/scene/resources/particle_process_material.h index fe4741d6e5..9430e5797d 100644 --- a/scene/resources/particle_process_material.h +++ b/scene/resources/particle_process_material.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/templates/rid.h" -#include "scene/resources/material.h" - #ifndef PARTICLE_PROCESS_MATERIAL_H #define PARTICLE_PROCESS_MATERIAL_H +#include "core/templates/rid.h" +#include "scene/resources/material.h" + /* TODO: -Path following diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 280477ebfa..ee61f0ac55 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -262,6 +262,19 @@ public: VARIANT_ENUM_CAST(PlaneMesh::Orientation) +/* + A flat rectangle, inherits from PlaneMesh but defaults to facing the Z-plane. +*/ +class QuadMesh : public PlaneMesh { + GDCLASS(QuadMesh, PlaneMesh); + +public: + QuadMesh() { + set_orientation(FACE_Z); + set_size(Size2(1, 1)); + } +}; + /** A prism shapen, handy for ramps, triangles, etc. */ diff --git a/scene/resources/shader.h b/scene/resources/shader.h index d267e6520e..57be142a95 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -87,15 +87,44 @@ public: virtual bool is_text_shader() const; - _FORCE_INLINE_ StringName remap_uniform(const StringName &p_uniform) const { + // Finds the shader parameter name for the given property name, which should start with "shader_parameter/". + _FORCE_INLINE_ StringName remap_parameter(const StringName &p_property) const { if (params_cache_dirty) { get_shader_uniform_list(nullptr); } - const HashMap<StringName, StringName>::Iterator E = params_cache.find(p_uniform); - if (E) { - return E->value; + String n = p_property; + + // Backwards compatibility with old shader parameter names. + // Note: The if statements are important to make sure we are only replacing text exactly at index 0. + if (n.find("param/") == 0) { + n = n.replace_first("param/", "shader_parameter/"); + } + if (n.find("shader_param/") == 0) { + n = n.replace_first("shader_param/", "shader_parameter/"); + } + if (n.find("shader_uniform/") == 0) { + n = n.replace_first("shader_uniform/", "shader_parameter/"); + } + + { + // Additional backwards compatibility for projects between #62972 and #64092 (about a month of v4.0 development). + // These projects did not have any prefix for shader uniforms due to a bug. + // This code should be removed during beta or rc of 4.0. + const HashMap<StringName, StringName>::Iterator E = params_cache.find(n); + if (E) { + return E->value; + } + } + + if (n.begins_with("shader_parameter/")) { + n = n.replace_first("shader_parameter/", ""); + const HashMap<StringName, StringName>::Iterator E = params_cache.find(n); + if (E) { + return E->value; + } } + return StringName(); } diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp index 068c756849..56234a8a14 100644 --- a/scene/resources/skeleton_modification_stack_2d.cpp +++ b/scene/resources/skeleton_modification_stack_2d.cpp @@ -182,11 +182,11 @@ void SkeletonModificationStack2D::delete_modification(int p_mod_idx) { void SkeletonModificationStack2D::set_modification(int p_mod_idx, Ref<SkeletonModification2D> p_mod) { ERR_FAIL_INDEX(p_mod_idx, modifications.size()); - if (p_mod == nullptr) { - modifications.insert(p_mod_idx, nullptr); + if (p_mod.is_null()) { + modifications.write[p_mod_idx] = Ref<SkeletonModification2D>(); } else { + modifications.write[p_mod_idx] = p_mod; p_mod->_setup_modification(this); - modifications.insert(p_mod_idx, p_mod); } #ifdef TOOLS_ENABLED diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp index 1367ea86dd..61a0350440 100644 --- a/scene/resources/skeleton_profile.cpp +++ b/scene/resources/skeleton_profile.cpp @@ -566,7 +566,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.write[14].bone_name = "LeftThumbMetacarpal"; bones.write[14].bone_parent = "LeftHand"; - bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0.707, 0.577, 0.408, -0.707, 0.577, 0.408, -0.025, 0, 0); + bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0, 0.816, 0.577, -1, 0, 0, -0.025, 0.025, 0); bones.write[14].handle_offset = Vector2(0.4, 0.8); bones.write[14].group = "LeftHand"; @@ -686,7 +686,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.write[33].bone_name = "RightThumbMetacarpal"; bones.write[33].bone_parent = "RightHand"; - bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, -0.707, 0.577, 0.408, 0.707, 0.577, 0.408, 0.025, 0, 0); + bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, 0, 0.816, 0.577, 1, 0, 0, 0.025, 0.025, 0); bones.write[33].handle_offset = Vector2(0.6, 0.8); bones.write[33].group = "RightHand"; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index fc999d5fcb..d21f04fab8 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -34,7 +34,7 @@ #include "core/version.h" Mutex ProceduralSkyMaterial::shader_mutex; -RID ProceduralSkyMaterial::shader; +RID ProceduralSkyMaterial::shader_cache[2]; void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { sky_top_color = p_sky_top; @@ -147,7 +147,11 @@ float ProceduralSkyMaterial::get_sun_curve() const { void ProceduralSkyMaterial::set_use_debanding(bool p_use_debanding) { use_debanding = p_use_debanding; - RS::get_singleton()->material_set_param(_get_material(), "use_debanding", use_debanding); + _update_shader(); + // Only set if shader already compiled + if (shader_set) { + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); + } } bool ProceduralSkyMaterial::get_use_debanding() const { @@ -161,7 +165,8 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { RID ProceduralSkyMaterial::get_rid() const { _update_shader(); if (!shader_set) { - RS::get_singleton()->material_set_shader(_get_material(), shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); shader_set = true; } return _get_material(); @@ -169,7 +174,7 @@ RID ProceduralSkyMaterial::get_rid() const { RID ProceduralSkyMaterial::get_shader_rid() const { _update_shader(); - return shader; + return shader_cache[int(use_debanding)]; } void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const { @@ -241,21 +246,24 @@ void ProceduralSkyMaterial::_bind_methods() { } void ProceduralSkyMaterial::cleanup_shader() { - if (shader.is_valid()) { - RS::get_singleton()->free(shader); + if (shader_cache[0].is_valid()) { + RS::get_singleton()->free(shader_cache[0]); + RS::get_singleton()->free(shader_cache[1]); } } void ProceduralSkyMaterial::_update_shader() { shader_mutex.lock(); - if (shader.is_null()) { - shader = RS::get_singleton()->shader_create(); + if (shader_cache[0].is_null()) { + for (int i = 0; i < 2; i++) { + shader_cache[i] = RS::get_singleton()->shader_create(); - // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). - RS::get_singleton()->shader_set_code(shader, R"( + // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). + RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"( // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s ProceduralSkyMaterial. shader_type sky; +%s uniform vec4 sky_top_color : source_color = vec4(0.385, 0.454, 0.55, 1.0); uniform vec4 sky_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0); @@ -269,14 +277,6 @@ uniform float ground_curve : hint_range(0, 1) = 0.02; uniform float ground_energy = 1.0; uniform float sun_angle_max = 30.0; uniform float sun_curve : hint_range(0, 1) = 0.15; -uniform bool use_debanding = true; - -// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare -vec3 interleaved_gradient_noise(vec2 pos) { - const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); - float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; - return vec3(res, -res, res) / 255.0; -} void sky() { float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0)); @@ -332,11 +332,10 @@ void sky() { ground *= ground_energy; COLOR = mix(ground, sky, step(0.0, EYEDIR.y)); - if (use_debanding) { - COLOR += interleaved_gradient_noise(FRAGCOORD.xy); - } } -)"); +)", + i ? "render_mode use_debanding;" : "")); + } } shader_mutex.unlock(); } @@ -546,7 +545,11 @@ float PhysicalSkyMaterial::get_energy_multiplier() const { void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) { use_debanding = p_use_debanding; - RS::get_singleton()->material_set_param(_get_material(), "use_debanding", use_debanding); + _update_shader(); + // Only set if shader already compiled + if (shader_set) { + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); + } } bool PhysicalSkyMaterial::get_use_debanding() const { @@ -570,7 +573,8 @@ Shader::Mode PhysicalSkyMaterial::get_shader_mode() const { RID PhysicalSkyMaterial::get_rid() const { _update_shader(); if (!shader_set) { - RS::get_singleton()->material_set_shader(_get_material(), shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); + RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); shader_set = true; } return _get_material(); @@ -578,7 +582,7 @@ RID PhysicalSkyMaterial::get_rid() const { RID PhysicalSkyMaterial::get_shader_rid() const { _update_shader(); - return shader; + return shader_cache[int(use_debanding)]; } void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const { @@ -588,7 +592,7 @@ void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const { } Mutex PhysicalSkyMaterial::shader_mutex; -RID PhysicalSkyMaterial::shader; +RID PhysicalSkyMaterial::shader_cache[2]; void PhysicalSkyMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient); @@ -642,21 +646,24 @@ void PhysicalSkyMaterial::_bind_methods() { } void PhysicalSkyMaterial::cleanup_shader() { - if (shader.is_valid()) { - RS::get_singleton()->free(shader); + if (shader_cache[0].is_valid()) { + RS::get_singleton()->free(shader_cache[0]); + RS::get_singleton()->free(shader_cache[1]); } } void PhysicalSkyMaterial::_update_shader() { shader_mutex.lock(); - if (shader.is_null()) { - shader = RS::get_singleton()->shader_create(); + if (shader_cache[0].is_null()) { + for (int i = 0; i < 2; i++) { + shader_cache[i] = RS::get_singleton()->shader_create(); - // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). - RS::get_singleton()->shader_set_code(shader, R"( + // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). + RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"( // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PhysicalSkyMaterial. shader_type sky; +%s uniform float rayleigh : hint_range(0, 64) = 2.0; uniform vec4 rayleigh_color : source_color = vec4(0.3, 0.405, 0.6, 1.0); @@ -668,7 +675,6 @@ uniform float turbidity : hint_range(0, 1000) = 10.0; uniform float sun_disk_scale : hint_range(0, 360) = 1.0; uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0); uniform float exposure : hint_range(0, 128) = 1.0; -uniform bool use_debanding = true; uniform sampler2D night_sky : source_color, hint_default_black; @@ -683,13 +689,6 @@ float henyey_greenstein(float cos_theta, float g) { return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5)); } -// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare -vec3 interleaved_gradient_noise(vec2 pos) { - const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); - float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; - return vec3(res, -res, res) / 255.0; -} - void sky() { if (LIGHT0_ENABLED) { float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 ); @@ -737,16 +736,15 @@ void sky() { vec3 color = Lin + L0; COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade)))); COLOR *= exposure; - if (use_debanding) { - COLOR += interleaved_gradient_noise(FRAGCOORD.xy); - } } else { // There is no sun, so display night_sky and nothing else. COLOR = texture(night_sky, SKY_COORDS).xyz; COLOR *= exposure; } } -)"); +)", + i ? "render_mode use_debanding;" : "")); + } } shader_mutex.unlock(); diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h index b517fd806b..3de1a4b26f 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/templates/rid.h" -#include "scene/resources/material.h" - #ifndef SKY_MATERIAL_H #define SKY_MATERIAL_H +#include "core/templates/rid.h" +#include "scene/resources/material.h" + class ProceduralSkyMaterial : public Material { GDCLASS(ProceduralSkyMaterial, Material); @@ -55,7 +55,7 @@ private: bool use_debanding = true; static Mutex shader_mutex; - static RID shader; + static RID shader_cache[2]; static void _update_shader(); mutable bool shader_set = false; @@ -160,7 +160,7 @@ class PhysicalSkyMaterial : public Material { private: static Mutex shader_mutex; - static RID shader; + static RID shader_cache[2]; float rayleigh = 0.0f; Color rayleigh_color; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d53dc1a8fc..15678c9281 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -38,6 +38,7 @@ #include "scene/resources/bit_map.h" #include "scene/resources/mesh.h" #include "servers/camera/camera_feed.h" + int Texture2D::get_width() const { int ret; if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) { @@ -3105,7 +3106,7 @@ Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Imag uint32_t layer_count = f->get_32(); //layer count uint32_t type = f->get_32(); //layer count - ERR_FAIL_COND_V(type != layered_type, ERR_INVALID_DATA); + ERR_FAIL_COND_V((int)type != layered_type, ERR_INVALID_DATA); uint32_t df = f->get_32(); //data format mipmap_limit = int(f->get_32()); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index da4b8046a5..4e529de8ee 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -769,15 +769,6 @@ public: class GradientTexture1D : public Texture2D { GDCLASS(GradientTexture1D, Texture2D); -public: - struct Point { - float offset = 0.0; - Color color; - bool operator<(const Point &p_ponit) const { - return offset < p_ponit.offset; - } - }; - private: Ref<Gradient> gradient; bool update_pending = false; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 9138a82ba8..65f3767449 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -1537,7 +1537,6 @@ Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) { } return _get_half_offset_terrain_polygon(tile_size, overlap, tile_offset_axis); } - return Vector<Point2>(); } Vector<Point2> TileSet::get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit) { @@ -5276,6 +5275,7 @@ void TileData::set_terrain_set(int p_terrain_set) { } if (tile_set) { ERR_FAIL_COND(p_terrain_set >= tile_set->get_terrain_sets_count()); + terrain = -1; for (int i = 0; i < 16; i++) { terrain_peering_bits[i] = -1; } diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 35686b293c..e14081c681 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -50,16 +50,16 @@ public: virtual void set_loop(bool p_enable) = 0; virtual bool has_loop() const = 0; - virtual float get_length() const = 0; + virtual double get_length() const = 0; - virtual float get_playback_position() const = 0; - virtual void seek(float p_time) = 0; + virtual double get_playback_position() const = 0; + virtual void seek(double p_time) = 0; virtual void set_audio_track(int p_idx) = 0; virtual Ref<Texture2D> get_texture() const = 0; - virtual void update(float p_delta) = 0; + virtual void update(double p_delta) = 0; virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0; virtual int get_channels() const = 0; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 262dbe28ed..9174fcd9e3 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -955,7 +955,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po } bool VisualShader::is_port_types_compatible(int p_a, int p_b) const { - return MAX(0, p_a - 4) == (MAX(0, p_b - 4)); + return MAX(0, p_a - 5) == (MAX(0, p_b - 5)); } void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { @@ -2763,6 +2763,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light_color", "LIGHT_COLOR" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_position", "LIGHT_POSITION" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_direction", "LIGHT_DIRECTION" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light_is_directional", "LIGHT_IS_DIRECTIONAL" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_energy", "LIGHT_ENERGY" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_vertex", "LIGHT_VERTEX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "shadow", "SHADOW_MODULATE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 4116eaa196..3aba550f03 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -90,11 +90,10 @@ public: struct Varying { String name; - VaryingMode mode; - VaryingType type; + VaryingMode mode = VARYING_MODE_MAX; + VaryingType type = VARYING_TYPE_MAX; - Varying() { - } + Varying() {} Varying(String p_name, VaryingMode p_mode, VaryingType p_type) : name(p_name), mode(p_mode), type(p_type) {} diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index bdfbb59fa6..df6abe161e 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -1130,31 +1130,38 @@ VisualShaderNodeParticleAccelerator::VisualShaderNodeParticleAccelerator() { // VisualShaderNodeParticleOutput String VisualShaderNodeParticleOutput::get_caption() const { - if (shader_type == VisualShader::TYPE_START) { - return "StartOutput"; - } else if (shader_type == VisualShader::TYPE_PROCESS) { - return "ProcessOutput"; - } else if (shader_type == VisualShader::TYPE_COLLIDE) { - return "CollideOutput"; - } else if (shader_type == VisualShader::TYPE_START_CUSTOM) { - return "CustomStartOutput"; - } else if (shader_type == VisualShader::TYPE_PROCESS_CUSTOM) { - return "CustomProcessOutput"; + switch (shader_type) { + case VisualShader::TYPE_START: + return "StartOutput"; + case VisualShader::TYPE_PROCESS: + return "ProcessOutput"; + case VisualShader::TYPE_COLLIDE: + return "CollideOutput"; + case VisualShader::TYPE_START_CUSTOM: + return "CustomStartOutput"; + case VisualShader::TYPE_PROCESS_CUSTOM: + return "CustomProcessOutput"; + default: + ERR_PRINT(vformat("Unexpected shader_type %d for VisualShaderNodeParticleOutput.", shader_type)); + return ""; } - return String(); } int VisualShaderNodeParticleOutput::get_input_port_count() const { - if (shader_type == VisualShader::TYPE_START) { - return 8; - } else if (shader_type == VisualShader::TYPE_COLLIDE) { - return 5; - } else if (shader_type == VisualShader::TYPE_START_CUSTOM || shader_type == VisualShader::TYPE_PROCESS_CUSTOM) { - return 6; - } else { // TYPE_PROCESS - return 7; + switch (shader_type) { + case VisualShader::TYPE_START: + return 8; + case VisualShader::TYPE_PROCESS: + return 7; + case VisualShader::TYPE_COLLIDE: + return 5; + case VisualShader::TYPE_START_CUSTOM: + case VisualShader::TYPE_PROCESS_CUSTOM: + return 6; + default: + ERR_PRINT(vformat("Unexpected shader_type %d for VisualShaderNodeParticleOutput.", shader_type)); + return 0; } - return 0; } VisualShaderNodeParticleOutput::PortType VisualShaderNodeParticleOutput::get_input_port_type(int p_port) const { |