summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/extension/extension_api_dump.cpp221
-rw-r--r--core/extension/extension_api_dump.h4
-rw-r--r--core/io/image.cpp20
-rw-r--r--core/io/resource.cpp3
-rw-r--r--core/io/resource.h2
-rw-r--r--core/math/bvh_split.inc18
-rw-r--r--core/variant/array.cpp2
-rw-r--r--core/variant/dictionary.cpp2
-rw-r--r--core/variant/variant.cpp9
-rw-r--r--core/variant/variant.h3
10 files changed, 252 insertions, 32 deletions
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index f11a4bc9a4..58cb51245a 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -39,6 +39,7 @@
#include "core/version.h"
#ifdef TOOLS_ENABLED
+#include "editor/editor_help.h"
static String get_builtin_or_variant_type_name(const Variant::Type p_type) {
if (p_type == Variant::NIL) {
@@ -88,7 +89,16 @@ static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) {
return argmeta[metadata];
}
-Dictionary GDExtensionAPIDump::generate_extension_api() {
+static String fix_doc_description(const String &p_bbcode) {
+ // Based on what EditorHelp does.
+
+ return p_bbcode.dedent()
+ .replace("\t", "")
+ .replace("\r", "")
+ .strip_edges();
+}
+
+Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
Dictionary api_dump;
{
@@ -460,12 +470,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
}
+ if (p_include_docs) {
+ EditorHelp::generate_doc(false);
+ }
+
{
// Global enums and constants.
Array constants;
HashMap<String, List<Pair<String, int64_t>>> enum_list;
HashMap<String, bool> enum_is_bitfield;
+ const DocData::ClassDoc *global_scope_doc = nullptr;
+ if (p_include_docs) {
+ global_scope_doc = EditorHelp::get_doc_data()->class_list.getptr("@GlobalScope");
+ CRASH_COND_MSG(!global_scope_doc, "Could not find '@GlobalScope' in DocData.");
+ }
+
for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
int64_t value = CoreConstants::get_global_constant_value(i);
String enum_name = CoreConstants::get_global_constant_enum(i);
@@ -479,6 +499,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d["name"] = name;
d["value"] = value;
d["is_bitfield"] = bitfield;
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : global_scope_doc->constants) {
+ if (constant_doc.name == name) {
+ d["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
constants.push_back(d);
}
}
@@ -490,11 +518,25 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary d1;
d1["name"] = E.key;
d1["is_bitfield"] = enum_is_bitfield[E.key];
+ if (p_include_docs) {
+ const DocData::EnumDoc *enum_doc = global_scope_doc->enums.getptr(E.key);
+ if (enum_doc) {
+ d1["documentation"] = fix_doc_description(enum_doc->description);
+ }
+ }
Array values;
for (const Pair<String, int64_t> &F : E.value) {
Dictionary d2;
d2["name"] = F.first;
d2["value"] = F.second;
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : global_scope_doc->constants) {
+ if (constant_doc.name == F.first) {
+ d2["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
values.push_back(d2);
}
d1["values"] = values;
@@ -509,6 +551,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
List<StringName> utility_func_names;
Variant::get_utility_function_list(&utility_func_names);
+ const DocData::ClassDoc *global_scope_doc = nullptr;
+ if (p_include_docs) {
+ global_scope_doc = EditorHelp::get_doc_data()->class_list.getptr("@GlobalScope");
+ CRASH_COND_MSG(!global_scope_doc, "Could not find '@GlobalScope' in DocData.");
+ }
+
for (const StringName &name : utility_func_names) {
Dictionary func;
func["name"] = String(name);
@@ -545,6 +593,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
func["arguments"] = arguments;
}
+ if (p_include_docs) {
+ for (const DocData::MethodDoc &method_doc : global_scope_doc->methods) {
+ if (method_doc.name == name) {
+ func["documentation"] = fix_doc_description(method_doc.description);
+ break;
+ }
+ }
+ }
+
utility_funcs.push_back(func);
}
@@ -571,6 +628,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d["is_keyed"] = Variant::is_keyed(type);
+ DocData::ClassDoc *builtin_doc = nullptr;
+ if (p_include_docs && d["name"] != "Nil") {
+ builtin_doc = EditorHelp::get_doc_data()->class_list.getptr(d["name"]);
+ CRASH_COND_MSG(!builtin_doc, vformat("Could not find '%s' in DocData.", d["name"]));
+ }
+
{
//members
Array members;
@@ -581,6 +644,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary d2;
d2["name"] = String(member_name);
d2["type"] = get_builtin_or_variant_type_name(Variant::get_member_type(type, member_name));
+ if (p_include_docs) {
+ for (const DocData::PropertyDoc &property_doc : builtin_doc->properties) {
+ if (property_doc.name == member_name) {
+ d2["documentation"] = fix_doc_description(property_doc.description);
+ break;
+ }
+ }
+ }
members.push_back(d2);
}
if (members.size()) {
@@ -599,6 +670,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Variant constant = Variant::get_constant_value(type, constant_name);
d2["type"] = get_builtin_or_variant_type_name(constant.get_type());
d2["value"] = constant.get_construct_string();
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : builtin_doc->constants) {
+ if (constant_doc.name == constant_name) {
+ d2["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
constants.push_back(d2);
}
if (constants.size()) {
@@ -624,9 +703,24 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary values_dict;
values_dict["name"] = String(enumeration);
values_dict["value"] = Variant::get_enum_value(type, enum_name, enumeration);
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : builtin_doc->constants) {
+ if (constant_doc.name == enumeration) {
+ values_dict["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
values.push_back(values_dict);
}
+ if (p_include_docs) {
+ const DocData::EnumDoc *enum_doc = builtin_doc->enums.getptr(enum_name);
+ if (enum_doc) {
+ enum_dict["documentation"] = fix_doc_description(enum_doc->description);
+ }
+ }
+
if (values.size()) {
enum_dict["values"] = values;
}
@@ -646,11 +740,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
if (rt != Variant::NIL) {
Dictionary d2;
- d2["name"] = Variant::get_operator_name(Variant::Operator(k));
+ String operator_name = Variant::get_operator_name(Variant::Operator(k));
+ d2["name"] = operator_name;
if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
d2["right_type"] = get_builtin_or_variant_type_name(Variant::Type(j));
}
d2["return_type"] = get_builtin_or_variant_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j)));
+
+ if (p_include_docs && builtin_doc != nullptr) {
+ for (const DocData::MethodDoc &operator_doc : builtin_doc->operators) {
+ if (operator_doc.name == "operator " + operator_name) {
+ d2["documentation"] = fix_doc_description(operator_doc.description);
+ break;
+ }
+ }
+ }
+
operators.push_back(d2);
}
}
@@ -697,6 +802,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d2["arguments"] = arguments;
}
+ if (p_include_docs) {
+ for (const DocData::MethodDoc &method_doc : builtin_doc->methods) {
+ if (method_doc.name == method_name) {
+ d2["documentation"] = fix_doc_description(method_doc.description);
+ break;
+ }
+ }
+ }
+
methods.push_back(d2);
}
if (methods.size()) {
@@ -722,6 +836,28 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
if (arguments.size()) {
d2["arguments"] = arguments;
}
+
+ if (p_include_docs && builtin_doc) {
+ for (const DocData::MethodDoc &constructor_doc : builtin_doc->constructors) {
+ if (constructor_doc.arguments.size() != argcount) {
+ continue;
+ }
+ bool constructor_found = true;
+ for (int k = 0; k < argcount; k++) {
+ const DocData::ArgumentDoc &argument_doc = constructor_doc.arguments[k];
+ const Dictionary &argument_dict = arguments[k];
+ const String &argument_string = argument_dict["type"];
+ if (argument_doc.type != argument_string) {
+ constructor_found = false;
+ break;
+ }
+ }
+ if (constructor_found) {
+ d2["documentation"] = fix_doc_description(constructor_doc.description);
+ }
+ }
+ }
+
constructors.push_back(d2);
}
@@ -734,6 +870,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d["has_destructor"] = Variant::has_destructor(type);
}
+ if (p_include_docs && builtin_doc != nullptr) {
+ d["documentation"] = fix_doc_description(builtin_doc->description);
+ }
+
builtins.push_back(d);
}
@@ -763,6 +903,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d["inherits"] = String(parent_class);
}
+ DocData::ClassDoc *class_doc = nullptr;
+ if (p_include_docs) {
+ class_doc = EditorHelp::get_doc_data()->class_list.getptr(class_name);
+ CRASH_COND_MSG(!class_doc, vformat("Could not find '%s' in DocData.", class_name));
+ }
+
{
ClassDB::APIType api = ClassDB::get_api_type(class_name);
static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
@@ -784,6 +930,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d2["name"] = String(F);
d2["value"] = ClassDB::get_integer_constant(class_name, F);
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
+ if (constant_doc.name == F) {
+ d2["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
+
constants.push_back(d2);
}
@@ -808,11 +963,28 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Dictionary d3;
d3["name"] = String(G->get());
d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
+
+ if (p_include_docs) {
+ for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
+ if (constant_doc.name == G->get()) {
+ d3["documentation"] = fix_doc_description(constant_doc.description);
+ break;
+ }
+ }
+ }
+
values.push_back(d3);
}
d2["values"] = values;
+ if (p_include_docs) {
+ const DocData::EnumDoc *enum_doc = class_doc->enums.getptr(F);
+ if (enum_doc) {
+ d2["documentation"] = fix_doc_description(enum_doc->description);
+ }
+ }
+
enums.push_back(d2);
}
@@ -864,6 +1036,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d2["arguments"] = arguments;
}
+ if (p_include_docs) {
+ for (const DocData::MethodDoc &method_doc : class_doc->methods) {
+ if (method_doc.name == method_name) {
+ d2["documentation"] = fix_doc_description(method_doc.description);
+ break;
+ }
+ }
+ }
+
methods.push_back(d2);
} else if (F.name.begins_with("_")) {
@@ -932,6 +1113,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d2["arguments"] = arguments;
}
+ if (p_include_docs) {
+ for (const DocData::MethodDoc &method_doc : class_doc->methods) {
+ if (method_doc.name == method_name) {
+ d2["documentation"] = fix_doc_description(method_doc.description);
+ break;
+ }
+ }
+ }
+
methods.push_back(d2);
}
}
@@ -966,6 +1156,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
d2["arguments"] = arguments;
}
+ if (p_include_docs) {
+ for (const DocData::MethodDoc &signal_doc : class_doc->signals) {
+ if (signal_doc.name == signal_name) {
+ d2["documentation"] = fix_doc_description(signal_doc.description);
+ break;
+ }
+ }
+ }
+
signals.push_back(d2);
}
@@ -1005,6 +1204,16 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
if (index != -1) {
d2["index"] = index;
}
+
+ if (p_include_docs) {
+ for (const DocData::PropertyDoc &property_doc : class_doc->properties) {
+ if (property_doc.name == property_name) {
+ d2["documentation"] = fix_doc_description(property_doc.description);
+ break;
+ }
+ }
+ }
+
properties.push_back(d2);
}
@@ -1013,6 +1222,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
}
}
+ if (p_include_docs && class_doc != nullptr) {
+ d["documentation"] = fix_doc_description(class_doc->description);
+ }
+
classes.push_back(d);
}
@@ -1065,8 +1278,8 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
return api_dump;
}
-void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) {
- Dictionary api = generate_extension_api();
+void GDExtensionAPIDump::generate_extension_json_file(const String &p_path, bool p_include_docs) {
+ Dictionary api = generate_extension_api(p_include_docs);
Ref<JSON> json;
json.instantiate();
diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h
index 11ea2cf923..204a115f84 100644
--- a/core/extension/extension_api_dump.h
+++ b/core/extension/extension_api_dump.h
@@ -37,8 +37,8 @@
class GDExtensionAPIDump {
public:
- static Dictionary generate_extension_api();
- static void generate_extension_json_file(const String &p_path);
+ static Dictionary generate_extension_api(bool p_include_docs = false);
+ static void generate_extension_json_file(const String &p_path, bool p_include_docs = false);
static Error validate_extension_json_file(const String &p_path);
};
#endif
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 674af6b0a6..15d0182dfc 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -1930,8 +1930,7 @@ Error Image::generate_mipmaps(bool p_renormalize) {
}
Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) {
- Vector<double> normal_sat_vec; //summed area table
- double *normal_sat = nullptr; //summed area table for normal map
+ LocalVector<double> normal_sat_vec; //summed area table
int normal_w = 0, normal_h = 0;
ERR_FAIL_COND_V_MSG(p_normal_map.is_null() || p_normal_map->is_empty(), ERR_INVALID_PARAMETER, "Must provide a valid normal map for roughness mipmaps");
@@ -1945,8 +1944,7 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
normal_h = nm->get_height();
normal_sat_vec.resize(normal_w * normal_h * 3);
-
- normal_sat = normal_sat_vec.ptrw();
+ double *normal_sat = normal_sat_vec.ptr();
//create summed area table
@@ -2021,24 +2019,26 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con
avg[2] += normal_sat[tofs + 2];
}
- if (from_y > 0) {
+ if (from_y > 0 && to_x > 0) {
uint32_t tofs = ((from_y - 1) * normal_w + to_x) * 3;
avg[0] -= normal_sat[tofs + 0];
avg[1] -= normal_sat[tofs + 1];
avg[2] -= normal_sat[tofs + 2];
}
- if (from_x > 0) {
+ if (from_x > 0 && to_y > 0) {
uint32_t tofs = (to_y * normal_w + (from_x - 1)) * 3;
avg[0] -= normal_sat[tofs + 0];
avg[1] -= normal_sat[tofs + 1];
avg[2] -= normal_sat[tofs + 2];
}
- uint32_t tofs = (to_y * normal_w + to_x) * 3;
- avg[0] += normal_sat[tofs + 0];
- avg[1] += normal_sat[tofs + 1];
- avg[2] += normal_sat[tofs + 2];
+ if (to_y > 0 && to_x > 0) {
+ uint32_t tofs = (to_y * normal_w + to_x) * 3;
+ avg[0] += normal_sat[tofs + 0];
+ avg[1] += normal_sat[tofs + 1];
+ avg[2] += normal_sat[tofs + 2];
+ }
double div = double(size_x * size_y);
Vector3 vec(avg[0] / div, avg[1] / div, avg[2] / div);
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 68cdeabac7..e0d42a274a 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -379,8 +379,8 @@ Node *Resource::get_local_scene() const {
}
void Resource::setup_local_to_scene() {
- // Can't use GDVIRTUAL in Resource, so this will have to be done with a signal
emit_signal(SNAME("setup_local_to_scene_requested"));
+ GDVIRTUAL_CALL(_setup_local_to_scene);
}
void Resource::reset_local_to_scene() {
@@ -460,6 +460,7 @@ void Resource::_bind_methods() {
get_rid_bind.return_val.type = Variant::RID;
::ClassDB::add_virtual_method(get_class_static(), get_rid_bind, true, Vector<String>(), true);
+ GDVIRTUAL_BIND(_setup_local_to_scene);
}
Resource::Resource() :
diff --git a/core/io/resource.h b/core/io/resource.h
index f848bdba99..a9b1a88f6b 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -33,6 +33,7 @@
#include "core/io/resource_uid.h"
#include "core/object/class_db.h"
+#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
#include "core/templates/safe_refcount.h"
#include "core/templates/self_list.h"
@@ -81,6 +82,7 @@ protected:
void _take_over_path(const String &p_path);
virtual void reset_local_to_scene();
+ GDVIRTUAL0(_setup_local_to_scene);
public:
static Node *(*_get_local_scene_func)(); //used by editor
diff --git a/core/math/bvh_split.inc b/core/math/bvh_split.inc
index 875abedb70..2c85a63575 100644
--- a/core/math/bvh_split.inc
+++ b/core/math/bvh_split.inc
@@ -20,8 +20,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
group_b[num_b++] = ind;
// remove from a
- group_a[0] = group_a[num_a - 1];
num_a--;
+ group_a[0] = group_a[num_a];
return;
}
@@ -30,15 +30,15 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
int order[POINT::AXIS_COUNT];
- order[0] = size.min_axis_index();
- order[POINT::AXIS_COUNT - 1] = size.max_axis_index();
+ order[0] = size.max_axis_index(); // The longest axis.
+ order[POINT::AXIS_COUNT - 1] = size.min_axis_index(); // The shortest axis.
static_assert(POINT::AXIS_COUNT <= 3, "BVH POINT::AXIS_COUNT has unexpected size");
if constexpr (POINT::AXIS_COUNT == 3) {
order[1] = 3 - (order[0] + order[2]);
}
- // simplest case, split on the longest axis
+ // Simplest case, split on the longest axis.
int split_axis = order[0];
for (int a = 0; a < num_a; a++) {
uint32_t ind = group_a[a];
@@ -48,8 +48,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
group_b[num_b++] = ind;
// remove from a
- group_a[a] = group_a[num_a - 1];
num_a--;
+ group_a[a] = group_a[num_a];
// do this one again, as it has been replaced
a--;
@@ -67,7 +67,7 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
}
num_b = 0;
- // now calculate the best split
+ // Now calculate the best split.
for (int axis = 1; axis < POINT::AXIS_COUNT; axis++) {
split_axis = order[axis];
int count = 0;
@@ -105,8 +105,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
group_b[num_b++] = ind;
// remove from a
- group_a[a] = group_a[num_a - 1];
num_a--;
+ group_a[a] = group_a[num_a];
// do this one again, as it has been replaced
a--;
@@ -123,8 +123,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
group_b[num_b++] = ind;
// remove from a
- group_a[0] = group_a[num_a - 1];
num_a--;
+ group_a[0] = group_a[num_a];
}
// opposite problem! :)
if (!num_a) {
@@ -134,8 +134,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
group_a[num_a++] = ind;
// remove from b
- group_b[0] = group_b[num_b - 1];
num_b--;
+ group_b[0] = group_b[num_b];
}
}
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 4c9ee68ab5..ab0315ae34 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -137,7 +137,7 @@ bool Array::recursive_equal(const Array &p_array, int recursion_count) const {
}
recursion_count++;
for (int i = 0; i < size; i++) {
- if (!a1[i].hash_compare(a2[i], recursion_count)) {
+ if (!a1[i].hash_compare(a2[i], recursion_count, false)) {
return false;
}
}
diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp
index 2dda9fc1f8..141ce25fa6 100644
--- a/core/variant/dictionary.cpp
+++ b/core/variant/dictionary.cpp
@@ -210,7 +210,7 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
recursion_count++;
for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator other_E(p_dictionary._p->variant_map.find(this_E.key));
- if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) {
+ if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count, false)) {
return false;
}
}
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 8a0289898d..63ea3274ce 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3235,8 +3235,11 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
return 0;
}
+#define hash_compare_scalar_base(p_lhs, p_rhs, semantic_comparison) \
+ (((p_lhs) == (p_rhs)) || (semantic_comparison && Math::is_nan(p_lhs) && Math::is_nan(p_rhs)))
+
#define hash_compare_scalar(p_lhs, p_rhs) \
- (((p_lhs) == (p_rhs)) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)))
+ (hash_compare_scalar_base(p_lhs, p_rhs, true))
#define hash_compare_vector2(p_lhs, p_rhs) \
(hash_compare_scalar((p_lhs).x, (p_rhs).x) && \
@@ -3282,7 +3285,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const {
\
return true
-bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const {
+bool Variant::hash_compare(const Variant &p_variant, int recursion_count, bool semantic_comparison) const {
if (type != p_variant.type) {
return false;
}
@@ -3293,7 +3296,7 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const
} break;
case FLOAT: {
- return hash_compare_scalar(_data._float, p_variant._data._float);
+ return hash_compare_scalar_base(_data._float, p_variant._data._float, semantic_comparison);
} break;
case STRING: {
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 04c2fe2012..d698f85754 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -751,7 +751,8 @@ public:
uint32_t hash() const;
uint32_t recursive_hash(int recursion_count) const;
- bool hash_compare(const Variant &p_variant, int recursion_count = 0) const;
+ // By default, performs a semantic comparison. Otherwise, numeric/binary comparison (if appropriate).
+ bool hash_compare(const Variant &p_variant, int recursion_count = 0, bool semantic_comparison = true) const;
bool identity_compare(const Variant &p_variant) const;
bool booleanize() const;
String stringify(int recursion_count = 0) const;