summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/extension/extension_api_dump.cpp32
-rw-r--r--core/io/image.cpp9
-rw-r--r--core/io/image.h3
-rw-r--r--core/object/method_bind.h14
-rw-r--r--core/object/object.cpp190
-rw-r--r--core/object/object.h83
-rw-r--r--core/templates/hash_map.h33
-rw-r--r--core/templates/hash_set.h33
-rw-r--r--core/templates/hashfuncs.h62
-rw-r--r--core/variant/variant.h4
-rw-r--r--core/variant/variant_call.cpp82
11 files changed, 287 insertions, 258 deletions
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index edd48cf9cd..9d846f87c2 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -474,6 +474,38 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
}
}
{
+ //enums
+ Array enums;
+
+ List<StringName> enum_names;
+ Variant::get_enums_for_type(type, &enum_names);
+ for (const StringName &enum_name : enum_names) {
+ Dictionary enum_dict;
+ enum_dict["name"] = String(enum_name);
+
+ List<StringName> enumeration_names;
+ Variant::get_enumerations_for_enum(type, enum_name, &enumeration_names);
+
+ Array values;
+
+ for (const StringName &enumeration : enumeration_names) {
+ Dictionary values_dict;
+ values_dict["name"] = String(enumeration);
+ values_dict["value"] = Variant::get_enum_value(type, enum_name, enumeration);
+ values.push_back(values_dict);
+ }
+
+ if (values.size()) {
+ enum_dict["values"] = values;
+ }
+ enums.push_back(enum_dict);
+ }
+
+ if (enums.size()) {
+ d["enums"] = enums;
+ }
+ }
+ {
//operators
Array operators;
diff --git a/core/io/image.cpp b/core/io/image.cpp
index a945d3e6cd..f065dac212 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -85,6 +85,7 @@ SaveJPGFunc Image::save_jpg_func = nullptr;
SaveEXRFunc Image::save_exr_func = nullptr;
SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
+SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr;
SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr;
SaveWebPFunc Image::save_webp_func = nullptr;
@@ -2323,6 +2324,13 @@ Error Image::save_exr(const String &p_path, bool p_grayscale) const {
return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale);
}
+Vector<uint8_t> Image::save_exr_to_buffer(bool p_grayscale) const {
+ if (save_exr_buffer_func == nullptr) {
+ return Vector<uint8_t>();
+ }
+ return save_exr_buffer_func(Ref<Image>((Image *)this), p_grayscale);
+}
+
Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const {
if (save_webp_func == nullptr) {
return ERR_UNAVAILABLE;
@@ -3180,6 +3188,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_jpg", "path", "quality"), &Image::save_jpg, DEFVAL(0.75));
ClassDB::bind_method(D_METHOD("save_jpg_to_buffer", "quality"), &Image::save_jpg_to_buffer, DEFVAL(0.75));
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::save_exr_to_buffer, DEFVAL(false));
ClassDB::bind_method(D_METHOD("save_webp", "path", "lossy", "quality"), &Image::save_webp, DEFVAL(false), DEFVAL(0.75f));
ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f));
diff --git a/core/io/image.h b/core/io/image.h
index 229103f792..2cad26f3e9 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -52,6 +52,7 @@ typedef Error (*SaveWebPFunc)(const String &p_path, const Ref<Image> &p_img, con
typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const bool p_lossy, const float p_quality);
typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
+typedef Vector<uint8_t> (*SaveEXRBufferFunc)(const Ref<Image> &p_img, bool p_grayscale);
class Image : public Resource {
GDCLASS(Image, Resource);
@@ -61,6 +62,7 @@ public:
static SaveJPGFunc save_jpg_func;
static SaveEXRFunc save_exr_func;
static SavePNGBufferFunc save_png_buffer_func;
+ static SaveEXRBufferFunc save_exr_buffer_func;
static SaveJPGBufferFunc save_jpg_buffer_func;
static SaveWebPFunc save_webp_func;
static SaveWebPBufferFunc save_webp_buffer_func;
@@ -292,6 +294,7 @@ public:
Error save_jpg(const String &p_path, float p_quality = 0.75) const;
Vector<uint8_t> save_png_to_buffer() const;
Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const;
+ Vector<uint8_t> save_exr_to_buffer(bool p_grayscale) const;
Error save_exr(const String &p_path, bool p_grayscale) const;
Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const;
Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const;
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 2870195911..d60550c899 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -33,20 +33,6 @@
#include "core/variant/binder_common.h"
-enum MethodFlags {
- METHOD_FLAG_NORMAL = 1,
- METHOD_FLAG_EDITOR = 2,
- METHOD_FLAG_NOSCRIPT = 4,
- METHOD_FLAG_CONST = 8,
- METHOD_FLAG_REVERSE = 16, // used for events
- METHOD_FLAG_VIRTUAL = 32,
- METHOD_FLAG_FROM_SCRIPT = 64,
- METHOD_FLAG_VARARG = 128,
- METHOD_FLAG_STATIC = 256,
- METHOD_FLAG_OBJECT_CORE = 512,
- METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
-};
-
VARIANT_ENUM_CAST(MethodFlags)
// some helpers
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 96469db8c6..6585c3fa79 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -161,196 +161,6 @@ MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
return mi;
}
-MethodInfo::MethodInfo() :
- flags(METHOD_FLAG_NORMAL) {}
-
-MethodInfo::MethodInfo(const String &p_name) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
-}
-
-MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
- arguments.push_back(p_param6);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret) :
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
-}
-
-MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6) :
- name(p_name),
- flags(METHOD_FLAG_NORMAL) {
- return_val.type = ret;
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
- arguments.push_back(p_param6);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
-}
-
-MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6) :
- name(p_name),
- return_val(p_ret),
- flags(METHOD_FLAG_NORMAL) {
- arguments.push_back(p_param1);
- arguments.push_back(p_param2);
- arguments.push_back(p_param3);
- arguments.push_back(p_param4);
- arguments.push_back(p_param5);
- arguments.push_back(p_param6);
-}
-
Object::Connection::operator Variant() const {
Dictionary d;
d["signal"] = signal;
diff --git a/core/object/object.h b/core/object/object.h
index 02dd875acf..fe9231cfd8 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -204,10 +204,24 @@ struct PropertyInfo {
Array convert_property_list(const List<PropertyInfo> *p_list);
+enum MethodFlags {
+ METHOD_FLAG_NORMAL = 1,
+ METHOD_FLAG_EDITOR = 2,
+ METHOD_FLAG_NOSCRIPT = 4,
+ METHOD_FLAG_CONST = 8,
+ METHOD_FLAG_REVERSE = 16, // used for events
+ METHOD_FLAG_VIRTUAL = 32,
+ METHOD_FLAG_FROM_SCRIPT = 64,
+ METHOD_FLAG_VARARG = 128,
+ METHOD_FLAG_STATIC = 256,
+ METHOD_FLAG_OBJECT_CORE = 512,
+ METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
+};
+
struct MethodInfo {
String name;
PropertyInfo return_val;
- uint32_t flags; // NOLINT - prevent clang-tidy to assign method_bind.h constant here, it should stay in .cpp.
+ uint32_t flags = METHOD_FLAGS_DEFAULT;
int id = 0;
List<PropertyInfo> arguments;
Vector<Variant> default_arguments;
@@ -219,29 +233,50 @@ struct MethodInfo {
static MethodInfo from_dict(const Dictionary &p_dict);
- MethodInfo();
- MethodInfo(const String &p_name);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5);
- MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6);
- MethodInfo(Variant::Type ret);
- MethodInfo(Variant::Type ret, const String &p_name);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5);
- MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5);
- MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5, const PropertyInfo &p_param6);
+ MethodInfo() {}
+
+ void _push_params(const PropertyInfo &p_param) {
+ arguments.push_back(p_param);
+ }
+
+ template <typename... VarArgs>
+ void _push_params(const PropertyInfo &p_param, VarArgs... p_params) {
+ arguments.push_back(p_param);
+ _push_params(p_params...);
+ }
+
+ MethodInfo(const String &p_name) { name = p_name; }
+
+ template <typename... VarArgs>
+ MethodInfo(const String &p_name, VarArgs... p_params) {
+ name = p_name;
+ _push_params(p_params...);
+ }
+
+ MethodInfo(Variant::Type ret) { return_val.type = ret; }
+ MethodInfo(Variant::Type ret, const String &p_name) {
+ return_val.type = ret;
+ name = p_name;
+ }
+
+ template <typename... VarArgs>
+ MethodInfo(Variant::Type ret, const String &p_name, VarArgs... p_params) {
+ name = p_name;
+ return_val.type = ret;
+ _push_params(p_params...);
+ }
+
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name) {
+ return_val = p_ret;
+ name = p_name;
+ }
+
+ template <typename... VarArgs>
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name, VarArgs... p_params) {
+ return_val = p_ret;
+ name = p_name;
+ _push_params(p_params...);
+ }
};
// API used to extend in GDNative and other C compatible compiled languages.
diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h
index e5f73171a2..191f21a3dd 100644
--- a/core/templates/hash_map.h
+++ b/core/templates/hash_map.h
@@ -91,9 +91,9 @@ private:
return hash;
}
- _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const {
- uint32_t original_pos = p_hash % p_capacity;
- return (p_pos - original_pos + p_capacity) % p_capacity;
+ static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) {
+ const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity);
+ return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity);
}
bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
@@ -101,9 +101,10 @@ private:
return false; // Failed lookups, no elements
}
- uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t hash = _hash(p_key);
- uint32_t pos = hash % capacity;
+ uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t distance = 0;
while (true) {
@@ -111,7 +112,7 @@ private:
return false;
}
- if (distance > _get_probe_length(pos, hashes[pos], capacity)) {
+ if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) {
return false;
}
@@ -120,17 +121,18 @@ private:
return true;
}
- pos = (pos + 1) % capacity;
+ pos = fastmod((pos + 1), capacity_inv, capacity);
distance++;
}
}
void _insert_with_hash(uint32_t p_hash, HashMapElement<TKey, TValue> *p_value) {
- uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t hash = p_hash;
HashMapElement<TKey, TValue> *value = p_value;
uint32_t distance = 0;
- uint32_t pos = hash % capacity;
+ uint32_t pos = fastmod(hash, capacity_inv, capacity);
while (true) {
if (hashes[pos] == EMPTY_HASH) {
@@ -143,14 +145,14 @@ private:
}
// Not an empty slot, let's check the probing length of the existing one.
- uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity);
+ uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv);
if (existing_probe_len < distance) {
SWAP(hash, hashes[pos]);
SWAP(value, elements[pos]);
distance = existing_probe_len;
}
- pos = (pos + 1) % capacity;
+ pos = fastmod((pos + 1), capacity_inv, capacity);
distance++;
}
}
@@ -316,13 +318,14 @@ public:
return false;
}
- uint32_t capacity = hash_table_size_primes[capacity_index];
- uint32_t next_pos = (pos + 1) % capacity;
- while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) {
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
+ uint32_t next_pos = fastmod((pos + 1), capacity_inv, capacity);
+ while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) {
SWAP(hashes[next_pos], hashes[pos]);
SWAP(elements[next_pos], elements[pos]);
pos = next_pos;
- next_pos = (pos + 1) % capacity;
+ next_pos = fastmod((pos + 1), capacity_inv, capacity);
}
hashes[pos] = EMPTY_HASH;
diff --git a/core/templates/hash_set.h b/core/templates/hash_set.h
index 2318067dcc..7b3a5d46f8 100644
--- a/core/templates/hash_set.h
+++ b/core/templates/hash_set.h
@@ -74,9 +74,9 @@ private:
return hash;
}
- _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const {
- uint32_t original_pos = p_hash % p_capacity;
- return (p_pos - original_pos + p_capacity) % p_capacity;
+ static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) {
+ const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity);
+ return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity);
}
bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
@@ -84,9 +84,10 @@ private:
return false; // Failed lookups, no elements
}
- uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t hash = _hash(p_key);
- uint32_t pos = hash % capacity;
+ uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t distance = 0;
while (true) {
@@ -94,7 +95,7 @@ private:
return false;
}
- if (distance > _get_probe_length(pos, hashes[pos], capacity)) {
+ if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) {
return false;
}
@@ -103,17 +104,18 @@ private:
return true;
}
- pos = (pos + 1) % capacity;
+ pos = fastmod(pos + 1, capacity_inv, capacity);
distance++;
}
}
uint32_t _insert_with_hash(uint32_t p_hash, uint32_t p_index) {
- uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t hash = p_hash;
uint32_t index = p_index;
uint32_t distance = 0;
- uint32_t pos = hash % capacity;
+ uint32_t pos = fastmod(hash, capacity_inv, capacity);
while (true) {
if (hashes[pos] == EMPTY_HASH) {
@@ -124,7 +126,7 @@ private:
}
// Not an empty slot, let's check the probing length of the existing one.
- uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity);
+ uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv);
if (existing_probe_len < distance) {
key_to_hash[index] = pos;
SWAP(hash, hashes[pos]);
@@ -132,7 +134,7 @@ private:
distance = existing_probe_len;
}
- pos = (pos + 1) % capacity;
+ pos = fastmod(pos + 1, capacity_inv, capacity);
distance++;
}
}
@@ -265,9 +267,10 @@ public:
uint32_t key_pos = pos;
pos = key_to_hash[pos]; //make hash pos
- uint32_t capacity = hash_table_size_primes[capacity_index];
- uint32_t next_pos = (pos + 1) % capacity;
- while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) {
+ const uint32_t capacity = hash_table_size_primes[capacity_index];
+ const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
+ uint32_t next_pos = fastmod(pos + 1, capacity_inv, capacity);
+ while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) {
uint32_t kpos = hash_to_key[pos];
uint32_t kpos_next = hash_to_key[next_pos];
SWAP(key_to_hash[kpos], key_to_hash[kpos_next]);
@@ -275,7 +278,7 @@ public:
SWAP(hash_to_key[next_pos], hash_to_key[pos]);
pos = next_pos;
- next_pos = (pos + 1) % capacity;
+ next_pos = fastmod(pos + 1, capacity_inv, capacity);
}
hashes[pos] = EMPTY_HASH;
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index b0371f2ab5..547534f26a 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -437,4 +437,66 @@ const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
1610612741,
};
+// Computed with elem_i = UINT64_C (0 x FFFFFFFF FFFFFFFF ) / d_i + 1, where d_i is the i-th element of the above array.
+const uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = {
+ 3689348814741910324,
+ 1418980313362273202,
+ 802032351030850071,
+ 392483916461905354,
+ 190172619316593316,
+ 95578984837873325,
+ 47420935922132524,
+ 23987963684927896,
+ 11955116055547344,
+ 5991147799191151,
+ 2998982941588287,
+ 1501077717772769,
+ 750081082979285,
+ 375261795343686,
+ 187625172388393,
+ 93822606204624,
+ 46909513691883,
+ 23456218233098,
+ 11728086747027,
+ 5864041509391,
+ 2932024948977,
+ 1466014921160,
+ 733007198436,
+ 366503839517,
+ 183251896093,
+ 91625960335,
+ 45812983922,
+ 22906489714,
+ 11453246088
+};
+
+/**
+ * Fastmod computes ( n mod d ) given the precomputed c much faster than n % d.
+ * The implementation of fastmod is based on the following paper by Daniel Lemire et al.
+ * Faster Remainder by Direct Computation: Applications to Compilers and Software Libraries
+ * https://arxiv.org/abs/1902.01961
+ */
+static _FORCE_INLINE_ uint32_t fastmod(const uint32_t n, const uint64_t c, const uint32_t d) {
+#if defined(_MSC_VER)
+ // Returns the upper 64 bits of the product of two 64-bit unsigned integers.
+ // This intrinsic function is required since MSVC does not support unsigned 128-bit integers.
+#if defined(_M_X64) || defined(_M_ARM64)
+ return __umulh(c * n, d);
+#else
+ // Fallback to the slower method for 32-bit platforms.
+ return n % d;
+#endif // _M_X64 || _M_ARM64
+#else
+#ifdef __SIZEOF_INT128__
+ // Prevent compiler warning, because we know what we are doing.
+ uint64_t lowbits = c * n;
+ __extension__ typedef unsigned __int128 uint128;
+ return static_cast<uint64_t>(((uint128)lowbits * d) >> 64);
+#else
+ // Fallback to the slower method if no 128-bit unsigned integer type is available.
+ return n % d;
+#endif // __SIZEOF_INT128__
+#endif // _MSC_VER
+}
+
#endif // HASHFUNCS_H
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 726ba120b5..992d9cad40 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -716,6 +716,10 @@ public:
static bool has_constant(Variant::Type p_type, const StringName &p_value);
static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
+ static void get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums);
+ static void get_enumerations_for_enum(Variant::Type p_type, StringName p_enum_name, List<StringName> *p_enumerations);
+ static int get_enum_value(Variant::Type p_type, StringName p_enum_name, StringName p_enumeration, bool *r_valid = nullptr);
+
typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud);
typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index cb9dfe478b..8e420ecf04 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -944,9 +944,20 @@ struct _VariantCall {
constant_data[p_type].variant_value_ordered.push_back(p_constant_name);
#endif
}
+
+ struct EnumData {
+ HashMap<StringName, HashMap<StringName, int>> value;
+ };
+
+ static EnumData *enum_data;
+
+ static void add_enum_constant(int p_type, StringName p_enum_type_name, StringName p_enumeration_name, int p_enum_value) {
+ enum_data[p_type].value[p_enum_type_name][p_enumeration_name] = p_enum_value;
+ }
};
_VariantCall::ConstantData *_VariantCall::constant_data = nullptr;
+_VariantCall::EnumData *_VariantCall::enum_data = nullptr;
struct VariantBuiltInMethodInfo {
void (*call)(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) = nullptr;
@@ -1300,6 +1311,54 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
return E->value;
}
+void Variant::get_enums_for_type(Variant::Type p_type, List<StringName> *p_enums) {
+ ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
+
+ _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type];
+
+ for (const KeyValue<StringName, HashMap<StringName, int>> &E : enum_data.value) {
+ p_enums->push_back(E.key);
+ }
+}
+
+void Variant::get_enumerations_for_enum(Variant::Type p_type, StringName p_enum_name, List<StringName> *p_enumerations) {
+ ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
+
+ _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type];
+
+ for (const KeyValue<StringName, HashMap<StringName, int>> &E : enum_data.value) {
+ for (const KeyValue<StringName, int> &V : E.value) {
+ p_enumerations->push_back(V.key);
+ }
+ }
+}
+
+int Variant::get_enum_value(Variant::Type p_type, StringName p_enum_name, StringName p_enumeration, bool *r_valid) {
+ if (r_valid) {
+ *r_valid = false;
+ }
+
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+
+ _VariantCall::EnumData &enum_data = _VariantCall::enum_data[p_type];
+
+ HashMap<StringName, HashMap<StringName, int>>::Iterator E = enum_data.value.find(p_enum_name);
+ if (!E) {
+ return -1;
+ }
+
+ HashMap<StringName, int>::Iterator V = E->value.find(p_enumeration);
+ if (!V) {
+ return -1;
+ }
+
+ if (r_valid) {
+ *r_valid = true;
+ }
+
+ return V->value;
+}
+
#ifdef DEBUG_METHODS_ENABLED
#define bind_method(m_type, m_method, m_arg_names, m_default_args) \
METHOD_CLASS(m_type, m_method, &m_type::m_method); \
@@ -1360,6 +1419,7 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
static void _register_variant_builtin_methods() {
_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
+ _VariantCall::enum_data = memnew_arr(_VariantCall::EnumData, Variant::VARIANT_MAX);
builtin_method_info = memnew_arr(BuiltinMethodMap, Variant::VARIANT_MAX);
builtin_method_names = memnew_arr(List<StringName>, Variant::VARIANT_MAX);
@@ -2124,6 +2184,10 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_constant(Variant::VECTOR3, "AXIS_Y", Vector3::AXIS_Y);
_VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z);
+ _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_X", Vector3::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_Y", Vector3::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR3, "Axis", "AXIS_Z", Vector3::AXIS_Z);
+
_VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(INFINITY, INFINITY, INFINITY));
@@ -2138,6 +2202,10 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y);
_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z);
+ _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_X", Vector3i::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Y", Vector3i::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR3I, "Axis", "AXIS_Z", Vector3i::AXIS_Z);
+
_VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0));
@@ -2150,9 +2218,15 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X);
_VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR2, "Axis", "AXIS_X", Vector2::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR2, "Axis", "AXIS_Y", Vector2::AXIS_Y);
+
_VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2i::AXIS_X);
_VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2i::AXIS_Y);
+ _VariantCall::add_enum_constant(Variant::VECTOR2I, "Axis", "AXIS_X", Vector2i::AXIS_X);
+ _VariantCall::add_enum_constant(Variant::VECTOR2I, "Axis", "AXIS_Y", Vector2i::AXIS_Y);
+
_VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1));
_VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(INFINITY, INFINITY));
@@ -2175,6 +2249,13 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZXY", Basis::EULER_ORDER_ZXY);
_VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZYX", Basis::EULER_ORDER_ZYX);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_XYZ", Basis::EULER_ORDER_XYZ);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_XZY", Basis::EULER_ORDER_XZY);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_YXZ", Basis::EULER_ORDER_YXZ);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_YZX", Basis::EULER_ORDER_YZX);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_ZXY", Basis::EULER_ORDER_ZXY);
+ _VariantCall::add_enum_constant(Variant::BASIS, "EulerOrder", "EULER_ORDER_ZYX", Basis::EULER_ORDER_ZYX);
+
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
@@ -2213,4 +2294,5 @@ void Variant::_unregister_variant_methods() {
memdelete_arr(builtin_method_names);
memdelete_arr(builtin_method_info);
memdelete_arr(_VariantCall::constant_data);
+ memdelete_arr(_VariantCall::enum_data);
}