diff options
Diffstat (limited to 'scene/resources')
23 files changed, 788 insertions, 327 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/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 208e28f17a..869d582935 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -51,10 +51,7 @@ static const int default_corner_radius = 3; static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = default_margin, float p_margin_top = default_margin, float p_margin_right = default_margin, float p_margin_bottom = default_margin, int p_corner_radius = default_corner_radius, bool p_draw_center = true, int p_border_width = 0) { Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); style->set_bg_color(p_color); - style->set_default_margin(SIDE_LEFT, p_margin_left * scale); - style->set_default_margin(SIDE_RIGHT, p_margin_right * scale); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale); - style->set_default_margin(SIDE_TOP, p_margin_top * scale); + style->set_default_margin_individual(p_margin_left * scale, p_margin_top * scale, p_margin_right * scale, p_margin_bottom * scale); style->set_corner_radius_all(p_corner_radius); style->set_anti_aliased(true); @@ -93,12 +90,7 @@ static Ref<ImageTexture> generate_icon(int p_index) { static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { Ref<StyleBox> style(memnew(StyleBoxEmpty)); - - style->set_default_margin(SIDE_LEFT, p_margin_left * scale); - style->set_default_margin(SIDE_RIGHT, p_margin_right * scale); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale); - style->set_default_margin(SIDE_TOP, p_margin_top * scale); - + style->set_default_margin_individual(p_margin_left * scale, p_margin_top * scale, p_margin_right * scale, p_margin_bottom * scale); return style; } @@ -139,7 +131,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Panel theme->set_stylebox("panel", "Panel", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); - theme->set_stylebox("panel_fg", "Panel", make_flat_stylebox(style_normal_color, 0, 0, 0, 0)); // Button @@ -280,15 +271,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // CheckBox Ref<StyleBox> cbx_empty = memnew(StyleBoxEmpty); - cbx_empty->set_default_margin(SIDE_LEFT, 4 * scale); - cbx_empty->set_default_margin(SIDE_RIGHT, 4 * scale); - cbx_empty->set_default_margin(SIDE_TOP, 4 * scale); - cbx_empty->set_default_margin(SIDE_BOTTOM, 4 * scale); + cbx_empty->set_default_margin_all(4 * scale); Ref<StyleBox> cbx_focus = focus; - cbx_focus->set_default_margin(SIDE_LEFT, 4 * scale); - cbx_focus->set_default_margin(SIDE_RIGHT, 4 * scale); - cbx_focus->set_default_margin(SIDE_TOP, 4 * scale); - cbx_focus->set_default_margin(SIDE_BOTTOM, 4 * scale); + cbx_focus->set_default_margin_all(4 * scale); theme->set_stylebox("normal", "CheckBox", cbx_empty); theme->set_stylebox("pressed", "CheckBox", cbx_empty); @@ -318,16 +303,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_outline_color", "CheckBox", Color(1, 1, 1)); theme->set_constant("h_separation", "CheckBox", 4 * scale); - theme->set_constant("check_v_adjust", "CheckBox", 0 * scale); + theme->set_constant("check_v_offset", "CheckBox", 0 * scale); theme->set_constant("outline_size", "CheckBox", 0); // CheckButton Ref<StyleBox> cb_empty = memnew(StyleBoxEmpty); - cb_empty->set_default_margin(SIDE_LEFT, 6 * scale); - cb_empty->set_default_margin(SIDE_RIGHT, 6 * scale); - cb_empty->set_default_margin(SIDE_TOP, 4 * scale); - cb_empty->set_default_margin(SIDE_BOTTOM, 4 * scale); + cb_empty->set_default_margin_individual(6 * scale, 4 * scale, 6 * scale, 4 * scale); theme->set_stylebox("normal", "CheckButton", cb_empty); theme->set_stylebox("pressed", "CheckButton", cb_empty); @@ -336,15 +318,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("hover_pressed", "CheckButton", cb_empty); theme->set_stylebox("focus", "CheckButton", focus); - theme->set_icon("on", "CheckButton", icons["toggle_on"]); - theme->set_icon("on_disabled", "CheckButton", icons["toggle_on_disabled"]); - theme->set_icon("off", "CheckButton", icons["toggle_off"]); - theme->set_icon("off_disabled", "CheckButton", icons["toggle_off_disabled"]); + theme->set_icon("checked", "CheckButton", icons["toggle_on"]); + theme->set_icon("checked_disabled", "CheckButton", icons["toggle_on_disabled"]); + theme->set_icon("unchecked", "CheckButton", icons["toggle_off"]); + theme->set_icon("unchecked_disabled", "CheckButton", icons["toggle_off_disabled"]); - theme->set_icon("on_mirrored", "CheckButton", icons["toggle_on_mirrored"]); - theme->set_icon("on_disabled_mirrored", "CheckButton", icons["toggle_on_disabled_mirrored"]); - theme->set_icon("off_mirrored", "CheckButton", icons["toggle_off_mirrored"]); - theme->set_icon("off_disabled_mirrored", "CheckButton", icons["toggle_off_disabled_mirrored"]); + theme->set_icon("checked_mirrored", "CheckButton", icons["toggle_on_mirrored"]); + theme->set_icon("checked_disabled_mirrored", "CheckButton", icons["toggle_on_disabled_mirrored"]); + theme->set_icon("unchecked_mirrored", "CheckButton", icons["toggle_off_mirrored"]); + theme->set_icon("unchecked_disabled_mirrored", "CheckButton", icons["toggle_off_disabled_mirrored"]); theme->set_font("font", "CheckButton", Ref<Font>()); theme->set_font_size("font_size", "CheckButton", -1); @@ -358,7 +340,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_outline_color", "CheckButton", Color(1, 1, 1)); theme->set_constant("h_separation", "CheckButton", 4 * scale); - theme->set_constant("check_v_adjust", "CheckButton", 0 * scale); + theme->set_constant("check_v_offset", "CheckButton", 0 * scale); theme->set_constant("outline_size", "CheckButton", 0); // Label @@ -423,8 +405,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // ProgressBar - theme->set_stylebox("bg", "ProgressBar", make_flat_stylebox(style_disabled_color, 2, 2, 2, 2, 6)); - theme->set_stylebox("fg", "ProgressBar", make_flat_stylebox(style_progress_color, 2, 2, 2, 2, 6)); + theme->set_stylebox("background", "ProgressBar", make_flat_stylebox(style_disabled_color, 2, 2, 2, 2, 6)); + theme->set_stylebox("fill", "ProgressBar", make_flat_stylebox(style_progress_color, 2, 2, 2, 2, 6)); theme->set_font("font", "ProgressBar", Ref<Font>()); theme->set_font_size("font_size", "ProgressBar", -1); @@ -588,7 +570,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<StyleBoxEmpty> empty; empty.instantiate(); - theme->set_stylebox("bg", "ScrollContainer", empty); + theme->set_stylebox("panel", "ScrollContainer", empty); // Window @@ -610,9 +592,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Dialogs // AcceptDialog is currently the base dialog, so this defines styles for all extending nodes. - theme->set_constant("margin", "AcceptDialog", 8 * scale); - theme->set_constant("button_margin", "AcceptDialog", 32 * scale); - theme->set_stylebox("panel", "AcceptDialog", make_flat_stylebox(style_popup_color, 0, 0, 0, 0)); + theme->set_stylebox("panel", "AcceptDialog", make_flat_stylebox(style_popup_color, 8 * scale, 8 * scale, 8 * scale, 8 * scale)); + theme->set_constant("buttons_separation", "AcceptDialog", 10 * scale); // File Dialog @@ -623,9 +604,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("toggle_hidden", "FileDialog", icons["visibility_visible"]); theme->set_icon("folder", "FileDialog", icons["folder"]); theme->set_icon("file", "FileDialog", icons["file"]); - theme->set_color("folder_icon_modulate", "FileDialog", Color(1, 1, 1)); - theme->set_color("file_icon_modulate", "FileDialog", Color(1, 1, 1)); - theme->set_color("files_disabled", "FileDialog", Color(1, 1, 1, 0.25)); + theme->set_color("folder_icon_color", "FileDialog", Color(1, 1, 1)); + theme->set_color("file_icon_color", "FileDialog", Color(1, 1, 1)); + theme->set_color("file_disabled_color", "FileDialog", Color(1, 1, 1, 0.25)); // Popup @@ -640,16 +621,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<StyleBoxLine> separator_horizontal = memnew(StyleBoxLine); separator_horizontal->set_thickness(Math::round(scale)); separator_horizontal->set_color(style_separator_color); - separator_horizontal->set_default_margin(SIDE_LEFT, default_margin); - separator_horizontal->set_default_margin(SIDE_TOP, 0); - separator_horizontal->set_default_margin(SIDE_RIGHT, default_margin); - separator_horizontal->set_default_margin(SIDE_BOTTOM, 0); + separator_horizontal->set_default_margin_individual(default_margin, 0, default_margin, 0); Ref<StyleBoxLine> separator_vertical = separator_horizontal->duplicate(); separator_vertical->set_vertical(true); - separator_vertical->set_default_margin(SIDE_LEFT, 0); - separator_vertical->set_default_margin(SIDE_TOP, default_margin); - separator_vertical->set_default_margin(SIDE_RIGHT, 0); - separator_vertical->set_default_margin(SIDE_BOTTOM, default_margin); + separator_vertical->set_default_margin_individual(0, default_margin, 0, default_margin); // Always display a border for PopupMenus so they can be distinguished from their background. Ref<StyleBoxFlat> style_popup_panel = make_flat_stylebox(style_popup_color); @@ -737,8 +712,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Tree - theme->set_stylebox("bg", "Tree", make_flat_stylebox(style_normal_color, 4, 4, 4, 5)); - theme->set_stylebox("bg_focus", "Tree", focus); + theme->set_stylebox("panel", "Tree", make_flat_stylebox(style_normal_color, 4, 4, 4, 5)); + theme->set_stylebox("focus", "Tree", focus); theme->set_stylebox("selected", "Tree", make_flat_stylebox(style_selected_color)); theme->set_stylebox("selected_focus", "Tree", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "Tree", focus); @@ -791,8 +766,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // ItemList - theme->set_stylebox("bg", "ItemList", make_flat_stylebox(style_normal_color)); - theme->set_stylebox("bg_focus", "ItemList", focus); + theme->set_stylebox("panel", "ItemList", make_flat_stylebox(style_normal_color)); + theme->set_stylebox("focus", "ItemList", focus); theme->set_constant("h_separation", "ItemList", 4); theme->set_constant("v_separation", "ItemList", 2); theme->set_constant("icon_margin", "ItemList", 4); @@ -1013,6 +988,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("separation", "SplitContainer", 12 * scale); theme->set_constant("separation", "HSplitContainer", 12 * scale); theme->set_constant("separation", "VSplitContainer", 12 * scale); + theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * scale); + theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * scale); + theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * scale); theme->set_constant("autohide", "SplitContainer", 1 * scale); theme->set_constant("autohide", "HSplitContainer", 1 * scale); theme->set_constant("autohide", "VSplitContainer", 1 * scale); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 189d8d5502..3d9e4e4a63 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -554,7 +554,6 @@ Font::Font() { } Font::~Font() { - reset_state(); } /*************************************************************************/ @@ -2433,11 +2432,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 +2686,6 @@ FontVariation::FontVariation() { } FontVariation::~FontVariation() { - reset_state(); } /*************************************************************************/ @@ -3081,5 +3078,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..c1e30dd93c 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; 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/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 6c9c8ffdba..90ea879012 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -32,7 +32,7 @@ #ifdef DEBUG_ENABLED #include "servers/navigation_server_3d.h" -#endif +#endif // DEBUG_ENABLED void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { ERR_FAIL_COND(p_mesh.is_null()); @@ -341,94 +341,8 @@ void NavigationMesh::clear_polygons() { polygons.clear(); } -#ifndef DISABLE_DEPRECATED -Ref<Mesh> NavigationMesh::get_debug_mesh() { - if (debug_mesh.is_valid()) { - return debug_mesh; - } - - Vector<Vector3> vertices = get_vertices(); - const Vector3 *vr = vertices.ptr(); - List<Face3> faces; - for (int i = 0; i < get_polygon_count(); i++) { - Vector<int> p = get_polygon(i); - - for (int j = 2; j < p.size(); j++) { - Face3 f; - f.vertex[0] = vr[p[0]]; - f.vertex[1] = vr[p[j - 1]]; - f.vertex[2] = vr[p[j]]; - - faces.push_back(f); - } - } - - HashMap<_EdgeKey, bool, _EdgeKey> edge_map; - Vector<Vector3> tmeshfaces; - tmeshfaces.resize(faces.size() * 3); - - { - Vector3 *tw = tmeshfaces.ptrw(); - int tidx = 0; - - for (const Face3 &f : faces) { - for (int j = 0; j < 3; j++) { - tw[tidx++] = f.vertex[j]; - _EdgeKey ek; - ek.from = f.vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); - ek.to = f.vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); - if (ek.from < ek.to) { - SWAP(ek.from, ek.to); - } - - HashMap<_EdgeKey, bool, _EdgeKey>::Iterator F = edge_map.find(ek); - - if (F) { - F->value = false; - - } else { - edge_map[ek] = true; - } - } - } - } - List<Vector3> lines; - - for (const KeyValue<_EdgeKey, bool> &E : edge_map) { - if (E.value) { - lines.push_back(E.key.from); - lines.push_back(E.key.to); - } - } - - Vector<Vector3> varr; - varr.resize(lines.size()); - { - Vector3 *w = varr.ptrw(); - int idx = 0; - for (const Vector3 &E : lines) { - w[idx++] = E; - } - } - - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); - - if (!lines.size()) { - return debug_mesh; - } - - Array arr; - arr.resize(Mesh::ARRAY_MAX); - arr[Mesh::ARRAY_VERTEX] = varr; - - debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); - - return debug_mesh; -} -#endif // DISABLE_DEPRECATED - #ifdef DEBUG_ENABLED -Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() { +Ref<ArrayMesh> NavigationMesh::get_debug_mesh() { if (debug_mesh.is_valid()) { // Blocks further updates for now, code below is intended for dynamic updates e.g. when settings change. return debug_mesh; @@ -479,8 +393,6 @@ Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() { for (int i = 0; i < polygon_count; i++) { polygon_color = debug_navigation_geometry_face_color * (Color(Math::randf(), Math::randf(), Math::randf())); - Vector<int> polygon = get_polygon(i); - face_color_array.push_back(polygon_color); face_color_array.push_back(polygon_color); face_color_array.push_back(polygon_color); @@ -490,7 +402,7 @@ Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() { debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, face_mesh_array); Ref<StandardMaterial3D> debug_geometry_face_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_face_material(); - debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_face_material); + debug_mesh->surface_set_material(0, debug_geometry_face_material); // if enabled build geometry edge line surface bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines(); @@ -515,12 +427,12 @@ Ref<ArrayMesh> NavigationMesh::_get_debug_mesh() { line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array; debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, line_mesh_array); Ref<StandardMaterial3D> debug_geometry_edge_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_geometry_edge_material(); - debug_mesh->surface_set_material(debug_mesh->get_surface_count(), debug_geometry_edge_material); + debug_mesh->surface_set_material(1, debug_geometry_edge_material); } return debug_mesh; } -#endif +#endif // DEBUG_ENABLED void NavigationMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type); diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index c66025dc6d..5ddbd75dcb 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -202,11 +202,9 @@ public: Vector<int> get_polygon(int p_idx); void clear_polygons(); -#ifndef DISABLE_DEPRECATED - Ref<Mesh> get_debug_mesh(); -#endif // DISABLE_DEPRECATED - - Ref<ArrayMesh> _get_debug_mesh(); +#ifdef DEBUG_ENABLED + Ref<ArrayMesh> get_debug_mesh(); +#endif // DEBUG_ENABLED NavigationMesh(); }; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 727f7a4e09..c017c90370 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -2663,9 +2663,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { vertices_ptr[p_idx] = point; normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); if (has_depth) { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); } else { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); } tangents_ptr[p_idx * 4 + 0] = 1.0; tangents_ptr[p_idx * 4 + 1] = 0.0; @@ -2680,7 +2680,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); vertices_ptr[p_idx] = point; normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4))); + uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4))); tangents_ptr[p_idx * 4 + 0] = -1.0; tangents_ptr[p_idx * 4 + 1] = 0.0; tangents_ptr[p_idx * 4 + 2] = 0.0; @@ -2721,9 +2721,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { vertices_ptr[p_idx + m] = quad_faces[m]; normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); if (m < 2) { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + uvs_ptr[p_idx + m] = Vector2(Math::remap(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); } else { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + uvs_ptr[p_idx + m] = Vector2(Math::remap(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); } tangents_ptr[(p_idx + m) * 4 + 0] = d.x; tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; @@ -2760,9 +2760,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { vertices_ptr[p_idx + k] = quad_faces[k]; normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); if (has_depth) { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + uvs_ptr[p_idx + k] = Vector2(Math::remap(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); } else { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + uvs_ptr[p_idx + k] = Vector2(Math::remap(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); } tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; 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/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..fbb202d8d8 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -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/style_box.cpp b/scene/resources/style_box.cpp index 4b151eed12..cd893d8c23 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -41,6 +41,7 @@ float StyleBox::get_style_margin(Side p_side) const { } return 0; } + bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const { bool ret; if (GDVIRTUAL_CALL(_test_mask, p_point, p_rect, ret)) { @@ -63,6 +64,21 @@ void StyleBox::set_default_margin(Side p_side, float p_value) { emit_changed(); } +void StyleBox::set_default_margin_all(float p_value) { + for (int i = 0; i < 4; i++) { + margin[i] = p_value; + } + emit_changed(); +} + +void StyleBox::set_default_margin_individual(float p_left, float p_top, float p_right, float p_bottom) { + margin[SIDE_LEFT] = p_left; + margin[SIDE_TOP] = p_top; + margin[SIDE_RIGHT] = p_right; + margin[SIDE_BOTTOM] = p_bottom; + emit_changed(); +} + float StyleBox::get_default_margin(Side p_side) const { ERR_FAIL_INDEX_V((int)p_side, 4, 0.0); @@ -112,6 +128,7 @@ void StyleBox::_bind_methods() { ClassDB::bind_method(D_METHOD("test_mask", "point", "rect"), &StyleBox::test_mask); ClassDB::bind_method(D_METHOD("set_default_margin", "margin", "offset"), &StyleBox::set_default_margin); + ClassDB::bind_method(D_METHOD("set_default_margin_all", "offset"), &StyleBox::set_default_margin_all); ClassDB::bind_method(D_METHOD("get_default_margin", "margin"), &StyleBox::get_default_margin); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &StyleBox::get_margin); @@ -165,6 +182,21 @@ void StyleBoxTexture::set_margin_size(Side p_side, float p_size) { emit_changed(); } +void StyleBoxTexture::set_margin_size_all(float p_size) { + for (int i = 0; i < 4; i++) { + margin[i] = p_size; + } + emit_changed(); +} + +void StyleBoxTexture::set_margin_size_individual(float p_left, float p_top, float p_right, float p_bottom) { + margin[SIDE_LEFT] = p_left; + margin[SIDE_TOP] = p_top; + margin[SIDE_RIGHT] = p_right; + margin[SIDE_BOTTOM] = p_bottom; + emit_changed(); +} + float StyleBoxTexture::get_margin_size(Side p_side) const { ERR_FAIL_INDEX_V((int)p_side, 4, 0.0); @@ -292,11 +324,11 @@ void StyleBoxTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture"), &StyleBoxTexture::get_texture); ClassDB::bind_method(D_METHOD("set_margin_size", "margin", "size"), &StyleBoxTexture::set_margin_size); + ClassDB::bind_method(D_METHOD("set_margin_size_all", "size"), &StyleBoxTexture::set_margin_size_all); ClassDB::bind_method(D_METHOD("get_margin_size", "margin"), &StyleBoxTexture::get_margin_size); ClassDB::bind_method(D_METHOD("set_expand_margin_size", "margin", "size"), &StyleBoxTexture::set_expand_margin_size); ClassDB::bind_method(D_METHOD("set_expand_margin_all", "size"), &StyleBoxTexture::set_expand_margin_size_all); - ClassDB::bind_method(D_METHOD("set_expand_margin_individual", "size_left", "size_top", "size_right", "size_bottom"), &StyleBoxTexture::set_expand_margin_size_individual); ClassDB::bind_method(D_METHOD("get_expand_margin_size", "margin"), &StyleBoxTexture::get_expand_margin_size); ClassDB::bind_method(D_METHOD("set_region_rect", "region"), &StyleBoxTexture::set_region_rect); @@ -864,7 +896,6 @@ void StyleBoxFlat::_bind_methods() { ClassDB::bind_method(D_METHOD("set_border_blend", "blend"), &StyleBoxFlat::set_border_blend); ClassDB::bind_method(D_METHOD("get_border_blend"), &StyleBoxFlat::get_border_blend); - ClassDB::bind_method(D_METHOD("set_corner_radius_individual", "radius_top_left", "radius_top_right", "radius_bottom_right", "radius_bottom_left"), &StyleBoxFlat::set_corner_radius_individual); ClassDB::bind_method(D_METHOD("set_corner_radius_all", "radius"), &StyleBoxFlat::set_corner_radius_all); ClassDB::bind_method(D_METHOD("set_corner_radius", "corner", "radius"), &StyleBoxFlat::set_corner_radius); @@ -872,7 +903,6 @@ void StyleBoxFlat::_bind_methods() { ClassDB::bind_method(D_METHOD("set_expand_margin", "margin", "size"), &StyleBoxFlat::set_expand_margin_size); ClassDB::bind_method(D_METHOD("set_expand_margin_all", "size"), &StyleBoxFlat::set_expand_margin_size_all); - ClassDB::bind_method(D_METHOD("set_expand_margin_individual", "size_left", "size_top", "size_right", "size_bottom"), &StyleBoxFlat::set_expand_margin_size_individual); ClassDB::bind_method(D_METHOD("get_expand_margin", "margin"), &StyleBoxFlat::get_expand_margin_size); ClassDB::bind_method(D_METHOD("set_draw_center", "draw_center"), &StyleBoxFlat::set_draw_center); diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 88db4f5fbd..2c72446567 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -57,7 +57,10 @@ public: virtual bool test_mask(const Point2 &p_point, const Rect2 &p_rect) const; void set_default_margin(Side p_side, float p_value); + void set_default_margin_all(float p_value); + void set_default_margin_individual(float p_left, float p_top, float p_right, float p_bottom); float get_default_margin(Side p_side) const; + float get_margin(Side p_side) const; virtual Size2 get_center_size() const; @@ -112,6 +115,8 @@ public: float get_expand_margin_size(Side p_expand_side) const; void set_margin_size(Side p_side, float p_size); + void set_margin_size_all(float p_size); + void set_margin_size_individual(float p_left, float p_top, float p_right, float p_bottom); float get_margin_size(Side p_side) const; void set_region_rect(const Rect2 &p_region_rect); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index a269416d8b..d53dc1a8fc 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2617,26 +2617,30 @@ void AnimatedTexture::_update_proxy() { time += delta; - float limit; - - if (fps == 0) { - limit = 0; - } else { - limit = 1.0 / fps; - } + float speed = speed_scale == 0 ? 0 : abs(1.0 / speed_scale); int iter_max = frame_count; while (iter_max && !pause) { - float frame_limit = limit + frames[current_frame].delay_sec; + float frame_limit = frames[current_frame].duration * speed; if (time > frame_limit) { - current_frame++; + if (speed_scale > 0.0) { + current_frame++; + } else { + current_frame--; + } if (current_frame >= frame_count) { - if (oneshot) { + if (one_shot) { current_frame = frame_count - 1; } else { current_frame = 0; } + } else if (current_frame < 0) { + if (one_shot) { + current_frame = 0; + } else { + current_frame = frame_count - 1; + } } time -= frame_limit; @@ -2684,13 +2688,13 @@ bool AnimatedTexture::get_pause() const { return pause; } -void AnimatedTexture::set_oneshot(bool p_oneshot) { +void AnimatedTexture::set_one_shot(bool p_one_shot) { RWLockWrite r(rw_lock); - oneshot = p_oneshot; + one_shot = p_one_shot; } -bool AnimatedTexture::get_oneshot() const { - return oneshot; +bool AnimatedTexture::get_one_shot() const { + return one_shot; } void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture) { @@ -2710,30 +2714,30 @@ Ref<Texture2D> AnimatedTexture::get_frame_texture(int p_frame) const { return frames[p_frame].texture; } -void AnimatedTexture::set_frame_delay(int p_frame, float p_delay_sec) { +void AnimatedTexture::set_frame_duration(int p_frame, float p_duration) { ERR_FAIL_INDEX(p_frame, MAX_FRAMES); RWLockRead r(rw_lock); - frames[p_frame].delay_sec = p_delay_sec; + frames[p_frame].duration = p_duration; } -float AnimatedTexture::get_frame_delay(int p_frame) const { +float AnimatedTexture::get_frame_duration(int p_frame) const { ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, 0); RWLockRead r(rw_lock); - return frames[p_frame].delay_sec; + return frames[p_frame].duration; } -void AnimatedTexture::set_fps(float p_fps) { - ERR_FAIL_COND(p_fps < 0 || p_fps >= 1000); +void AnimatedTexture::set_speed_scale(float p_scale) { + ERR_FAIL_COND(p_scale < -1000 || p_scale >= 1000); - fps = p_fps; + speed_scale = p_scale; } -float AnimatedTexture::get_fps() const { - return fps; +float AnimatedTexture::get_speed_scale() const { + return speed_scale; } int AnimatedTexture::get_width() const { @@ -2809,27 +2813,27 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "pause"), &AnimatedTexture::set_pause); ClassDB::bind_method(D_METHOD("get_pause"), &AnimatedTexture::get_pause); - ClassDB::bind_method(D_METHOD("set_oneshot", "oneshot"), &AnimatedTexture::set_oneshot); - ClassDB::bind_method(D_METHOD("get_oneshot"), &AnimatedTexture::get_oneshot); + ClassDB::bind_method(D_METHOD("set_one_shot", "one_shot"), &AnimatedTexture::set_one_shot); + ClassDB::bind_method(D_METHOD("get_one_shot"), &AnimatedTexture::get_one_shot); - ClassDB::bind_method(D_METHOD("set_fps", "fps"), &AnimatedTexture::set_fps); - ClassDB::bind_method(D_METHOD("get_fps"), &AnimatedTexture::get_fps); + ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &AnimatedTexture::set_speed_scale); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &AnimatedTexture::get_speed_scale); ClassDB::bind_method(D_METHOD("set_frame_texture", "frame", "texture"), &AnimatedTexture::set_frame_texture); ClassDB::bind_method(D_METHOD("get_frame_texture", "frame"), &AnimatedTexture::get_frame_texture); - ClassDB::bind_method(D_METHOD("set_frame_delay", "frame", "delay"), &AnimatedTexture::set_frame_delay); - ClassDB::bind_method(D_METHOD("get_frame_delay", "frame"), &AnimatedTexture::get_frame_delay); + ClassDB::bind_method(D_METHOD("set_frame_duration", "frame", "duration"), &AnimatedTexture::set_frame_duration); + ClassDB::bind_method(D_METHOD("get_frame_duration", "frame"), &AnimatedTexture::get_frame_duration); ADD_PROPERTY(PropertyInfo(Variant::INT, "frames", PROPERTY_HINT_RANGE, "1," + itos(MAX_FRAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_frames", "get_frames"); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_frame", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_frame", "get_current_frame"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pause"), "set_pause", "get_pause"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "oneshot"), "set_oneshot", "get_oneshot"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fps", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_fps", "get_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "-60,60,0.1,or_greater,or_lesser"), "set_speed_scale", "get_speed_scale"); for (int i = 0; i < MAX_FRAMES; i++) { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "frame_" + itos(i) + "/texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_texture", "get_frame_texture", i); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "frame_" + itos(i) + "/delay_sec", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_delay", "get_frame_delay", i); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "frame_" + itos(i) + "/duration", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater,suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_duration", "get_frame_duration", i); } BIND_CONSTANT(MAX_FRAMES); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 430c73dbc6..da4b8046a5 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -922,15 +922,15 @@ private: struct Frame { Ref<Texture2D> texture; - float delay_sec = 0.0; + float duration = 1.0; }; Frame frames[MAX_FRAMES]; int frame_count = 1.0; int current_frame = 0; bool pause = false; - bool oneshot = false; - float fps = 4.0; + bool one_shot = false; + float speed_scale = 1.0; float time = 0.0; @@ -952,17 +952,17 @@ public: void set_pause(bool p_pause); bool get_pause() const; - void set_oneshot(bool p_oneshot); - bool get_oneshot() const; + void set_one_shot(bool p_one_shot); + bool get_one_shot() const; void set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture); Ref<Texture2D> get_frame_texture(int p_frame) const; - void set_frame_delay(int p_frame, float p_delay_sec); - float get_frame_delay(int p_frame) const; + void set_frame_duration(int p_frame, float p_duration); + float get_frame_duration(int p_frame) const; - void set_fps(float p_fps); - float get_fps() const; + void set_speed_scale(float p_scale); + float get_speed_scale() const; virtual int get_width() const override; virtual int get_height() const override; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 70a73186bc..262dbe28ed 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -3718,6 +3718,17 @@ bool VisualShaderNodeParameter::is_global_code_generated() const { return global_code_generated; } +#ifndef DISABLE_DEPRECATED +// Kept for compatibility from 3.x to 4.0. +bool VisualShaderNodeParameter::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "uniform_name") { + set_parameter_name(p_value); + return true; + } + return false; +} +#endif + void VisualShaderNodeParameter::_bind_methods() { ClassDB::bind_method(D_METHOD("set_parameter_name", "name"), &VisualShaderNodeParameter::set_parameter_name); ClassDB::bind_method(D_METHOD("get_parameter_name"), &VisualShaderNodeParameter::get_parameter_name); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 88e92f15cf..4116eaa196 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -519,6 +519,10 @@ protected: static void _bind_methods(); String _get_qual_str() const; +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); +#endif + public: void set_parameter_name(const String &p_name); String get_parameter_name() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 72e55ac47d..de13912b75 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -1636,10 +1636,14 @@ String VisualShaderNodeLinearSceneDepth::get_output_port_name(int p_port) const return "linear depth"; } +bool VisualShaderNodeLinearSceneDepth::has_output_port_preview(int p_port) const { + return false; +} + String VisualShaderNodeLinearSceneDepth::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; - code += " float _log_depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;\n"; + code += " float _log_depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;\n"; code += " vec3 _depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, _log_depth);\n"; code += " vec4 _depth_view = INV_PROJECTION_MATRIX * vec4(_depth_ndc, 1.0);\n"; code += " _depth_view.xyz /= _depth_view.w;"; @@ -6115,6 +6119,13 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shade return code; } +String VisualShaderNodeTextureParameterTriplanar::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name(); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += ";\n"; + return code; +} + String VisualShaderNodeTextureParameterTriplanar::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String id = get_parameter_name(); @@ -7194,6 +7205,10 @@ String VisualShaderNodeDistanceFade::get_output_port_name(int p_port) const { return "amount"; } +bool VisualShaderNodeDistanceFade::has_output_port_preview(int p_port) const { + return false; +} + String VisualShaderNodeDistanceFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; code += vformat(" %s = clamp(smoothstep(%s, %s,-VERTEX.z),0.0,1.0);\n", p_output_vars[0], p_input_vars[0], p_input_vars[1]); @@ -7235,6 +7250,10 @@ String VisualShaderNodeProximityFade::get_output_port_name(int p_port) const { return "fade"; } +bool VisualShaderNodeProximityFade::has_output_port_preview(int p_port) const { + return false; +} + String VisualShaderNodeProximityFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index ecba412fcb..4b883c25cc 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -636,6 +636,7 @@ public: virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual bool has_output_port_preview(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2278,6 +2279,7 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeTextureParameterTriplanar(); @@ -2643,6 +2645,7 @@ public: virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual bool has_output_port_preview(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; @@ -2662,6 +2665,7 @@ public: virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual bool has_output_port_preview(int p_port) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; |