diff options
Diffstat (limited to 'core')
33 files changed, 426 insertions, 226 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index ff5ff83bf8..12d936d456 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -205,6 +205,11 @@ void ProjectSettings::set_as_basic(const String &p_name, bool p_basic) { props[p_name].basic = p_basic; } +void ProjectSettings::set_as_internal(const String &p_name, bool p_internal) { + ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); + props[p_name].internal = p_internal; +} + void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) { ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); #ifdef DEBUG_METHODS_ENABLED @@ -344,7 +349,7 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { vc.name = E.key; vc.order = v->order; vc.type = v->variant.get_type(); - if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload")) { + if (v->internal || vc.name.begins_with("input/") || vc.name.begins_with("importer_defaults/") || vc.name.begins_with("import/") || vc.name.begins_with("autoload/") || vc.name.begins_with("editor_plugins/") || vc.name.begins_with("shader_globals/")) { vc.flags = PROPERTY_USAGE_STORAGE; } else { vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE; @@ -890,7 +895,7 @@ Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other par Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) { ERR_FAIL_COND_V_MSG(p_path.is_empty(), ERR_INVALID_PARAMETER, "Project settings save path cannot be empty."); - PackedStringArray project_features = has_setting("application/config/features") ? (PackedStringArray)get_setting("application/config/features") : PackedStringArray(); + PackedStringArray project_features = get_setting("application/config/features"); // If there is no feature list currently present, force one to generate. if (project_features.is_empty()) { project_features = ProjectSettings::get_required_features(); @@ -994,7 +999,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust } } -Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed, bool p_ignore_value_in_docs, bool p_basic) { +Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed, bool p_ignore_value_in_docs, bool p_basic, bool p_internal) { Variant ret; if (!ProjectSettings::get_singleton()->has_setting(p_var)) { ProjectSettings::get_singleton()->set(p_var, p_default); @@ -1006,6 +1011,7 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restar ProjectSettings::get_singleton()->set_as_basic(p_var, p_basic); ProjectSettings::get_singleton()->set_restart_if_changed(p_var, p_restart_if_changed); ProjectSettings::get_singleton()->set_ignore_value_in_docs(p_var, p_ignore_value_in_docs); + ProjectSettings::get_singleton()->set_as_internal(p_var, p_internal); return ret; } @@ -1151,7 +1157,7 @@ void ProjectSettings::_add_builtin_input_map() { action["events"] = events; String action_name = "input/" + E.key; - GLOBAL_DEF(action_name, action); + GLOBAL_DEF_INTERNAL(action_name, action); input_presets.push_back(action_name); } } @@ -1235,6 +1241,11 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("compression/formats/gzip/compression_level", Compression::gzip_level); custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1"); + + // These properties will not show up in the dialog nor in the documentation. If you want to exclude whole groups, see _get_property_list() method. + GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray()); + GLOBAL_DEF_INTERNAL("internationalization/locale/translation_remaps", PackedStringArray()); + GLOBAL_DEF_INTERNAL("internationalization/locale/translations", PackedStringArray()); } ProjectSettings::~ProjectSettings() { diff --git a/core/config/project_settings.h b/core/config/project_settings.h index d9b1a9b81b..c3992a4db2 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -62,6 +62,7 @@ protected: int order = 0; bool persist = false; bool basic = false; + bool internal = false; Variant variant; Variant initial; bool hide_from_editor = false; @@ -141,6 +142,7 @@ public: void set_initial_value(const String &p_name, const Variant &p_value); void set_as_basic(const String &p_name, bool p_basic); + void set_as_internal(const String &p_name, bool p_internal); void set_restart_if_changed(const String &p_name, bool p_restart); void set_ignore_value_in_docs(const String &p_name, bool p_ignore); bool get_ignore_value_in_docs(const String &p_name) const; @@ -191,8 +193,8 @@ public: ~ProjectSettings(); }; -//not a macro any longer -Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false, bool p_basic = false); +// Not a macro any longer. +Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false, bool p_basic = false, bool p_internal = false); #define GLOBAL_DEF(m_var, m_value) _GLOBAL_DEF(m_var, m_value) #define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true) #define GLOBAL_DEF_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true) @@ -204,4 +206,6 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restar #define GLOBAL_DEF_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true, true) #define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true) +#define GLOBAL_DEF_INTERNAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, false, true) + #endif // PROJECT_SETTINGS_H diff --git a/core/core_constants.cpp b/core/core_constants.cpp index a53929a3af..4f22c99656 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -552,6 +552,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LINK); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS); @@ -638,6 +639,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VARARG); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_STATIC); BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_OBJECT_CORE); BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT); @@ -645,7 +647,7 @@ void register_global_constants() { // rpc BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_DISABLED", Multiplayer::RPC_MODE_DISABLED); BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_ANY_PEER", Multiplayer::RPC_MODE_ANY_PEER); - BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTH", Multiplayer::RPC_MODE_AUTHORITY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("RPC_MODE_AUTHORITY", Multiplayer::RPC_MODE_AUTHORITY); BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE", Multiplayer::TRANSFER_MODE_UNRELIABLE); BIND_CORE_ENUM_CONSTANT_CUSTOM("TRANSFER_MODE_UNRELIABLE_ORDERED", Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED); diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index a1d54f9c6d..58103e3af3 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -230,6 +230,16 @@ static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeV } /// Variant functions. +static GDNativeInt gdnative_variant_hash(const GDNativeVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return self->hash(); +} + +static GDNativeInt gdnative_variant_recursive_hash(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count) { + const Variant *self = (const Variant *)p_self; + return self->recursive_hash(p_recursion_count); +} + static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) { const Variant *self = (const Variant *)p_self; const Variant *other = (const Variant *)p_other; @@ -944,6 +954,8 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { gdni.variant_iter_init = gdnative_variant_iter_init; gdni.variant_iter_next = gdnative_variant_iter_next; gdni.variant_iter_get = gdnative_variant_iter_get; + gdni.variant_hash = gdnative_variant_hash; + gdni.variant_recursive_hash = gdnative_variant_recursive_hash; gdni.variant_hash_compare = gdnative_variant_hash_compare; gdni.variant_booleanize = gdnative_variant_booleanize; gdni.variant_sub = gdnative_variant_sub; diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 98976b29f6..095c7983ee 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -413,6 +413,8 @@ typedef struct { GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); + GDNativeInt (*variant_hash)(const GDNativeVariantPtr p_self); + GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count); GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other); GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self); void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst); diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index 5738b42049..ac9d2ca8a6 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -295,9 +295,12 @@ Error NativeExtension::open_library(const String &p_path, const String &p_entry_ GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr; - initialization_function(&gdnative_interface, this, &initialization); - level_initialized = -1; - return OK; + if (initialization_function(&gdnative_interface, this, &initialization)) { + level_initialized = -1; + return OK; + } else { + return FAILED; + } } void NativeExtension::close_library() { diff --git a/core/input/input.cpp b/core/input/input.cpp index 4befdfac58..b3a68bb98c 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -134,8 +134,12 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); + ClassDB::bind_method(D_METHOD("is_using_accumulated_input"), &Input::is_using_accumulated_input); ClassDB::bind_method(D_METHOD("flush_buffered_events"), &Input::flush_buffered_events); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_mode"), "set_mouse_mode", "get_mouse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_accumulated_input"), "set_use_accumulated_input", "is_using_accumulated_input"); + BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); @@ -897,6 +901,10 @@ void Input::set_use_accumulated_input(bool p_enable) { use_accumulated_input = p_enable; } +bool Input::is_using_accumulated_input() { + return use_accumulated_input; +} + void Input::release_pressed_events() { flush_buffered_events(); // this is needed to release actions strengths @@ -1401,8 +1409,8 @@ String Input::get_joy_guid(int p_device) const { return joy_names[p_device].uid; } -Array Input::get_connected_joypads() { - Array ret; +TypedArray<int> Input::get_connected_joypads() { + TypedArray<int> ret; HashMap<int, Joypad>::Iterator elem = joy_names.begin(); while (elem) { if (elem->value.connected) { diff --git a/core/input/input.h b/core/input/input.h index 9a5b8e6e06..f02f2abae5 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -36,6 +36,7 @@ #include "core/os/keyboard.h" #include "core/os/thread_safe.h" #include "core/templates/rb_set.h" +#include "core/variant/typed_array.h" class Input : public Object { GDCLASS(Input, Object); @@ -259,7 +260,7 @@ public: float get_joy_axis(int p_device, JoyAxis p_axis) const; String get_joy_name(int p_idx); - Array get_connected_joypads(); + TypedArray<int> get_connected_joypads(); Vector2 get_joy_vibration_strength(int p_device); float get_joy_vibration_duration(int p_device); uint64_t get_joy_vibration_timestamp(int p_device); @@ -326,6 +327,7 @@ public: bool is_using_input_buffering(); void set_use_input_buffering(bool p_enable); void set_use_accumulated_input(bool p_enable); + bool is_using_accumulated_input(); void release_pressed_events(); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 2d4c203748..32e025417e 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -525,8 +525,8 @@ void InputEventMouse::_bind_methods() { ClassDB::bind_method(D_METHOD("get_global_position"), &InputEventMouse::get_global_position); ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask"), "set_button_mask", "get_button_mask"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position"), "set_global_position", "get_global_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px"), "set_global_position", "get_global_position"); } /////////////////////////////////// @@ -867,8 +867,8 @@ void InputEventMouseMotion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity"); } /////////////////////////////////// @@ -1167,7 +1167,7 @@ void InputEventScreenTouch::_bind_methods() { //ClassDB::bind_method(D_METHOD("is_pressed"),&InputEventScreenTouch::is_pressed); ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); } @@ -1260,9 +1260,9 @@ void InputEventScreenDrag::_bind_methods() { ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventScreenDrag::get_velocity); ADD_PROPERTY(PropertyInfo(Variant::INT, "index"), "set_index", "get_index"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative"), "set_relative", "get_relative"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity"), "set_velocity", "get_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity"); } /////////////////////////////////// @@ -1362,7 +1362,7 @@ void InputEventGesture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventGesture::set_position); ClassDB::bind_method(D_METHOD("get_position"), &InputEventGesture::get_position); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position"); } Vector2 InputEventGesture::get_position() const { diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index dd0191f43f..ae421654ca 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -61,19 +61,19 @@ PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { } void ConfigFile::set_value(const String &p_section, const String &p_key, const Variant &p_value) { - if (p_value.get_type() == Variant::NIL) { - //erase + if (p_value.get_type() == Variant::NIL) { // Erase key. if (!values.has(p_section)) { - return; // ? + return; } + values[p_section].erase(p_key); if (values[p_section].is_empty()) { values.erase(p_section); } - } else { if (!values.has(p_section)) { - values[p_section] = HashMap<String, Variant>(); + // Insert section-less keys at the beginning. + values.insert(p_section, HashMap<String, Variant>(), p_section.is_empty()); } values[p_section][p_key] = p_value; @@ -125,6 +125,9 @@ void ConfigFile::erase_section_key(const String &p_section, const String &p_key) ERR_FAIL_COND_MSG(!values[p_section].has(p_key), vformat("Cannot erase nonexistent key \"%s\" from section \"%s\".", p_key, p_section)); values[p_section].erase(p_key); + if (values[p_section].is_empty()) { + values.erase(p_section); + } } Error ConfigFile::save(const String &p_path) { diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 24458f20b4..2469e1a4be 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1547,10 +1547,11 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V case Variant::COLOR: { f->store_32(VARIANT_COLOR); Color val = p_property; - f->store_real(val.r); - f->store_real(val.g); - f->store_real(val.b); - f->store_real(val.a); + // Color are always floats + f->store_float(val.r); + f->store_float(val.g); + f->store_float(val.b); + f->store_float(val.a); } break; case Variant::STRING_NAME: { @@ -1685,7 +1686,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V f->store_32(len); const float *r = arr.ptr(); for (int i = 0; i < len; i++) { - f->store_real(r[i]); + f->store_float(r[i]); } } break; @@ -1743,10 +1744,10 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V f->store_32(len); const Color *r = arr.ptr(); for (int i = 0; i < len; i++) { - f->store_real(r[i].r); - f->store_real(r[i].g); - f->store_real(r[i].b); - f->store_real(r[i].a); + f->store_float(r[i].r); + f->store_float(r[i].g); + f->store_float(r[i].b); + f->store_float(r[i].a); } } break; diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index ea8435e587..5b90fb52a6 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -60,6 +60,7 @@ void StreamPeerSSL::_bind_methods() { ClassDB::bind_method(D_METHOD("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerSSL::accept_stream, DEFVAL(Ref<X509Certificate>())); ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSSL::get_status); + ClassDB::bind_method(D_METHOD("get_stream"), &StreamPeerSSL::get_stream); ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerSSL::disconnect_from_stream); ClassDB::bind_method(D_METHOD("set_blocking_handshake_enabled", "enabled"), &StreamPeerSSL::set_blocking_handshake_enabled); ClassDB::bind_method(D_METHOD("is_blocking_handshake_enabled"), &StreamPeerSSL::is_blocking_handshake_enabled); diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h index 15f646d897..fe68667adc 100644 --- a/core/io/stream_peer_ssl.h +++ b/core/io/stream_peer_ssl.h @@ -61,6 +61,7 @@ public: virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>()) = 0; virtual Status get_status() const = 0; + virtual Ref<StreamPeer> get_stream() const = 0; virtual void disconnect_from_stream() = 0; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 9443addd22..57c53b0adb 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -710,6 +710,11 @@ void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) { matrix[3][3] = 1; } +void CameraMatrix::add_jitter_offset(const Vector2 &p_offset) { + matrix[3][0] += p_offset.x; + matrix[3][1] += p_offset.y; +} + CameraMatrix::operator Transform3D() const { Transform3D tr; const real_t *m = &matrix[0][0]; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index f1aea5e4e8..a4051cee3b 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -95,6 +95,7 @@ struct CameraMatrix { operator String() const; void scale_translate_to_fit(const AABB &p_aabb); + void add_jitter_offset(const Vector2 &p_offset); void make_scale(const Vector3 &p_scale); int get_pixels_per_meter(int p_for_pixel_width) const; operator Transform3D() const; diff --git a/core/math/color.cpp b/core/math/color.cpp index 74552a2894..4bdeafd2f2 100644 --- a/core/math/color.cpp +++ b/core/math/color.cpp @@ -35,6 +35,8 @@ #include "core/string/print_string.h" #include "core/templates/rb_map.h" +#include "thirdparty/misc/ok_color.h" + uint32_t Color::to_argb32() const { uint32_t c = (uint8_t)Math::round(a * 255); c <<= 8; @@ -240,6 +242,20 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { } } +void Color::set_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) { + ok_color::HSL hsl; + hsl.h = p_h; + hsl.s = p_s; + hsl.l = p_l; + ok_color new_ok_color; + ok_color::RGB rgb = new_ok_color.okhsl_to_srgb(hsl); + Color c = Color(rgb.r, rgb.g, rgb.b, p_alpha).clamp(); + r = c.r; + g = c.g; + b = c.b; + a = c.a; +} + bool Color::is_equal_approx(const Color &p_color) const { return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a); } @@ -568,3 +584,48 @@ Color Color::operator-() const { 1.0f - b, 1.0f - a); } + +Color Color::from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) { + Color c; + c.set_ok_hsl(p_h, p_s, p_l, p_alpha); + return c; +} + +float Color::get_ok_hsl_h() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color new_ok_color; + ok_color::HSL ok_hsl = new_ok_color.srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.h)) { + return 0.0f; + } + return CLAMP(ok_hsl.h, 0.0f, 1.0f); +} + +float Color::get_ok_hsl_s() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color new_ok_color; + ok_color::HSL ok_hsl = new_ok_color.srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.s)) { + return 0.0f; + } + return CLAMP(ok_hsl.s, 0.0f, 1.0f); +} + +float Color::get_ok_hsl_l() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color new_ok_color; + ok_color::HSL ok_hsl = new_ok_color.srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.l)) { + return 0.0f; + } + return CLAMP(ok_hsl.l, 0.0f, 1.0f); +} diff --git a/core/math/color.h b/core/math/color.h index 91e0bf5532..0afa6006a8 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -56,6 +56,10 @@ struct _NO_DISCARD_ Color { float get_s() const; float get_v() const; void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0); + float get_ok_hsl_h() const; + float get_ok_hsl_s() const; + float get_ok_hsl_l() const; + void set_ok_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0); _FORCE_INLINE_ float &operator[](int p_idx) { return components[p_idx]; @@ -195,6 +199,7 @@ struct _NO_DISCARD_ Color { static Color get_named_color(int p_idx); static Color from_string(const String &p_string, const Color &p_default); static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0); + static Color from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0); static Color from_rgbe9995(uint32_t p_rgbe); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys @@ -213,6 +218,9 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); } _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); } _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); } + _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l()); } + _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l()); } + _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l); } _FORCE_INLINE_ Color() {} diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 97dc175d94..5a90f68b66 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1245,7 +1245,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: case Expression::ENode::TYPE_INPUT: { const Expression::InputNode *in = static_cast<const Expression::InputNode *>(p_node); if (in->index < 0 || in->index >= p_inputs.size()) { - r_error_str = vformat(RTR("Invalid input %i (not passed) in expression"), in->index); + r_error_str = vformat(RTR("Invalid input %d (not passed) in expression"), in->index); return true; } r_ret = p_inputs[in->index]; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 068bc0397e..c8a55341aa 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -302,11 +302,19 @@ public: } static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { double range = max - min; - return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + double result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_equal_approx(result, max)) { + return min; + } + return result; } static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { float range = max - min; - return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + float result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_equal_approx(result, max)) { + return min; + } + return result; } static _ALWAYS_INLINE_ float fract(float value) { diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h index 5eb968171a..f4c965b0f8 100644 --- a/core/multiplayer/multiplayer.h +++ b/core/multiplayer/multiplayer.h @@ -46,7 +46,7 @@ enum TransferMode { enum RPCMode { RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) RPC_MODE_ANY_PEER, // Any peer can call this RPC - RPC_MODE_AUTHORITY, // / Only the node's multiplayer authority (server by default) can call this RPC + RPC_MODE_AUTHORITY, // Only the node's multiplayer authority (server by default) can call this RPC }; struct RPCConfig { diff --git a/core/object/object.cpp b/core/object/object.cpp index 0912ea55f0..9dec417b11 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1196,7 +1196,7 @@ Array Object::_get_signal_list() const { return ret; } -Array Object::_get_signal_connection_list(const String &p_signal) const { +Array Object::_get_signal_connection_list(const StringName &p_signal) const { List<Connection> conns; get_all_signal_connections(&conns); @@ -1422,11 +1422,11 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, } } -void Object::_set_bind(const String &p_set, const Variant &p_value) { +void Object::_set_bind(const StringName &p_set, const Variant &p_value) { set(p_set, p_value); } -Variant Object::_get_bind(const String &p_name) const { +Variant Object::_get_bind(const StringName &p_name) const { return get(p_name); } diff --git a/core/object/object.h b/core/object/object.h index 988d261d77..7cbedd29d9 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -52,6 +52,7 @@ enum PropertyHint { PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout") PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + PROPERTY_HINT_LINK, PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, @@ -523,10 +524,10 @@ private: bool _has_user_signal(const StringName &p_name) const; Error _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Array _get_signal_list() const; - Array _get_signal_connection_list(const String &p_signal) const; + Array _get_signal_connection_list(const StringName &p_signal) const; Array _get_incoming_connections() const; - void _set_bind(const String &p_set, const Variant &p_value); - Variant _get_bind(const String &p_name) const; + void _set_bind(const StringName &p_set, const Variant &p_value); + Variant _get_bind(const StringName &p_name) const; void _set_indexed_bind(const NodePath &p_name, const Variant &p_value); Variant _get_indexed_bind(const NodePath &p_name) const; diff --git a/core/os/os.cpp b/core/os/os.cpp index 4f7095b0fc..327f1c95f2 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -413,19 +413,29 @@ bool OS::has_feature(const String &p_feature) { if (sizeof(void *) == 4 && p_feature == "32") { return true; } -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) if (p_feature == "x86_64") { return true; } -#elif (defined(__i386) || defined(__i386__)) +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + if (p_feature == "x86_32") { + return true; + } +#endif if (p_feature == "x86") { return true; } -#elif defined(__aarch64__) +#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) +#if defined(__aarch64__) || defined(_M_ARM64) if (p_feature == "arm64") { return true; } -#elif defined(__arm__) +#elif defined(__arm__) || defined(_M_ARM) + if (p_feature == "arm32") { + return true; + } +#endif #if defined(__ARM_ARCH_7A__) if (p_feature == "armv7a" || p_feature == "armv7") { return true; @@ -457,6 +467,19 @@ bool OS::has_feature(const String &p_feature) { if (p_feature == "ppc") { return true; } +#elif defined(__wasm__) +#if defined(__wasm64__) + if (p_feature == "wasm64") { + return true; + } +#elif defined(__wasm32__) + if (p_feature == "wasm32") { + return true; + } +#endif + if (p_feature == "wasm") { + return true; + } #endif if (_check_internal_feature_support(p_feature)) { diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 44df349613..df1aae5370 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3359,36 +3359,36 @@ String String::repeat(int p_count) const { return new_string; } -String String::left(int p_pos) const { - if (p_pos < 0) { - p_pos = length() + p_pos; +String String::left(int p_len) const { + if (p_len < 0) { + p_len = length() + p_len; } - if (p_pos <= 0) { + if (p_len <= 0) { return ""; } - if (p_pos >= length()) { + if (p_len >= length()) { return *this; } - return substr(0, p_pos); + return substr(0, p_len); } -String String::right(int p_pos) const { - if (p_pos < 0) { - p_pos = length() + p_pos; +String String::right(int p_len) const { + if (p_len < 0) { + p_len = length() + p_len; } - if (p_pos <= 0) { + if (p_len <= 0) { return ""; } - if (p_pos >= length()) { + if (p_len >= length()) { return *this; } - return substr(length() - p_pos); + return substr(length() - p_len); } char32_t String::unicode_at(int p_idx) const { @@ -3712,18 +3712,15 @@ String String::uri_encode() const { const CharString temp = utf8(); String res; for (int i = 0; i < temp.length(); ++i) { - char ord = temp[i]; + uint8_t ord = temp[i]; if (ord == '.' || ord == '-' || ord == '~' || is_ascii_identifier_char(ord)) { res += ord; } else { - char h_Val[3]; -#if defined(__GNUC__) || defined(_MSC_VER) - snprintf(h_Val, 3, "%02hhX", ord); -#else - sprintf(h_Val, "%02hhX", ord); -#endif - res += "%"; - res += h_Val; + char p[4] = { '%', 0, 0, 0 }; + static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + p[1] = hex[ord >> 4]; + p[2] = hex[ord & 0xF]; + res += p; } } return res; diff --git a/core/string/ustring.h b/core/string/ustring.h index e4f6c3327a..11d0974381 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -356,8 +356,8 @@ public: int count(const String &p_string, int p_from = 0, int p_to = 0) const; int countn(const String &p_string, int p_from = 0, int p_to = 0) const; - String left(int p_pos) const; - String right(int p_pos) const; + String left(int p_len) const; + String right(int p_len) const; String indent(const String &p_prefix) const; String dedent() const; String strip_edges(bool left = true, bool right = true) const; diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 1330d55270..98ff7fa4ce 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -56,7 +56,7 @@ * @param C String * @return 32-bits hashcode */ -static inline uint32_t hash_djb2(const char *p_cstr) { +static _FORCE_INLINE_ uint32_t hash_djb2(const char *p_cstr) { const unsigned char *chr = (const unsigned char *)p_cstr; uint32_t hash = 5381; uint32_t c; @@ -68,7 +68,7 @@ static inline uint32_t hash_djb2(const char *p_cstr) { return hash; } -static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) { +static _FORCE_INLINE_ uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) { uint32_t hash = p_prev; for (int i = 0; i < p_len; i++) { @@ -78,7 +78,7 @@ static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32 return hash; } -static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) { +static _FORCE_INLINE_ uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) { return ((p_prev << 5) + p_prev) + p_in; } @@ -89,7 +89,7 @@ static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) { * @param p_int - 64-bit unsigned integer key to be hashed * @return unsigned 32-bit value representing hashcode */ -static inline uint32_t hash_one_uint64(const uint64_t p_int) { +static _FORCE_INLINE_ uint32_t hash_one_uint64(const uint64_t p_int) { uint64_t v = p_int; v = (~v) + (v << 18); // v = (v << 18) - v - 1; v = v ^ (v >> 31); @@ -100,7 +100,72 @@ static inline uint32_t hash_one_uint64(const uint64_t p_int) { return uint32_t(v); } -static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) { +// Murmurhash3 32-bit version. +// All MurmurHash versions are public domain software, and the author disclaims all copyright to their code. + +static _FORCE_INLINE_ uint32_t rotl32(uint32_t x, int8_t r) { + return (x << r) | (x >> (32 - r)); +} + +static _FORCE_INLINE_ uint32_t fmix32(uint32_t h) { + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +static _FORCE_INLINE_ uint32_t hash_murmur3_32(const void *key, int length, const uint32_t seed = 0x7F07C65) { + // Although not required, this is a random prime number. + const uint8_t *data = (const uint8_t *)key; + const int nblocks = length / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); + + for (int i = -nblocks; i; i++) { + uint32_t k1 = blocks[i]; + + k1 *= c1; + k1 = rotl32(k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = rotl32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } + + const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); + + uint32_t k1 = 0; + + switch (length & 3) { + case 3: + k1 ^= tail[2] << 16; + [[fallthrough]]; + case 2: + k1 ^= tail[1] << 8; + [[fallthrough]]; + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = rotl32(k1, 15); + k1 *= c2; + h1 ^= k1; + }; + + // Finalize with additional bit mixing. + h1 ^= length; + return fmix32(h1); +} + +static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) { union { double d; uint64_t i; @@ -119,7 +184,7 @@ static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) } template <class T> -static inline uint32_t make_uint32_t(T p_in) { +static _FORCE_INLINE_ uint32_t make_uint32_t(T p_in) { union { T t; uint32_t _u32; @@ -129,7 +194,7 @@ static inline uint32_t make_uint32_t(T p_in) { return _u._u32; } -static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) { +static _FORCE_INLINE_ uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) { union { double d; uint64_t i; @@ -147,12 +212,12 @@ static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 538 return ((p_prev << 5) + p_prev) + u.i; } -static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) { +static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) { return ((p_prev << 5) + p_prev) + p_in; } template <class T> -static inline uint64_t make_uint64_t(T p_in) { +static _FORCE_INLINE_ uint64_t make_uint64_t(T p_in) { union { T t; uint64_t _u64; @@ -167,78 +232,40 @@ template <class T> class Ref; struct HashMapHasherDefault { - static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } - static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } - static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } - static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } - - static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } - static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } - static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } - static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return (uint32_t)p_uchar; } - static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return (uint32_t)p_uchar; } - static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } - - static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } - static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } - + // Generic hash function for any type. template <class T> static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } template <class T> static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); } - static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { - uint32_t h = hash_djb2_one_32(p_vec.x); - return hash_djb2_one_32(p_vec.y, h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { - uint32_t h = hash_djb2_one_32(p_vec.x); - h = hash_djb2_one_32(p_vec.y, h); - return hash_djb2_one_32(p_vec.z, h); - } - - static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { - uint32_t h = hash_djb2_one_float(p_vec.x); - return hash_djb2_one_float(p_vec.y, h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) { - uint32_t h = hash_djb2_one_float(p_vec.x); - h = hash_djb2_one_float(p_vec.y, h); - return hash_djb2_one_float(p_vec.z, h); - } - - static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { - uint32_t h = hash_djb2_one_32(p_rect.position.x); - h = hash_djb2_one_32(p_rect.position.y, h); - h = hash_djb2_one_32(p_rect.size.x, h); - return hash_djb2_one_32(p_rect.size.y, h); - } - - static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { - uint32_t h = hash_djb2_one_float(p_rect.position.x); - h = hash_djb2_one_float(p_rect.position.y, h); - h = hash_djb2_one_float(p_rect.size.x, h); - return hash_djb2_one_float(p_rect.size.y, h); - } - - static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) { - uint32_t h = hash_djb2_one_float(p_aabb.position.x); - h = hash_djb2_one_float(p_aabb.position.y, h); - h = hash_djb2_one_float(p_aabb.position.z, h); - h = hash_djb2_one_float(p_aabb.size.x, h); - h = hash_djb2_one_float(p_aabb.size.y, h); - return hash_djb2_one_float(p_aabb.size.z, h); - } + static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } + static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } + static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return fmix32(p_wchar); } + static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return fmix32(p_uchar); } + static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return fmix32(p_uchar); } + static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } + static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } + static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } + static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } - //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } + static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); } + static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } + static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } + static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector2i)); } + static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector3i)); } + static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector2)); } + static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) { return hash_murmur3_32(&p_vec, sizeof(Vector3)); } + static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { return hash_murmur3_32(&p_rect, sizeof(Rect2i)); } + static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { return hash_murmur3_32(&p_rect, sizeof(Rect2)); } + static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) { return hash_murmur3_32(&p_aabb, sizeof(AABB)); } }; template <typename T> diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 7551350c95..599c3e1dfe 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -260,7 +260,9 @@ void Array::push_back(const Variant &p_value) { void Array::append_array(const Array &p_array) { ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state."); - ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array")); + for (int i = 0; i < p_array.size(); ++i) { + ERR_FAIL_COND(!_p->typed.validate(p_array[i], "append_array")); + } _p->array.append_array(p_array._p->array); } @@ -501,6 +503,50 @@ Variant Array::reduce(const Callable &p_callable, const Variant &p_accum) const return ret; } +bool Array::any(const Callable &p_callable) const { + const Variant *argptrs[1]; + for (int i = 0; i < size(); i++) { + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(false, "Error calling method from 'any': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + if (result.operator bool()) { + // Return as early as possible when one of the conditions is `true`. + // This improves performance compared to relying on `filter(...).size() >= 1`. + return true; + } + } + + return false; +} + +bool Array::all(const Callable &p_callable) const { + const Variant *argptrs[1]; + for (int i = 0; i < size(); i++) { + argptrs[0] = &get(i); + + Variant result; + Callable::CallError ce; + p_callable.call(argptrs, 1, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_V_MSG(false, "Error calling method from 'all': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce)); + } + + if (!(result.operator bool())) { + // Return as early as possible when one of the inverted conditions is `false`. + // This improves performance compared to relying on `filter(...).size() >= array_size().`. + return false; + } + } + + return true; +} + struct _ArrayVariantSort { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { bool valid = false; diff --git a/core/variant/array.h b/core/variant/array.h index f537700f99..c007376734 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -108,6 +108,8 @@ public: Array filter(const Callable &p_callable) const; Array map(const Callable &p_callable) const; Variant reduce(const Callable &p_callable, const Variant &p_accum) const; + bool any(const Callable &p_callable) const; + bool all(const Callable &p_callable) const; bool operator<(const Array &p_array) const; bool operator<=(const Array &p_array) const; diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index bda8c93a79..822021f440 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -269,6 +269,14 @@ void Dictionary::clear() { _p->variant_map.clear(); } +void Dictionary::merge(const Dictionary &p_dictionary, bool p_overwrite) { + for (const KeyValue<Variant, Variant> &E : p_dictionary._p->variant_map) { + if (p_overwrite || !has(E.key)) { + this->operator[](E.key) = E.value; + } + } +} + void Dictionary::_unref() const { ERR_FAIL_COND(!_p); if (_p->refcount.unref()) { diff --git a/core/variant/dictionary.h b/core/variant/dictionary.h index 1224a4ff6f..2632893e8d 100644 --- a/core/variant/dictionary.h +++ b/core/variant/dictionary.h @@ -62,6 +62,7 @@ public: int size() const; bool is_empty() const; void clear(); + void merge(const Dictionary &p_dictionary, bool p_overwrite = false); bool has(const Variant &p_key) const; bool has_all(const Array &p_keys) const; diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index e69bd88413..aa640924e4 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -2788,106 +2788,50 @@ uint32_t Variant::recursive_hash(int recursion_count) const { // math types case VECTOR2: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x); - return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash); + return hash_murmur3_32(reinterpret_cast<const Vector2 *>(_data._mem), sizeof(Vector2)); } break; case VECTOR2I: { - uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector2i *>(_data._mem)->x); - return hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector2i *>(_data._mem)->y, hash); + return hash_murmur3_32(reinterpret_cast<const Vector2i *>(_data._mem), sizeof(Vector2i)); } break; case RECT2: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x); - hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.y, hash); - hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash); - return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash); + return hash_murmur3_32(reinterpret_cast<const Rect2 *>(_data._mem), sizeof(Rect2)); } break; case RECT2I: { - uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->position.x); - hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash); - hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash); - return hash_djb2_one_32((uint32_t) reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash); + return hash_murmur3_32(reinterpret_cast<const Rect2i *>(_data._mem), sizeof(Rect2i)); } break; case TRANSFORM2D: { - uint32_t hash = 5831; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 2; j++) { - hash = hash_djb2_one_float(_data._transform2d->columns[i][j], hash); - } - } - - return hash; + return hash_murmur3_32(reinterpret_cast<const Transform2D *>(_data._transform2d), sizeof(Transform2D)); } break; case VECTOR3: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->x); - hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash); - return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash); + return hash_murmur3_32(reinterpret_cast<const Vector3 *>(_data._mem), sizeof(Vector3)); } break; case VECTOR3I: { - uint32_t hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->x); - hash = hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->y, hash); - return hash_djb2_one_32((uint32_t) reinterpret_cast<const Vector3i *>(_data._mem)->z, hash); + return hash_murmur3_32(reinterpret_cast<const Vector3i *>(_data._mem), sizeof(Vector3i)); } break; case PLANE: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x); - hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.y, hash); - hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.z, hash); - return hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->d, hash); - + return hash_murmur3_32(reinterpret_cast<const Plane *>(_data._mem), sizeof(Plane)); } break; case AABB: { - uint32_t hash = 5831; - for (int i = 0; i < 3; i++) { - hash = hash_djb2_one_float(_data._aabb->position[i], hash); - hash = hash_djb2_one_float(_data._aabb->size[i], hash); - } - - return hash; - + return hash_murmur3_32(_data._aabb, sizeof(AABB)); } break; case QUATERNION: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->x); - hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->y, hash); - hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->z, hash); - return hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->w, hash); - + return hash_murmur3_32(reinterpret_cast<const Quaternion *>(_data._mem), sizeof(Quaternion)); } break; case BASIS: { - uint32_t hash = 5831; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - hash = hash_djb2_one_float(_data._basis->rows[i][j], hash); - } - } - - return hash; - + return hash_murmur3_32(_data._basis, sizeof(Basis)); } break; case TRANSFORM3D: { - uint32_t hash = 5831; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - hash = hash_djb2_one_float(_data._transform3d->basis.rows[i][j], hash); - } - hash = hash_djb2_one_float(_data._transform3d->origin[i], hash); - } - - return hash; - + return hash_murmur3_32(_data._transform3d, sizeof(Transform3D)); } break; - // misc types case COLOR: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->r); - hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->g, hash); - hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->b, hash); - return hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->a, hash); - + return hash_murmur3_32(reinterpret_cast<const Color *>(_data._mem), sizeof(Color)); } break; case RID: { - return hash_djb2_one_64(reinterpret_cast<const ::RID *>(_data._mem)->get_id()); + return hash_one_uint64(reinterpret_cast<const ::RID *>(_data._mem)->get_id()); } break; case OBJECT: { - return hash_djb2_one_64(make_uint64_t(_get_obj().obj)); + return hash_one_uint64(make_uint64_t(_get_obj().obj)); } break; case STRING_NAME: { return reinterpret_cast<const StringName *>(_data._mem)->hash(); @@ -2918,7 +2862,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { int len = arr.size(); if (likely(len)) { const uint8_t *r = arr.ptr(); - return hash_djb2_buffer((uint8_t *)&r[0], len); + return hash_murmur3_32((uint8_t *)&r[0], len); } else { return hash_djb2_one_64(0); } @@ -2929,7 +2873,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { int len = arr.size(); if (likely(len)) { const int32_t *r = arr.ptr(); - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int32_t)); + return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(int32_t)); } else { return hash_djb2_one_64(0); } @@ -2940,7 +2884,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { int len = arr.size(); if (likely(len)) { const int64_t *r = arr.ptr(); - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int64_t)); + return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(int64_t)); } else { return hash_djb2_one_64(0); } @@ -2952,7 +2896,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { if (likely(len)) { const float *r = arr.ptr(); - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(float)); + return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(float)); } else { return hash_djb2_one_float(0.0); } @@ -2964,7 +2908,7 @@ uint32_t Variant::recursive_hash(int recursion_count) const { if (likely(len)) { const double *r = arr.ptr(); - return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(double)); + return hash_murmur3_32((uint8_t *)&r[0], len * sizeof(double)); } else { return hash_djb2_one_float(0.0); } @@ -3102,6 +3046,10 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem); } break; + case STRING_NAME: { + return *reinterpret_cast<const StringName *>(_data._mem) == *reinterpret_cast<const StringName *>(p_variant._data._mem); + } break; + case VECTOR2: { const Vector2 *l = reinterpret_cast<const Vector2 *>(_data._mem); const Vector2 *r = reinterpret_cast<const Vector2 *>(p_variant._data._mem); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index a3568a8d6a..b335f2fcf4 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1402,8 +1402,8 @@ static void _register_variant_builtin_methods() { bind_method(String, to_upper, sarray(), varray()); bind_method(String, to_lower, sarray(), varray()); - bind_method(String, left, sarray("position"), varray()); - bind_method(String, right, sarray("position"), varray()); + bind_method(String, left, sarray("length"), varray()); + bind_method(String, right, sarray("length"), varray()); bind_method(String, strip_edges, sarray("left", "right"), varray(true, true)); bind_method(String, strip_escapes, sarray(), varray()); @@ -1472,6 +1472,10 @@ static void _register_variant_builtin_methods() { bind_static_method(String, chr, sarray("char"), varray()); bind_static_method(String, humanize_size, sarray("size"), varray()); + /* StringName */ + + bind_method(StringName, hash, sarray(), varray()); + /* Vector2 */ bind_method(Vector2, angle, sarray(), varray()); @@ -1671,6 +1675,8 @@ static void _register_variant_builtin_methods() { bind_static_method(Color, get_named_color, sarray("idx"), varray()); bind_static_method(Color, from_string, sarray("str", "default"), varray()); bind_static_method(Color, from_hsv, sarray("h", "s", "v", "alpha"), varray(1.0)); + bind_static_method(Color, from_ok_hsl, sarray("h", "s", "l", "alpha"), varray(1.0)); + bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray()); /* RID */ @@ -1684,6 +1690,7 @@ static void _register_variant_builtin_methods() { bind_method(NodePath, get_name_count, sarray(), varray()); bind_method(NodePath, get_name, sarray("idx"), varray()); bind_method(NodePath, get_subname_count, sarray(), varray()); + bind_method(NodePath, hash, sarray(), varray()); bind_method(NodePath, get_subname, sarray("idx"), varray()); bind_method(NodePath, get_concatenated_subnames, sarray(), varray()); bind_method(NodePath, get_as_property_path, sarray(), varray()); @@ -1808,6 +1815,7 @@ static void _register_variant_builtin_methods() { bind_method(Dictionary, size, sarray(), varray()); bind_method(Dictionary, is_empty, sarray(), varray()); bind_method(Dictionary, clear, sarray(), varray()); + bind_method(Dictionary, merge, sarray("dictionary", "overwrite"), varray(false)); bind_method(Dictionary, has, sarray("key"), varray()); bind_method(Dictionary, has_all, sarray("keys"), varray()); bind_method(Dictionary, erase, sarray("key"), varray()); @@ -1853,6 +1861,8 @@ static void _register_variant_builtin_methods() { bind_method(Array, filter, sarray("method"), varray()); bind_method(Array, map, sarray("method"), varray()); bind_method(Array, reduce, sarray("method", "accum"), varray(Variant())); + bind_method(Array, any, sarray("method"), varray()); + bind_method(Array, all, sarray("method"), varray()); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); diff --git a/core/variant/variant_setget.h b/core/variant/variant_setget.h index 3b95f0531b..bc4dc4b408 100644 --- a/core/variant/variant_setget.h +++ b/core/variant/variant_setget.h @@ -329,4 +329,8 @@ SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h) SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s) SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v) +SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_h, set_ok_hsl_h, get_ok_hsl_h) +SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_s, set_ok_hsl_s, get_ok_hsl_s) +SETGET_NUMBER_STRUCT_FUNC(Color, double, ok_hsl_l, set_ok_hsl_l, get_ok_hsl_l) + #endif // VARIANT_SETGET_H |