diff options
108 files changed, 1143 insertions, 474 deletions
diff --git a/SConstruct b/SConstruct index 1eb6bdcbfd..7009cb8fbe 100644 --- a/SConstruct +++ b/SConstruct @@ -182,8 +182,8 @@ opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated an opts.Add(EnumVariable("float", "Floating-point precision", "32", ("32", "64"))) opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True)) opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False)) -opts.Add(BoolVariable("vulkan", "Enable the vulkan video driver", True)) -opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 video driver", True)) +opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True)) +opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True)) opts.Add(BoolVariable("openxr", "Enable the OpenXR driver", True)) opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True)) opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "") @@ -687,6 +687,14 @@ if selected_platform in platform_list: if methods.using_gcc(env): common_warnings += ["-Wshadow-local", "-Wno-misleading-indentation"] + if cc_version_major == 7: # Bogus warning fixed in 8+. + common_warnings += ["-Wno-strict-overflow"] + if cc_version_major < 11: + # Regression in GCC 9/10, spams so much in our variadic templates + # that we need to outright disable it. + common_warnings += ["-Wno-type-limits"] + if cc_version_major >= 12: # False positives in our error macros, see GH-58747. + common_warnings += ["-Wno-return-type"] elif methods.using_clang(env) or methods.using_emcc(env): # We often implement `operator<` for structs of pointers as a requirement # for putting them in `Set` or `Map`. We don't mind about unreliable ordering. @@ -702,13 +710,16 @@ if selected_platform in platform_list: "-Wduplicated-branches", "-Wduplicated-cond", "-Wstringop-overflow=4", - "-Wlogical-op", ] ) - # -Wnoexcept was removed temporarily due to GH-36325. env.Append(CXXFLAGS=["-Wplacement-new=1"]) + # Need to fix a warning with AudioServer lambdas before enabling. + # if cc_version_major != 9: # GCC 9 had a regression (GH-36325). + # env.Append(CXXFLAGS=["-Wnoexcept"]) if cc_version_major >= 9: env.Append(CCFLAGS=["-Wattribute-alias=2"]) + if cc_version_major >= 11: # Broke on MethodBind templates before GCC 11. + env.Append(CCFLAGS=["-Wlogical-op"]) elif methods.using_clang(env) or methods.using_emcc(env): env.Append(CCFLAGS=["-Wimplicit-fallthrough"]) elif env["warnings"] == "all": @@ -720,15 +731,6 @@ if selected_platform in platform_list: if env["werror"]: env.Append(CCFLAGS=["-Werror"]) - # FIXME: Temporary workaround after the Vulkan merge, remove once warnings are fixed. - if methods.using_gcc(env): - env.Append(CXXFLAGS=["-Wno-error=cpp"]) - if cc_version_major == 7: # Bogus warning fixed in 8+. - env.Append(CCFLAGS=["-Wno-error=strict-overflow"]) - if cc_version_major >= 12: # False positives in our error macros, see GH-58747. - env.Append(CCFLAGS=["-Wno-error=return-type"]) - elif methods.using_clang(env) or methods.using_emcc(env): - env.Append(CXXFLAGS=["-Wno-error=#warnings"]) if hasattr(detect, "get_program_suffix"): suffix = "." + detect.get_program_suffix() diff --git a/core/doc_data.h b/core/doc_data.h index bb356f027e..d5fbe37c96 100644 --- a/core/doc_data.h +++ b/core/doc_data.h @@ -57,6 +57,27 @@ public: } return name < p_arg.name; } + static ArgumentDoc from_dict(const Dictionary &p_dict) { + ArgumentDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("type")) { + doc.type = p_dict["type"]; + } + + if (p_dict.has("enumeration")) { + doc.enumeration = p_dict["enumeration"]; + } + + if (p_dict.has("default_value")) { + doc.default_value = p_dict["default_value"]; + } + + return doc; + } }; struct MethodDoc { @@ -97,6 +118,55 @@ public: } return name < p_method.name; } + static MethodDoc from_dict(const Dictionary &p_dict) { + MethodDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("return_type")) { + doc.return_type = p_dict["return_type"]; + } + + if (p_dict.has("return_enum")) { + doc.return_enum = p_dict["return_enum"]; + } + + if (p_dict.has("qualifiers")) { + doc.qualifiers = p_dict["qualifiers"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + if (p_dict.has("is_deprecated")) { + doc.is_deprecated = p_dict["is_deprecated"]; + } + + if (p_dict.has("is_experimental")) { + doc.is_experimental = p_dict["is_experimental"]; + } + + Array arguments; + if (p_dict.has("arguments")) { + arguments = p_dict["arguments"]; + } + for (int i = 0; i < arguments.size(); i++) { + doc.arguments.push_back(ArgumentDoc::from_dict(arguments[i])); + } + + Array errors_returned; + if (p_dict.has("errors_returned")) { + errors_returned = p_dict["errors_returned"]; + } + for (int i = 0; i < errors_returned.size(); i++) { + doc.errors_returned.push_back(errors_returned[i]); + } + + return doc; + } }; struct ConstantDoc { @@ -111,6 +181,43 @@ public: bool operator<(const ConstantDoc &p_const) const { return name < p_const.name; } + static ConstantDoc from_dict(const Dictionary &p_dict) { + ConstantDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("value")) { + doc.value = p_dict["value"]; + } + + if (p_dict.has("is_value_valid")) { + doc.is_value_valid = p_dict["is_value_valid"]; + } + + if (p_dict.has("enumeration")) { + doc.enumeration = p_dict["enumeration"]; + } + + if (p_dict.has("is_bitfield")) { + doc.is_bitfield = p_dict["is_bitfield"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + if (p_dict.has("is_deprecated")) { + doc.is_deprecated = p_dict["is_deprecated"]; + } + + if (p_dict.has("is_experimental")) { + doc.is_experimental = p_dict["is_experimental"]; + } + + return doc; + } }; struct EnumDoc { @@ -118,6 +225,31 @@ public: bool is_bitfield = false; String description; Vector<DocData::ConstantDoc> values; + static EnumDoc from_dict(const Dictionary &p_dict) { + EnumDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("is_bitfield")) { + doc.is_bitfield = p_dict["is_bitfield"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + Array values; + if (p_dict.has("values")) { + values = p_dict["values"]; + } + for (int i = 0; i < values.size(); i++) { + doc.values.push_back(ConstantDoc::from_dict(values[i])); + } + + return doc; + } }; struct PropertyDoc { @@ -134,6 +266,55 @@ public: bool operator<(const PropertyDoc &p_prop) const { return name < p_prop.name; } + static PropertyDoc from_dict(const Dictionary &p_dict) { + PropertyDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("type")) { + doc.type = p_dict["type"]; + } + + if (p_dict.has("enumeration")) { + doc.enumeration = p_dict["enumeration"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + if (p_dict.has("setter")) { + doc.setter = p_dict["setter"]; + } + + if (p_dict.has("getter")) { + doc.getter = p_dict["getter"]; + } + + if (p_dict.has("default_value")) { + doc.default_value = p_dict["default_value"]; + } + + if (p_dict.has("overridden")) { + doc.overridden = p_dict["overridden"]; + } + + if (p_dict.has("overrides")) { + doc.overrides = p_dict["overrides"]; + } + + if (p_dict.has("is_deprecated")) { + doc.is_deprecated = p_dict["is_deprecated"]; + } + + if (p_dict.has("is_experimental")) { + doc.is_experimental = p_dict["is_experimental"]; + } + + return doc; + } }; struct ThemeItemDoc { @@ -149,11 +330,49 @@ public: } return data_type < p_theme_item.data_type; } + static ThemeItemDoc from_dict(const Dictionary &p_dict) { + ThemeItemDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("type")) { + doc.type = p_dict["type"]; + } + + if (p_dict.has("data_type")) { + doc.data_type = p_dict["data_type"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + if (p_dict.has("default_value")) { + doc.default_value = p_dict["default_value"]; + } + + return doc; + } }; struct TutorialDoc { String link; String title; + static TutorialDoc from_dict(const Dictionary &p_dict) { + TutorialDoc doc; + + if (p_dict.has("link")) { + doc.link = p_dict["link"]; + } + + if (p_dict.has("title")) { + doc.title = p_dict["title"]; + } + + return doc; + } }; struct ClassDoc { @@ -179,6 +398,127 @@ public: bool operator<(const ClassDoc &p_class) const { return name < p_class.name; } + static ClassDoc from_dict(const Dictionary &p_dict) { + ClassDoc doc; + + if (p_dict.has("name")) { + doc.name = p_dict["name"]; + } + + if (p_dict.has("inherits")) { + doc.inherits = p_dict["inherits"]; + } + + if (p_dict.has("category")) { + doc.category = p_dict["category"]; + } + + if (p_dict.has("brief_description")) { + doc.brief_description = p_dict["brief_description"]; + } + + if (p_dict.has("description")) { + doc.description = p_dict["description"]; + } + + Array tutorials; + if (p_dict.has("tutorials")) { + tutorials = p_dict["tutorials"]; + } + for (int i = 0; i < tutorials.size(); i++) { + doc.tutorials.push_back(TutorialDoc::from_dict(tutorials[i])); + } + + Array constructors; + if (p_dict.has("constructors")) { + constructors = p_dict["constructors"]; + } + for (int i = 0; i < constructors.size(); i++) { + doc.constructors.push_back(MethodDoc::from_dict(constructors[i])); + } + + Array methods; + if (p_dict.has("methods")) { + methods = p_dict["methods"]; + } + for (int i = 0; i < methods.size(); i++) { + doc.methods.push_back(MethodDoc::from_dict(methods[i])); + } + + Array operators; + if (p_dict.has("operators")) { + operators = p_dict["operators"]; + } + for (int i = 0; i < operators.size(); i++) { + doc.operators.push_back(MethodDoc::from_dict(operators[i])); + } + + Array signals; + if (p_dict.has("signals")) { + signals = p_dict["signals"]; + } + for (int i = 0; i < signals.size(); i++) { + doc.signals.push_back(MethodDoc::from_dict(signals[i])); + } + + Array constants; + if (p_dict.has("constants")) { + constants = p_dict["constants"]; + } + for (int i = 0; i < constants.size(); i++) { + doc.constants.push_back(ConstantDoc::from_dict(constants[i])); + } + + Dictionary enums; + if (p_dict.has("enums")) { + enums = p_dict["enums"]; + } + for (int i = 0; i < enums.size(); i++) { + doc.enums[enums.get_key_at_index(i)] = enums.get_value_at_index(i); + } + + Array properties; + if (p_dict.has("properties")) { + properties = p_dict["properties"]; + } + for (int i = 0; i < properties.size(); i++) { + doc.properties.push_back(PropertyDoc::from_dict(properties[i])); + } + + Array annotations; + if (p_dict.has("annotations")) { + annotations = p_dict["annotations"]; + } + for (int i = 0; i < annotations.size(); i++) { + doc.annotations.push_back(MethodDoc::from_dict(annotations[i])); + } + + Array theme_properties; + if (p_dict.has("theme_properties")) { + theme_properties = p_dict["theme_properties"]; + } + for (int i = 0; i < theme_properties.size(); i++) { + doc.theme_properties.push_back(ThemeItemDoc::from_dict(theme_properties[i])); + } + + if (p_dict.has("is_deprecated")) { + doc.is_deprecated = p_dict["is_deprecated"]; + } + + if (p_dict.has("is_experimental")) { + doc.is_experimental = p_dict["is_experimental"]; + } + + if (p_dict.has("is_script_doc")) { + doc.is_script_doc = p_dict["is_script_doc"]; + } + + if (p_dict.has("script_path")) { + doc.script_path = p_dict["script_path"]; + } + + return doc; + } }; static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo); diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index a018221b7f..2fb357b520 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -49,6 +49,11 @@ Ref<ResourceFormatLoader> ResourceLoader::loader[ResourceLoader::MAX_LOADERS]; int ResourceLoader::loader_count = 0; bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_for_type) const { + bool ret = false; + if (GDVIRTUAL_CALL(_recognize_path, p_path, p_for_type, ret)) { + return ret; + } + String extension = p_path.get_extension(); List<String> extensions; @@ -189,6 +194,7 @@ void ResourceFormatLoader::_bind_methods() { BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE); GDVIRTUAL_BIND(_get_recognized_extensions); + GDVIRTUAL_BIND(_recognize_path, "path", "type"); GDVIRTUAL_BIND(_handles_type, "type"); GDVIRTUAL_BIND(_get_resource_type, "path"); GDVIRTUAL_BIND(_get_resource_uid, "path"); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 91ba930176..243670b2d0 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -51,6 +51,7 @@ protected: static void _bind_methods(); GDVIRTUAL0RC(Vector<String>, _get_recognized_extensions) + GDVIRTUAL2RC(bool, _recognize_path, String, StringName) GDVIRTUAL1RC(bool, _handles_type, StringName) GDVIRTUAL1RC(String, _get_resource_type, String) GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String) diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 026f179445..fcf245d2ad 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -76,6 +76,10 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const { return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size); } +bool AABB::is_finite() const { + return position.is_finite() && size.is_finite(); +} + AABB AABB::intersection(const AABB &p_aabb) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) { diff --git a/core/math/aabb.h b/core/math/aabb.h index b9f777c6cf..9d5837ad37 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -63,6 +63,7 @@ struct _NO_DISCARD_ AABB { bool operator!=(const AABB &p_rval) const; bool is_equal_approx(const AABB &p_aabb) const; + bool is_finite() const; _FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap _FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap _FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 845686f339..9b8188eed8 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -691,6 +691,10 @@ bool Basis::is_equal_approx(const Basis &p_basis) const { return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]); } +bool Basis::is_finite() const { + return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite(); +} + bool Basis::operator==(const Basis &p_matrix) const { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { diff --git a/core/math/basis.h b/core/math/basis.h index cc2924f5ff..69bef5a7be 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -134,6 +134,7 @@ struct _NO_DISCARD_ Basis { } bool is_equal_approx(const Basis &p_basis) const; + bool is_finite() const; bool operator==(const Basis &p_matrix) const; bool operator!=(const Basis &p_matrix) const; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 7fa674a23d..0af529ad98 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -184,6 +184,9 @@ public: #endif } + static _ALWAYS_INLINE_ bool is_finite(double p_val) { return isfinite(p_val); } + static _ALWAYS_INLINE_ bool is_finite(float p_val) { return isfinite(p_val); } + static _ALWAYS_INLINE_ double abs(double g) { return absd(g); } static _ALWAYS_INLINE_ float abs(float g) { return absf(g); } static _ALWAYS_INLINE_ int abs(int g) { return g > 0 ? g : -g; } diff --git a/core/math/plane.cpp b/core/math/plane.cpp index 3b2eab4ae2..a5d2fe5628 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -176,6 +176,10 @@ bool Plane::is_equal_approx(const Plane &p_plane) const { return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d); } +bool Plane::is_finite() const { + return normal.is_finite() && Math::is_finite(d); +} + Plane::operator String() const { return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]"; } diff --git a/core/math/plane.h b/core/math/plane.h index 73babfa496..77da59fb27 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -74,6 +74,7 @@ struct _NO_DISCARD_ Plane { Plane operator-() const { return Plane(-normal, -d); } bool is_equal_approx(const Plane &p_plane) const; bool is_equal_approx_any_side(const Plane &p_plane) const; + bool is_finite() const; _FORCE_INLINE_ bool operator==(const Plane &p_plane) const; _FORCE_INLINE_ bool operator!=(const Plane &p_plane) const; diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp index 4a8d29e402..6a5f29f3d8 100644 --- a/core/math/quaternion.cpp +++ b/core/math/quaternion.cpp @@ -79,6 +79,10 @@ bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const { return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w); } +bool Quaternion::is_finite() const { + return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w); +} + real_t Quaternion::length() const { return Math::sqrt(length_squared()); } diff --git a/core/math/quaternion.h b/core/math/quaternion.h index 178cfaca70..7aa400aa8c 100644 --- a/core/math/quaternion.h +++ b/core/math/quaternion.h @@ -55,6 +55,7 @@ struct _NO_DISCARD_ Quaternion { } _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quaternion &p_quaternion) const; + bool is_finite() const; real_t length() const; void normalize(); Quaternion normalized() const; diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp index 9e78ead816..facf4eb3c4 100644 --- a/core/math/rect2.cpp +++ b/core/math/rect2.cpp @@ -38,6 +38,10 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const { return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size); } +bool Rect2::is_finite() const { + return position.is_finite() && size.is_finite(); +} + bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0)) { diff --git a/core/math/rect2.h b/core/math/rect2.h index 50dd2dc1df..9863405d8e 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -207,6 +207,7 @@ struct _NO_DISCARD_ Rect2 { } bool is_equal_approx(const Rect2 &p_rect) const; + bool is_finite() const; bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; } bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 2bfefe979f..548a82d254 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -168,6 +168,10 @@ bool Transform2D::is_equal_approx(const Transform2D &p_transform) const { return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]); } +bool Transform2D::is_finite() const { + return columns[0].is_finite() && columns[1].is_finite() && columns[2].is_finite(); +} + Transform2D Transform2D::looking_at(const Vector2 &p_target) const { Transform2D return_trans = Transform2D(get_rotation(), get_origin()); Vector2 target_position = affine_inverse().xform(p_target); diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index f23f32867a..2b11f36535 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -98,6 +98,7 @@ struct _NO_DISCARD_ Transform2D { void orthonormalize(); Transform2D orthonormalized() const; bool is_equal_approx(const Transform2D &p_transform) const; + bool is_finite() const; Transform2D looking_at(const Vector2 &p_target) const; diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index 6741ef4034..3285cbd664 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -174,6 +174,10 @@ bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); } +bool Transform3D::is_finite() const { + return basis.is_finite() && origin.is_finite(); +} + bool Transform3D::operator==(const Transform3D &p_transform) const { return (basis == p_transform.basis && origin == p_transform.origin); } diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index 44d6d826f3..cb347aa1c1 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -75,6 +75,7 @@ struct _NO_DISCARD_ Transform3D { void orthogonalize(); Transform3D orthogonalized() const; bool is_equal_approx(const Transform3D &p_transform) const; + bool is_finite() const; bool operator==(const Transform3D &p_transform) const; bool operator!=(const Transform3D &p_transform) const; diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 56dbba393a..5366587126 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -186,6 +186,10 @@ bool Vector2::is_zero_approx() const { return Math::is_zero_approx(x) && Math::is_zero_approx(y); } +bool Vector2::is_finite() const { + return Math::is_finite(x) && Math::is_finite(y); +} + Vector2::operator String() const { return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")"; } diff --git a/core/math/vector2.h b/core/math/vector2.h index 75364f72f0..5775d8e735 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -121,6 +121,7 @@ struct _NO_DISCARD_ Vector2 { bool is_equal_approx(const Vector2 &p_v) const; bool is_zero_approx() const; + bool is_finite() const; Vector2 operator+(const Vector2 &p_v) const; void operator+=(const Vector2 &p_v); diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 55ba509144..b106200c4a 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -139,6 +139,10 @@ bool Vector3::is_zero_approx() const { return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z); } +bool Vector3::is_finite() const { + return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z); +} + Vector3::operator String() const { return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")"; } diff --git a/core/math/vector3.h b/core/math/vector3.h index 62e810fb4d..19771eb312 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -136,6 +136,7 @@ struct _NO_DISCARD_ Vector3 { bool is_equal_approx(const Vector3 &p_v) const; bool is_zero_approx() const; + bool is_finite() const; /* Operators */ diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp index 9fd980aaff..3b189f7ed4 100644 --- a/core/math/vector4.cpp +++ b/core/math/vector4.cpp @@ -64,6 +64,10 @@ bool Vector4::is_zero_approx() const { return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z) && Math::is_zero_approx(w); } +bool Vector4::is_finite() const { + return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w); +} + real_t Vector4::length() const { return Math::sqrt(length_squared()); } diff --git a/core/math/vector4.h b/core/math/vector4.h index ac7b6c3aee..7c4bdc1788 100644 --- a/core/math/vector4.h +++ b/core/math/vector4.h @@ -71,6 +71,7 @@ struct _NO_DISCARD_ Vector4 { _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Vector4 &p_vec4) const; bool is_zero_approx() const; + bool is_finite() const; real_t length() const; void normalize(); Vector4 normalized() const; diff --git a/core/object/method_bind.h b/core/object/method_bind.h index 0d3e40f709..598e8a224d 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -292,11 +292,6 @@ class MethodBindT : public MethodBind { void (MB_T::*method)(P...); protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -304,9 +299,6 @@ protected: return Variant::NIL; } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; @@ -367,11 +359,6 @@ class MethodBindTC : public MethodBind { void (MB_T::*method)(P...) const; protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -379,9 +366,6 @@ protected: return Variant::NIL; } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; @@ -444,11 +428,6 @@ class MethodBindTR : public MethodBind { (P...); protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -466,9 +445,6 @@ protected: return GetTypeInfo<R>::get_class_info(); } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -531,11 +507,6 @@ class MethodBindTRC : public MethodBind { (P...) const; protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -553,9 +524,6 @@ protected: return GetTypeInfo<R>::get_class_info(); } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -615,11 +583,6 @@ class MethodBindTS : public MethodBind { void (*function)(P...); protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -627,9 +590,6 @@ protected: return Variant::NIL; } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { PropertyInfo pi; @@ -678,11 +638,6 @@ class MethodBindTRS : public MethodBind { (P...); protected: -// GCC raises warnings in the case P = {} as the comparison is always false... -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlogical-op" -#endif virtual Variant::Type _gen_argument_type(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { return call_get_argument_type<P...>(p_arg); @@ -690,9 +645,6 @@ protected: return GetTypeInfo<R>::VARIANT_TYPE; } } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 7e74f6a2be..c32fb9d85b 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -82,9 +82,10 @@ public: GDVIRTUAL_REQUIRED_CALL(_get_documentation, doc); Vector<DocData::ClassDoc> class_doc; -#ifndef _MSC_VER -#warning missing conversion from documentation to ClassDoc -#endif + for (int i = 0; i < doc.size(); i++) { + class_doc.append(DocData::ClassDoc::from_dict(doc[i])); + } + return class_doc; } #endif // TOOLS_ENABLED diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index dbbcedca84..872c8357ae 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -4654,10 +4654,10 @@ String String::sprintf(const Array &values, bool *error) const { double value = values[value_index]; bool is_negative = (value < 0); String str = String::num(ABS(value), min_decimals); - bool not_numeric = isinf(value) || isnan(value); + const bool is_finite = Math::is_finite(value); // Pad decimals out. - if (!not_numeric) { + if (is_finite) { str = str.pad_decimals(min_decimals); } @@ -4665,7 +4665,7 @@ String String::sprintf(const Array &values, bool *error) const { // Padding. Leave room for sign later if required. int pad_chars_count = (is_negative || show_sign) ? min_chars - 1 : min_chars; - String pad_char = (pad_with_zeros && !not_numeric) ? String("0") : String(" "); // Never pad NaN or inf with zeros + String pad_char = (pad_with_zeros && is_finite) ? String("0") : String(" "); // Never pad NaN or inf with zeros if (left_justified) { str = str.rpad(pad_chars_count, pad_char); } else { @@ -4716,10 +4716,10 @@ String String::sprintf(const Array &values, bool *error) const { for (int i = 0; i < count; i++) { double val = vec[i]; String number_str = String::num(ABS(val), min_decimals); - bool not_numeric = isinf(val) || isnan(val); + const bool is_finite = Math::is_finite(val); // Pad decimals out. - if (!not_numeric) { + if (is_finite) { number_str = number_str.pad_decimals(min_decimals); } @@ -4727,7 +4727,7 @@ String String::sprintf(const Array &values, bool *error) const { // Padding. Leave room for sign later if required. int pad_chars_count = val < 0 ? min_chars - 1 : min_chars; - String pad_char = (pad_with_zeros && !not_numeric) ? String("0") : String(" "); // Never pad NaN or inf with zeros + String pad_char = (pad_with_zeros && is_finite) ? String("0") : String(" "); // Never pad NaN or inf with zeros if (left_justified) { number_str = number_str.rpad(pad_chars_count, pad_char); } else { diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 4eae23b0fb..b4528e67d1 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -47,146 +47,126 @@ String Variant::get_type_name(Variant::Type p_type) { switch (p_type) { case NIL: { return "Nil"; - } break; + } - // atomic types + // Atomic types. case BOOL: { return "bool"; - } break; + } case INT: { return "int"; - - } break; + } case FLOAT: { return "float"; - - } break; + } case STRING: { return "String"; - } break; + } - // math types + // Math types. case VECTOR2: { return "Vector2"; - } break; + } case VECTOR2I: { return "Vector2i"; - } break; + } case RECT2: { return "Rect2"; - } break; + } case RECT2I: { return "Rect2i"; - } break; + } case TRANSFORM2D: { return "Transform2D"; - } break; + } case VECTOR3: { return "Vector3"; - } break; + } case VECTOR3I: { return "Vector3i"; - } break; + } case VECTOR4: { return "Vector4"; - } break; + } case VECTOR4I: { return "Vector4i"; - } break; + } case PLANE: { return "Plane"; - - } break; + } case AABB: { return "AABB"; - } break; + } case QUATERNION: { return "Quaternion"; - - } break; + } case BASIS: { return "Basis"; - - } break; + } case TRANSFORM3D: { return "Transform3D"; - - } break; + } case PROJECTION: { return "Projection"; + } - } break; - - // misc types + // Miscellaneous types. case COLOR: { return "Color"; - - } break; + } case RID: { return "RID"; - } break; + } case OBJECT: { return "Object"; - } break; + } case CALLABLE: { return "Callable"; - } break; + } case SIGNAL: { return "Signal"; - } break; + } case STRING_NAME: { return "StringName"; - - } break; + } case NODE_PATH: { return "NodePath"; - - } break; + } case DICTIONARY: { return "Dictionary"; - - } break; + } case ARRAY: { return "Array"; + } - } break; - - // arrays + // Arrays. case PACKED_BYTE_ARRAY: { return "PackedByteArray"; - - } break; + } case PACKED_INT32_ARRAY: { return "PackedInt32Array"; - - } break; + } case PACKED_INT64_ARRAY: { return "PackedInt64Array"; - - } break; + } case PACKED_FLOAT32_ARRAY: { return "PackedFloat32Array"; - - } break; + } case PACKED_FLOAT64_ARRAY: { return "PackedFloat64Array"; - - } break; + } case PACKED_STRING_ARRAY: { return "PackedStringArray"; - } break; + } case PACKED_VECTOR2_ARRAY: { return "PackedVector2Array"; - - } break; + } case PACKED_VECTOR3_ARRAY: { return "PackedVector3Array"; - - } break; + } case PACKED_COLOR_ARRAY: { return "PackedColorArray"; - - } break; + } default: { } } @@ -880,157 +860,126 @@ bool Variant::is_zero() const { switch (type) { case NIL: { return true; - } break; + } - // atomic types + // Atomic types. case BOOL: { return !(_data._bool); - } break; + } case INT: { return _data._int == 0; - - } break; + } case FLOAT: { return _data._float == 0; - - } break; + } case STRING: { return *reinterpret_cast<const String *>(_data._mem) == String(); + } - } break; - - // math types + // Math types. case VECTOR2: { return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(); - - } break; + } case VECTOR2I: { return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(); - - } break; + } case RECT2: { return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(); - - } break; + } case RECT2I: { return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(); - - } break; + } case TRANSFORM2D: { return *_data._transform2d == Transform2D(); - - } break; + } case VECTOR3: { return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(); - - } break; + } case VECTOR3I: { return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(); - - } break; + } case VECTOR4: { return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4(); - - } break; + } case VECTOR4I: { return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i(); - - } break; + } case PLANE: { return *reinterpret_cast<const Plane *>(_data._mem) == Plane(); - - } break; + } case AABB: { return *_data._aabb == ::AABB(); - } break; + } case QUATERNION: { return *reinterpret_cast<const Quaternion *>(_data._mem) == Quaternion(); - - } break; + } case BASIS: { return *_data._basis == Basis(); - - } break; + } case TRANSFORM3D: { return *_data._transform3d == Transform3D(); - - } break; + } case PROJECTION: { return *_data._projection == Projection(); + } - } break; - - // misc types + // Miscellaneous types. case COLOR: { return *reinterpret_cast<const Color *>(_data._mem) == Color(); - - } break; + } case RID: { return *reinterpret_cast<const ::RID *>(_data._mem) == ::RID(); - } break; + } case OBJECT: { return _get_obj().obj == nullptr; - } break; + } case CALLABLE: { return reinterpret_cast<const Callable *>(_data._mem)->is_null(); - } break; + } case SIGNAL: { return reinterpret_cast<const Signal *>(_data._mem)->is_null(); - } break; + } case STRING_NAME: { return *reinterpret_cast<const StringName *>(_data._mem) != StringName(); - - } break; + } case NODE_PATH: { return reinterpret_cast<const NodePath *>(_data._mem)->is_empty(); - - } break; + } case DICTIONARY: { return reinterpret_cast<const Dictionary *>(_data._mem)->is_empty(); - - } break; + } case ARRAY: { return reinterpret_cast<const Array *>(_data._mem)->is_empty(); + } - } break; - - // arrays + // Arrays. case PACKED_BYTE_ARRAY: { return PackedArrayRef<uint8_t>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_INT32_ARRAY: { return PackedArrayRef<int32_t>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_INT64_ARRAY: { return PackedArrayRef<int64_t>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_FLOAT32_ARRAY: { return PackedArrayRef<float>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_FLOAT64_ARRAY: { return PackedArrayRef<double>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_STRING_ARRAY: { return PackedArrayRef<String>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_VECTOR2_ARRAY: { return PackedArrayRef<Vector2>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_VECTOR3_ARRAY: { return PackedArrayRef<Vector3>::get_array(_data.packed_array).size() == 0; - - } break; + } case PACKED_COLOR_ARRAY: { return PackedArrayRef<Color>::get_array(_data.packed_array).size() == 0; - - } break; + } default: { } } @@ -1042,60 +991,49 @@ bool Variant::is_one() const { switch (type) { case NIL: { return true; - } break; + } - // atomic types case BOOL: { return _data._bool; - } break; + } case INT: { return _data._int == 1; - - } break; + } case FLOAT: { return _data._float == 1; + } - } break; case VECTOR2: { return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(1, 1); - - } break; + } case VECTOR2I: { return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(1, 1); - - } break; + } case RECT2: { return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(1, 1, 1, 1); - - } break; + } case RECT2I: { return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(1, 1, 1, 1); - - } break; + } case VECTOR3: { return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(1, 1, 1); - - } break; + } case VECTOR3I: { return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1); - - } break; + } case VECTOR4: { return *reinterpret_cast<const Vector4 *>(_data._mem) == Vector4(1, 1, 1, 1); - - } break; + } case VECTOR4I: { return *reinterpret_cast<const Vector4i *>(_data._mem) == Vector4i(1, 1, 1, 1); - - } break; + } case PLANE: { return *reinterpret_cast<const Plane *>(_data._mem) == Plane(1, 1, 1, 1); + } - } break; case COLOR: { return *reinterpret_cast<const Color *>(_data._mem) == Color(1, 1, 1, 1); - - } break; + } default: { return !is_zero(); @@ -1133,10 +1071,10 @@ void Variant::reference(const Variant &p_variant) { switch (p_variant.type) { case NIL: { - // none + // None. } break; - // atomic types + // Atomic types. case BOOL: { _data._bool = p_variant._data._bool; } break; @@ -1150,7 +1088,7 @@ void Variant::reference(const Variant &p_variant) { memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem))); } break; - // math types + // Math types. case VECTOR2: { memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem))); } break; @@ -1202,10 +1140,9 @@ void Variant::reference(const Variant &p_variant) { memnew_placement(_data._projection, Projection(*p_variant._data._projection)); } break; - // misc types + // Miscellaneous types. case COLOR: { memnew_placement(_data._mem, Color(*reinterpret_cast<const Color *>(p_variant._data._mem))); - } break; case RID: { memnew_placement(_data._mem, ::RID(*reinterpret_cast<const ::RID *>(p_variant._data._mem))); @@ -1224,7 +1161,6 @@ void Variant::reference(const Variant &p_variant) { _get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj); _get_obj().id = p_variant._get_obj().id; - } break; case CALLABLE: { memnew_placement(_data._mem, Callable(*reinterpret_cast<const Callable *>(p_variant._data._mem))); @@ -1234,84 +1170,71 @@ void Variant::reference(const Variant &p_variant) { } break; case STRING_NAME: { memnew_placement(_data._mem, StringName(*reinterpret_cast<const StringName *>(p_variant._data._mem))); - } break; case NODE_PATH: { memnew_placement(_data._mem, NodePath(*reinterpret_cast<const NodePath *>(p_variant._data._mem))); - } break; case DICTIONARY: { memnew_placement(_data._mem, Dictionary(*reinterpret_cast<const Dictionary *>(p_variant._data._mem))); - } break; case ARRAY: { memnew_placement(_data._mem, Array(*reinterpret_cast<const Array *>(p_variant._data._mem))); - } break; - // arrays + // Arrays. case PACKED_BYTE_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<uint8_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<uint8_t>::create(); } - } break; case PACKED_INT32_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<int32_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<int32_t>::create(); } - } break; case PACKED_INT64_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<int64_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<int64_t>::create(); } - } break; case PACKED_FLOAT32_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<float> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<float>::create(); } - } break; case PACKED_FLOAT64_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<double> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<double>::create(); } - } break; case PACKED_STRING_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<String> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<String>::create(); } - } break; case PACKED_VECTOR2_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<Vector2> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Vector2>::create(); } - } break; case PACKED_VECTOR3_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<Vector3> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Vector3>::create(); } - } break; case PACKED_COLOR_ARRAY: { _data.packed_array = static_cast<PackedArrayRef<Color> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Color>::create(); } - } break; default: { } @@ -1331,6 +1254,7 @@ void Variant::zero() { case FLOAT: this->_data._float = 0; break; + case VECTOR2: *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); break; @@ -1361,9 +1285,11 @@ void Variant::zero() { case QUATERNION: *reinterpret_cast<Quaternion *>(this->_data._mem) = Quaternion(); break; + case COLOR: *reinterpret_cast<Color *>(this->_data._mem) = Color(); break; + default: this->clear(); break; @@ -1375,15 +1301,8 @@ void Variant::_clear_internal() { case STRING: { reinterpret_cast<String *>(_data._mem)->~String(); } break; - /* - // no point, they don't allocate memory - VECTOR3, - PLANE, - QUATERNION, - COLOR, - VECTOR2, - RECT2 - */ + + // Math types. case TRANSFORM2D: { if (_data._transform2d) { _data._transform2d->~Transform2D(); @@ -1419,7 +1338,8 @@ void Variant::_clear_internal() { _data._projection = nullptr; } } break; - // misc types + + // Miscellaneous types. case STRING_NAME: { reinterpret_cast<StringName *>(_data._mem)->~StringName(); } break; @@ -1428,7 +1348,7 @@ void Variant::_clear_internal() { } break; case OBJECT: { if (_get_obj().id.is_ref_counted()) { - //we are safe that there is a reference here + // We are safe that there is a reference here. RefCounted *ref_counted = static_cast<RefCounted *>(_get_obj().obj); if (ref_counted->unreference()) { memdelete(ref_counted); @@ -1438,8 +1358,8 @@ void Variant::_clear_internal() { _get_obj().id = ObjectID(); } break; case RID: { - // not much need probably - // Can't seem to use destructor + scoping operator, so hack. + // Not much need probably. + // HACK: Can't seem to use destructor + scoping operator, so hack. typedef ::RID RID_Class; reinterpret_cast<RID_Class *>(_data._mem)->~RID_Class(); } break; @@ -1455,7 +1375,8 @@ void Variant::_clear_internal() { case ARRAY: { reinterpret_cast<Array *>(_data._mem)->~Array(); } break; - // arrays + + // Arrays. case PACKED_BYTE_ARRAY: { PackedArrayRefBase::destroy(_data.packed_array); } break; @@ -1484,7 +1405,9 @@ void Variant::_clear_internal() { PackedArrayRefBase::destroy(_data.packed_array); } break; default: { - } /* not needed */ + // Not needed, there is no point. The following do not allocate memory: + // VECTOR2, VECTOR3, RECT2, PLANE, QUATERNION, COLOR. + } } } @@ -1863,34 +1786,34 @@ String Variant::stringify(int recursion_count) const { str += " }"; return str; - } break; + } case PACKED_VECTOR2_ARRAY: { return stringify_vector(operator Vector<Vector2>(), recursion_count); - } break; + } case PACKED_VECTOR3_ARRAY: { return stringify_vector(operator Vector<Vector3>(), recursion_count); - } break; + } case PACKED_COLOR_ARRAY: { return stringify_vector(operator Vector<Color>(), recursion_count); - } break; + } case PACKED_STRING_ARRAY: { return stringify_vector(operator Vector<String>(), recursion_count); - } break; + } case PACKED_BYTE_ARRAY: { return stringify_vector(operator Vector<uint8_t>(), recursion_count); - } break; + } case PACKED_INT32_ARRAY: { return stringify_vector(operator Vector<int32_t>(), recursion_count); - } break; + } case PACKED_INT64_ARRAY: { return stringify_vector(operator Vector<int64_t>(), recursion_count); - } break; + } case PACKED_FLOAT32_ARRAY: { return stringify_vector(operator Vector<float>(), recursion_count); - } break; + } case PACKED_FLOAT64_ARRAY: { return stringify_vector(operator Vector<double>(), recursion_count); - } break; + } case ARRAY: { Array arr = operator Array(); if (recursion_count > MAX_RECURSION) { @@ -1899,8 +1822,7 @@ String Variant::stringify(int recursion_count) const { } return stringify_vector(arr, recursion_count); - - } break; + } case OBJECT: { if (_get_obj().obj) { if (!_get_obj().id.is_ref_counted() && ObjectDB::get_instance(_get_obj().id) == nullptr) { @@ -1911,20 +1833,19 @@ String Variant::stringify(int recursion_count) const { } else { return "<Object#null>"; } - - } break; + } case CALLABLE: { const Callable &c = *reinterpret_cast<const Callable *>(_data._mem); return c; - } break; + } case SIGNAL: { const Signal &s = *reinterpret_cast<const Signal *>(_data._mem); return s; - } break; + } case RID: { const ::RID &s = *reinterpret_cast<const ::RID *>(_data._mem); return "RID(" + itos(s.get_id()) + ")"; - } break; + } default: { return "<" + get_type_name(type) + ">"; } @@ -1932,8 +1853,7 @@ String Variant::stringify(int recursion_count) const { } String Variant::to_json_string() const { - JSON json; - return json.stringify(*this); + return JSON::stringify(*this); } Variant::operator Vector2() const { diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 1831f7b72a..900e3d8e77 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1606,6 +1606,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, is_normalized, sarray(), varray()); bind_method(Vector2, is_equal_approx, sarray("to"), varray()); bind_method(Vector2, is_zero_approx, sarray(), varray()); + bind_method(Vector2, is_finite, sarray(), varray()); bind_method(Vector2, posmod, sarray("mod"), varray()); bind_method(Vector2, posmodv, sarray("modv"), varray()); bind_method(Vector2, project, sarray("b"), varray()); @@ -1653,6 +1654,7 @@ static void _register_variant_builtin_methods() { bind_method(Rect2, has_area, sarray(), varray()); bind_method(Rect2, has_point, sarray("point"), varray()); bind_method(Rect2, is_equal_approx, sarray("rect"), varray()); + bind_method(Rect2, is_finite, sarray(), varray()); bind_method(Rect2, intersects, sarray("b", "include_borders"), varray(false)); bind_method(Rect2, encloses, sarray("b"), varray()); bind_method(Rect2, intersection, sarray("b"), varray()); @@ -1695,6 +1697,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, is_normalized, sarray(), varray()); bind_method(Vector3, is_equal_approx, sarray("to"), varray()); bind_method(Vector3, is_zero_approx, sarray(), varray()); + bind_method(Vector3, is_finite, sarray(), varray()); bind_method(Vector3, inverse, sarray(), varray()); bind_method(Vector3, clamp, sarray("min", "max"), varray()); bind_method(Vector3, snapped, sarray("step"), varray()); @@ -1759,6 +1762,7 @@ static void _register_variant_builtin_methods() { bind_method(Vector4, inverse, sarray(), varray()); bind_method(Vector4, is_equal_approx, sarray("with"), varray()); bind_method(Vector4, is_zero_approx, sarray(), varray()); + bind_method(Vector4, is_finite, sarray(), varray()); /* Vector4i */ @@ -1775,6 +1779,7 @@ static void _register_variant_builtin_methods() { bind_method(Plane, normalized, sarray(), varray()); bind_method(Plane, center, sarray(), varray()); bind_method(Plane, is_equal_approx, sarray("to_plane"), varray()); + bind_method(Plane, is_finite, sarray(), varray()); bind_method(Plane, is_point_over, sarray("point"), varray()); bind_method(Plane, distance_to, sarray("point"), varray()); bind_method(Plane, has_point, sarray("point", "tolerance"), varray(CMP_EPSILON)); @@ -1790,6 +1795,7 @@ static void _register_variant_builtin_methods() { bind_method(Quaternion, normalized, sarray(), varray()); bind_method(Quaternion, is_normalized, sarray(), varray()); bind_method(Quaternion, is_equal_approx, sarray("to"), varray()); + bind_method(Quaternion, is_finite, sarray(), varray()); bind_method(Quaternion, inverse, sarray(), varray()); bind_method(Quaternion, log, sarray(), varray()); bind_method(Quaternion, exp, sarray(), varray()); @@ -1909,6 +1915,7 @@ static void _register_variant_builtin_methods() { bind_method(Transform2D, basis_xform_inv, sarray("v"), varray()); bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray()); bind_method(Transform2D, is_equal_approx, sarray("xform"), varray()); + bind_method(Transform2D, is_finite, sarray(), varray()); bind_method(Transform2D, set_rotation, sarray("rotation"), varray()); bind_method(Transform2D, set_scale, sarray("scale"), varray()); bind_method(Transform2D, set_skew, sarray("skew"), varray()); @@ -1929,6 +1936,7 @@ static void _register_variant_builtin_methods() { bind_method(Basis, tdotz, sarray("with"), varray()); bind_method(Basis, slerp, sarray("to", "weight"), varray()); bind_method(Basis, is_equal_approx, sarray("b"), varray()); + bind_method(Basis, is_finite, sarray(), varray()); bind_method(Basis, get_rotation_quaternion, sarray(), varray()); bind_static_method(Basis, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0))); bind_static_method(Basis, from_scale, sarray("scale"), varray()); @@ -1943,6 +1951,7 @@ static void _register_variant_builtin_methods() { bind_method(AABB, has_surface, sarray(), varray()); bind_method(AABB, has_point, sarray("point"), varray()); bind_method(AABB, is_equal_approx, sarray("aabb"), varray()); + bind_method(AABB, is_finite, sarray(), varray()); bind_method(AABB, intersects, sarray("with"), varray()); bind_method(AABB, encloses, sarray("with"), varray()); bind_method(AABB, intersects_plane, sarray("plane"), varray()); @@ -1975,6 +1984,7 @@ static void _register_variant_builtin_methods() { bind_method(Transform3D, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0))); bind_method(Transform3D, interpolate_with, sarray("xform", "weight"), varray()); bind_method(Transform3D, is_equal_approx, sarray("xform"), varray()); + bind_method(Transform3D, is_finite, sarray(), varray()); /* Projection */ diff --git a/core/variant/variant_destruct.cpp b/core/variant/variant_destruct.cpp index ab8303f3ae..5117c33e2b 100644 --- a/core/variant/variant_destruct.cpp +++ b/core/variant/variant_destruct.cpp @@ -41,13 +41,8 @@ static void add_destructor() { void Variant::_register_variant_destructors() { add_destructor<VariantDestruct<String>>(); - add_destructor<VariantDestruct<Transform2D>>(); - add_destructor<VariantDestruct<::AABB>>(); - add_destructor<VariantDestruct<Basis>>(); - add_destructor<VariantDestruct<Transform3D>>(); add_destructor<VariantDestruct<StringName>>(); add_destructor<VariantDestruct<NodePath>>(); - add_destructor<VariantDestruct<::RID>>(); add_destructor<VariantDestruct<Callable>>(); add_destructor<VariantDestruct<Signal>>(); add_destructor<VariantDestruct<Dictionary>>(); diff --git a/core/variant/variant_destruct.h b/core/variant/variant_destruct.h index 5e3478635d..2730110c0f 100644 --- a/core/variant/variant_destruct.h +++ b/core/variant/variant_destruct.h @@ -50,13 +50,8 @@ struct VariantDestruct {}; } MAKE_PTRDESTRUCT(String); -MAKE_PTRDESTRUCT(Transform2D); -MAKE_PTRDESTRUCT(AABB); -MAKE_PTRDESTRUCT(Basis); -MAKE_PTRDESTRUCT(Transform3D); MAKE_PTRDESTRUCT(StringName); MAKE_PTRDESTRUCT(NodePath); -MAKE_PTRDESTRUCT(RID); MAKE_PTRDESTRUCT(Callable); MAKE_PTRDESTRUCT(Signal); MAKE_PTRDESTRUCT(Dictionary); diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 670b66d53e..3843c32bcc 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -310,6 +310,10 @@ struct VariantUtilityFunctions { return Math::is_zero_approx(x); } + static inline bool is_finite(double x) { + return Math::is_finite(x); + } + static inline double ease(float x, float curve) { return Math::ease(x, curve); } @@ -1420,6 +1424,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(is_zero_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(is_finite, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 6e9e82bbf0..43f85fcdbc 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -476,6 +476,13 @@ Infinity values of the same sign are considered equal. </description> </method> + <method name="is_finite"> + <return type="bool" /> + <param index="0" name="x" type="float" /> + <description> + Returns whether [code]x[/code] is a finite value, i.e. it is not [constant @GDScript.NAN], positive infinity, or negative infinity. + </description> + </method> <method name="is_inf"> <return type="bool" /> <param index="0" name="x" type="float" /> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index 23dd41f275..1ac3e6b64c 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -205,6 +205,12 @@ Returns [code]true[/code] if this [AABB] and [param aabb] are approximately equal, by calling [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this [AABB] is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="merge" qualifiers="const"> <return type="AABB" /> <param index="0" name="with" type="AABB" /> diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index 6d9b679fbc..f499be34a0 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -112,6 +112,12 @@ Returns [code]true[/code] if this basis and [param b] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this basis is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="looking_at" qualifiers="static"> <return type="Basis" /> <param index="0" name="target" type="Vector3" /> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 7f3ffce9b7..68de08f094 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -457,6 +457,12 @@ If [code]true[/code], when saving a file, the editor will rename the old file to a different name, save a new file, then only remove the old file once the new file has been saved. This makes loss of data less likely to happen if the editor or operating system exits unexpectedly while saving (e.g. due to a crash or power outage). [b]Note:[/b] On Windows, this feature can interact negatively with certain antivirus programs. In this case, you may have to set this to [code]false[/code] to prevent file locking issues. </member> + <member name="interface/editor/accept_dialog_cancel_ok_buttons" type="int" setter="" getter=""> + How to position the Cancel and OK buttons in the editor's [AcceptDialog]s. Different platforms have different standard behaviors for this, which can be overridden using this setting. This is useful if you use Godot both on Windows and macOS/Linux and your Godot muscle memory is stronger than your OS specific one. + - [b]Auto[/b] follows the platform convention: Cancel first on macOS and Linux, OK first on Windows. + - [b]Cancel First[/b] forces the ordering Cancel/OK. + - [b]OK First[/b] forces the ordering OK/Cancel. + </member> <member name="interface/editor/automatically_open_screenshots" type="bool" setter="" getter=""> If [code]true[/code], automatically opens screenshots with the default program associated to [code].png[/code] files after a screenshot is taken using the [b]Editor > Take Screenshot[/b] action. </member> diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index e51e3753fc..fbe8afa8d1 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -119,6 +119,12 @@ Returns [code]true[/code] if this plane and [param to_plane] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this plane is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="is_point_over" qualifiers="const"> <return type="bool" /> <param index="0" name="point" type="Vector3" /> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 214f087d78..4b2bb3b6e9 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -566,7 +566,7 @@ If [code]true[/code], the home indicator is hidden automatically. This only affects iOS devices without a physical home button. </member> <member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter="" default="false"> - If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. + If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. See also [member display/window/size/transparent] and [member rendering/transparent_background]. </member> <member name="display/window/size/always_on_top" type="bool" setter="" getter="" default="false"> Forces the main window to be always on top. @@ -591,8 +591,8 @@ [b]Note:[/b] This setting is ignored on iOS. </member> <member name="display/window/size/transparent" type="bool" setter="" getter="" default="false"> - Main window background can be transparent. - [b]Note:[/b] To use transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code]. + If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/transparent_background]. + [b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code]. [b]Note:[/b] This setting has no effect if [member display/window/per_pixel_transparency/allowed] is set to [code]false[/code]. </member> <member name="display/window/size/viewport_height" type="int" setter="" getter="" default="648"> @@ -2100,8 +2100,6 @@ <member name="rendering/renderer/rendering_method.web" type="String" setter="" getter="" default=""gl_compatibility""> Override for [member rendering/renderer/rendering_method] on web. </member> - <member name="rendering/rendering_device/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64"> - </member> <member name="rendering/rendering_device/driver" type="String" setter="" getter="" default=""vulkan""> Sets the driver to be used by the renderer when using a RenderingDevice-based renderer like the clustered renderer or the mobile renderer. This property can not be edited directly, instead, set the driver using the platform-specific overrides. </member> @@ -2126,6 +2124,8 @@ </member> <member name="rendering/rendering_device/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64"> </member> + <member name="rendering/rendering_device/vulkan/max_descriptors_per_pool" type="int" setter="" getter="" default="64"> + </member> <member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2"> Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference. </member> @@ -2202,6 +2202,9 @@ If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles. [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]). </member> + <member name="rendering/transparent_background" type="bool" setter="" getter="" default="false"> + If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed]. + </member> <member name="rendering/vrs/mode" type="int" setter="" getter="" default="0"> Set the default Variable Rate Shading (VRS) mode for the main viewport. See [member Viewport.vrs_mode] to change this at runtime, and [enum Viewport.VRSMode] for possible values. </member> diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index f21ebf57e2..99dffeff9d 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -115,6 +115,12 @@ Returns [code]true[/code] if this quaternion and [param to] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this quaternion is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="is_normalized" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index ac012e9604..28fe42afae 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -165,6 +165,12 @@ Returns [code]true[/code] if this [Rect2] and [param rect] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this [Rect2] is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="merge" qualifiers="const"> <return type="Rect2" /> <param index="0" name="b" type="Rect2" /> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index 9b8c8d4d9d..2b6376f2cd 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -71,6 +71,15 @@ The [param cache_mode] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details. </description> </method> + <method name="_recognize_path" qualifiers="virtual const"> + <return type="bool" /> + <param index="0" name="path" type="String" /> + <param index="1" name="type" type="StringName" /> + <description> + Tells whether or not this loader should load a resource from its resource path for a given type. + If it is not implemented, the default behavior returns whether the path's extension is within the ones provided by [method _get_recognized_extensions], and if the type is within the ones provided by [method _get_resource_type]. + </description> + </method> <method name="_rename_dependencies" qualifiers="virtual const"> <return type="int" /> <param index="0" name="path" type="String" /> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 905b3d77af..23d20a5a75 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -123,6 +123,12 @@ Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this transform is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="looking_at" qualifiers="const"> <return type="Transform2D" /> <param index="0" name="target" type="Vector2" default="Vector2(0, 0)" /> diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 18b4f9e6f9..b3145ea022 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -82,6 +82,12 @@ Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this transform is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="looking_at" qualifiers="const"> <return type="Transform3D" /> <param index="0" name="target" type="Vector3" /> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index e1852340c0..5590f82336 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -206,6 +206,12 @@ Returns [code]true[/code] if this vector and [code]v[/code] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this vector is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="is_normalized" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 1ef84050cd..81e8dd2260 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -174,6 +174,12 @@ Returns [code]true[/code] if this vector and [param to] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this vector is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="is_normalized" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/Vector4.xml b/doc/classes/Vector4.xml index fdc93f82ec..662d0bce3a 100644 --- a/doc/classes/Vector4.xml +++ b/doc/classes/Vector4.xml @@ -135,6 +135,12 @@ Returns [code]true[/code] if this vector and [param with] are approximately equal, by running [method @GlobalScope.is_equal_approx] on each component. </description> </method> + <method name="is_finite" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this vector is finite, by calling [method @GlobalScope.is_finite] on each component. + </description> + </method> <method name="is_normalized" qualifiers="const"> <return type="bool" /> <description> diff --git a/drivers/SCsub b/drivers/SCsub index dd81fc645c..6cfcb1d18c 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -24,6 +24,7 @@ SConscript("winmidi/SCsub") # Graphics drivers if env["vulkan"]: + SConscript("spirv-reflect/SCsub") SConscript("vulkan/SCsub") if env["opengl3"]: SConscript("gl_context/SCsub") @@ -31,7 +32,6 @@ if env["opengl3"]: # Core dependencies SConscript("png/SCsub") -SConscript("spirv-reflect/SCsub") env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 72ae609fb4..c6b327eeee 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -179,8 +179,8 @@ NetSocketPosix::~NetSocketPosix() { close(); } -// Silent a warning reported in #27594 - +// Silence a warning reported in GH-27594. +// EAGAIN and EWOULDBLOCK have the same value on most platforms, but it's not guaranteed. #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index f6adbee108..5154feb478 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) +#if defined(UNIX_ENABLED) #include "thread_posix.h" @@ -73,4 +73,4 @@ void init_thread_posix() { Thread::_set_platform_functions({ .set_name = set_name }); } -#endif // UNIX_ENABLED || PTHREAD_ENABLED +#endif // UNIX_ENABLED diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 9b193056c2..036489a9bc 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1655,9 +1655,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_create_info.pNext = nullptr; image_create_info.flags = 0; -#ifndef _MSC_VER -#warning TODO check for support via RenderingDevice to enable on mobile when possible -#endif + // TODO: Check for support via RenderingDevice to enable on mobile when possible. #ifndef ANDROID_ENABLED @@ -5172,9 +5170,9 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve uint32_t offset = 0; uint8_t *binptr = ret.ptrw(); binptr[0] = 'G'; - binptr[1] = 'V'; + binptr[1] = 'S'; binptr[2] = 'B'; - binptr[3] = 'D'; // Godot vulkan binary data. + binptr[3] = 'D'; // Godot Shader Binary Data. offset += 4; encode_uint32(SHADER_BINARY_VERSION, binptr + offset); offset += sizeof(uint32_t); @@ -5235,7 +5233,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_ uint32_t read_offset = 0; // Consistency check. ERR_FAIL_COND_V(binsize < sizeof(uint32_t) * 3 + sizeof(RenderingDeviceVulkanShaderBinaryData), RID()); - ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID()); + ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'S' || binptr[2] != 'B' || binptr[3] != 'D', RID()); uint32_t bin_version = decode_uint32(binptr + 4); ERR_FAIL_COND_V(bin_version != SHADER_BINARY_VERSION, RID()); @@ -9393,7 +9391,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de ERR_CONTINUE(err != OK); } - max_descriptors_per_pool = GLOBAL_DEF("rendering/rendering_device/descriptor_pools/max_descriptors_per_pool", 64); + max_descriptors_per_pool = GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); // Check to make sure DescriptorPoolKey is good. static_assert(sizeof(uint64_t) * 3 >= UNIFORM_TYPE_MAX * sizeof(uint16_t)); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index ceca428306..7a4e58c6f9 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -752,9 +752,7 @@ CreateDialog::CreateDialog() { favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected)); favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated)); favorites->add_theme_constant_override("draw_guides", 1); -#ifndef _MSC_VER -#warning cannot forward drag data to a non control, must be fixed -#endif + // Cannot forward drag data to a non control, must be fixed. //favorites->set_drag_forwarding(this); fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index 809c0c2cff..ae8752eb6d 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -656,7 +656,7 @@ int DebugAdapterProtocol::parse_variant(const Variant &p_var) { bool DebugAdapterProtocol::process_message(const String &p_text) { JSON json; - ERR_FAIL_COND_V_MSG(json.parse(p_text) != OK, true, "Mal-formed message!"); + ERR_FAIL_COND_V_MSG(json.parse(p_text) != OK, true, "Malformed message!"); Dictionary params = json.get_data(); bool completed = true; diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp index 0f0ab4a339..7fd27692b0 100644 --- a/editor/editor_build_profile.cpp +++ b/editor/editor_build_profile.cpp @@ -255,8 +255,7 @@ Error EditorBuildProfile::save_to_file(const String &p_path) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); - JSON json; - String text = json.stringify(data, "\t"); + String text = JSON::stringify(data, "\t"); f->store_string(text); return OK; } diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 651501f75e..c28bb18891 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -2259,7 +2259,7 @@ void EditorFileSystem::move_group_file(const String &p_path, const String &p_new ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) { if (!p_path.is_resource_file() || p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path())) { - //saved externally (configuration file) or internal file, do not assign an ID. + // Saved externally (configuration file) or internal file, do not assign an ID. return ResourceUID::INVALID_ID; } @@ -2267,15 +2267,21 @@ ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const int cpos = -1; if (!singleton->_find_file(p_path, &fs, cpos)) { + // Fallback to ResourceLoader if filesystem cache fails (can happen during scanning etc.). + ResourceUID::ID fallback = ResourceLoader::get_resource_uid(p_path); + if (fallback != ResourceUID::INVALID_ID) { + return fallback; + } + if (p_generate) { - return ResourceUID::get_singleton()->create_id(); //just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple. + return ResourceUID::get_singleton()->create_id(); // Just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple. } else { return ResourceUID::INVALID_ID; } } else if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) { return fs->files[cpos]->uid; } else if (p_generate) { - return ResourceUID::get_singleton()->create_id(); //just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple. + return ResourceUID::get_singleton()->create_id(); // Just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple. } else { return ResourceUID::INVALID_ID; } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7aca8fde6f..460dc7e3bb 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6181,10 +6181,17 @@ EditorNode::EditorNode() { // Define a minimum window size to prevent UI elements from overlapping or being cut off. DisplayServer::get_singleton()->window_set_min_size(Size2(1024, 600) * EDSCALE); - ResourceLoader::set_abort_on_missing_resources(false); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int()); + + int swap_cancel_ok = EDITOR_GET("interface/editor/accept_dialog_cancel_ok_buttons"); + if (swap_cancel_ok != 0) { // 0 is auto, set in register_scene based on DisplayServer. + // Swap on means OK first. + AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2); + } + + ResourceLoader::set_abort_on_missing_resources(false); ResourceLoader::set_error_notify_func(this, _load_error_notify); ResourceLoader::set_dependency_error_notify_func(this, _dependency_error_report); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 0c01fcb869..5bdfd8d377 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -438,6 +438,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) _initial_set("interface/editor/mouse_extra_buttons_navigate_history", true); _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression + EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/accept_dialog_cancel_ok_buttons", 0, + vformat("Auto (%s),Cancel First,OK First", DisplayServer::get_singleton()->get_swap_cancel_ok() ? "OK First" : "Cancel First"), + PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); #ifdef DEV_ENABLED EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/show_internal_errors_in_toast_notifications", 0, "Auto (Enabled),Enabled,Disabled") #else diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 05a17c9951..9b5e76bcd7 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -1015,9 +1015,7 @@ ProjectExportDialog::ProjectExportDialog() { preset_vb->add_child(mc); mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); presets = memnew(ItemList); -#ifndef _MSC_VER -#warning must reimplement drag forward -#endif + // TODO: Must reimplement drag forwarding. //presets->set_drag_forwarding(this); mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 6e108a9a72..4c792d0dca 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5316,7 +5316,7 @@ CanvasItemEditor::CanvasItemEditor() { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KeyModifierMask::SHIFT | Key::F), VIEW_FRAME_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL | Key::P), PREVIEW_CANVAS_SCALE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale")), PREVIEW_CANVAS_SCALE); main_menu_hbox->add_child(memnew(VSeparator)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 4430877b8a..70489f0841 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2400,6 +2400,9 @@ void Node3DEditorViewport::_project_settings_changed() { const bool use_taa = GLOBAL_GET("rendering/anti_aliasing/quality/use_taa"); viewport->set_use_taa(use_taa); + const bool transparent_background = GLOBAL_GET("rendering/transparent_background"); + viewport->set_transparent_background(transparent_background); + const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding"); viewport->set_use_debanding(use_debanding); @@ -4773,9 +4776,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_menu->get_popup()->connect("id_pressed", callable_mp(this, &Node3DEditorViewport::_menu_option)); display_submenu->connect("id_pressed", callable_mp(this, &Node3DEditorViewport::_menu_option)); view_menu->set_disable_shortcuts(true); -#ifndef _MSC_VER -#warning this needs to be fixed -#endif + + // TODO: Re-evaluate with new OpenGL3 renderer, and implement. //if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { if (false) { // Alternate display modes only work when using the Vulkan renderer; make this explicit. diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 05015528c6..c6fcdc890c 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2594,6 +2594,12 @@ ProjectManager::ProjectManager() { EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); + int swap_cancel_ok = EDITOR_GET("interface/editor/accept_dialog_cancel_ok_buttons"); + if (swap_cancel_ok != 0) { // 0 is auto, set in register_scene based on DisplayServer. + // Swap on means OK first. + AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2); + } + set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); set_theme(create_custom_theme()); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index acaa4ec3c9..ee358a8064 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2176,11 +2176,15 @@ void SceneTreeDock::_selection_changed() { void SceneTreeDock::_do_create(Node *p_parent) { Variant c = create_dialog->instance_selected(); - - ERR_FAIL_COND(!c); Node *child = Object::cast_to<Node>(c); ERR_FAIL_COND(!child); + String new_name = p_parent->validate_child_name(child); + if (GLOBAL_GET("editor/node_naming/name_casing").operator int() != NAME_CASING_PASCAL_CASE) { + new_name = adjust_name_casing(new_name); + } + child->set_name(new_name); + editor_data->get_undo_redo()->create_action_for_history(TTR("Create Node"), editor_data->get_current_edited_scene_history_id()); if (edited_scene) { @@ -2191,7 +2195,6 @@ void SceneTreeDock::_do_create(Node *p_parent) { editor_data->get_undo_redo()->add_do_reference(child); editor_data->get_undo_redo()->add_undo_method(p_parent, "remove_child", child); - String new_name = p_parent->validate_child_name(child); EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); editor_data->get_undo_redo()->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name); editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).path_join(new_name))); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 8272db9018..6700b6de0a 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -2590,10 +2590,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { Mesh::PRIMITIVE_TRIANGLES, // 4 TRIANGLES Mesh::PRIMITIVE_TRIANGLE_STRIP, // 5 TRIANGLE_STRIP Mesh::PRIMITIVE_TRIANGLES, // 6 TRIANGLE_FAN fan not supported, should be converted -#ifndef _MSC_VER -#warning line loop and triangle fan are not supported and need to be converted to lines and triangles -#endif - + // TODO: Line loop and triangle fan are not supported and need to be converted to lines and triangles. }; primitive = primitives2[mode]; diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index c4547b4323..1f4b085bfb 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -227,8 +227,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Ref<FileAccess> f = FileAccess::open(p_output_file, FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_output_file + "'."); - JSON json; - f->store_string(json.stringify(classes_dict, "\t")); + f->store_string(JSON::stringify(classes_dict, "\t")); print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file)); } diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h index 690fddae21..895bc70103 100644 --- a/platform/android/api/jni_singleton.h +++ b/platform/android/api/jni_singleton.h @@ -150,9 +150,8 @@ public: env->DeleteLocalRef(arr); } break; -#ifndef _MSC_VER -#warning This is missing 64 bits arrays, I have no idea how to do it in JNI -#endif + // TODO: This is missing 64 bits arrays, I have no idea how to do it in JNI. + case Variant::DICTIONARY: { jobject obj = env->CallObjectMethodA(instance, E->get().method, v); ret = _jobject_to_variant(env, obj); diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 366bd1c48c..ef3b79b630 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -2639,8 +2639,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP } if (user_data.libs.size() > 0) { Ref<FileAccess> fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE); - JSON json; - fa->store_string(json.stringify(user_data.libs, "\t")); + fa->store_string(JSON::stringify(user_data.libs, "\t")); } } else { print_verbose("Saving apk expansion file.."); diff --git a/platform/android/jni_utils.cpp b/platform/android/jni_utils.cpp index 193ef61264..d46b4f39de 100644 --- a/platform/android/jni_utils.cpp +++ b/platform/android/jni_utils.cpp @@ -167,9 +167,8 @@ jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant *p_a v.obj = arr; } break; -#ifndef _MSC_VER -#warning This is missing 64 bits arrays, I have no idea how to do it in JNI -#endif + + // TODO: This is missing 64 bits arrays, I have no idea how to do it in JNI. default: { v.val.i = 0; diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 5256d91a80..e0963f42ce 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -1202,16 +1202,6 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { return SCREEN_REFRESH_RATE_FALLBACK; } -bool DisplayServerX11::screen_is_touchscreen(int p_screen) const { - _THREAD_SAFE_METHOD_ - -#ifndef _MSC_VER -#warning Need to get from proper window -#endif - - return DisplayServer::screen_is_touchscreen(p_screen); -} - #ifdef DBUS_ENABLED void DisplayServerX11::screen_set_keep_on(bool p_enable) { if (screen_is_kept_on() == p_enable) { diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index a5fa7613bc..5723abc751 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -349,7 +349,6 @@ public: virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; #if defined(DBUS_ENABLED) virtual void screen_set_keep_on(bool p_enable) override; diff --git a/platform/macos/joypad_macos.h b/platform/macos/joypad_macos.h index 4b14fed6d5..8743fc91a9 100644 --- a/platform/macos/joypad_macos.h +++ b/platform/macos/joypad_macos.h @@ -31,14 +31,10 @@ #ifndef JOYPAD_MACOS_H #define JOYPAD_MACOS_H -#ifdef MACOS_10_0_4 -#import <IOKit/hidsystem/IOHIDUsageTables.h> -#else -#import <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> -#endif #import <ForceFeedback/ForceFeedback.h> #import <ForceFeedback/ForceFeedbackConstants.h> #import <IOKit/hid/IOHIDLib.h> +#import <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> #include "core/input/input.h" diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 8050d299f0..c93c3896ab 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -826,10 +826,6 @@ OS_UWP::OS_UWP() { pressrc = 0; old_invalid = true; mouse_mode = MOUSE_MODE_VISIBLE; -#ifdef STDOUT_FILE - stdo = fopen("stdout.txt", "wb"); -#endif - gl_context = nullptr; display_request = ref new Windows::System::Display::DisplayRequest(); @@ -847,7 +843,4 @@ OS_UWP::OS_UWP() { } OS_UWP::~OS_UWP() { -#ifdef STDOUT_FILE - fclose(stdo); -#endif } diff --git a/platform/web/js/libs/library_godot_javascript_singleton.js b/platform/web/js/libs/library_godot_javascript_singleton.js index 692f27676a..c86cbbae45 100644 --- a/platform/web/js/libs/library_godot_javascript_singleton.js +++ b/platform/web/js/libs/library_godot_javascript_singleton.js @@ -88,7 +88,7 @@ const GodotJSWrapper = { return GodotRuntime.getHeapValue(val, 'double'); case 4: return GodotRuntime.parseString(GodotRuntime.getHeapValue(val, '*')); - case 21: // OBJECT + case 24: // OBJECT return GodotJSWrapper.get_proxied_value(GodotRuntime.getHeapValue(val, 'i64')); default: return undefined; @@ -117,7 +117,7 @@ const GodotJSWrapper = { } const id = GodotJSWrapper.get_proxied(p_val); GodotRuntime.setHeapValue(p_exchange, id, 'i64'); - return 21; + return 24; // OBJECT }, }, diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 16853a0be7..3b773685c3 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -561,20 +561,6 @@ float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const { return data.rate; } -bool DisplayServerWindows::screen_is_touchscreen(int p_screen) const { -#ifndef _MSC_VER -#warning touchscreen not working -#endif - return DisplayServer::screen_is_touchscreen(p_screen); -} - -void DisplayServerWindows::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) { -} - -DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(int p_screen) const { - return SCREEN_LANDSCAPE; -} - void DisplayServerWindows::screen_set_keep_on(bool p_enable) { if (keep_screen_on == p_enable) { return; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 3523e8b3d1..6403b57d8d 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -516,10 +516,6 @@ public: virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - - virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override; - virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver virtual bool screen_is_kept_on() const override; diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h index d239471a5c..56a9f3e9c9 100644 --- a/platform/windows/joypad_windows.h +++ b/platform/windows/joypad_windows.h @@ -85,6 +85,8 @@ private: last_pad = -1; attached = false; confirmed = false; + di_joy = nullptr; + guid = {}; for (int i = 0; i < MAX_JOY_BUTTONS; i++) { last_buttons[i] = false; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 241e0b382e..2f69a3b07e 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1123,15 +1123,7 @@ Error OS_Windows::move_to_trash(const String &p_path) { } OS_Windows::OS_Windows(HINSTANCE _hInstance) { - ticks_per_second = 0; - ticks_start = 0; - main_loop = nullptr; - process_map = nullptr; - hInstance = _hInstance; -#ifdef STDOUT_FILE - stdo = fopen("stdout.txt", "wb"); -#endif #ifdef WASAPI_ENABLED AudioDriverManager::add_driver(&driver_wasapi); @@ -1147,11 +1139,8 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { // // NOTE: The engine does not use ANSI escape codes to color error/warning messages; it uses Windows API calls instead. // Therefore, error/warning messages are still colored on Windows versions older than 10. - HANDLE stdoutHandle; - stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD outMode = 0; - outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - + HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD outMode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(stdoutHandle, outMode)) { // Windows 8.1 or below, or Windows 10 prior to Anniversary Update. print_verbose("Can't set the ENABLE_VIRTUAL_TERMINAL_PROCESSING Windows console mode. `print_rich()` will not work as expected."); @@ -1163,7 +1152,4 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { } OS_Windows::~OS_Windows() { -#ifdef STDOUT_FILE - fclose(stdo); -#endif } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index b792f6fa44..177b69eaac 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -84,13 +84,10 @@ public: }; class JoypadWindows; -class OS_Windows : public OS { -#ifdef STDOUT_FILE - FILE *stdo = nullptr; -#endif - uint64_t ticks_start; - uint64_t ticks_per_second; +class OS_Windows : public OS { + uint64_t ticks_start = 0; + uint64_t ticks_per_second = 0; HINSTANCE hInstance; MainLoop *main_loop = nullptr; @@ -130,7 +127,7 @@ protected: STARTUPINFO si; PROCESS_INFORMATION pi; }; - HashMap<ProcessID, ProcessInfo> *process_map; + HashMap<ProcessID, ProcessInfo> *process_map = nullptr; public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 90402260ed..80169bc80c 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -454,7 +454,7 @@ void DirectionalLight2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &DirectionalLight2D::set_max_distance); ClassDB::bind_method(D_METHOD("get_max_distance"), &DirectionalLight2D::get_max_distance); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1,0.01,suffix:px"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,16384.0,1.0,or_greater,suffix:px"), "set_max_distance", "get_max_distance"); } diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index dd016d5e92..f80b2a07c9 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -192,10 +192,8 @@ void Bone2D::_notification(int p_what) { cache_transform = tmp_trans; } break; - // Bone2D Editor gizmo drawing: -#ifndef _MSC_VER -#warning TODO Bone2D gizmo drawing needs to be moved to an editor plugin -#endif + // Bone2D Editor gizmo drawing. + // TODO: Bone2D gizmo drawing needs to be moved to an editor plugin. case NOTIFICATION_DRAW: { // Only draw the gizmo in the editor! if (Engine::get_singleton()->is_editor_hint() == false) { diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 0ecf8333a0..0784318442 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -309,9 +309,7 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const { q.y = 1.0f - q.y; } q = q * src_rect.size + src_rect.position; -#ifndef _MSC_VER -#warning this need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that) -#endif + // TODO: This need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that). bool is_repeat = false; bool is_mirrored_repeat = false; if (is_repeat) { @@ -446,7 +444,7 @@ void Sprite2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 23fd091be6..198dba7811 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -165,6 +165,16 @@ AABB Light3D::get_aabb() const { return AABB(); } +PackedStringArray Light3D::get_configuration_warnings() const { + PackedStringArray warnings = VisualInstance3D::get_configuration_warnings(); + + if (!get_scale().is_equal_approx(Vector3(1, 1, 1))) { + warnings.push_back(RTR("A light's scale does not affect the visual size of the light.")); + } + + return warnings; +} + void Light3D::set_bake_mode(BakeMode p_mode) { bake_mode = p_mode; RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode)); @@ -579,7 +589,7 @@ OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const { } PackedStringArray OmniLight3D::get_configuration_warnings() const { - PackedStringArray warnings = Node::get_configuration_warnings(); + PackedStringArray warnings = Light3D::get_configuration_warnings(); if (!has_shadow() && get_projector().is_valid()) { warnings.push_back(RTR("Projector texture only works with shadows active.")); @@ -609,7 +619,7 @@ OmniLight3D::OmniLight3D() : } PackedStringArray SpotLight3D::get_configuration_warnings() const { - PackedStringArray warnings = Node::get_configuration_warnings(); + PackedStringArray warnings = Light3D::get_configuration_warnings(); if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { warnings.push_back(RTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows.")); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 8da45bee79..84d214030b 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -147,6 +147,7 @@ public: Color get_correlated_color() const; virtual AABB get_aabb() const override; + virtual PackedStringArray get_configuration_warnings() const override; Light3D(); ~Light3D(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index cc69a1cc51..be6eab2178 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -810,7 +810,7 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect"); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index f1e18640e6..a2c138c0b2 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -1403,9 +1403,7 @@ void ColorPicker::_screen_pick_pressed() { screen->show(); } screen->move_to_front(); -#ifndef _MSC_VER -#warning show modal no longer works, needs to be converted to a popup -#endif + // TODO: show modal no longer works, needs to be converted to a popup. //screen->show_modal(); } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 101a63db1b..6ab27853f1 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1024,11 +1024,9 @@ String increase_numeric_string(const String &s) { void Node::_generate_serial_child_name(const Node *p_child, StringName &name) const { if (name == StringName()) { - //no name and a new name is needed, create one. + // No name and a new name is needed, create one. name = p_child->get_class(); - // Adjust casing according to project setting. - name = adjust_name_casing(name); } //quickly test if proposed name exists diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index af481749d5..64eb3b879b 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1390,6 +1390,9 @@ SceneTree::SceneTree() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa_3d", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)"))); root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d)); + const bool transparent_background = GLOBAL_DEF("rendering/transparent_background", false); + root->set_transparent_background(transparent_background); + const int ssaa_mode = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/screen_space_aa", 0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/screen_space_aa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)")); root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode)); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 2bcf569f4e..dfd9c6eb2f 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -5239,9 +5239,7 @@ bool Animation::_fetch_compressed(uint32_t p_compressed_track, double p_time, Ve double page_base_time = compression.pages[page_index].time_offset; const uint8_t *page_data = compression.pages[page_index].data.ptr(); -#ifndef _MSC_VER -#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported -#endif + // Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported. const uint32_t *indices = (const uint32_t *)page_data; const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]]; uint32_t time_key_count = indices[p_compressed_track * 3 + 1]; @@ -5384,9 +5382,7 @@ void Animation::_get_compressed_key_indices_in_range(uint32_t p_compressed_track double page_base_time = compression.pages[page_index].time_offset; const uint8_t *page_data = compression.pages[page_index].data.ptr(); -#ifndef _MSC_VER -#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported -#endif + // Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported. const uint32_t *indices = (const uint32_t *)page_data; const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]]; uint32_t time_key_count = indices[p_compressed_track * 3 + 1]; @@ -5456,9 +5452,7 @@ int Animation::_get_compressed_key_count(uint32_t p_compressed_track) const { for (uint32_t i = 0; i < compression.pages.size(); i++) { const uint8_t *page_data = compression.pages[i].data.ptr(); -#ifndef _MSC_VER -#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported -#endif + // Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported. const uint32_t *indices = (const uint32_t *)page_data; const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]]; uint32_t time_key_count = indices[p_compressed_track * 3 + 1]; @@ -5492,9 +5486,7 @@ bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_in for (uint32_t i = 0; i < compression.pages.size(); i++) { const uint8_t *page_data = compression.pages[i].data.ptr(); -#ifndef _MSC_VER -#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported -#endif + // Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported. const uint32_t *indices = (const uint32_t *)page_data; const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]]; uint32_t time_key_count = indices[p_compressed_track * 3 + 1]; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 03ccae5b74..706db3af16 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1576,9 +1576,8 @@ void ArrayMesh::_recompute_aabb() { } } } -#ifndef _MSC_VER -#warning need to add binding to add_surface using future MeshSurfaceData object -#endif + +// TODO: Need to add binding to add_surface using future MeshSurfaceData object. void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) { _create_if_empty(); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index df9addb6bb..640f6dfcb7 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1509,11 +1509,10 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const { } void VisualShader::reset_state() { -#ifndef _MSC_VER -#warning everything needs to be cleared here -#endif + // TODO: Everything needs to be cleared here. emit_changed(); } + void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { //mode p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky,Fog")); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 84d2ad328c..039a2d2bf4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -754,7 +754,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid(); - if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && repeats < RenderElementInfo::MAX_REPEATS) { + if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && inst->mirror == prev_surface->owner->mirror && repeats < RenderElementInfo::MAX_REPEATS) { //this element is the same as the previous one, count repeats to draw it using instancing repeats++; } else { diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp index 9151c53823..7a2336970b 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "pipeline_cache_rd.h" + #include "core/os/memory.h" RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations) { @@ -70,9 +71,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD } void PipelineCacheRD::_clear() { -#ifndef _MSC_VER -#warning Clear should probably recompile all the variants already compiled instead to avoid stalls? needs discussion -#endif + // TODO: Clear should probably recompile all the variants already compiled instead to avoid stalls? Needs discussion. if (versions) { for (uint32_t i = 0; i < version_count; i++) { //shader may be gone, so this may not be valid diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index e5e82552f4..5728444312 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1075,10 +1075,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target)); texture_storage->render_target_disable_clear_request(p_to_render_target); } -#ifndef _MSC_VER -#warning TODO obtain from framebuffer format eventually when this is implemented -#endif - + // TODO: Obtain from framebuffer format eventually when this is implemented. fb_uniform_set = texture_storage->render_target_get_framebuffer_uniform_set(p_to_render_target); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index dd3f62e509..3289bfb0ea 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -102,10 +102,8 @@ void RendererCompositorRD::begin_frame(double frame_step) { } void RendererCompositorRD::end_frame(bool p_swap_buffers) { -#ifndef _MSC_VER -#warning TODO: likely pass a bool to swap buffers to avoid display? -#endif - RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display? + // TODO: Likely pass a bool to swap buffers to avoid display? + RD::get_singleton()->swap_buffers(); } void RendererCompositorRD::initialize() { diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 0f2dea6fe9..5e9eadadd9 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -180,6 +180,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) builder.append("#define MOLTENVK_USED\n"); #endif + builder.append(String("#define RENDER_DRIVER_") + OS::get_singleton()->get_current_rendering_driver_name().to_upper() + "\n"); } break; case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: { builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 78f4c410c3..240f743387 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "particles_storage.h" + #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/rendering_server_globals.h" #include "texture_storage.h" @@ -1334,10 +1335,7 @@ void ParticlesStorage::update_particles() { } } -#ifndef _MSC_VER -#warning Should use display refresh rate for all this -#endif - + // TODO: Should use display refresh rate for all this. float screen_hz = 60; int fixed_fps = 0; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index b3a7e05ff5..add3e03389 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "texture_storage.h" + #include "../effects/copy_effects.h" #include "../framebuffer_cache_rd.h" #include "material_storage.h" @@ -1496,9 +1497,7 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T } break; case Image::FORMAT_RGBE9995: { r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; -#ifndef _MSC_VER -#warning TODO need to make a function in Image to swap bits for this -#endif + // TODO: Need to make a function in Image to swap bits for this. r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 2b25e8962f..d0cb46dee9 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -869,12 +869,7 @@ void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D for (int i = 0; i < 4; i++) { const Vector3 &v = i < 3 ? p_transform.basis.rows[i] : p_transform.origin; - ERR_FAIL_COND(Math::is_inf(v.x)); - ERR_FAIL_COND(Math::is_nan(v.x)); - ERR_FAIL_COND(Math::is_inf(v.y)); - ERR_FAIL_COND(Math::is_nan(v.y)); - ERR_FAIL_COND(Math::is_inf(v.z)); - ERR_FAIL_COND(Math::is_nan(v.z)); + ERR_FAIL_COND(!v.is_finite()); } #endif diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 627cd9f062..e12c4fc79a 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2868,12 +2868,13 @@ void RenderingServer::init() { GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048); - // Already defined in RenderingDeviceVulkan::initialize which runs before this code. + // Already defined in some RenderingDevice*::initialize, which run before this code. // We re-define them here just for doctool's sake. Make sure to keep default values in sync. GLOBAL_DEF("rendering/rendering_device/staging_buffer/block_size_kb", 256); GLOBAL_DEF("rendering/rendering_device/staging_buffer/max_size_mb", 128); GLOBAL_DEF("rendering/rendering_device/staging_buffer/texture_upload_region_size_px", 64); - GLOBAL_DEF("rendering/rendering_device/descriptor_pools/max_descriptors_per_pool", 64); + // Vulkan-specific. + GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); // Number of commands that can be drawn per frame. GLOBAL_DEF_RST("rendering/gl_compatibility/item_buffer_size", 16384); diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index d5f54a139e..ebaf441abf 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -389,6 +389,27 @@ TEST_CASE("[AABB] Expanding") { aabb.expand(Vector3(-20, 0, 0)).is_equal_approx(AABB(Vector3(-20, 0, -2.5), Vector3(22.5, 7, 6))), "expand() with non-contained point should return the expected AABB."); } + +TEST_CASE("[AABB] Finite number checks") { + const Vector3 x(0, 1, 2); + const Vector3 infinite(NAN, NAN, NAN); + + CHECK_MESSAGE( + AABB(x, x).is_finite(), + "AABB with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + AABB(infinite, x).is_finite(), + "AABB with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + AABB(x, infinite).is_finite(), + "AABB with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + AABB(infinite, infinite).is_finite(), + "AABB with two components infinite should not be finite."); +} + } // namespace TestAABB #endif // TEST_AABB_H diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h index b6493c5726..a65020597a 100644 --- a/tests/core/math/test_basis.h +++ b/tests/core/math/test_basis.h @@ -334,6 +334,40 @@ TEST_CASE("[Basis] Set axis angle") { bugNan.get_axis_angle(axis, angle); CHECK(!Math::is_nan(angle)); } + +TEST_CASE("[Basis] Finite number checks") { + const Vector3 x(0, 1, 2); + const Vector3 infinite(NAN, NAN, NAN); + + CHECK_MESSAGE( + Basis(x, x, x).is_finite(), + "Basis with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Basis(infinite, x, x).is_finite(), + "Basis with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Basis(x, infinite, x).is_finite(), + "Basis with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Basis(x, x, infinite).is_finite(), + "Basis with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Basis(infinite, infinite, x).is_finite(), + "Basis with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Basis(infinite, x, infinite).is_finite(), + "Basis with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Basis(x, infinite, infinite).is_finite(), + "Basis with two components infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Basis(infinite, infinite, infinite).is_finite(), + "Basis with three components infinite should not be finite."); +} + } // namespace TestBasis #endif // TEST_BASIS_H diff --git a/tests/core/math/test_plane.h b/tests/core/math/test_plane.h index d81a5af1ce..84d9a0ff7d 100644 --- a/tests/core/math/test_plane.h +++ b/tests/core/math/test_plane.h @@ -167,6 +167,29 @@ TEST_CASE("[Plane] Intersection") { vec_out.is_equal_approx(Vector3(1, 1, 1)), "intersects_segment() should modify vec_out to the expected result."); } + +TEST_CASE("[Plane] Finite number checks") { + const Vector3 x(0, 1, 2); + const Vector3 infinite_vec(NAN, NAN, NAN); + const real_t y = 0; + const real_t infinite_y = NAN; + + CHECK_MESSAGE( + Plane(x, y).is_finite(), + "Plane with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Plane(x, infinite_y).is_finite(), + "Plane with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Plane(infinite_vec, y).is_finite(), + "Plane with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Plane(infinite_vec, infinite_y).is_finite(), + "Plane with two components infinite should not be finite."); +} + } // namespace TestPlane #endif // TEST_PLANE_H diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h index 63d30759bb..d1912cbf42 100644 --- a/tests/core/math/test_quaternion.h +++ b/tests/core/math/test_quaternion.h @@ -384,6 +384,63 @@ TEST_CASE("[Stress][Quaternion] Many vector xforms") { } } +TEST_CASE("[Quaternion] Finite number checks") { + const real_t x = NAN; + + CHECK_MESSAGE( + Quaternion(0, 1, 2, 3).is_finite(), + "Quaternion with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Quaternion(x, 1, 2, 3).is_finite(), + "Quaternion with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, x, 2, 3).is_finite(), + "Quaternion with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, 1, x, 3).is_finite(), + "Quaternion with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, 1, 2, x).is_finite(), + "Quaternion with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Quaternion(x, x, 2, 3).is_finite(), + "Quaternion with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(x, 1, x, 3).is_finite(), + "Quaternion with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(x, 1, 2, x).is_finite(), + "Quaternion with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, x, x, 3).is_finite(), + "Quaternion with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, x, 2, x).is_finite(), + "Quaternion with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(0, 1, x, x).is_finite(), + "Quaternion with two components infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Quaternion(0, x, x, x).is_finite(), + "Quaternion with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(x, 1, x, x).is_finite(), + "Quaternion with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(x, x, 2, x).is_finite(), + "Quaternion with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Quaternion(x, x, x, 3).is_finite(), + "Quaternion with three components infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Quaternion(x, x, x, x).is_finite(), + "Quaternion with four components infinite should not be finite."); +} + } // namespace TestQuaternion #endif // TEST_QUATERNION_H diff --git a/tests/core/math/test_rect2.h b/tests/core/math/test_rect2.h index 6323b214db..d784875c1c 100644 --- a/tests/core/math/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -300,6 +300,27 @@ TEST_CASE("[Rect2] Merging") { Rect2(0, 100, 1280, 720).merge(Rect2(-4000, -4000, 100, 100)).is_equal_approx(Rect2(-4000, -4000, 5280, 4820)), "merge() with non-enclosed Rect2 should return the expected result."); } + +TEST_CASE("[Rect2] Finite number checks") { + const Vector2 x(0, 1); + const Vector2 infinite(NAN, NAN); + + CHECK_MESSAGE( + Rect2(x, x).is_finite(), + "Rect2 with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Rect2(infinite, x).is_finite(), + "Rect2 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Rect2(x, infinite).is_finite(), + "Rect2 with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Rect2(infinite, infinite).is_finite(), + "Rect2 with two components infinite should not be finite."); +} + } // namespace TestRect2 #endif // TEST_RECT2_H diff --git a/tests/core/math/test_transform_2d.h b/tests/core/math/test_transform_2d.h index 697bf63fc5..ab51bcd7da 100644 --- a/tests/core/math/test_transform_2d.h +++ b/tests/core/math/test_transform_2d.h @@ -83,6 +83,40 @@ TEST_CASE("[Transform2D] rotation") { CHECK(orig.rotated(phi) == R * orig); CHECK(orig.rotated_local(phi) == orig * R); } + +TEST_CASE("[Transform2D] Finite number checks") { + const Vector2 x(0, 1); + const Vector2 infinite(NAN, NAN); + + CHECK_MESSAGE( + Transform2D(x, x, x).is_finite(), + "Transform2D with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Transform2D(infinite, x, x).is_finite(), + "Transform2D with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Transform2D(x, infinite, x).is_finite(), + "Transform2D with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Transform2D(x, x, infinite).is_finite(), + "Transform2D with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Transform2D(infinite, infinite, x).is_finite(), + "Transform2D with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Transform2D(infinite, x, infinite).is_finite(), + "Transform2D with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Transform2D(x, infinite, infinite).is_finite(), + "Transform2D with two components infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Transform2D(infinite, infinite, infinite).is_finite(), + "Transform2D with three components infinite should not be finite."); +} + } // namespace TestTransform2D #endif // TEST_TRANSFORM_2D_H diff --git a/tests/core/math/test_transform_3d.h b/tests/core/math/test_transform_3d.h index da166b43f7..d2730f3577 100644 --- a/tests/core/math/test_transform_3d.h +++ b/tests/core/math/test_transform_3d.h @@ -84,6 +84,29 @@ TEST_CASE("[Transform3D] rotation") { CHECK(orig.rotated(axis, phi) == R * orig); CHECK(orig.rotated_local(axis, phi) == orig * R); } + +TEST_CASE("[Transform3D] Finite number checks") { + const Vector3 y(0, 1, 2); + const Vector3 infinite_vec(NAN, NAN, NAN); + const Basis x(y, y, y); + const Basis infinite_basis(infinite_vec, infinite_vec, infinite_vec); + + CHECK_MESSAGE( + Transform3D(x, y).is_finite(), + "Transform3D with all components finite should be finite"); + + CHECK_FALSE_MESSAGE( + Transform3D(x, infinite_vec).is_finite(), + "Transform3D with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Transform3D(infinite_basis, y).is_finite(), + "Transform3D with one component infinite should not be finite."); + + CHECK_FALSE_MESSAGE( + Transform3D(infinite_basis, infinite_vec).is_finite(), + "Transform3D with two components infinite should not be finite."); +} + } // namespace TestTransform3D #endif // TEST_TRANSFORM_3D_H diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h index 0d7f1163e4..a87b9ffc02 100644 --- a/tests/core/math/test_vector2.h +++ b/tests/core/math/test_vector2.h @@ -465,6 +465,32 @@ TEST_CASE("[Vector2] Linear algebra methods") { Math::is_equal_approx(Vector2(-a.x, a.y).dot(Vector2(b.x, -b.y)), (real_t)-57.3), "Vector2 dot should return expected value."); } + +TEST_CASE("[Vector2] Finite number checks") { + const double infinite[] = { NAN, INFINITY, -INFINITY }; + + CHECK_MESSAGE( + Vector2(0, 1).is_finite(), + "Vector2(0, 1) should be finite"); + + for (double x : infinite) { + CHECK_FALSE_MESSAGE( + Vector2(x, 1).is_finite(), + "Vector2 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector2(0, x).is_finite(), + "Vector2 with one component infinite should not be finite."); + } + + for (double x : infinite) { + for (double y : infinite) { + CHECK_FALSE_MESSAGE( + Vector2(x, y).is_finite(), + "Vector2 with two components infinite should not be finite."); + } + } +} + } // namespace TestVector2 #endif // TEST_VECTOR2_H diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h index be271bad1f..4932cd04db 100644 --- a/tests/core/math/test_vector3.h +++ b/tests/core/math/test_vector3.h @@ -479,6 +479,51 @@ TEST_CASE("[Vector3] Linear algebra methods") { Math::is_equal_approx(Vector3(-a.x, a.y, -a.z).dot(Vector3(b.x, -b.y, b.z)), (real_t)-75.24), "Vector3 dot should return expected value."); } + +TEST_CASE("[Vector3] Finite number checks") { + const double infinite[] = { NAN, INFINITY, -INFINITY }; + + CHECK_MESSAGE( + Vector3(0, 1, 2).is_finite(), + "Vector3(0, 1, 2) should be finite"); + + for (double x : infinite) { + CHECK_FALSE_MESSAGE( + Vector3(x, 1, 2).is_finite(), + "Vector3 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector3(0, x, 2).is_finite(), + "Vector3 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector3(0, 1, x).is_finite(), + "Vector3 with one component infinite should not be finite."); + } + + for (double x : infinite) { + for (double y : infinite) { + CHECK_FALSE_MESSAGE( + Vector3(x, y, 2).is_finite(), + "Vector3 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector3(x, 1, y).is_finite(), + "Vector3 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector3(0, x, y).is_finite(), + "Vector3 with two components infinite should not be finite."); + } + } + + for (double x : infinite) { + for (double y : infinite) { + for (double z : infinite) { + CHECK_FALSE_MESSAGE( + Vector3(x, y, z).is_finite(), + "Vector3 with three components infinite should not be finite."); + } + } + } +} + } // namespace TestVector3 #endif // TEST_VECTOR3_H diff --git a/tests/core/math/test_vector4.h b/tests/core/math/test_vector4.h index 3f50f16635..b31db56f67 100644 --- a/tests/core/math/test_vector4.h +++ b/tests/core/math/test_vector4.h @@ -314,6 +314,84 @@ TEST_CASE("[Vector4] Linear algebra methods") { Math::is_equal_approx((vector1 * 2).dot(vector2 * 4), (real_t)-25.9 * 8), "Vector4 dot product should work as expected."); } + +TEST_CASE("[Vector4] Finite number checks") { + const double infinite[] = { NAN, INFINITY, -INFINITY }; + + CHECK_MESSAGE( + Vector4(0, 1, 2, 3).is_finite(), + "Vector4(0, 1, 2, 3) should be finite"); + + for (double x : infinite) { + CHECK_FALSE_MESSAGE( + Vector4(x, 1, 2, 3).is_finite(), + "Vector4 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, x, 2, 3).is_finite(), + "Vector4 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, 1, x, 3).is_finite(), + "Vector4 with one component infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, 1, 2, x).is_finite(), + "Vector4 with one component infinite should not be finite."); + } + + for (double x : infinite) { + for (double y : infinite) { + CHECK_FALSE_MESSAGE( + Vector4(x, y, 2, 3).is_finite(), + "Vector4 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(x, 1, y, 3).is_finite(), + "Vector4 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(x, 1, 2, y).is_finite(), + "Vector4 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, x, y, 3).is_finite(), + "Vector4 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, x, 2, y).is_finite(), + "Vector4 with two components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(0, 1, x, y).is_finite(), + "Vector4 with two components infinite should not be finite."); + } + } + + for (double x : infinite) { + for (double y : infinite) { + for (double z : infinite) { + CHECK_FALSE_MESSAGE( + Vector4(0, x, y, z).is_finite(), + "Vector4 with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(x, 1, y, z).is_finite(), + "Vector4 with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(x, y, 2, z).is_finite(), + "Vector4 with three components infinite should not be finite."); + CHECK_FALSE_MESSAGE( + Vector4(x, y, z, 3).is_finite(), + "Vector4 with three components infinite should not be finite."); + } + } + } + + for (double x : infinite) { + for (double y : infinite) { + for (double z : infinite) { + for (double w : infinite) { + CHECK_FALSE_MESSAGE( + Vector4(x, y, z, w).is_finite(), + "Vector4 with four components infinite should not be finite."); + } + } + } + } +} + } // namespace TestVector4 #endif // TEST_VECTOR4_H |