diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/animation.cpp | 86 | ||||
-rw-r--r-- | scene/resources/bone_map.cpp | 2 | ||||
-rw-r--r-- | scene/resources/font.cpp | 10 | ||||
-rw-r--r-- | scene/resources/importer_mesh.cpp | 2 | ||||
-rw-r--r-- | scene/resources/mesh.cpp | 12 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.cpp | 583 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.h | 35 | ||||
-rw-r--r-- | scene/resources/resource_format_text.cpp | 2 | ||||
-rw-r--r-- | scene/resources/shader.cpp | 2 | ||||
-rw-r--r-- | scene/resources/shape_2d.cpp | 2 | ||||
-rw-r--r-- | scene/resources/skeleton_modification_2d_fabrik.h | 4 | ||||
-rw-r--r-- | scene/resources/skeleton_modification_3d_fabrik.h | 6 | ||||
-rw-r--r-- | scene/resources/syntax_highlighter.cpp | 2 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 1 | ||||
-rw-r--r-- | scene/resources/tile_set.cpp | 2 | ||||
-rw-r--r-- | scene/resources/tile_set.h | 2 | ||||
-rw-r--r-- | scene/resources/visual_shader_nodes.cpp | 4 |
17 files changed, 609 insertions, 148 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index dfd9c6eb2f..ef619c9893 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -4964,7 +4964,7 @@ void Animation::compress(uint32_t p_page_size, uint32_t p_fps, float p_split_tol if (rollback || best_frame == FRAME_MAX) { // Commit the page if had to rollback or if no track was found - print_animc("\tCommiting page.."); + print_animc("\tCommiting page..."); // The end frame for the page depends entirely on whether its valid or // no more keys were found. @@ -5851,18 +5851,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float 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) { + const Vector<int32_t> arr_a = a; + const Vector<int32_t> arr_b = 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(); + const int32_t *ar = arr_a.ptr(); + const int32_t *br = arr_b.ptr(); Variant va; for (int32_t i = 0; i < sz; i++) { @@ -5874,18 +5874,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<int64_t> arr_a = a; + const Vector<int64_t> arr_b = 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(); + const int64_t *ar = arr_a.ptr(); + const int64_t *br = arr_b.ptr(); Variant va; for (int64_t i = 0; i < sz; i++) { @@ -5897,18 +5897,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<float> arr_a = a; + const Vector<float> arr_b = 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(); + const float *ar = arr_a.ptr(); + const float *br = arr_b.ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -5920,18 +5920,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<double> arr_a = a; + const Vector<double> arr_b = 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(); + const double *ar = arr_a.ptr(); + const double *br = arr_b.ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -5943,18 +5943,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<Vector2> arr_a = a; + const Vector<Vector2> arr_b = 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(); + 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); @@ -5964,18 +5964,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<Vector3> arr_a = a; + const Vector<Vector3> arr_b = 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(); + 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); @@ -5985,18 +5985,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } 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) { + const Vector<Color> arr_a = a; + const Vector<Color> arr_b = 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(); + 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); diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index dfaf82f36a..5698e61004 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -93,7 +93,7 @@ void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const Strin } StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) const { - StringName profile_bone_name = StringName(); + StringName profile_bone_name; HashMap<StringName, StringName>::ConstIterator E = bone_map.begin(); while (E) { if (E->value == p_skeleton_bone_name) { diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 185b6f4bdc..84814d939b 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1396,6 +1396,9 @@ Error FontFile::load_bitmap_font(const String &p_path) { case 1: /* info */ { ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, RTR("Invalid BMFont info block size.")); base_size = f->get_16(); + if (base_size <= 0) { + base_size = 16; + } uint8_t flags = f->get_8(); if (flags & (1 << 3)) { st_flags.set_flag(TextServer::FONT_BOLD); @@ -1681,7 +1684,6 @@ Error FontFile::load_bitmap_font(const String &p_path) { if (type == "info") { if (keys.has("size")) { base_size = keys["size"].to_int(); - set_fixed_size(base_size); } if (keys.has("outline")) { outline = keys["outline"].to_int(); @@ -1730,6 +1732,7 @@ Error FontFile::load_bitmap_font(const String &p_path) { encoding = 2; } } + set_fixed_size(base_size); } else if (type == "common") { if (keys.has("lineHeight")) { height = keys["lineHeight"].to_int(); @@ -1788,7 +1791,10 @@ Error FontFile::load_bitmap_font(const String &p_path) { ERR_FAIL_V_MSG(ERR_CANT_CREATE, RTR("Unsupported BMFont texture format.")); } } else { - if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline + if ((ch[3] == 0) && (ch[0] == 4) && (ch[1] == 4) && (ch[2] == 4) && img->get_format() == Image::FORMAT_RGBA8) { // might be RGBA8 color, no outline (color part of the image should be sold white, but some apps designed for Godot 3 generate color fonts with this config) + outline = 0; + set_texture_image(0, Vector2i(base_size, 0), page, img); + } else if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline outline = 0; ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, RTR("Unsupported BMFont texture format.")); set_texture_image(0, Vector2i(base_size, 0), page, img); diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index b728c24e0d..cec5569345 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -255,7 +255,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma } #define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \ - Vector3 transformed_vert = Vector3(); \ + Vector3 transformed_vert; \ 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]; \ diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 706db3af16..d1e300e057 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -940,7 +940,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (int16_t)CLAMP(src[0] / 127.0f * 32767, -32768, 32767); dst[1] = (int16_t)CLAMP(src[1] / 127.0f * 32767, -32768, 32767); } - src_offset += sizeof(int16_t) * 2; + src_offset += sizeof(int8_t) * 2; } else { for (uint32_t i = 0; i < p_elements; i++) { const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; @@ -962,7 +962,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint16_t) * 2; + src_offset += sizeof(uint8_t) * 4; // 1 byte padding } else { for (uint32_t i = 0; i < p_elements; i++) { const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; @@ -973,7 +973,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint16_t) * 2; + src_offset += sizeof(float) * 3; } } @@ -988,7 +988,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (uint16_t)CLAMP((src[0] / 127.0f * .5f + .5f) * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP((src[1] / 127.0f * .5f + .5f) * 65535, 0, 65535); } - src_offset += sizeof(uint16_t) * 2; + src_offset += sizeof(uint8_t) * 2; } else { // int16 SNORM -> uint16 UNORM for (uint32_t i = 0; i < p_elements; i++) { const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; @@ -1010,7 +1010,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint16_t) * 2; + src_offset += sizeof(uint8_t) * 4; } else { for (uint32_t i = 0; i < p_elements; i++) { const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; @@ -1021,7 +1021,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint16_t) * 2; + src_offset += sizeof(float) * 4; } } } break; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index eb83a37c7b..4c6d533c72 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -30,6 +30,7 @@ #include "primitive_meshes.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "scene/resources/theme.h" #include "scene/theme/theme_db.h" @@ -37,6 +38,8 @@ #include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/polypartition.h" +#define PADDING_REF_SIZE 1024.0 + /** PrimitiveMesh */ @@ -94,6 +97,26 @@ void PrimitiveMesh::_update() const { } } + if (add_uv2) { + // _create_mesh_array should populate our UV2, this is a fallback in case it doesn't. + // As we don't know anything about the geometry we only pad the right and bottom edge + // of our texture. + Vector<Vector2> uv = arr[RS::ARRAY_TEX_UV]; + Vector<Vector2> uv2 = arr[RS::ARRAY_TEX_UV2]; + + if (uv.size() > 0 && uv2.size() == 0) { + Vector2 uv2_scale = get_uv2_scale(); + uv2.resize(uv.size()); + + Vector2 *uv2w = uv2.ptrw(); + for (int i = 0; i < uv.size(); i++) { + uv2w[i] = uv[i] * uv2_scale; + } + } + + arr[RS::ARRAY_TEX_UV2] = uv2; + } + array_len = pc; index_array_len = indices.size(); // in with the new @@ -160,7 +183,12 @@ TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) c uint32_t PrimitiveMesh::surface_get_format(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, 1, 0); - return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX; + uint32_t mesh_format = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX; + if (add_uv2) { + mesh_format |= RS::ARRAY_FORMAT_TEX_UV2; + } + + return mesh_format; } Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const { @@ -219,9 +247,17 @@ void PrimitiveMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces); ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces); + ClassDB::bind_method(D_METHOD("set_add_uv2", "add_uv2"), &PrimitiveMesh::set_add_uv2); + ClassDB::bind_method(D_METHOD("get_add_uv2"), &PrimitiveMesh::get_add_uv2); + + ClassDB::bind_method(D_METHOD("set_uv2_padding", "uv2_padding"), &PrimitiveMesh::set_uv2_padding); + ClassDB::bind_method(D_METHOD("get_uv2_padding"), &PrimitiveMesh::get_uv2_padding); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material"); ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "add_uv2"), "set_add_uv2", "get_add_uv2"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_padding"), "set_uv2_padding", "get_uv2_padding"); GDVIRTUAL_BIND(_create_mesh_array); } @@ -233,7 +269,7 @@ void PrimitiveMesh::set_material(const Ref<Material> &p_material) { RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); notify_property_list_changed(); emit_changed(); - }; + } } Ref<Material> PrimitiveMesh::get_material() const { @@ -263,6 +299,42 @@ bool PrimitiveMesh::get_flip_faces() const { return flip_faces; } +void PrimitiveMesh::set_add_uv2(bool p_enable) { + add_uv2 = p_enable; + _update_lightmap_size(); + _request_update(); +} + +void PrimitiveMesh::set_uv2_padding(float p_padding) { + uv2_padding = p_padding; + _update_lightmap_size(); + _request_update(); +} + +Vector2 PrimitiveMesh::get_uv2_scale(Vector2 p_margin_scale) const { + Vector2 uv2_scale; + Vector2 lightmap_size = get_lightmap_size_hint(); + + // Calculate it as a margin, if no lightmap size hint is given we assume "PADDING_REF_SIZE" as our texture size. + uv2_scale.x = p_margin_scale.x * uv2_padding / (lightmap_size.x == 0.0 ? PADDING_REF_SIZE : lightmap_size.x); + uv2_scale.y = p_margin_scale.y * uv2_padding / (lightmap_size.y == 0.0 ? PADDING_REF_SIZE : lightmap_size.y); + + // Inverse it to turn our margin into a scale + uv2_scale = Vector2(1.0, 1.0) - uv2_scale; + + return uv2_scale; +} + +float PrimitiveMesh::get_lightmap_texel_size() const { + float texel_size = GLOBAL_GET("rendering/lightmapping/primitive_meshes/texel_size"); + + if (texel_size <= 0.0) { + texel_size = 0.2; + } + + return texel_size; +} + PrimitiveMesh::PrimitiveMesh() { mesh = RenderingServer::get_singleton()->mesh_create(); } @@ -275,22 +347,52 @@ PrimitiveMesh::~PrimitiveMesh() { CapsuleMesh */ +void CapsuleMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend + float vertical_length = radial_length * 2 + (height - 2.0 * radius); // total vertical length + + _lightmap_size_hint.x = MAX(1.0, 4.0 * radial_length / texel_size) + padding; + _lightmap_size_hint.y = MAX(1.0, vertical_length / texel_size) + padding; + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void CapsuleMesh::_create_mesh_array(Array &p_arr) const { - create_mesh_array(p_arr, radius, height, radial_segments, rings); + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + create_mesh_array(p_arr, radius, height, radial_segments, rings, _add_uv2, _uv2_padding); } -void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) { +void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings, bool p_add_uv2, const float p_uv2_padding) { int i, j, prevrow, thisrow, point; float x, y, z, u, v, w; float onethird = 1.0 / 3.0; float twothirds = 2.0 / 3.0; + // Only used if we calculate UV2 + float radial_width = 2.0 * radius * Math_PI; + float radial_h = radial_width / (radial_width + p_uv2_padding); + float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend + float vertical_length = radial_length * 2 + (height - 2.0 * radius) + p_uv2_padding; // total vertical length + float radial_v = radial_length / vertical_length; // v size of top and bottom section + float height_v = (height - 2.0 * radius) / vertical_length; // v size of height section + // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom Vector<Vector3> points; Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; point = 0; @@ -322,6 +424,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa normals.push_back(p.normalized()); ADD_TANGENT(-z, 0.0, -x, 1.0) uvs.push_back(Vector2(u, v * onethird)); + if (p_add_uv2) { + uv2s.push_back(Vector2(u * radial_h, v * radial_v)); + } point++; if (i > 0 && j > 0) { @@ -332,12 +437,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; - }; + } + } prevrow = thisrow; thisrow = point; - }; + } /* cylinder */ thisrow = point; @@ -361,6 +466,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa normals.push_back(Vector3(x, 0.0, -z)); ADD_TANGENT(-z, 0.0, -x, 1.0) uvs.push_back(Vector2(u, onethird + (v * onethird))); + if (p_add_uv2) { + uv2s.push_back(Vector2(u * radial_h, radial_v + (v * height_v))); + } point++; if (i > 0 && j > 0) { @@ -371,12 +479,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; - }; + } + } prevrow = thisrow; thisrow = point; - }; + } /* bottom hemisphere */ thisrow = point; @@ -390,17 +498,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa y = radius * cos(0.5 * Math_PI * v); for (i = 0; i <= radial_segments; i++) { - float u2 = i; - u2 /= radial_segments; + u = i; + u /= radial_segments; - x = -sin(u2 * Math_TAU); - z = cos(u2 * Math_TAU); + x = -sin(u * Math_TAU); + z = cos(u * Math_TAU); Vector3 p = Vector3(x * radius * w, y, -z * radius * w); points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0)); normals.push_back(p.normalized()); ADD_TANGENT(-z, 0.0, -x, 1.0) - uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird))); + uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird))); + if (p_add_uv2) { + uv2s.push_back(Vector2(u * radial_h, radial_v + height_v + ((v - 1.0) * radial_v))); + } point++; if (i > 0 && j > 0) { @@ -411,17 +522,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; - }; + } + } prevrow = thisrow; thisrow = point; - }; + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (p_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -450,6 +564,7 @@ void CapsuleMesh::set_radius(const float p_radius) { if (radius > height * 0.5) { height = radius * 2.0; } + _update_lightmap_size(); _request_update(); } @@ -462,6 +577,7 @@ void CapsuleMesh::set_height(const float p_height) { if (radius > height * 0.5) { radius = height * 0.5; } + _update_lightmap_size(); _request_update(); } @@ -493,16 +609,53 @@ CapsuleMesh::CapsuleMesh() {} BoxMesh */ +void BoxMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + float width = (size.x + size.z) / texel_size; + float length = (size.y + size.y + MAX(size.x, size.z)) / texel_size; + + _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding; + _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding; + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void BoxMesh::_create_mesh_array(Array &p_arr) const { - BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d); + // Note about padding, with our box each face of the box faces a different direction so we want a seam + // around every face. We thus add our padding to the right and bottom of each face. + // With 3 faces along the width and 2 along the height of the texture we need to adjust our scale + // accordingly. + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d, _add_uv2, _uv2_padding); } -void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d) { +void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d, bool p_add_uv2, const float p_uv2_padding) { int i, j, prevrow, thisrow, point; float x, y, z; float onethird = 1.0 / 3.0; float twothirds = 2.0 / 3.0; + // Only used if we calculate UV2 + // TODO this could be improved by changing the order depending on which side is the longest (basically the below works best if size.y is the longest) + float total_h = (size.x + size.z + (2.0 * p_uv2_padding)); + float padding_h = p_uv2_padding / total_h; + float width_h = size.x / total_h; + float depth_h = size.z / total_h; + float total_v = (size.y + size.y + MAX(size.x, size.z) + (3.0 * p_uv2_padding)); + float padding_v = p_uv2_padding / total_v; + float width_v = size.x / total_v; + float height_v = size.y / total_v; + float depth_v = size.z / total_v; + Vector3 start_pos = size * -0.5; // set our bounding box @@ -511,6 +664,7 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; point = 0; @@ -525,18 +679,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int thisrow = point; prevrow = 0; for (j = 0; j <= subdivide_h + 1; j++) { + float v = j; + float v2 = v / (subdivide_w + 1.0); + v /= (2.0 * (subdivide_h + 1.0)); + x = start_pos.x; for (i = 0; i <= subdivide_w + 1; i++) { float u = i; - float v = j; + float u2 = u / (subdivide_w + 1.0); u /= (3.0 * (subdivide_w + 1.0)); - v /= (2.0 * (subdivide_h + 1.0)); // front points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z! normals.push_back(Vector3(0.0, 0.0, 1.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(u, v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(u2 * width_h, v2 * height_v)); + } point++; // back @@ -544,6 +704,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int normals.push_back(Vector3(0.0, 0.0, -1.0)); ADD_TANGENT(-1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(twothirds + u, v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(u2 * width_h, height_v + padding_v + (v2 * height_v))); + } point++; if (i > 0 && j > 0) { @@ -564,33 +727,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int indices.push_back(prevrow + i2 + 1); indices.push_back(thisrow + i2 + 1); indices.push_back(thisrow + i2 - 1); - }; + } x += size.x / (subdivide_w + 1.0); - }; + } y += size.y / (subdivide_h + 1.0); prevrow = thisrow; thisrow = point; - }; + } // left + right y = start_pos.y; thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_h + 1); j++) { + float v = j; + float v2 = v / (subdivide_h + 1.0); + v /= (2.0 * (subdivide_h + 1.0)); + z = start_pos.z; for (i = 0; i <= (subdivide_d + 1); i++) { float u = i; - float v = j; + float u2 = u / (subdivide_d + 1.0); u /= (3.0 * (subdivide_d + 1.0)); - v /= (2.0 * (subdivide_h + 1.0)); // right points.push_back(Vector3(-start_pos.x, -y, -z)); normals.push_back(Vector3(1.0, 0.0, 0.0)); ADD_TANGENT(0.0, 0.0, -1.0, 1.0); uvs.push_back(Vector2(onethird + u, v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), v2 * height_v)); + } point++; // left @@ -598,6 +767,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int normals.push_back(Vector3(-1.0, 0.0, 0.0)); ADD_TANGENT(0.0, 0.0, 1.0, 1.0); uvs.push_back(Vector2(u, 0.5 + v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), height_v + padding_v + (v2 * height_v))); + } point++; if (i > 0 && j > 0) { @@ -618,33 +790,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int indices.push_back(prevrow + i2 + 1); indices.push_back(thisrow + i2 + 1); indices.push_back(thisrow + i2 - 1); - }; + } z += size.z / (subdivide_d + 1.0); - }; + } y += size.y / (subdivide_h + 1.0); prevrow = thisrow; thisrow = point; - }; + } // top + bottom z = start_pos.z; thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_d + 1); j++) { + float v = j; + float v2 = v / (subdivide_d + 1.0); + v /= (2.0 * (subdivide_d + 1.0)); + x = start_pos.x; for (i = 0; i <= (subdivide_w + 1); i++) { float u = i; - float v = j; + float u2 = u / (subdivide_w + 1.0); u /= (3.0 * (subdivide_w + 1.0)); - v /= (2.0 * (subdivide_d + 1.0)); // top points.push_back(Vector3(-x, -start_pos.y, -z)); normals.push_back(Vector3(0.0, 1.0, 0.0)); ADD_TANGENT(-1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(onethird + u, 0.5 + v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(u2 * width_h, ((height_v + padding_v) * 2.0) + (v2 * depth_v))); + } point++; // bottom @@ -652,6 +830,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int normals.push_back(Vector3(0.0, -1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(twothirds + u, 0.5 + v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), ((height_v + padding_v) * 2.0) + (v2 * width_v))); + } point++; if (i > 0 && j > 0) { @@ -672,20 +853,23 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int indices.push_back(prevrow + i2 + 1); indices.push_back(thisrow + i2 + 1); indices.push_back(thisrow + i2 - 1); - }; + } x += size.x / (subdivide_w + 1.0); - }; + } z += size.z / (subdivide_d + 1.0); prevrow = thisrow; thisrow = point; - }; + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (p_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -708,6 +892,7 @@ void BoxMesh::_bind_methods() { void BoxMesh::set_size(const Vector3 &p_size) { size = p_size; + _update_lightmap_size(); _request_update(); } @@ -748,18 +933,58 @@ BoxMesh::BoxMesh() {} CylinderMesh */ +void CylinderMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + float top_circumference = top_radius * Math_PI * 2.0; + float bottom_circumference = bottom_radius * Math_PI * 2.0; + + float _width = MAX(top_circumference, bottom_circumference) / texel_size + padding; + _width = MAX(_width, (((top_radius + bottom_radius) / texel_size) + padding) * 2.0); // this is extremely unlikely to be larger, will only happen if padding is larger then our diameter. + _lightmap_size_hint.x = MAX(1.0, _width); + + float _height = ((height + (MAX(top_radius, bottom_radius) * 2.0)) / texel_size) + (2.0 * padding); + + _lightmap_size_hint.y = MAX(1.0, _height); + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void CylinderMesh::_create_mesh_array(Array &p_arr) const { - create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom); + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom, _add_uv2, _uv2_padding); } -void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom) { +void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom, bool p_add_uv2, const float p_uv2_padding) { int i, j, prevrow, thisrow, point; - float x, y, z, u, v, radius; + float x, y, z, u, v, radius, radius_h; + + // Only used if we calculate UV2 + float top_circumference = top_radius * Math_PI * 2.0; + float bottom_circumference = bottom_radius * Math_PI * 2.0; + float vertical_length = height + MAX(2.0 * top_radius, 2.0 * bottom_radius) + (2.0 * p_uv2_padding); + float height_v = height / vertical_length; + float padding_v = p_uv2_padding / vertical_length; + + float horizonal_length = MAX(MAX(2.0 * (top_radius + bottom_radius + p_uv2_padding), top_circumference + p_uv2_padding), bottom_circumference + p_uv2_padding); + float center_h = 0.5 * (horizonal_length - p_uv2_padding) / horizonal_length; + float top_h = top_circumference / horizonal_length; + float bottom_h = bottom_circumference / horizonal_length; + float padding_h = p_uv2_padding / horizonal_length; Vector<Vector3> points; Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; point = 0; @@ -777,6 +1002,7 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto v /= (rings + 1); radius = top_radius + ((bottom_radius - top_radius) * v); + radius_h = top_h + ((bottom_h - top_h) * v); y = height * v; y = (height * 0.5) - y; @@ -793,6 +1019,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto normals.push_back(Vector3(x, side_normal_y, z).normalized()); ADD_TANGENT(z, 0.0, -x, 1.0) uvs.push_back(Vector2(u, v * 0.5)); + if (p_add_uv2) { + uv2s.push_back(Vector2(center_h + (u - 0.5) * radius_h, v * height_v)); + } point++; if (i > 0 && j > 0) { @@ -803,14 +1032,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; - }; + } + } prevrow = thisrow; thisrow = point; - }; + } - // add top + // Adjust for bottom section, only used if we calculate UV2s. + top_h = top_radius / horizonal_length; + float top_v = top_radius / vertical_length; + bottom_h = bottom_radius / horizonal_length; + float bottom_v = bottom_radius / vertical_length; + + // Add top. if (cap_top && top_radius > 0.0) { y = height * 0.5; @@ -819,6 +1054,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto normals.push_back(Vector3(0.0, 1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0) uvs.push_back(Vector2(0.25, 0.75)); + if (p_add_uv2) { + uv2s.push_back(Vector2(top_h, height_v + padding_v + MAX(top_v, bottom_v))); + } point++; for (i = 0; i <= radial_segments; i++) { @@ -836,17 +1074,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto normals.push_back(Vector3(0.0, 1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0) uvs.push_back(Vector2(u, v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(top_h + (x * top_h), height_v + padding_v + MAX(top_v, bottom_v) + (z * top_v))); + } point++; if (i > 0) { indices.push_back(thisrow); indices.push_back(point - 1); indices.push_back(point - 2); - }; - }; - }; + } + } + } - // add bottom + // Add bottom. if (cap_bottom && bottom_radius > 0.0) { y = height * -0.5; @@ -855,6 +1096,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto normals.push_back(Vector3(0.0, -1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0) uvs.push_back(Vector2(0.75, 0.75)); + if (p_add_uv2) { + uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h, height_v + padding_v + MAX(top_v, bottom_v))); + } point++; for (i = 0; i <= radial_segments; i++) { @@ -872,20 +1116,26 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto normals.push_back(Vector3(0.0, -1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0) uvs.push_back(Vector2(u, v)); + if (p_add_uv2) { + uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h + (x * bottom_h), height_v + padding_v + MAX(top_v, bottom_v) - (z * bottom_v))); + } point++; if (i > 0) { indices.push_back(thisrow); indices.push_back(point - 2); indices.push_back(point - 1); - }; - }; - }; + } + } + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (p_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -919,6 +1169,7 @@ void CylinderMesh::_bind_methods() { void CylinderMesh::set_top_radius(const float p_radius) { top_radius = p_radius; + _update_lightmap_size(); _request_update(); } @@ -928,6 +1179,7 @@ float CylinderMesh::get_top_radius() const { void CylinderMesh::set_bottom_radius(const float p_radius) { bottom_radius = p_radius; + _update_lightmap_size(); _request_update(); } @@ -937,6 +1189,7 @@ float CylinderMesh::get_bottom_radius() const { void CylinderMesh::set_height(const float p_height) { height = p_height; + _update_lightmap_size(); _request_update(); } @@ -986,10 +1239,26 @@ CylinderMesh::CylinderMesh() {} PlaneMesh */ +void PlaneMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + _lightmap_size_hint.x = MAX(1.0, (size.x / texel_size) + padding); + _lightmap_size_hint.y = MAX(1.0, (size.y / texel_size) + padding); + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void PlaneMesh::_create_mesh_array(Array &p_arr) const { int i, j, prevrow, thisrow, point; float x, z; + // Plane mesh can use default UV2 calculation as implemented in Primitive Mesh + Size2 start_pos = size * -0.5; Vector3 normal = Vector3(0.0, 1.0, 0.0); @@ -1043,15 +1312,15 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; + } x += size.x / (subdivide_w + 1.0); - }; + } z += size.y / (subdivide_d + 1.0); prevrow = thisrow; thisrow = point; - }; + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; @@ -1088,6 +1357,7 @@ void PlaneMesh::_bind_methods() { void PlaneMesh::set_size(const Size2 &p_size) { size = p_size; + _update_lightmap_size(); _request_update(); } @@ -1137,12 +1407,49 @@ PlaneMesh::PlaneMesh() {} PrismMesh */ +void PrismMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + // left_to_right does not effect the surface area of the prism so we ignore that. + // TODO we could combine the two triangles and save some space but we need to re-align the uv1 and adjust the tangent. + + float width = (size.x + size.z) / texel_size; + float length = (size.y + size.y + size.z) / texel_size; + + _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding; + _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding; + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void PrismMesh::_create_mesh_array(Array &p_arr) const { int i, j, prevrow, thisrow, point; float x, y, z; float onethird = 1.0 / 3.0; float twothirds = 2.0 / 3.0; + // Only used if we calculate UV2 + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + float horizontal_total = size.x + size.z + 2.0 * _uv2_padding; + float width_h = size.x / horizontal_total; + float depth_h = size.z / horizontal_total; + float padding_h = _uv2_padding / horizontal_total; + + float vertical_total = (size.y + size.y + size.z) + (3.0 * _uv2_padding); + float height_v = size.y / vertical_total; + float depth_v = size.z / vertical_total; + float padding_v = _uv2_padding / vertical_total; + + // and start building + Vector3 start_pos = size * -0.5; // set our bounding box @@ -1151,6 +1458,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; point = 0; @@ -1171,12 +1479,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { float offset_front = (1.0 - scale) * onethird * left_to_right; float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right); + float v = j; + float v2 = j / (subdivide_h + 1.0); + v /= (2.0 * (subdivide_h + 1.0)); + x = 0.0; for (i = 0; i <= (subdivide_w + 1); i++) { float u = i; - float v = j; + float u2 = i / (subdivide_w + 1.0); u /= (3.0 * (subdivide_w + 1.0)); - v /= (2.0 * (subdivide_h + 1.0)); u *= scale; @@ -1185,6 +1496,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { normals.push_back(Vector3(0.0, 0.0, 1.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(offset_front + u, v)); + if (_add_uv2) { + uv2s.push_back(Vector2(u2 * scale * width_h, v2 * height_v)); + } point++; /* back */ @@ -1192,6 +1506,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { normals.push_back(Vector3(0.0, 0.0, -1.0)); ADD_TANGENT(-1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(twothirds + offset_back + u, v)); + if (_add_uv2) { + uv2s.push_back(Vector2(u2 * scale * width_h, height_v + padding_v + v2 * height_v)); + } point++; if (i > 0 && j == 1) { @@ -1224,15 +1541,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(prevrow + i2 + 1); indices.push_back(thisrow + i2 + 1); indices.push_back(thisrow + i2 - 1); - }; + } x += scale * size.x / (subdivide_w + 1.0); - }; + } y += size.y / (subdivide_h + 1.0); prevrow = thisrow; thisrow = point; - }; + } /* left + right */ Vector3 normal_left, normal_right; @@ -1246,6 +1563,10 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_h + 1); j++) { + float v = j; + float v2 = j / (subdivide_h + 1.0); + v /= (2.0 * (subdivide_h + 1.0)); + float left, right; float scale = (y - start_pos.y) / size.y; @@ -1255,15 +1576,17 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { z = start_pos.z; for (i = 0; i <= (subdivide_d + 1); i++) { float u = i; - float v = j; + float u2 = u / (subdivide_d + 1.0); u /= (3.0 * (subdivide_d + 1.0)); - v /= (2.0 * (subdivide_h + 1.0)); /* right */ points.push_back(Vector3(right, -y, -z)); normals.push_back(normal_right); ADD_TANGENT(0.0, 0.0, -1.0, 1.0); uvs.push_back(Vector2(onethird + u, v)); + if (_add_uv2) { + uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, v2 * height_v)); + } point++; /* left */ @@ -1271,6 +1594,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { normals.push_back(normal_left); ADD_TANGENT(0.0, 0.0, 1.0, 1.0); uvs.push_back(Vector2(u, 0.5 + v)); + if (_add_uv2) { + uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, height_v + padding_v + v2 * height_v)); + } point++; if (i > 0 && j > 0) { @@ -1291,33 +1617,39 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(prevrow + i2 + 1); indices.push_back(thisrow + i2 + 1); indices.push_back(thisrow + i2 - 1); - }; + } z += size.z / (subdivide_d + 1.0); - }; + } y += size.y / (subdivide_h + 1.0); prevrow = thisrow; thisrow = point; - }; + } /* bottom */ z = start_pos.z; thisrow = point; prevrow = 0; for (j = 0; j <= (subdivide_d + 1); j++) { + float v = j; + float v2 = v / (subdivide_d + 1.0); + v /= (2.0 * (subdivide_d + 1.0)); + x = start_pos.x; for (i = 0; i <= (subdivide_w + 1); i++) { float u = i; - float v = j; + float u2 = u / (subdivide_w + 1.0); u /= (3.0 * (subdivide_w + 1.0)); - v /= (2.0 * (subdivide_d + 1.0)); /* bottom */ points.push_back(Vector3(x, start_pos.y, -z)); normals.push_back(Vector3(0.0, -1.0, 0.0)); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(twothirds + u, 0.5 + v)); + if (_add_uv2) { + uv2s.push_back(Vector2(u2 * width_h, 2.0 * (height_v + padding_v) + v2 * depth_v)); + } point++; if (i > 0 && j > 0) { @@ -1328,20 +1660,23 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; + } x += size.x / (subdivide_w + 1.0); - }; + } z += size.z / (subdivide_d + 1.0); prevrow = thisrow; thisrow = point; - }; + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -1377,6 +1712,7 @@ float PrismMesh::get_left_to_right() const { void PrismMesh::set_size(const Vector3 &p_size) { size = p_size; + _update_lightmap_size(); _request_update(); } @@ -1417,22 +1753,50 @@ PrismMesh::PrismMesh() {} SphereMesh */ +void SphereMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + float _width = radius * Math_TAU; + _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding); + float _height = (is_hemisphere ? 1.0 : 0.5) * height * Math_PI; // note, with hemisphere height is our radius, while with a full sphere it is the diameter.. + _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding); + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void SphereMesh::_create_mesh_array(Array &p_arr) const { - create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere); + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere, _add_uv2, _uv2_padding); } -void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) { +void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere, bool p_add_uv2, const float p_uv2_padding) { int i, j, prevrow, thisrow, point; float x, y, z; float scale = height * (is_hemisphere ? 1.0 : 0.5); + // Only used if we calculate UV2 + float circumference = radius * Math_TAU; + float horizontal_length = circumference + p_uv2_padding; + float center_h = 0.5 * circumference / horizontal_length; + + float height_v = scale * Math_PI / ((scale * Math_PI) + p_uv2_padding); + // set our bounding box Vector<Vector3> points; Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; point = 0; @@ -1467,9 +1831,13 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int points.push_back(p); Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale); normals.push_back(normal.normalized()); - }; + } ADD_TANGENT(z, 0.0, -x, 1.0) uvs.push_back(Vector2(u, v)); + if (p_add_uv2) { + float w_h = w * 2.0 * center_h; + uv2s.push_back(Vector2(center_h + ((u - 0.5) * w_h), v * height_v)); + } point++; if (i > 0 && j > 0) { @@ -1480,17 +1848,20 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int indices.push_back(prevrow + i); indices.push_back(thisrow + i); indices.push_back(thisrow + i - 1); - }; - }; + } + } prevrow = thisrow; thisrow = point; - }; + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (p_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -1517,6 +1888,7 @@ void SphereMesh::_bind_methods() { void SphereMesh::set_radius(const float p_radius) { radius = p_radius; + _update_lightmap_size(); _request_update(); } @@ -1526,6 +1898,7 @@ float SphereMesh::get_radius() const { void SphereMesh::set_height(const float p_height) { height = p_height; + _update_lightmap_size(); _request_update(); } @@ -1553,6 +1926,7 @@ int SphereMesh::get_rings() const { void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { is_hemisphere = p_is_hemisphere; + _update_lightmap_size(); _request_update(); } @@ -1566,6 +1940,31 @@ SphereMesh::SphereMesh() {} TorusMesh */ +void TorusMesh::_update_lightmap_size() { + if (get_add_uv2()) { + // size must have changed, update lightmap size hint + Size2i _lightmap_size_hint; + float texel_size = get_lightmap_texel_size(); + float padding = get_uv2_padding(); + + float min_radius = inner_radius; + float max_radius = outer_radius; + + if (min_radius > max_radius) { + SWAP(min_radius, max_radius); + } + + float radius = (max_radius - min_radius) * 0.5; + + float _width = max_radius * Math_TAU; + _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding); + float _height = radius * Math_TAU; + _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding); + + set_lightmap_size_hint(_lightmap_size_hint); + } +} + void TorusMesh::_create_mesh_array(Array &p_arr) const { // set our bounding box @@ -1573,6 +1972,7 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const { Vector<Vector3> normals; Vector<float> tangents; Vector<Vector2> uvs; + Vector<Vector2> uv2s; Vector<int> indices; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -1592,6 +1992,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const { float radius = (max_radius - min_radius) * 0.5; + // Only used if we calculate UV2 + bool _add_uv2 = get_add_uv2(); + float texel_size = get_lightmap_texel_size(); + float _uv2_padding = get_uv2_padding() * texel_size; + + float horizontal_total = max_radius * Math_TAU + _uv2_padding; + float max_h = max_radius * Math_TAU / horizontal_total; + float delta_h = (max_radius - min_radius) * Math_TAU / horizontal_total; + + float height_v = radius * Math_TAU / (radius * Math_TAU + _uv2_padding); + for (int i = 0; i <= rings; i++) { int prevrow = (i - 1) * (ring_segments + 1); int thisrow = i * (ring_segments + 1); @@ -1607,10 +2018,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const { Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj)); Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0); + float offset_h = 0.5 * (1.0 - normalj.x) * delta_h; + float adj_h = max_h - offset_h; + offset_h *= 0.5; + points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x)); normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x)); ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0); uvs.push_back(Vector2(inci, incj)); + if (_add_uv2) { + uv2s.push_back(Vector2(offset_h + inci * adj_h, incj * height_v)); + } if (i > 0 && j > 0) { indices.push_back(thisrow + j - 1); @@ -1628,6 +2046,9 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const { p_arr[RS::ARRAY_NORMAL] = normals; p_arr[RS::ARRAY_TANGENT] = tangents; p_arr[RS::ARRAY_TEX_UV] = uvs; + if (_add_uv2) { + p_arr[RS::ARRAY_TEX_UV2] = uv2s; + } p_arr[RS::ARRAY_INDEX] = indices; } @@ -1785,6 +2206,8 @@ Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const { } void TubeTrailMesh::_create_mesh_array(Array &p_arr) const { + // Seeing use case for TubeTrailMesh, no need to do anything more then default UV2 calculation + PackedVector3Array points; PackedVector3Array normals; PackedFloat32Array tangents; @@ -1920,9 +2343,9 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(thisrow); indices.push_back(point - 1); indices.push_back(point - 2); - }; - }; - }; + } + } + } float scale_neg = 1.0; if (curve.is_valid() && curve->get_point_count() > 0) { @@ -1983,9 +2406,9 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const { indices.push_back(thisrow); indices.push_back(point - 2); indices.push_back(point - 1); - }; - }; - }; + } + } + } p_arr[RS::ARRAY_VERTEX] = points; p_arr[RS::ARRAY_NORMAL] = normals; @@ -2109,6 +2532,8 @@ Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const { } void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const { + // Seeing use case of ribbon trail mesh, no need to implement special UV2 calculation + PackedVector3Array points; PackedVector3Array normals; PackedFloat32Array tangents; diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index ee61f0ac55..06f9781b84 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -56,6 +56,9 @@ private: Ref<Material> material; bool flip_faces = false; + bool add_uv2 = false; + float uv2_padding = 2.0; + // make sure we do an update after we've finished constructing our object mutable bool pending_request = true; void _update() const; @@ -70,6 +73,10 @@ protected: void _request_update(); GDVIRTUAL0RC(Array, _create_mesh_array) + Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const; + float get_lightmap_texel_size() const; + virtual void _update_lightmap_size(){}; + public: virtual int get_surface_count() const override; virtual int surface_get_array_len(int p_idx) const override; @@ -98,6 +105,12 @@ public: void set_flip_faces(bool p_enable); bool get_flip_faces() const; + void set_add_uv2(bool p_enable); + bool get_add_uv2() const { return add_uv2; } + + void set_uv2_padding(float p_padding); + float get_uv2_padding() const { return uv2_padding; } + PrimitiveMesh(); ~PrimitiveMesh(); }; @@ -118,8 +131,10 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: - static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8); + static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8, bool p_add_uv2 = false, const float p_uv2_padding = 1.0); void set_radius(const float p_radius); float get_radius() const; @@ -152,8 +167,10 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: - static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0); + static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0, bool p_add_uv2 = false, const float p_uv2_padding = 1.0); void set_size(const Vector3 &p_size); Vector3 get_size() const; @@ -190,8 +207,10 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: - static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true); + static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true, bool p_add_uv2 = false, const float p_uv2_padding = 1.0); void set_top_radius(const float p_radius); float get_top_radius() const; @@ -241,6 +260,8 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: void set_size(const Size2 &p_size); Size2 get_size() const; @@ -292,6 +313,8 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: void set_left_to_right(const float p_left_to_right); float get_left_to_right() const; @@ -328,8 +351,10 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: - static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false); + static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false, bool p_add_uv2 = false, const float p_uv2_padding = 1.0); void set_radius(const float p_radius); float get_radius() const; @@ -365,6 +390,8 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) const override; + virtual void _update_lightmap_size() override; + public: void set_inner_radius(const float p_inner_radius); float get_inner_radius() const; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index ab21e2bbaa..712a67547b 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -511,6 +511,7 @@ Error ResourceLoaderText::load() { if (error) { _printerr(); + return error; } resource_current++; @@ -884,6 +885,7 @@ void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_d error_text = "Unexpected end of file"; _printerr(); error = ERR_FILE_CORRUPT; + return; } } } diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 4d566178a5..3a671edeea 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -177,7 +177,7 @@ bool Shader::is_text_shader() const { } bool Shader::has_parameter(const StringName &p_name) const { - return params_cache.has("shader_parameter/" + p_name); + return params_cache.has(p_name); } void Shader::_update_shader() const { diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 61daf801e8..af84144591 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -116,7 +116,7 @@ bool Shape2D::is_collision_outline_enabled() { return true; } #endif - return GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); + return GLOBAL_GET("debug/shapes/collision/draw_2d_outlines"); } Shape2D::Shape2D(const RID &p_rid) { diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h index 4a875d039f..0ca6582965 100644 --- a/scene/resources/skeleton_modification_2d_fabrik.h +++ b/scene/resources/skeleton_modification_2d_fabrik.h @@ -68,8 +68,8 @@ private: float chain_tolarance = 0.01; int chain_max_iterations = 10; int chain_iterations = 0; - Transform2D target_global_pose = Transform2D(); - Transform2D origin_global_pose = Transform2D(); + Transform2D target_global_pose; + Transform2D origin_global_pose; void fabrik_joint_update_bone2d_cache(int p_joint_idx); void chain_backwards(); diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h index e2e490d636..3e3aa5e587 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.h +++ b/scene/resources/skeleton_modification_3d_fabrik.h @@ -47,7 +47,7 @@ private: bool auto_calculate_length = true; bool use_tip_node = false; - NodePath tip_node = NodePath(); + NodePath tip_node; ObjectID tip_node_cache; bool use_target_basis = false; @@ -68,8 +68,8 @@ private: void update_joint_tip_cache(int p_joint_idx); int final_joint_idx = 0; - Transform3D target_global_pose = Transform3D(); - Transform3D origin_global_pose = Transform3D(); + Transform3D target_global_pose; + Transform3D origin_global_pose; void chain_backwards(); void chain_forwards(); diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index f1eddd8ffc..cb5cb4ef96 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -336,7 +336,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) { } String word = str.substr(j, to - j); - Color col = Color(); + Color col; if (keywords.has(word)) { col = keywords[word]; } else if (member_keywords.has(word)) { diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index a6fb359051..b5754caa6a 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -64,6 +64,7 @@ bool Texture2D::is_pixel_opaque(int p_x, int p_y) const { GDVIRTUAL_CALL(_is_pixel_opaque, p_x, p_y, ret); return ret; } + bool Texture2D::has_alpha() const { bool ret = true; GDVIRTUAL_CALL(_has_alpha, ret); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 3caf6484d9..d4ad81614d 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3789,7 +3789,7 @@ Vector2i TileSetAtlasSource::get_atlas_grid_size() const { Size2i valid_area = txt->get_size() - margins; // Compute the number of valid tiles in the tiles atlas - Size2i grid_size = Size2i(); + Size2i grid_size; if (valid_area.x >= texture_region_size.x && valid_area.y >= texture_region_size.y) { valid_area -= texture_region_size; grid_size = Size2i(1, 1) + valid_area / (texture_region_size + separation); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 8f175e99a6..9f465a17e9 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -785,7 +785,7 @@ private: bool flip_h = false; bool flip_v = false; bool transpose = false; - Vector2i tex_offset = Vector2i(); + Vector2i tex_offset; Ref<Material> material = Ref<Material>(); Color modulate = Color(1.0, 1.0, 1.0, 1.0); int z_index = 0; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 04637983b5..03abac1b3e 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3108,9 +3108,9 @@ void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_fun return; } if (p_func == FUNC_PANNING) { - set_input_port_default_value(2, Vector2()); // offset + set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // offset } else { // FUNC_SCALING - set_input_port_default_value(2, Vector2(0.5, 0.5)); // pivot + set_input_port_default_value(2, Vector2(0.5, 0.5), get_input_port_default_value(2)); // pivot } func = p_func; emit_changed(); |