diff options
Diffstat (limited to 'core')
81 files changed, 2220 insertions, 325 deletions
diff --git a/core/SCsub b/core/SCsub index 91620cb075..640c6de6a1 100644 --- a/core/SCsub +++ b/core/SCsub @@ -4,44 +4,9 @@ Import("env") import core_builders import methods - -env.core_sources = [] - - -# Generate AES256 script encryption key import os -txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0" -if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ: - key = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"] - ec_valid = True - if len(key) != 64: - ec_valid = False - else: - txt = "" - for i in range(len(key) >> 1): - if i > 0: - txt += "," - txts = "0x" + key[i * 2 : i * 2 + 2] - try: - int(txts, 16) - except Exception: - ec_valid = False - txt += txts - if not ec_valid: - methods.print_error( - f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{key}".\n' - "Unset 'SCRIPT_AES256_ENCRYPTION_KEY' in your environment " - "or make sure that it contains exactly 64 hexadecimal characters." - ) - Exit(255) - - -script_encryption_key_contents = ( - '#include "core/config/project_settings.h"\nuint8_t script_encryption_key[32]={' + txt + "};\n" -) - -methods.write_file_if_needed("script_encryption_key.gen.cpp", script_encryption_key_contents) +env.core_sources = [] # Add required thirdparty code. @@ -193,8 +158,96 @@ env.core_sources += thirdparty_obj # Godot source files env.add_source_files(env.core_sources, "*.cpp") -env.add_source_files(env.core_sources, "script_encryption_key.gen.cpp") -env.add_source_files(env.core_sources, "version_hash.gen.cpp") + + +# Generate disabled classes +def disabled_class_builder(target, source, env): + with methods.generated_wrapper(target) as file: + for c in source[0].read(): + cs = c.strip() + if cs != "": + file.write(f"#define ClassDB_Disable_{cs} 1") + + +env.CommandNoCache("disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(disabled_class_builder)) + + +# Generate version info +def version_info_builder(target, source, env): + with methods.generated_wrapper(target) as file: + file.write( + """\ +#define VERSION_SHORT_NAME "{short_name}" +#define VERSION_NAME "{name}" +#define VERSION_MAJOR {major} +#define VERSION_MINOR {minor} +#define VERSION_PATCH {patch} +#define VERSION_STATUS "{status}" +#define VERSION_BUILD "{build}" +#define VERSION_MODULE_CONFIG "{module_config}" +#define VERSION_WEBSITE "{website}" +#define VERSION_DOCS_BRANCH "{docs_branch}" +#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH +""".format( + **env.version_info + ) + ) + + +env.CommandNoCache("version_generated.gen.h", "#version.py", env.Run(version_info_builder)) + + +# Generate version hash +def version_hash_builder(target, source, env): + with methods.generated_wrapper(target) as file: + file.write( + """\ +#include "core/version.h" + +const char *const VERSION_HASH = "{git_hash}"; +const uint64_t VERSION_TIMESTAMP = {git_timestamp}; +""".format( + **env.version_info + ) + ) + + +gen_hash = env.CommandNoCache( + "version_hash.gen.cpp", env.Value(env.version_info["git_hash"]), env.Run(version_hash_builder) +) +env.add_source_files(env.core_sources, gen_hash) + + +# Generate AES256 script encryption key +def encryption_key_builder(target, source, env): + with methods.generated_wrapper(target) as file: + file.write( + f"""\ +#include "core/config/project_settings.h" + +uint8_t script_encryption_key[32] = {{ + {source[0]} +}};""" + ) + + +gdkey = os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY", "0" * 64) +ec_valid = len(gdkey) == 64 +if ec_valid: + try: + gdkey = ", ".join([str(int(f"{a}{b}", 16)) for a, b in zip(gdkey[0::2], gdkey[1::2])]) + except Exception: + ec_valid = False +if not ec_valid: + methods.print_error( + f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{gdkey}".\n' + "Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment " + "or make sure that it contains exactly 64 hexadecimal characters." + ) + Exit(255) +gen_encrypt = env.CommandNoCache("script_encryption_key.gen.cpp", env.Value(gdkey), env.Run(encryption_key_builder)) +env.add_source_files(env.core_sources, gen_encrypt) + # Certificates env.Depends( diff --git a/core/config/engine.cpp b/core/config/engine.cpp index f2f8aebe8b..3574430cf7 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -384,6 +384,12 @@ Engine::Engine() { singleton = this; } +Engine::~Engine() { + if (singleton == this) { + singleton = nullptr; + } +} + Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) : name(p_name), ptr(p_ptr), diff --git a/core/config/engine.h b/core/config/engine.h index 8dece803e3..7e617d8773 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -187,7 +187,7 @@ public: bool notify_frame_server_synced(); Engine(); - virtual ~Engine() {} + virtual ~Engine(); }; #endif // ENGINE_H diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index ee20aea35d..a116c9c270 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -253,7 +253,7 @@ bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const { } void ProjectSettings::add_hidden_prefix(const String &p_prefix) { - ERR_FAIL_COND_MSG(hidden_prefixes.find(p_prefix) > -1, vformat("Hidden prefix '%s' already exists.", p_prefix)); + ERR_FAIL_COND_MSG(hidden_prefixes.has(p_prefix), vformat("Hidden prefix '%s' already exists.", p_prefix)); hidden_prefixes.push_back(p_prefix); } @@ -291,7 +291,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { } } } else { - if (p_name == CoreStringNames::get_singleton()->_custom_features) { + if (p_name == CoreStringName(_custom_features)) { Vector<String> custom_feature_array = String(p_value).split(","); for (int i = 0; i < custom_feature_array.size(); i++) { custom_features.insert(custom_feature_array[i]); @@ -875,7 +875,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S if (!p_custom_features.is_empty()) { // Store how many properties are saved, add one for custom features, which must always go first. file->store_32(count + 1); - String key = CoreStringNames::get_singleton()->_custom_features; + String key = CoreStringName(_custom_features); file->store_pascal_string(key); int len; diff --git a/core/core_constants.cpp b/core/core_constants.cpp index aaabbabfd9..5322e39ec0 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -761,6 +761,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR4_ARRAY", Variant::PACKED_VECTOR4_ARRAY); BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX); //comparison diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp index 21645e5efc..1ffe76495d 100644 --- a/core/core_string_names.cpp +++ b/core/core_string_names.cpp @@ -33,12 +33,10 @@ CoreStringNames *CoreStringNames::singleton = nullptr; CoreStringNames::CoreStringNames() : - _free(StaticCString::create("free")), + free_(StaticCString::create("free")), changed(StaticCString::create("changed")), - _script(StaticCString::create("script")), + script(StaticCString::create("script")), script_changed(StaticCString::create("script_changed")), - ___pdcdata(StaticCString::create("___pdcdata")), - __getvar(StaticCString::create("__getvar")), _iter_init(StaticCString::create("_iter_init")), _iter_next(StaticCString::create("_iter_next")), _iter_get(StaticCString::create("_iter_get")), diff --git a/core/core_string_names.h b/core/core_string_names.h index 1c77cef567..d7ddc39f5e 100644 --- a/core/core_string_names.h +++ b/core/core_string_names.h @@ -50,12 +50,10 @@ public: static CoreStringNames *singleton; - StringName _free; + StringName free_; // "free", conflict with C++ keyword. StringName changed; - StringName _script; + StringName script; StringName script_changed; - StringName ___pdcdata; - StringName __getvar; StringName _iter_init; StringName _iter_next; StringName _iter_get; @@ -98,4 +96,6 @@ public: StringName property_list_changed; }; +#define CoreStringName(m_name) CoreStringNames::get_singleton()->m_name + #endif // CORE_STRING_NAMES_H diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index 3e6b7501c7..f4283e0ea9 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -38,10 +38,10 @@ Array DebuggerMarshalls::ScriptStackDump::serialize() { Array arr; arr.push_back(frames.size() * 3); - for (int i = 0; i < frames.size(); i++) { - arr.push_back(frames[i].file); - arr.push_back(frames[i].line); - arr.push_back(frames[i].func); + for (const ScriptLanguage::StackInfo &frame : frames) { + arr.push_back(frame.file); + arr.push_back(frame.line); + arr.push_back(frame.func); } return arr; } diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index a7655c874a..97a020e4c3 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -137,7 +137,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co script_debugger = memnew(ScriptDebugger); // Tell the OS that we want to handle termination signals. OS::get_singleton()->initialize_debugging(); - } else if (p_uri.find("://") >= 0) { + } else if (p_uri.contains("://")) { const String proto = p_uri.substr(0, p_uri.find("://") + 3); if (!protocols.has(proto)) { return; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 1973663c72..bd30da3047 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -206,8 +206,7 @@ void RemoteDebugger::flush_output() { Vector<String> joined_log_strings; Vector<String> strings; Vector<int> types; - for (int i = 0; i < output_strings.size(); i++) { - const OutputString &output_string = output_strings[i]; + for (const OutputString &output_string : output_strings) { if (output_string.type == MESSAGE_TYPE_ERROR) { if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 81ee09f515..21a9014626 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -45,7 +45,7 @@ bool RemoteDebuggerPeerTCP::has_message() { Array RemoteDebuggerPeerTCP::get_message() { MutexLock lock(mutex); ERR_FAIL_COND_V(!has_message(), Array()); - Array out = in_queue[0]; + Array out = in_queue.front()->get(); in_queue.pop_front(); return out; } @@ -100,7 +100,7 @@ void RemoteDebuggerPeerTCP::_write_out() { break; // Nothing left to send } mutex.lock(); - Variant var = out_queue[0]; + Variant var = out_queue.front()->get(); out_queue.pop_front(); mutex.unlock(); int size = 0; diff --git a/core/doc_data.cpp b/core/doc_data.cpp index 7549ba884e..672a36c35c 100644 --- a/core/doc_data.cpp +++ b/core/doc_data.cpp @@ -152,9 +152,10 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met return_doc_from_retinfo(p_method, p_methodinfo.return_val); - for (int i = 0; i < p_methodinfo.arguments.size(); i++) { + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = p_methodinfo.arguments.begin(); itr != p_methodinfo.arguments.end(); ++itr, ++i) { DocData::ArgumentDoc argument; - argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]); + argument_doc_from_arginfo(argument, *itr); int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); if (default_arg_index >= 0) { Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 69be2d2a8f..848b6f3886 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -189,6 +189,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, { Variant::PACKED_COLOR_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, + { Variant::PACKED_VECTOR4_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 }, { Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 }, }; @@ -230,6 +231,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { static_assert(type_size_array[Variant::PACKED_VECTOR2_ARRAY][sizeof(void *)] == sizeof(PackedVector2Array), "Size of PackedVector2Array mismatch"); static_assert(type_size_array[Variant::PACKED_VECTOR3_ARRAY][sizeof(void *)] == sizeof(PackedVector3Array), "Size of PackedVector3Array mismatch"); static_assert(type_size_array[Variant::PACKED_COLOR_ARRAY][sizeof(void *)] == sizeof(PackedColorArray), "Size of PackedColorArray mismatch"); + static_assert(type_size_array[Variant::PACKED_VECTOR4_ARRAY][sizeof(void *)] == sizeof(PackedVector4Array), "Size of PackedVector4Array mismatch"); static_assert(type_size_array[Variant::VARIANT_MAX][sizeof(void *)] == sizeof(Variant), "Size of Variant mismatch"); Array core_type_sizes; @@ -1016,26 +1018,34 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { d2["is_virtual"] = true; // virtual functions have no hash since no MethodBind is involved bool has_return = mi.return_val.type != Variant::NIL || (mi.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT); - Array arguments; - for (int i = (has_return ? -1 : 0); i < mi.arguments.size(); i++) { - PropertyInfo pinfo = i == -1 ? mi.return_val : mi.arguments[i]; + if (has_return) { + PropertyInfo pinfo = mi.return_val; Dictionary d3; - if (i >= 0) { - d3["name"] = pinfo.name; + d3["type"] = get_property_info_type_name(pinfo); + + if (mi.get_argument_meta(-1) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(-1)); } + d2["return_value"] = d3; + } + + Array arguments; + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) { + const PropertyInfo &pinfo = *itr; + Dictionary d3; + + d3["name"] = pinfo.name; + d3["type"] = get_property_info_type_name(pinfo); if (mi.get_argument_meta(i) > 0) { d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(i)); } - if (i == -1) { - d2["return_value"] = d3; - } else { - arguments.push_back(d3); - } + arguments.push_back(d3); } if (arguments.size()) { @@ -1149,10 +1159,11 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { Array arguments; - for (int i = 0; i < F.arguments.size(); i++) { + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = F.arguments.begin(); itr != F.arguments.end(); ++itr, ++i) { Dictionary d3; - d3["name"] = F.arguments[i].name; - d3["type"] = get_property_info_type_name(F.arguments[i]); + d3["name"] = itr->name; + d3["type"] = get_property_info_type_name(*itr); if (F.get_argument_meta(i) > 0) { d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i)); } @@ -1190,7 +1201,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { if (F.name.begins_with("_")) { continue; //hidden property } - if (F.name.find("/") >= 0) { + if (F.name.contains("/")) { // Ignore properties with '/' (slash) in the name. These are only meant for use in the inspector. continue; } diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index b48ea97040..a26bb3e8f3 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -211,14 +211,14 @@ protected: if (p_arg < 0) { return return_value_info.type; } else { - return arguments_info[p_arg].type; + return arguments_info.get(p_arg).type; } } virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg < 0) { return return_value_info; } else { - return arguments_info[p_arg]; + return arguments_info.get(p_arg); } } @@ -232,7 +232,7 @@ public: if (p_arg < 0) { return return_value_metadata; } else { - return arguments_metadata[p_arg]; + return arguments_metadata.get(p_arg); } } #endif @@ -319,8 +319,9 @@ public: return false; } - for (uint32_t i = 0; i < p_method_info->argument_count; i++) { - if (arguments_info[i].type != (Variant::Type)p_method_info->arguments_info[i].type) { + List<PropertyInfo>::ConstIterator itr = arguments_info.begin(); + for (uint32_t i = 0; i < p_method_info->argument_count; ++itr, ++i) { + if (itr->type != (Variant::Type)p_method_info->arguments_info[i].type) { return false; } } diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index 9b4aa98357..98f5cb4d02 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -595,6 +595,8 @@ static GDExtensionVariantFromTypeConstructorFunc gdextension_get_variant_from_ty return VariantTypeConstructor<PackedVector2Array>::variant_from_type; case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: return VariantTypeConstructor<PackedVector3Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY: + return VariantTypeConstructor<PackedVector4Array>::variant_from_type; case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: return VariantTypeConstructor<PackedColorArray>::variant_from_type; case GDEXTENSION_VARIANT_TYPE_NIL: @@ -678,6 +680,8 @@ static GDExtensionTypeFromVariantConstructorFunc gdextension_get_variant_to_type return VariantTypeConstructor<PackedVector2Array>::type_from_variant; case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: return VariantTypeConstructor<PackedVector3Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY: + return VariantTypeConstructor<PackedVector4Array>::type_from_variant; case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: return VariantTypeConstructor<PackedColorArray>::type_from_variant; case GDEXTENSION_VARIANT_TYPE_NIL: @@ -1116,6 +1120,22 @@ static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index_const( return (GDExtensionTypePtr)&self->ptr()[p_index]; } +static GDExtensionTypePtr gdextension_packed_vector4_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedVector4Array *self = (PackedVector4Array *)p_self; + if (unlikely(p_index < 0 || p_index >= self->size())) { + return nullptr; + } + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector4_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedVector4Array *self = (const PackedVector4Array *)p_self; + if (unlikely(p_index < 0 || p_index >= self->size())) { + return nullptr; + } + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + static GDExtensionVariantPtr gdextension_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { Array *self = (Array *)p_self; if (unlikely(p_index < 0 || p_index >= self->size())) { @@ -1620,6 +1640,8 @@ void gdextension_setup_interface() { REGISTER_INTERFACE_FUNC(packed_vector2_array_operator_index_const); REGISTER_INTERFACE_FUNC(packed_vector3_array_operator_index); REGISTER_INTERFACE_FUNC(packed_vector3_array_operator_index_const); + REGISTER_INTERFACE_FUNC(packed_vector4_array_operator_index); + REGISTER_INTERFACE_FUNC(packed_vector4_array_operator_index_const); REGISTER_INTERFACE_FUNC(array_operator_index); REGISTER_INTERFACE_FUNC(array_operator_index_const); REGISTER_INTERFACE_FUNC(array_ref); diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 00a98af4e2..6fe6b8df20 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -96,6 +96,7 @@ typedef enum { GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY, GDEXTENSION_VARIANT_TYPE_VARIANT_MAX } GDExtensionVariantType; @@ -1964,32 +1965,6 @@ typedef uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndex)(GDExtension typedef const uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); /** - * @name packed_color_array_operator_index - * @since 4.1 - * - * Gets a pointer to a color in a PackedColorArray. - * - * @param p_self A pointer to a PackedColorArray object. - * @param p_index The index of the Color to get. - * - * @return A pointer to the requested Color. - */ -typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index); - -/** - * @name packed_color_array_operator_index_const - * @since 4.1 - * - * Gets a const pointer to a color in a PackedColorArray. - * - * @param p_self A const pointer to a const PackedColorArray object. - * @param p_index The index of the Color to get. - * - * @return A const pointer to the requested Color. - */ -typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); - -/** * @name packed_float32_array_operator_index * @since 4.1 * @@ -2172,6 +2147,58 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); /** + * @name packed_vector4_array_operator_index + * @since 4.3 + * + * Gets a pointer to a Vector4 in a PackedVector4Array. + * + * @param p_self A pointer to a PackedVector4Array object. + * @param p_index The index of the Vector4 to get. + * + * @return A pointer to the requested Vector4. + */ +typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index); + +/** + * @name packed_vector4_array_operator_index_const + * @since 4.3 + * + * Gets a const pointer to a Vector4 in a PackedVector4Array. + * + * @param p_self A const pointer to a PackedVector4Array object. + * @param p_index The index of the Vector4 to get. + * + * @return A const pointer to the requested Vector4. + */ +typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); + +/** + * @name packed_color_array_operator_index + * @since 4.1 + * + * Gets a pointer to a color in a PackedColorArray. + * + * @param p_self A pointer to a PackedColorArray object. + * @param p_index The index of the Color to get. + * + * @return A pointer to the requested Color. + */ +typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index); + +/** + * @name packed_color_array_operator_index_const + * @since 4.1 + * + * Gets a const pointer to a color in a PackedColorArray. + * + * @param p_self A const pointer to a PackedColorArray object. + * @param p_index The index of the Color to get. + * + * @return A const pointer to the requested Color. + */ +typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); + +/** * @name array_operator_index * @since 4.1 * @@ -2848,7 +2875,7 @@ typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNam * * The provided pointer can be immediately freed once the function returns. * - * @param p_data A pointer to an UTF-8 encoded C string (null terminated). + * @param p_data A pointer to a UTF-8 encoded C string (null terminated). */ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *p_data); @@ -2860,7 +2887,7 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char * * * The provided pointer can be immediately freed once the function returns. * - * @param p_data A pointer to an UTF-8 encoded C string. + * @param p_data A pointer to a UTF-8 encoded C string. * @param p_size The number of bytes (not code units). */ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size); diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp index a4d032f22f..1ee9de0776 100644 --- a/core/extension/gdextension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -295,6 +295,9 @@ GDExtensionManager::GDExtensionManager() { } GDExtensionManager::~GDExtensionManager() { + if (singleton == this) { + singleton = nullptr; + } #ifndef DISABLE_DEPRECATED GDExtensionCompatHashes::finalize(); #endif diff --git a/core/input/input.compat.inc b/core/input/input.compat.inc new file mode 100644 index 0000000000..cbc8b1df0f --- /dev/null +++ b/core/input/input.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* input.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +void Input::_vibrate_handheld_bind_compat_91143(int p_duration_ms) { + vibrate_handheld(p_duration_ms, -1.0); +} + +void Input::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::_vibrate_handheld_bind_compat_91143, DEFVAL(500)); +} + +#endif // DISABLE_DEPRECATED diff --git a/core/input/input.cpp b/core/input/input.cpp index c24a59203f..a8409cc06d 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "input.h" +#include "input.compat.inc" #include "core/config/project_settings.h" #include "core/input/default_controller_mappings.h" @@ -120,7 +121,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration); ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); - ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::vibrate_handheld, DEFVAL(500)); + ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms", "amplitude"), &Input::vibrate_handheld, DEFVAL(500), DEFVAL(-1.0)); ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity); ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer); ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer); @@ -803,8 +804,8 @@ void Input::stop_joy_vibration(int p_device) { joy_vibration[p_device] = vibration; } -void Input::vibrate_handheld(int p_duration_ms) { - OS::get_singleton()->vibrate_handheld(p_duration_ms); +void Input::vibrate_handheld(int p_duration_ms, float p_amplitude) { + OS::get_singleton()->vibrate_handheld(p_duration_ms, p_amplitude); } void Input::set_gravity(const Vector3 &p_gravity) { @@ -857,7 +858,7 @@ void Input::warp_mouse(const Vector2 &p_position) { warp_mouse_func(p_position); } -Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { +Point2 Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { // The relative distance reported for the next event after a warp is in the boundaries of the // size of the rect on that axis, but it may be greater, in which case there's no problem as fmod() // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation @@ -867,14 +868,14 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con // detect the warp: if the relative distance is greater than the half of the size of the relevant rect // (checked per each axis), it will be considered as the consequence of a former pointer warp. - const Point2i rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); - const Size2i warp_margin = p_rect.size * 0.5f; - const Point2i rel_warped( + const Point2 rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); + const Size2 warp_margin = p_rect.size * 0.5f; + const Point2 rel_warped( Math::fmod(p_motion->get_relative().x + rel_sign.x * warp_margin.x, p_rect.size.x) - rel_sign.x * warp_margin.x, Math::fmod(p_motion->get_relative().y + rel_sign.y * warp_margin.y, p_rect.size.y) - rel_sign.y * warp_margin.y); - const Point2i pos_local = p_motion->get_global_position() - p_rect.position; - const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); + const Point2 pos_local = p_motion->get_global_position() - p_rect.position; + const Point2 pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); if (pos_warped != pos_local) { warp_mouse(pos_warped + p_rect.position); } diff --git a/core/input/input.h b/core/input/input.h index d1f284e8f7..6e7ab43082 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -264,6 +264,11 @@ private: EventDispatchFunc event_dispatch_function = nullptr; +#ifndef DISABLE_DEPRECATED + void _vibrate_handheld_bind_compat_91143(int p_duration_ms = 500); + static void _bind_compatibility_methods(); +#endif // DISABLE_DEPRECATED + protected: static void _bind_methods(); @@ -311,7 +316,7 @@ public: BitField<MouseButtonMask> get_mouse_button_mask() const; void warp_mouse(const Vector2 &p_position); - Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); + Point2 warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); void parse_input_event(const Ref<InputEvent> &p_event); @@ -323,7 +328,7 @@ public: void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0); void stop_joy_vibration(int p_device); - void vibrate_handheld(int p_duration_ms = 500); + void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0); void set_mouse_position(const Point2 &p_posf); diff --git a/core/io/image.cpp b/core/io/image.cpp index 6096211cff..5498b448d7 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -521,7 +521,7 @@ void Image::convert(Format p_new_format) { // Includes the main image. const int mipmap_count = get_mipmap_count() + 1; - if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) { + if (Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format)) { ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); } else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) { @@ -1662,7 +1662,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & } bool Image::_can_modify(Format p_format) const { - return p_format <= FORMAT_RGBE9995; + return !Image::is_format_compressed(p_format); } template <typename Component, int CC, bool renormalize, @@ -2616,7 +2616,11 @@ int Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, For } bool Image::is_compressed() const { - return format > FORMAT_RGBE9995; + return is_format_compressed(format); +} + +bool Image::is_format_compressed(Format p_format) { + return p_format > FORMAT_RGBE9995; } Error Image::decompress() { diff --git a/core/io/image.h b/core/io/image.h index 2cabbb767a..daddfac59d 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -376,6 +376,7 @@ public: Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4); Error decompress(); bool is_compressed() const; + static bool is_format_compressed(Format p_format); void fix_alpha_edges(); void premultiply_alpha(); diff --git a/core/io/ip.cpp b/core/io/ip.cpp index ec86104926..f20d65bef9 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -148,8 +148,8 @@ PackedStringArray IP::resolve_hostname_addresses(const String &p_hostname, Type resolver->mutex.unlock(); PackedStringArray result; - for (int i = 0; i < res.size(); ++i) { - result.push_back(String(res[i])); + for (const IPAddress &E : res) { + result.push_back(String(E)); } return result; } @@ -206,9 +206,9 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const { List<IPAddress> res = resolver->queue[p_id].response; - for (int i = 0; i < res.size(); ++i) { - if (res[i].is_valid()) { - return res[i]; + for (const IPAddress &E : res) { + if (E.is_valid()) { + return E; } } return IPAddress(); @@ -226,9 +226,9 @@ Array IP::get_resolve_item_addresses(ResolverID p_id) const { List<IPAddress> res = resolver->queue[p_id].response; Array result; - for (int i = 0; i < res.size(); ++i) { - if (res[i].is_valid()) { - result.push_back(String(res[i])); + for (const IPAddress &E : res) { + if (E.is_valid()) { + result.push_back(String(E)); } } return result; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index ce74bb36d6..a93876a2b5 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -202,7 +202,7 @@ IPAddress::IPAddress(const String &p_string) { // Wildcard (not a valid IP) wildcard = true; - } else if (p_string.find(":") >= 0) { + } else if (p_string.contains(":")) { // IPv6 _parse_ipv6(p_string); valid = true; diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 18dbac991c..1928f86d6a 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -1179,6 +1179,73 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = carray; } break; + + case Variant::PACKED_VECTOR4_ARRAY: { + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int32_t count = decode_uint32(buf); + buf += 4; + len -= 4; + + Vector<Vector4> varray; + + if (header & HEADER_DATA_FLAG_64) { + ERR_FAIL_MUL_OF(count, sizeof(double) * 4, ERR_INVALID_DATA); + ERR_FAIL_COND_V(count < 0 || count * sizeof(double) * 4 > (size_t)len, ERR_INVALID_DATA); + + if (r_len) { + (*r_len) += 4; // Size of count number. + } + + if (count) { + varray.resize(count); + Vector4 *w = varray.ptrw(); + + for (int32_t i = 0; i < count; i++) { + w[i].x = decode_double(buf + i * sizeof(double) * 4 + sizeof(double) * 0); + w[i].y = decode_double(buf + i * sizeof(double) * 4 + sizeof(double) * 1); + w[i].z = decode_double(buf + i * sizeof(double) * 4 + sizeof(double) * 2); + w[i].w = decode_double(buf + i * sizeof(double) * 4 + sizeof(double) * 3); + } + + int adv = sizeof(double) * 4 * count; + + if (r_len) { + (*r_len) += adv; + } + len -= adv; + buf += adv; + } + } else { + ERR_FAIL_MUL_OF(count, sizeof(float) * 4, ERR_INVALID_DATA); + ERR_FAIL_COND_V(count < 0 || count * sizeof(float) * 4 > (size_t)len, ERR_INVALID_DATA); + + if (r_len) { + (*r_len) += 4; // Size of count number. + } + + if (count) { + varray.resize(count); + Vector4 *w = varray.ptrw(); + + for (int32_t i = 0; i < count; i++) { + w[i].x = decode_float(buf + i * sizeof(float) * 4 + sizeof(float) * 0); + w[i].y = decode_float(buf + i * sizeof(float) * 4 + sizeof(float) * 1); + w[i].z = decode_float(buf + i * sizeof(float) * 4 + sizeof(float) * 2); + w[i].w = decode_float(buf + i * sizeof(float) * 4 + sizeof(float) * 3); + } + + int adv = sizeof(float) * 4 * count; + + if (r_len) { + (*r_len) += adv; + } + len -= adv; + buf += adv; + } + } + r_variant = varray; + + } break; default: { ERR_FAIL_V(ERR_BUG); } @@ -1263,6 +1330,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo case Variant::VECTOR4: case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::TRANSFORM2D: case Variant::TRANSFORM3D: case Variant::PROJECTION: @@ -1628,7 +1696,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo Variant value; - if (E.name == CoreStringNames::get_singleton()->_script) { + if (E.name == CoreStringName(script)) { Ref<Script> script = obj->get_script(); if (script.is_valid()) { String path = script->get_path(); @@ -1947,6 +2015,32 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 4 * len; } break; + case Variant::PACKED_VECTOR4_ARRAY: { + Vector<Vector4> data = p_variant; + int len = data.size(); + + if (buf) { + encode_uint32(len, buf); + buf += 4; + } + + r_len += 4; + + if (buf) { + for (int i = 0; i < len; i++) { + Vector4 v = data.get(i); + + encode_real(v.x, &buf[0]); + encode_real(v.y, &buf[sizeof(real_t)]); + encode_real(v.z, &buf[sizeof(real_t) * 2]); + encode_real(v.w, &buf[sizeof(real_t) * 3]); + buf += sizeof(real_t) * 4; + } + } + + r_len += sizeof(real_t) * 4 * len; + + } break; default: { ERR_FAIL_V(ERR_BUG); } diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp index 11b0c69774..b20279c9ac 100644 --- a/core/io/packed_data_container.cpp +++ b/core/io/packed_data_container.cpp @@ -244,6 +244,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: case Variant::PACKED_COLOR_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::STRING_NAME: case Variant::NODE_PATH: { uint32_t pos = tmpdata.size(); diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 74f18ceee1..24ff0e83d2 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -43,9 +43,9 @@ void Resource::emit_changed() { if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) { // Let the connection happen on the main thread, later, since signals are not thread-safe. - call_deferred("emit_signal", CoreStringNames::get_singleton()->changed); + call_deferred("emit_signal", CoreStringName(changed)); } else { - emit_signal(CoreStringNames::get_singleton()->changed); + emit_signal(CoreStringName(changed)); } } @@ -172,8 +172,8 @@ void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) { callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags); return; } - if (!is_connected(CoreStringNames::get_singleton()->changed, p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) { - connect(CoreStringNames::get_singleton()->changed, p_callable, p_flags); + if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) { + connect(CoreStringName(changed), p_callable, p_flags); } } @@ -183,8 +183,8 @@ void Resource::disconnect_changed(const Callable &p_callable) { callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable); return; } - if (is_connected(CoreStringNames::get_singleton()->changed, p_callable)) { - disconnect(CoreStringNames::get_singleton()->changed, p_callable); + if (is_connected(CoreStringName(changed), p_callable)) { + disconnect(CoreStringName(changed), p_callable); } } @@ -383,7 +383,8 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { case Variant::Type::PACKED_FLOAT64_ARRAY: case Variant::Type::PACKED_STRING_ARRAY: case Variant::Type::PACKED_VECTOR2_ARRAY: - case Variant::Type::PACKED_VECTOR3_ARRAY: { + case Variant::Type::PACKED_VECTOR3_ARRAY: + case Variant::Type::PACKED_VECTOR4_ARRAY: { r->set(E.name, p.duplicate(p_subresources)); } break; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index d0a8200546..ab460c5f4c 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -85,15 +85,17 @@ enum { VARIANT_VECTOR4 = 50, VARIANT_VECTOR4I = 51, VARIANT_PROJECTION = 52, + VARIANT_PACKED_VECTOR4_ARRAY = 53, OBJECT_EMPTY = 0, OBJECT_EXTERNAL_RESOURCE = 1, OBJECT_INTERNAL_RESOURCE = 2, OBJECT_EXTERNAL_RESOURCE_INDEX = 3, - // Version 2: added 64 bits support for float and int. - // Version 3: changed nodepath encoding. - // Version 4: new string ID for ext/subresources, breaks forward compat. + // Version 2: Added 64-bit support for float and int. + // Version 3: Changed NodePath encoding. + // Version 4: New string ID for ext/subresources, breaks forward compat. // Version 5: Ability to store script class in the header. - FORMAT_VERSION = 5, + // Version 6: Added PackedVector4Array Variant type. + FORMAT_VERSION = 6, FORMAT_VERSION_CAN_RENAME_DEPS = 1, FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3, }; @@ -653,6 +655,19 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = array; } break; + case VARIANT_PACKED_VECTOR4_ARRAY: { + uint32_t len = f->get_32(); + + Vector<Vector4> array; + array.resize(len); + Vector4 *w = array.ptrw(); + static_assert(sizeof(Vector4) == 4 * sizeof(real_t)); + const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 4); + ERR_FAIL_COND_V(err != OK, err); + + r_v = array; + + } break; default: { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; @@ -1912,33 +1927,33 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V for (int i = 0; i < len; i++) { save_unicode_string(f, r[i]); } - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - f->store_32(VARIANT_PACKED_VECTOR3_ARRAY); - Vector<Vector3> arr = p_property; + + case Variant::PACKED_VECTOR2_ARRAY: { + f->store_32(VARIANT_PACKED_VECTOR2_ARRAY); + Vector<Vector2> arr = p_property; int len = arr.size(); f->store_32(len); - const Vector3 *r = arr.ptr(); + const Vector2 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); - f->store_real(r[i].z); } - } break; - case Variant::PACKED_VECTOR2_ARRAY: { - f->store_32(VARIANT_PACKED_VECTOR2_ARRAY); - Vector<Vector2> arr = p_property; + + case Variant::PACKED_VECTOR3_ARRAY: { + f->store_32(VARIANT_PACKED_VECTOR3_ARRAY); + Vector<Vector3> arr = p_property; int len = arr.size(); f->store_32(len); - const Vector2 *r = arr.ptr(); + const Vector3 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); + f->store_real(r[i].z); } - } break; + case Variant::PACKED_COLOR_ARRAY: { f->store_32(VARIANT_PACKED_COLOR_ARRAY); Vector<Color> arr = p_property; @@ -1953,6 +1968,20 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V } } break; + case Variant::PACKED_VECTOR4_ARRAY: { + f->store_32(VARIANT_PACKED_VECTOR4_ARRAY); + Vector<Vector4> arr = p_property; + int len = arr.size(); + f->store_32(len); + const Vector4 *r = arr.ptr(); + for (int i = 0; i < len; i++) { + f->store_real(r[i].x); + f->store_real(r[i].y); + f->store_real(r[i].z); + f->store_real(r[i].w); + } + + } break; default: { ERR_FAIL_MSG("Invalid variant."); } diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index 215c6903a6..75ba784dbd 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -161,7 +161,7 @@ Ref<PacketPeerUDP> UDPServer::take_connection() { return conn; } - Peer peer = pending[0]; + Peer peer = pending.front()->get(); pending.pop_front(); peers.push_back(peer); return peer.peer; diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 76e9e74dea..7d1d7c5648 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -117,55 +117,75 @@ AABB AABB::intersection(const AABB &p_aabb) const { return AABB(min, max - min); } -bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { +// Note that this routine returns the BACKTRACKED (i.e. behind the ray origin) +// intersection point + normal if INSIDE the AABB. +// The caller can therefore decide when INSIDE whether to use the +// backtracked intersection, or use p_from as the intersection, and +// carry on progressing without e.g. reflecting against the normal. +bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); } #endif - Vector3 c1, c2; Vector3 end = position + size; - real_t depth_near = -1e20; - real_t depth_far = 1e20; + real_t tmin = -1e20; + real_t tmax = 1e20; int axis = 0; + // Make sure r_inside is always initialized, + // to prevent reading uninitialized data in the client code. + r_inside = false; + for (int i = 0; i < 3; i++) { if (p_dir[i] == 0) { if ((p_from[i] < position[i]) || (p_from[i] > end[i])) { return false; } } else { // ray not parallel to planes in this direction - c1[i] = (position[i] - p_from[i]) / p_dir[i]; - c2[i] = (end[i] - p_from[i]) / p_dir[i]; + real_t t1 = (position[i] - p_from[i]) / p_dir[i]; + real_t t2 = (end[i] - p_from[i]) / p_dir[i]; - if (c1[i] > c2[i]) { - SWAP(c1, c2); + if (t1 > t2) { + SWAP(t1, t2); } - if (c1[i] > depth_near) { - depth_near = c1[i]; + if (t1 >= tmin) { + tmin = t1; axis = i; } - if (c2[i] < depth_far) { - depth_far = c2[i]; + if (t2 < tmax) { + if (t2 < 0) { + return false; + } + tmax = t2; } - if ((depth_near > depth_far) || (depth_far < 0)) { + if (tmin > tmax) { return false; } } } - if (r_clip) { - *r_clip = c1; + // Did the ray start from inside the box? + // In which case the intersection returned is the point of entry + // (behind the ray start) or the calling routine can use the ray origin as intersection point. + r_inside = tmin < 0; + + if (r_intersection_point) { + *r_intersection_point = p_from + p_dir * tmin; + + // Prevent float error by making sure the point is exactly + // on the AABB border on the relevant axis. + r_intersection_point->coord[axis] = (p_dir[axis] >= 0) ? position.coord[axis] : end.coord[axis]; } if (r_normal) { *r_normal = Vector3(); - (*r_normal)[axis] = p_dir[axis] ? -1 : 1; + (*r_normal)[axis] = (p_dir[axis] >= 0) ? -1 : 1; } return true; } -bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { +bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); @@ -223,8 +243,8 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector *r_normal = normal; } - if (r_clip) { - *r_clip = p_from + rel * min; + if (r_intersection_point) { + *r_intersection_point = p_from + rel * min; } return true; @@ -410,7 +430,15 @@ Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const { Vector3 inters; - if (intersects_ray(p_from, p_dir, &inters)) { + bool inside = false; + + if (find_intersects_ray(p_from, p_dir, inside, &inters)) { + // When inside the intersection point may be BEHIND the ray, + // so for general use we return the ray origin. + if (inside) { + return p_from; + } + return inters; } return Variant(); diff --git a/core/math/aabb.h b/core/math/aabb.h index 48a883e64c..9a74266ff7 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -71,10 +71,15 @@ struct _NO_DISCARD_ AABB { AABB merge(const AABB &p_with) const; void merge_with(const AABB &p_aabb); ///merge with another AABB AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs - bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; - bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const; + bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; + bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir) const { + bool inside; + return find_intersects_ray(p_from, p_dir, inside); + } + bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; + _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const; _FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const; bool intersects_plane(const Plane &p_plane) const; @@ -101,7 +106,7 @@ struct _NO_DISCARD_ AABB { _FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */ _FORCE_INLINE_ AABB abs() const { - return AABB(position + size.min(Vector3()), size.abs()); + return AABB(position + size.minf(0), size.abs()); } Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const; diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index 25bd4e8d89..4f21a665de 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -278,7 +278,7 @@ public: } Vector3i grid_pos = Vector3i(points[i] * proportions * ACCEL_GRID_SIZE); - grid_pos = grid_pos.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); + grid_pos = grid_pos.clampi(0, ACCEL_GRID_SIZE - 1); for (List<Simplex *>::Element *E = acceleration_grid[grid_pos.x][grid_pos.y][grid_pos.z].front(); E;) { List<Simplex *>::Element *N = E->next(); //may be deleted @@ -335,8 +335,8 @@ public: Vector3 extents = Vector3(radius2, radius2, radius2); Vector3i from = Vector3i((center - extents) * proportions * ACCEL_GRID_SIZE); Vector3i to = Vector3i((center + extents) * proportions * ACCEL_GRID_SIZE); - from = from.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); - to = to.clamp(Vector3i(), Vector3i(ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1, ACCEL_GRID_SIZE - 1)); + from = from.clampi(0, ACCEL_GRID_SIZE - 1); + to = to.clampi(0, ACCEL_GRID_SIZE - 1); for (int32_t x = from.x; x <= to.x; x++) { for (int32_t y = from.y; y <= to.y; y++) { diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 4483f61bc4..6a60a5925d 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -55,7 +55,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_ HashSet<Vector3> valid_cache; for (int i = 0; i < p_points.size(); i++) { - Vector3 sp = p_points[i].snapped(Vector3(0.0001, 0.0001, 0.0001)); + Vector3 sp = p_points[i].snappedf(0.0001); if (valid_cache.has(sp)) { valid_points.write[i] = false; } else { diff --git a/core/math/rect2.h b/core/math/rect2.h index 7f410feb1c..b4069ae86a 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -278,7 +278,7 @@ struct _NO_DISCARD_ Rect2 { } _FORCE_INLINE_ Rect2 abs() const { - return Rect2(position + size.min(Point2()), size.abs()); + return Rect2(position + size.minf(0), size.abs()); } _FORCE_INLINE_ Rect2 round() const { diff --git a/core/math/rect2i.h b/core/math/rect2i.h index 64806414c7..a1338da0bb 100644 --- a/core/math/rect2i.h +++ b/core/math/rect2i.h @@ -213,7 +213,7 @@ struct _NO_DISCARD_ Rect2i { } _FORCE_INLINE_ Rect2i abs() const { - return Rect2i(position + size.min(Point2i()), size.abs()); + return Rect2i(position + size.mini(0), size.abs()); } _FORCE_INLINE_ void set_end(const Vector2i &p_end) { diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h index c53868e12d..74e4b75163 100644 --- a/core/math/static_raycaster.h +++ b/core/math/static_raycaster.h @@ -49,7 +49,7 @@ protected: static StaticRaycaster *(*create_function)(); public: - // compatible with embree3 rays + // Compatible with embree4 rays. struct __aligned(16) Ray { const static unsigned int INVALID_GEOMETRY_ID = ((unsigned int)-1); // from rtcore_common.h diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 0da1b8c7ad..01b733183d 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -133,7 +133,7 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces, const Vector<int32_t> for (int j = 0; j < 3; j++) { int vidx = -1; - Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001)); + Vector3 vs = v[j].snappedf(0.0001); HashMap<Vector3, int>::Iterator E = db.find(vs); if (E) { vidx = E->value; diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 198fd85d20..e86b97d6a8 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -135,12 +135,24 @@ Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +Vector2 Vector2::clampf(real_t p_min, real_t p_max) const { + return Vector2( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max)); +} + Vector2 Vector2::snapped(const Vector2 &p_step) const { return Vector2( Math::snapped(x, p_step.x), Math::snapped(y, p_step.y)); } +Vector2 Vector2::snappedf(real_t p_step) const { + return Vector2( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); +} + Vector2 Vector2::limit_length(real_t p_len) const { const real_t l = length(); Vector2 v = *this; diff --git a/core/math/vector2.h b/core/math/vector2.h index 6ad003edd1..8851942cdd 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -89,10 +89,18 @@ struct _NO_DISCARD_ Vector2 { return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y)); } + Vector2 minf(real_t p_scalar) const { + return Vector2(MIN(x, p_scalar), MIN(y, p_scalar)); + } + Vector2 max(const Vector2 &p_vector2) const { return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y)); } + Vector2 maxf(real_t p_scalar) const { + return Vector2(MAX(x, p_scalar), MAX(y, p_scalar)); + } + real_t distance_to(const Vector2 &p_vector2) const; real_t distance_squared_to(const Vector2 &p_vector2) const; real_t angle_to(const Vector2 &p_vector2) const; @@ -168,7 +176,9 @@ struct _NO_DISCARD_ Vector2 { Vector2 ceil() const; Vector2 round() const; Vector2 snapped(const Vector2 &p_by) const; + Vector2 snappedf(real_t p_by) const; Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const; + Vector2 clampf(real_t p_min, real_t p_max) const; real_t aspect() const { return width / height; } operator String() const; diff --git a/core/math/vector2i.cpp b/core/math/vector2i.cpp index ba79d439dd..790f564734 100644 --- a/core/math/vector2i.cpp +++ b/core/math/vector2i.cpp @@ -39,12 +39,24 @@ Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { CLAMP(y, p_min.y, p_max.y)); } +Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { + return Vector2i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max)); +} + Vector2i Vector2i::snapped(const Vector2i &p_step) const { return Vector2i( Math::snapped(x, p_step.x), Math::snapped(y, p_step.y)); } +Vector2i Vector2i::snappedi(int32_t p_step) const { + return Vector2i( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); +} + int64_t Vector2i::length_squared() const { return x * (int64_t)x + y * (int64_t)y; } diff --git a/core/math/vector2i.h b/core/math/vector2i.h index aa29263a65..aca9ae8272 100644 --- a/core/math/vector2i.h +++ b/core/math/vector2i.h @@ -81,10 +81,18 @@ struct _NO_DISCARD_ Vector2i { return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y)); } + Vector2i mini(int32_t p_scalar) const { + return Vector2i(MIN(x, p_scalar), MIN(y, p_scalar)); + } + Vector2i max(const Vector2i &p_vector2i) const { return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y)); } + Vector2i maxi(int32_t p_scalar) const { + return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar)); + } + double distance_to(const Vector2i &p_to) const { return (p_to - *this).length(); } @@ -127,7 +135,9 @@ struct _NO_DISCARD_ Vector2i { Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; + Vector2i clampi(int32_t p_min, int32_t p_max) const; Vector2i snapped(const Vector2i &p_step) const; + Vector2i snappedi(int32_t p_step) const; operator String() const; operator Vector2() const; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index fad5f2c0fb..1e90002665 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -52,6 +52,13 @@ Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const { CLAMP(z, p_min.z, p_max.z)); } +Vector3 Vector3::clampf(real_t p_min, real_t p_max) const { + return Vector3( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max)); +} + void Vector3::snap(const Vector3 &p_step) { x = Math::snapped(x, p_step.x); y = Math::snapped(y, p_step.y); @@ -64,6 +71,18 @@ Vector3 Vector3::snapped(const Vector3 &p_step) const { return v; } +void Vector3::snapf(real_t p_step) { + x = Math::snapped(x, p_step); + y = Math::snapped(y, p_step); + z = Math::snapped(z, p_step); +} + +Vector3 Vector3::snappedf(real_t p_step) const { + Vector3 v = *this; + v.snapf(p_step); + return v; +} + Vector3 Vector3::limit_length(real_t p_len) const { const real_t l = length(); Vector3 v = *this; diff --git a/core/math/vector3.h b/core/math/vector3.h index f5d16984d9..2313eb557a 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -80,10 +80,18 @@ struct _NO_DISCARD_ Vector3 { return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z)); } + Vector3 minf(real_t p_scalar) const { + return Vector3(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar)); + } + Vector3 max(const Vector3 &p_vector3) const { return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z)); } + Vector3 maxf(real_t p_scalar) const { + return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar)); + } + _FORCE_INLINE_ real_t length() const; _FORCE_INLINE_ real_t length_squared() const; @@ -96,7 +104,9 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ void zero(); void snap(const Vector3 &p_step); + void snapf(real_t p_step); Vector3 snapped(const Vector3 &p_step) const; + Vector3 snappedf(real_t p_step) const; void rotate(const Vector3 &p_axis, real_t p_angle); Vector3 rotated(const Vector3 &p_axis, real_t p_angle) const; @@ -127,6 +137,7 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ Vector3 ceil() const; _FORCE_INLINE_ Vector3 round() const; Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const; + Vector3 clampf(real_t p_min, real_t p_max) const; _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index f41460e623..93f9d15ac1 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -48,6 +48,13 @@ Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const { CLAMP(z, p_min.z, p_max.z)); } +Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const { + return Vector3i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max)); +} + Vector3i Vector3i::snapped(const Vector3i &p_step) const { return Vector3i( Math::snapped(x, p_step.x), @@ -55,6 +62,13 @@ Vector3i Vector3i::snapped(const Vector3i &p_step) const { Math::snapped(z, p_step.z)); } +Vector3i Vector3i::snappedi(int32_t p_step) const { + return Vector3i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step)); +} + Vector3i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index a9f298bff1..035cfcf9e2 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -73,10 +73,18 @@ struct _NO_DISCARD_ Vector3i { return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z)); } + Vector3i mini(int32_t p_scalar) const { + return Vector3i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar)); + } + Vector3i max(const Vector3i &p_vector3i) const { return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z)); } + Vector3i maxi(int32_t p_scalar) const { + return Vector3i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; @@ -85,7 +93,9 @@ struct _NO_DISCARD_ Vector3i { _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; + Vector3i clampi(int32_t p_min, int32_t p_max) const; Vector3i snapped(const Vector3i &p_step) const; + Vector3i snappedi(int32_t p_step) const; _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp index e6f6dee42c..b6b914f36d 100644 --- a/core/math/vector4.cpp +++ b/core/math/vector4.cpp @@ -30,6 +30,8 @@ #include "vector4.h" +#include "core/math/math_funcs.h" +#include "core/math/vector4i.h" #include "core/string/ustring.h" Vector4::Axis Vector4::min_axis_index() const { @@ -171,12 +173,25 @@ void Vector4::snap(const Vector4 &p_step) { w = Math::snapped(w, p_step.w); } +void Vector4::snapf(real_t p_step) { + x = Math::snapped(x, p_step); + y = Math::snapped(y, p_step); + z = Math::snapped(z, p_step); + w = Math::snapped(w, p_step); +} + Vector4 Vector4::snapped(const Vector4 &p_step) const { Vector4 v = *this; v.snap(p_step); return v; } +Vector4 Vector4::snappedf(real_t p_step) const { + Vector4 v = *this; + v.snapf(p_step); + return v; +} + Vector4 Vector4::inverse() const { return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w); } @@ -189,8 +204,20 @@ Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const { CLAMP(w, p_min.w, p_max.w)); } +Vector4 Vector4::clampf(real_t p_min, real_t p_max) const { + return Vector4( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max), + CLAMP(w, p_min, p_max)); +} + Vector4::operator String() const { return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")"; } static_assert(sizeof(Vector4) == 4 * sizeof(real_t)); + +Vector4::operator Vector4i() const { + return Vector4i(x, y, z, w); +} diff --git a/core/math/vector4.h b/core/math/vector4.h index 4dba3126cb..f69b4752bb 100644 --- a/core/math/vector4.h +++ b/core/math/vector4.h @@ -32,9 +32,11 @@ #define VECTOR4_H #include "core/error/error_macros.h" -#include "core/math/math_funcs.h" +#include "core/math/math_defs.h" +#include "core/typedefs.h" class String; +struct Vector4i; struct _NO_DISCARD_ Vector4 { static const int AXIS_COUNT = 4; @@ -72,10 +74,18 @@ struct _NO_DISCARD_ Vector4 { return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w)); } + Vector4 minf(real_t p_scalar) const { + return Vector4(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar)); + } + Vector4 max(const Vector4 &p_vector4) const { return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w)); } + Vector4 maxf(real_t p_scalar) const { + return Vector4(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar)); + } + _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Vector4 &p_vec4) const; bool is_zero_approx() const; @@ -101,8 +111,11 @@ struct _NO_DISCARD_ Vector4 { Vector4 posmod(real_t p_mod) const; Vector4 posmodv(const Vector4 &p_modv) const; void snap(const Vector4 &p_step); + void snapf(real_t p_step); Vector4 snapped(const Vector4 &p_step) const; + Vector4 snappedf(real_t p_step) const; Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const; + Vector4 clampf(real_t p_min, real_t p_max) const; Vector4 inverse() const; _FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const; @@ -129,28 +142,14 @@ struct _NO_DISCARD_ Vector4 { _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const; operator String() const; + operator Vector4i() const; _FORCE_INLINE_ Vector4() {} - - _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : - x(p_x), - y(p_y), - z(p_z), - w(p_w) { - } - - Vector4(const Vector4 &p_vec4) : - x(p_vec4.x), - y(p_vec4.y), - z(p_vec4.z), - w(p_vec4.w) { - } - - void operator=(const Vector4 &p_vec4) { - x = p_vec4.x; - y = p_vec4.y; - z = p_vec4.z; - w = p_vec4.w; + _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) { + x = p_x; + y = p_y; + z = p_z; + w = p_w; } }; diff --git a/core/math/vector4i.cpp b/core/math/vector4i.cpp index 8e36c6b534..afa77a4988 100644 --- a/core/math/vector4i.cpp +++ b/core/math/vector4i.cpp @@ -65,6 +65,14 @@ Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const { CLAMP(w, p_min.w, p_max.w)); } +Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const { + return Vector4i( + CLAMP(x, p_min, p_max), + CLAMP(y, p_min, p_max), + CLAMP(z, p_min, p_max), + CLAMP(w, p_min, p_max)); +} + Vector4i Vector4i::snapped(const Vector4i &p_step) const { return Vector4i( Math::snapped(x, p_step.x), @@ -73,6 +81,14 @@ Vector4i Vector4i::snapped(const Vector4i &p_step) const { Math::snapped(w, p_step.w)); } +Vector4i Vector4i::snappedi(int32_t p_step) const { + return Vector4i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step), + Math::snapped(w, p_step)); +} + Vector4i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; } diff --git a/core/math/vector4i.h b/core/math/vector4i.h index 5a96d98d18..8a9c580bc1 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -75,10 +75,18 @@ struct _NO_DISCARD_ Vector4i { return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w)); } + Vector4i mini(int32_t p_scalar) const { + return Vector4i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar)); + } + Vector4i max(const Vector4i &p_vector4i) const { return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w)); } + Vector4i maxi(int32_t p_scalar) const { + return Vector4i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar)); + } + _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; @@ -90,7 +98,9 @@ struct _NO_DISCARD_ Vector4i { _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; + Vector4i clampi(int32_t p_min, int32_t p_max) const; Vector4i snapped(const Vector4i &p_step) const; + Vector4i snappedi(int32_t p_step) const; /* Operators */ diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 876635529c..7ea26c3fc5 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -425,8 +425,8 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { for (const StringName &F : snames) { MethodInfo &mi = t->signal_map[F]; hash = hash_murmur3_one_64(F.hash(), hash); - for (int i = 0; i < mi.arguments.size(); i++) { - hash = hash_murmur3_one_64(mi.arguments[i].type, hash); + for (const PropertyInfo &pi : mi.arguments) { + hash = hash_murmur3_one_64(pi.type, hash); } } } @@ -1554,7 +1554,7 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia } // The "free()" method is special, so we assume it exists and return a Callable. - if (p_property == CoreStringNames::get_singleton()->_free) { + if (p_property == CoreStringName(free_)) { r_value = Callable(p_object, p_property); return true; } @@ -1856,8 +1856,9 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ if (p_arg_names.size() != mi.arguments.size()) { WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name); } else { - for (int i = 0; i < p_arg_names.size(); i++) { - mi.arguments[i].name = p_arg_names[i]; + List<PropertyInfo>::Iterator itr = mi.arguments.begin(); + for (int i = 0; i < p_arg_names.size(); ++itr, ++i) { + itr->name = p_arg_names[i]; } } } diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp index 90536e58ff..6fab934395 100644 --- a/core/object/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -197,7 +197,7 @@ Error CallQueue::push_notification(ObjectID p_id, int p_notification) { Message *msg = memnew_placement(buffer_end, Message); msg->type = TYPE_NOTIFICATION; - msg->callable = Callable(p_id, CoreStringNames::get_singleton()->notification); //name is meaningless but callable needs it + msg->callable = Callable(p_id, CoreStringName(notification)); //name is meaningless but callable needs it //msg->target; msg->notification = p_notification; diff --git a/core/object/method_bind.h b/core/object/method_bind.h index e97f4abc6a..2f9a2d1679 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -152,7 +152,7 @@ public: if (p_arg < 0) { return _gen_return_type_info(); } else if (p_arg < method_info.arguments.size()) { - return method_info.arguments[p_arg]; + return method_info.arguments.get(p_arg); } else { return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); } @@ -193,10 +193,11 @@ public: Vector<StringName> names; names.resize(method_info.arguments.size()); #endif - for (int i = 0; i < method_info.arguments.size(); i++) { - at[i + 1] = method_info.arguments[i].type; + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) { + at[i + 1] = itr->type; #ifdef DEBUG_METHODS_ENABLED - names.write[i] = method_info.arguments[i].name; + names.write[i] = itr->name; #endif } diff --git a/core/object/object.cpp b/core/object/object.cpp index b6c8a87a22..57f8766509 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -260,7 +260,7 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid } } - if (p_name == CoreStringNames::get_singleton()->_script) { + if (p_name == CoreStringName(script)) { set_script(p_value); if (r_valid) { *r_valid = true; @@ -351,7 +351,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { } } - if (p_name == CoreStringNames::get_singleton()->_script) { + if (p_name == CoreStringName(script)) { ret = get_script(); if (r_valid) { *r_valid = true; @@ -672,7 +672,7 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call } bool Object::has_method(const StringName &p_method) const { - if (p_method == CoreStringNames::get_singleton()->_free) { + if (p_method == CoreStringName(free_)) { return true; } @@ -698,7 +698,7 @@ int Object::_get_method_argument_count_bind(const StringName &p_method) const { } int Object::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const { - if (p_method == CoreStringNames::get_singleton()->_free) { + if (p_method == CoreStringName(free_)) { if (r_is_valid) { *r_is_valid = true; } @@ -787,7 +787,7 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) { Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; - if (p_method == CoreStringNames::get_singleton()->_free) { + if (p_method == CoreStringName(free_)) { //free must be here, before anything, always ready #ifdef DEBUG_ENABLED if (p_argcount != 0) { @@ -850,7 +850,7 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_ Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; - if (p_method == CoreStringNames::get_singleton()->_free) { + if (p_method == CoreStringName(free_)) { // Free is not const, so fail. r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST; return Variant(); @@ -979,7 +979,7 @@ void Object::set_script(const Variant &p_script) { } notify_property_list_changed(); //scripts may add variables, so refresh is desired - emit_signal(CoreStringNames::get_singleton()->script_changed); + emit_signal(CoreStringName(script_changed)); } void Object::set_script_instance(ScriptInstance *p_instance) { @@ -1302,9 +1302,8 @@ TypedArray<Dictionary> Object::_get_signal_connection_list(const StringName &p_s TypedArray<Dictionary> Object::_get_incoming_connections() const { TypedArray<Dictionary> ret; - int connections_amount = connections.size(); - for (int idx_conn = 0; idx_conn < connections_amount; idx_conn++) { - ret.push_back(connections[idx_conn]); + for (const Object::Connection &connection : connections) { + ret.push_back(connection); } return ret; @@ -1655,7 +1654,7 @@ void Object::clear_internal_resource_paths() { } void Object::notify_property_list_changed() { - emit_signal(CoreStringNames::get_singleton()->property_list_changed); + emit_signal(CoreStringName(property_list_changed)); } void Object::_bind_methods() { @@ -2096,9 +2095,13 @@ Object::~Object() { _extension_instance = nullptr; } #ifdef TOOLS_ENABLED - else if (_instance_bindings != nullptr && Engine::get_singleton()->is_extension_reloading_enabled()) { - for (uint32_t i = 0; i < _instance_binding_count; i++) { - GDExtensionManager::get_singleton()->untrack_instance_binding(_instance_bindings[i].token, this); + else if (_instance_bindings != nullptr) { + Engine *engine = Engine::get_singleton(); + GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton(); + if (engine && gdextension_manager && engine->is_extension_reloading_enabled()) { + for (uint32_t i = 0; i < _instance_binding_count; i++) { + gdextension_manager->untrack_instance_binding(_instance_bindings[i].token, this); + } } } #endif @@ -2308,9 +2311,9 @@ void ObjectDB::setup() { } void ObjectDB::cleanup() { - if (slot_count > 0) { - spin_lock.lock(); + spin_lock.lock(); + if (slot_count > 0) { WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details)."); if (OS::get_singleton()->is_stdout_verbose()) { // Ensure calling the native classes because if a leaked instance has a script @@ -2341,10 +2344,11 @@ void ObjectDB::cleanup() { } print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`)."); } - spin_lock.unlock(); } if (object_slots) { memfree(object_slots); } + + spin_lock.unlock(); } diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index bd3199ca0a..820296e66d 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -537,6 +537,7 @@ void ScriptLanguage::get_core_type_words(List<String> *p_core_type_words) const p_core_type_words->push_back("PackedVector2Array"); p_core_type_words->push_back("PackedVector3Array"); p_core_type_words->push_back("PackedColorArray"); + p_core_type_words->push_back("PackedVector4Array"); } void ScriptLanguage::frame() { diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index cc6b729ae8..8fd26c3d2c 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -389,7 +389,16 @@ public: EXBIND0RC(bool, can_make_function) EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int) EXBIND0R(bool, overrides_external_editor) - EXBIND0RC(ScriptNameCasing, preferred_file_name_casing) + + GDVIRTUAL0RC(ScriptNameCasing, _preferred_file_name_casing); + + virtual ScriptNameCasing preferred_file_name_casing() const override { + ScriptNameCasing ret; + if (GDVIRTUAL_CALL(_preferred_file_name_casing, ret)) { + return ret; + } + return ScriptNameCasing::SCRIPT_NAME_CASING_SNAKE_CASE; + } GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *) diff --git a/core/os/os.h b/core/os/os.h index d20f84b4ff..63cc6ed50e 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -185,7 +185,7 @@ public: virtual int get_process_id() const; virtual bool is_process_running(const ProcessID &p_pid) const = 0; virtual int get_process_exit_code(const ProcessID &p_pid) const = 0; - virtual void vibrate_handheld(int p_duration_ms = 500) {} + virtual void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0) {} virtual Error shell_open(const String &p_uri); virtual Error shell_show_in_file_manager(String p_path, bool p_open_folder = true); diff --git a/core/string/char_range.inc b/core/string/char_range.inc index b7d6bbdb61..2b081b96de 100644 --- a/core/string/char_range.inc +++ b/core/string/char_range.inc @@ -2761,4 +2761,667 @@ inline constexpr CharRange lowercase_letter[] = { { 0x1e922, 0x1e943 }, }; +inline constexpr CharRange unicode_letter[] = { + { 0x41, 0x5a }, + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x370, 0x374 }, + { 0x376, 0x377 }, + { 0x37a, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x386 }, + { 0x388, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x620, 0x64a }, + { 0x66e, 0x66f }, + { 0x671, 0x6d3 }, + { 0x6d5, 0x6d5 }, + { 0x6e5, 0x6e6 }, + { 0x6ee, 0x6ef }, + { 0x6fa, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x710 }, + { 0x712, 0x72f }, + { 0x74d, 0x7a5 }, + { 0x7b1, 0x7b1 }, + { 0x7ca, 0x7ea }, + { 0x7f4, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x800, 0x815 }, + { 0x81a, 0x81a }, + { 0x824, 0x824 }, + { 0x828, 0x828 }, + { 0x840, 0x858 }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x8a0, 0x8c9 }, + { 0x904, 0x939 }, + { 0x93d, 0x93d }, + { 0x950, 0x950 }, + { 0x958, 0x961 }, + { 0x971, 0x980 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bd, 0x9bd }, + { 0x9ce, 0x9ce }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e1 }, + { 0x9f0, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa72, 0xa74 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabd, 0xabd }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae1 }, + { 0xaf9, 0xaf9 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3d, 0xb3d }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb61 }, + { 0xb71, 0xb71 }, + { 0xb83, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbd0, 0xbd0 }, + { 0xc05, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3d, 0xc3d }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc61 }, + { 0xc80, 0xc80 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbd, 0xcbd }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce1 }, + { 0xcf1, 0xcf2 }, + { 0xd04, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd3a }, + { 0xd3d, 0xd3d }, + { 0xd4e, 0xd4e }, + { 0xd54, 0xd56 }, + { 0xd5f, 0xd61 }, + { 0xd7a, 0xd7f }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xe01, 0xe30 }, + { 0xe32, 0xe33 }, + { 0xe40, 0xe46 }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xeb0 }, + { 0xeb2, 0xeb3 }, + { 0xebd, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf40, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf88, 0xf8c }, + { 0x1000, 0x102a }, + { 0x103f, 0x103f }, + { 0x1050, 0x1055 }, + { 0x105a, 0x105d }, + { 0x1061, 0x1061 }, + { 0x1065, 0x1066 }, + { 0x106e, 0x1070 }, + { 0x1075, 0x1081 }, + { 0x108e, 0x108e }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16f1, 0x16f8 }, + { 0x1700, 0x1711 }, + { 0x171f, 0x1731 }, + { 0x1740, 0x1751 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1780, 0x17b3 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dc }, + { 0x1820, 0x1878 }, + { 0x1880, 0x1884 }, + { 0x1887, 0x18a8 }, + { 0x18aa, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1950, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x1a00, 0x1a16 }, + { 0x1a20, 0x1a54 }, + { 0x1aa7, 0x1aa7 }, + { 0x1b05, 0x1b33 }, + { 0x1b45, 0x1b4c }, + { 0x1b83, 0x1ba0 }, + { 0x1bae, 0x1baf }, + { 0x1bba, 0x1be5 }, + { 0x1c00, 0x1c23 }, + { 0x1c4d, 0x1c4f }, + { 0x1c5a, 0x1c7d }, + { 0x1c80, 0x1c88 }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1ce9, 0x1cec }, + { 0x1cee, 0x1cf3 }, + { 0x1cf5, 0x1cf6 }, + { 0x1cfa, 0x1cfa }, + { 0x1d00, 0x1dbf }, + { 0x1e00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2119, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x212d }, + { 0x212f, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2183, 0x2184 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cee }, + { 0x2cf2, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d80, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x2e2f, 0x2e2f }, + { 0x3005, 0x3006 }, + { 0x3031, 0x3035 }, + { 0x303b, 0x303c }, + { 0x3041, 0x3096 }, + { 0x309d, 0x309f }, + { 0x30a1, 0x30fa }, + { 0x30fc, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa61f }, + { 0xa62a, 0xa62b }, + { 0xa640, 0xa66e }, + { 0xa67f, 0xa69d }, + { 0xa6a0, 0xa6e5 }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7ca }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7d9 }, + { 0xa7f2, 0xa801 }, + { 0xa803, 0xa805 }, + { 0xa807, 0xa80a }, + { 0xa80c, 0xa822 }, + { 0xa840, 0xa873 }, + { 0xa882, 0xa8b3 }, + { 0xa8f2, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa8fe }, + { 0xa90a, 0xa925 }, + { 0xa930, 0xa946 }, + { 0xa960, 0xa97c }, + { 0xa984, 0xa9b2 }, + { 0xa9cf, 0xa9cf }, + { 0xa9e0, 0xa9e4 }, + { 0xa9e6, 0xa9ef }, + { 0xa9fa, 0xa9fe }, + { 0xaa00, 0xaa28 }, + { 0xaa40, 0xaa42 }, + { 0xaa44, 0xaa4b }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaa7a }, + { 0xaa7e, 0xaaaf }, + { 0xaab1, 0xaab1 }, + { 0xaab5, 0xaab6 }, + { 0xaab9, 0xaabd }, + { 0xaac0, 0xaac0 }, + { 0xaac2, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaea }, + { 0xaaf2, 0xaaf4 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabe2 }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb1d }, + { 0xfb1f, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdfb }, + { 0xfe70, 0xfe74 }, + { 0xfe76, 0xfefc }, + { 0xff21, 0xff3a }, + { 0xff41, 0xff5a }, + { 0xff66, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x10340 }, + { 0x10342, 0x10349 }, + { 0x10350, 0x10375 }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x10400, 0x1049d }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a00 }, + { 0x10a10, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae4 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d23 }, + { 0x10e80, 0x10ea9 }, + { 0x10eb0, 0x10eb1 }, + { 0x10f00, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f45 }, + { 0x10f70, 0x10f81 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11003, 0x11037 }, + { 0x11071, 0x11072 }, + { 0x11075, 0x11075 }, + { 0x11083, 0x110af }, + { 0x110d0, 0x110e8 }, + { 0x11103, 0x11126 }, + { 0x11144, 0x11144 }, + { 0x11147, 0x11147 }, + { 0x11150, 0x11172 }, + { 0x11176, 0x11176 }, + { 0x11183, 0x111b2 }, + { 0x111c1, 0x111c4 }, + { 0x111da, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x1122b }, + { 0x1123f, 0x11240 }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112de }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133d, 0x1133d }, + { 0x11350, 0x11350 }, + { 0x1135d, 0x11361 }, + { 0x11400, 0x11434 }, + { 0x11447, 0x1144a }, + { 0x1145f, 0x11461 }, + { 0x11480, 0x114af }, + { 0x114c4, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x11580, 0x115ae }, + { 0x115d8, 0x115db }, + { 0x11600, 0x1162f }, + { 0x11644, 0x11644 }, + { 0x11680, 0x116aa }, + { 0x116b8, 0x116b8 }, + { 0x11700, 0x1171a }, + { 0x11740, 0x11746 }, + { 0x11800, 0x1182b }, + { 0x118a0, 0x118df }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x1192f }, + { 0x1193f, 0x1193f }, + { 0x11941, 0x11941 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d0 }, + { 0x119e1, 0x119e1 }, + { 0x119e3, 0x119e3 }, + { 0x11a00, 0x11a00 }, + { 0x11a0b, 0x11a32 }, + { 0x11a3a, 0x11a3a }, + { 0x11a50, 0x11a50 }, + { 0x11a5c, 0x11a89 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c2e }, + { 0x11c40, 0x11c40 }, + { 0x11c72, 0x11c8f }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d30 }, + { 0x11d46, 0x11d46 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d89 }, + { 0x11d98, 0x11d98 }, + { 0x11ee0, 0x11ef2 }, + { 0x11f02, 0x11f02 }, + { 0x11f04, 0x11f10 }, + { 0x11f12, 0x11f33 }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342f }, + { 0x13441, 0x13446 }, + { 0x14400, 0x14646 }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a70, 0x16abe }, + { 0x16ad0, 0x16aed }, + { 0x16b00, 0x16b2f }, + { 0x16b40, 0x16b43 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f50, 0x16f50 }, + { 0x16f93, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe3 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18d00, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, + { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e030, 0x1e06d }, + { 0x1e100, 0x1e12c }, + { 0x1e137, 0x1e13d }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ad }, + { 0x1e2c0, 0x1e2eb }, + { 0x1e4d0, 0x1e4eb }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e900, 0x1e943 }, + { 0x1e94b, 0x1e94b }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b739 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, +}; + #endif // CHAR_RANGE_INC diff --git a/core/string/char_utils.h b/core/string/char_utils.h index fc2fbb95a1..4acb81253f 100644 --- a/core/string/char_utils.h +++ b/core/string/char_utils.h @@ -70,6 +70,10 @@ static _FORCE_INLINE_ bool is_unicode_lower_case(char32_t c) { BSEARCH_CHAR_RANGE(lowercase_letter); } +static _FORCE_INLINE_ bool is_unicode_letter(char32_t c) { + BSEARCH_CHAR_RANGE(unicode_letter); +} + #undef BSEARCH_CHAR_RANGE static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) { diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 2b62b72a51..3d37e17ef8 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1184,6 +1184,26 @@ int String::get_slice_count(const String &p_splitter) const { return slices; } +int String::get_slice_count(const char *p_splitter) const { + if (is_empty()) { + return 0; + } + if (p_splitter == nullptr || *p_splitter == '\0') { + return 0; + } + + int pos = 0; + int slices = 1; + int splitter_length = strlen(p_splitter); + + while ((pos = find(p_splitter, pos)) >= 0) { + slices++; + pos += splitter_length; + } + + return slices; +} + String String::get_slice(const String &p_splitter, int p_slice) const { if (is_empty() || p_splitter.is_empty()) { return ""; @@ -1224,6 +1244,47 @@ String String::get_slice(const String &p_splitter, int p_slice) const { return ""; //no find! } +String String::get_slice(const char *p_splitter, int p_slice) const { + if (is_empty() || p_splitter == nullptr || *p_splitter == '\0') { + return ""; + } + + int pos = 0; + int prev_pos = 0; + //int slices=1; + if (p_slice < 0) { + return ""; + } + if (find(p_splitter) == -1) { + return *this; + } + + int i = 0; + int splitter_length = strlen(p_splitter); + while (true) { + pos = find(p_splitter, pos); + if (pos == -1) { + pos = length(); //reached end + } + + int from = prev_pos; + //int to=pos; + + if (p_slice == i) { + return substr(from, pos - from); + } + + if (pos == length()) { //reached end and no find + break; + } + pos += splitter_length; + prev_pos = pos; + i++; + } + + return ""; //no find! +} + String String::get_slicec(char32_t p_splitter, int p_slice) const { if (is_empty()) { return String(); @@ -1338,6 +1399,54 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p return ret; } +Vector<String> String::split(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const { + Vector<String> ret; + + if (is_empty()) { + if (p_allow_empty) { + ret.push_back(""); + } + return ret; + } + + int from = 0; + int len = length(); + + while (true) { + int end; + if (p_splitter == nullptr || *p_splitter == '\0') { + end = from + 1; + } else { + end = find(p_splitter, from); + if (end < 0) { + end = len; + } + } + if (p_allow_empty || (end > from)) { + if (p_maxsplit <= 0) { + ret.push_back(substr(from, end - from)); + } else { + // Put rest of the string and leave cycle. + if (p_maxsplit == ret.size()) { + ret.push_back(substr(from, len)); + break; + } + + // Otherwise, push items until positive limit is reached. + ret.push_back(substr(from, end - from)); + } + } + + if (end == len) { + break; + } + + from = end + strlen(p_splitter); + } + + return ret; +} + Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { Vector<String> ret; const int len = length(); @@ -1380,6 +1489,49 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int return ret; } +Vector<String> String::rsplit(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const { + Vector<String> ret; + const int len = length(); + const int splitter_length = strlen(p_splitter); + int remaining_len = len; + + while (true) { + if (remaining_len < splitter_length || (p_maxsplit > 0 && p_maxsplit == ret.size())) { + // no room for another splitter or hit max splits, push what's left and we're done + if (p_allow_empty || remaining_len > 0) { + ret.push_back(substr(0, remaining_len)); + } + break; + } + + int left_edge; + if (p_splitter == nullptr || *p_splitter == '\0') { + left_edge = remaining_len - 1; + if (left_edge == 0) { + left_edge--; // Skip to the < 0 condition. + } + } else { + left_edge = rfind(p_splitter, remaining_len - splitter_length); + } + + if (left_edge < 0) { + // no more splitters, we're done + ret.push_back(substr(0, remaining_len)); + break; + } + + int substr_start = left_edge + splitter_length; + if (p_allow_empty || substr_start < remaining_len) { + ret.push_back(substr(substr_start, remaining_len - substr_start)); + } + + remaining_len = left_edge; + } + + ret.reverse(); + return ret; +} + Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const { Vector<double> ret; int from = 0; @@ -3087,23 +3239,20 @@ int String::find(const String &p_str, int p_from) const { } int String::find(const char *p_str, int p_from) const { - if (p_from < 0) { + if (p_from < 0 || !p_str) { return -1; } + const int src_len = strlen(p_str); + const int len = length(); - if (len == 0) { + if (len == 0 || src_len == 0) { return -1; // won't find anything! } const char32_t *src = get_data(); - int src_len = 0; - while (p_str[src_len] != '\0') { - src_len++; - } - if (src_len == 1) { const char32_t needle = p_str[0]; @@ -3238,6 +3387,46 @@ int String::findn(const String &p_str, int p_from) const { return -1; } +int String::findn(const char *p_str, int p_from) const { + if (p_from < 0) { + return -1; + } + + int src_len = strlen(p_str); + + if (src_len == 0 || length() == 0) { + return -1; // won't find anything! + } + + const char32_t *srcd = get_data(); + + for (int i = p_from; i <= (length() - src_len); i++) { + bool found = true; + for (int j = 0; j < src_len; j++) { + int read_pos = i + j; + + if (read_pos >= length()) { + ERR_PRINT("read_pos>=length()"); + return -1; + } + + char32_t src = _find_lower(srcd[read_pos]); + char32_t dst = _find_lower(p_str[j]); + + if (src != dst) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + int String::rfind(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); @@ -3285,6 +3474,57 @@ int String::rfind(const String &p_str, int p_from) const { return -1; } +int String::rfind(const char *p_str, int p_from) const { + const int source_length = length(); + int substring_length = strlen(p_str); + + if (source_length == 0 || substring_length == 0) { + return -1; // won't find anything! + } + + // establish a limit + int limit = length() - substring_length; + if (limit < 0) { + return -1; + } + + // establish a starting point + int starting_point; + if (p_from < 0) { + starting_point = limit; + } else if (p_from > limit) { + starting_point = limit; + } else { + starting_point = p_from; + } + + const char32_t *source = get_data(); + + for (int i = starting_point; i >= 0; i--) { + bool found = true; + for (int j = 0; j < substring_length; j++) { + int read_pos = i + j; + + if (read_pos >= source_length) { + ERR_PRINT("read_pos>=source_length"); + return -1; + } + + const char32_t key_needle = p_str[j]; + if (source[read_pos] != key_needle) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + int String::rfindn(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); @@ -3335,6 +3575,60 @@ int String::rfindn(const String &p_str, int p_from) const { return -1; } +int String::rfindn(const char *p_str, int p_from) const { + const int source_length = length(); + int substring_length = strlen(p_str); + + if (source_length == 0 || substring_length == 0) { + return -1; // won't find anything! + } + + // establish a limit + int limit = length() - substring_length; + if (limit < 0) { + return -1; + } + + // establish a starting point + int starting_point; + if (p_from < 0) { + starting_point = limit; + } else if (p_from > limit) { + starting_point = limit; + } else { + starting_point = p_from; + } + + const char32_t *source = get_data(); + + for (int i = starting_point; i >= 0; i--) { + bool found = true; + for (int j = 0; j < substring_length; j++) { + int read_pos = i + j; + + if (read_pos >= source_length) { + ERR_PRINT("read_pos>=source_length"); + return -1; + } + + const char32_t key_needle = p_str[j]; + int srcc = _find_lower(source[read_pos]); + int keyc = _find_lower(key_needle); + + if (srcc != keyc) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + bool String::ends_with(const String &p_string) const { int l = p_string.length(); if (l > length()) { @@ -3357,6 +3651,31 @@ bool String::ends_with(const String &p_string) const { return true; } +bool String::ends_with(const char *p_string) const { + if (!p_string) { + return false; + } + + int l = strlen(p_string); + if (l > length()) { + return false; + } + + if (l == 0) { + return true; + } + + const char32_t *s = &operator[](length() - l); + + for (int i = 0; i < l; i++) { + if (static_cast<char32_t>(p_string[i]) != s[i]) { + return false; + } + } + + return true; +} + bool String::begins_with(const String &p_string) const { int l = p_string.length(); if (l > length()) { @@ -3380,11 +3699,11 @@ bool String::begins_with(const String &p_string) const { } bool String::begins_with(const char *p_string) const { - int l = length(); if (!p_string) { return false; } + int l = length(); if (l == 0) { return *p_string == 0; } @@ -3456,14 +3775,61 @@ int String::_count(const String &p_string, int p_from, int p_to, bool p_case_ins return c; } +int String::_count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const { + int substring_length = strlen(p_string); + if (substring_length == 0) { + return 0; + } + const int source_length = length(); + + if (source_length < substring_length) { + return 0; + } + String str; + int search_limit = p_to; + if (p_from >= 0 && p_to >= 0) { + if (p_to == 0) { + search_limit = source_length; + } else if (p_from >= p_to) { + return 0; + } + if (p_from == 0 && search_limit == source_length) { + str = String(); + str.copy_from_unchecked(&get_data()[0], source_length); + } else { + str = substr(p_from, search_limit - p_from); + } + } else { + return 0; + } + int c = 0; + int idx = -1; + do { + idx = p_case_insensitive ? str.findn(p_string) : str.find(p_string); + if (idx != -1) { + str = str.substr(idx + substring_length, str.length() - substring_length); + ++c; + } + } while (idx != -1); + return c; +} + int String::count(const String &p_string, int p_from, int p_to) const { return _count(p_string, p_from, p_to, false); } +int String::count(const char *p_string, int p_from, int p_to) const { + return _count(p_string, p_from, p_to, false); +} + int String::countn(const String &p_string, int p_from, int p_to) const { return _count(p_string, p_from, p_to, true); } +int String::countn(const char *p_string, int p_from, int p_to) const { + return _count(p_string, p_from, p_to, true); +} + bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const { int len = length(); if (len == 0) { @@ -3598,7 +3964,7 @@ String String::format(const Variant &values, const String &placeholder) const { Variant v_val = values_arr[i]; String val = v_val; - if (placeholder.find("_") > -1) { + if (placeholder.contains("_")) { new_string = new_string.replace(placeholder.replace("_", i_as_str), val); } else { new_string = new_string.replace_first(placeholder, val); @@ -3673,6 +4039,16 @@ String String::replace_first(const String &p_key, const String &p_with) const { return *this; } +String String::replace_first(const char *p_key, const char *p_with) const { + int pos = find(p_key); + if (pos >= 0) { + int substring_length = strlen(p_key); + return substr(0, pos) + p_with + substr(pos + substring_length, length()); + } + + return *this; +} + String String::replacen(const String &p_key, const String &p_with) const { String new_string; int search_from = 0; @@ -3692,6 +4068,31 @@ String String::replacen(const String &p_key, const String &p_with) const { return new_string; } +String String::replacen(const char *p_key, const char *p_with) const { + String new_string; + int search_from = 0; + int result = 0; + int substring_length = strlen(p_key); + + if (substring_length == 0) { + return *this; // there's nothing to match or substitute + } + + while ((result = findn(p_key, search_from)) >= 0) { + new_string += substr(search_from, result - search_from); + new_string += p_with; + search_from = result + substring_length; + } + + if (search_from == 0) { + return *this; + } + + new_string += substr(search_from, length() - search_from); + + return new_string; +} + String String::repeat(int p_count) const { ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number."); @@ -4420,6 +4821,15 @@ String String::trim_prefix(const String &p_prefix) const { return s; } +String String::trim_prefix(const char *p_prefix) const { + String s = *this; + if (s.begins_with(p_prefix)) { + int prefix_length = strlen(p_prefix); + return s.substr(prefix_length, s.length() - prefix_length); + } + return s; +} + String String::trim_suffix(const String &p_suffix) const { String s = *this; if (s.ends_with(p_suffix)) { @@ -4428,6 +4838,14 @@ String String::trim_suffix(const String &p_suffix) const { return s; } +String String::trim_suffix(const char *p_suffix) const { + String s = *this; + if (s.ends_with(p_suffix)) { + return s.substr(0, s.length() - strlen(p_suffix)); + } + return s; +} + bool String::is_valid_int() const { int len = length(); diff --git a/core/string/ustring.h b/core/string/ustring.h index 693df6dcba..9df2d56e80 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -198,6 +198,7 @@ class String { bool _base_is_subsequence_of(const String &p_string, bool case_insensitive) const; int _count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const; + int _count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const; String _camelcase_to_underscore() const; public: @@ -288,14 +289,18 @@ public: int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed int find_char(const char32_t &p_char, int p_from = 0) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive + int findn(const char *p_str, int p_from = 0) const; ///< return <0 if failed int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed + int rfind(const char *p_str, int p_from = -1) const; ///< return <0 if failed int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive + int rfindn(const char *p_str, int p_from = -1) const; ///< return <0 if failed int findmk(const Vector<String> &p_keys, int p_from = 0, int *r_key = nullptr) const; ///< return <0 if failed bool match(const String &p_wildcard) const; bool matchn(const String &p_wildcard) const; bool begins_with(const String &p_string) const; bool begins_with(const char *p_string) const; bool ends_with(const String &p_string) const; + bool ends_with(const char *p_string) const; bool is_enclosed_in(const String &p_string) const; bool is_subsequence_of(const String &p_string) const; bool is_subsequence_ofn(const String &p_string) const; @@ -304,9 +309,11 @@ public: float similarity(const String &p_string) const; String format(const Variant &values, const String &placeholder = "{_}") const; String replace_first(const String &p_key, const String &p_with) const; + String replace_first(const char *p_key, const char *p_with) const; String replace(const String &p_key, const String &p_with) const; String replace(const char *p_key, const char *p_with) const; String replacen(const String &p_key, const String &p_with) const; + String replacen(const char *p_key, const char *p_with) const; String repeat(int p_count) const; String reverse() const; String insert(int p_at_pos, const String &p_string) const; @@ -314,7 +321,9 @@ public: String pad_decimals(int p_digits) const; String pad_zeros(int p_digits) const; String trim_prefix(const String &p_prefix) const; + String trim_prefix(const char *p_prefix) const; String trim_suffix(const String &p_suffix) const; + String trim_suffix(const char *p_suffix) const; String lpad(int min_length, const String &character = " ") const; String rpad(int min_length, const String &character = " ") const; String sprintf(const Array &values, bool *error) const; @@ -353,11 +362,15 @@ public: String get_with_code_lines() const; int get_slice_count(const String &p_splitter) const; + int get_slice_count(const char *p_splitter) const; String get_slice(const String &p_splitter, int p_slice) const; + String get_slice(const char *p_splitter, int p_slice) const; String get_slicec(char32_t p_splitter, int p_slice) const; Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> split(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> rsplit(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split_spaces() const; Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; @@ -372,7 +385,9 @@ public: String to_lower() const; int count(const String &p_string, int p_from = 0, int p_to = 0) const; + int count(const char *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; + int countn(const char *p_string, int p_from = 0, int p_to = 0) const; String left(int p_len) const; String right(int p_len) const; @@ -414,6 +429,8 @@ public: _FORCE_INLINE_ bool is_empty() const { return length() == 0; } _FORCE_INLINE_ bool contains(const char *p_str) const { return find(p_str) != -1; } _FORCE_INLINE_ bool contains(const String &p_str) const { return find(p_str) != -1; } + _FORCE_INLINE_ bool containsn(const char *p_str) const { return findn(p_str) != -1; } + _FORCE_INLINE_ bool containsn(const String &p_str) const { return findn(p_str) != -1; } // path functions bool is_absolute_path() const; diff --git a/core/templates/command_queue_mt.cpp b/core/templates/command_queue_mt.cpp index d9e5e0b217..ef75a70868 100644 --- a/core/templates/command_queue_mt.cpp +++ b/core/templates/command_queue_mt.cpp @@ -42,6 +42,7 @@ void CommandQueueMT::unlock() { } CommandQueueMT::CommandQueueMT() { + command_mem.reserve(DEFAULT_COMMAND_MEM_SIZE_KB * 1024); } CommandQueueMT::~CommandQueueMT() { diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h index c149861467..349404d75b 100644 --- a/core/templates/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -208,7 +208,7 @@ #define ARG(N) p##N #define PARAM(N) P##N p##N #define TYPE_PARAM(N) typename P##N -#define PARAM_DECL(N) typename GetSimpleTypeT<P##N>::type_t p##N +#define PARAM_DECL(N) GetSimpleTypeT<P##N> p##N #define DECL_CMD(N) \ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \ @@ -302,7 +302,7 @@ class CommandQueueMT { struct CommandBase { bool sync = false; virtual void call() = 0; - virtual ~CommandBase() = default; // Won't be called. + virtual ~CommandBase() = default; }; struct SyncCommand : public CommandBase { @@ -325,16 +325,14 @@ class CommandQueueMT { /***** BASE *******/ - enum { - DEFAULT_COMMAND_MEM_SIZE_KB = 256, - SYNC_SEMAPHORES = 8 - }; + static const uint32_t DEFAULT_COMMAND_MEM_SIZE_KB = 64; BinaryMutex mutex; LocalVector<uint8_t> command_mem; ConditionVariable sync_cond_var; uint32_t sync_head = 0; uint32_t sync_tail = 0; + uint32_t sync_awaiters = 0; WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID; uint64_t flush_read_ptr = 0; @@ -349,6 +347,15 @@ class CommandQueueMT { return cmd; } + _FORCE_INLINE_ void _prevent_sync_wraparound() { + bool safe_to_reset = !sync_awaiters; + bool already_sync_to_latest = sync_head == sync_tail; + if (safe_to_reset && already_sync_to_latest) { + sync_head = 0; + sync_tail = 0; + } + } + void _flush() { if (unlikely(flush_read_ptr)) { // Re-entrant call. @@ -365,25 +372,39 @@ class CommandQueueMT { cmd->call(); if (unlikely(cmd->sync)) { sync_head++; + unlock(); // Give an opportunity to awaiters right away. sync_cond_var.notify_all(); + lock(); } + // If the command involved reallocating the buffer, the address may have changed. + cmd = reinterpret_cast<CommandBase *>(&command_mem[flush_read_ptr]); + cmd->~CommandBase(); + flush_read_ptr += size; } WorkerThreadPool::thread_exit_command_queue_mt_flush(); command_mem.clear(); flush_read_ptr = 0; + + _prevent_sync_wraparound(); + unlock(); } _FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) { + sync_awaiters++; uint32_t sync_head_goal = sync_tail; do { sync_cond_var.wait(p_lock); - } while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound. + } while (sync_head < sync_head_goal); + sync_awaiters--; + _prevent_sync_wraparound(); } + void _no_op() {} + public: void lock(); void unlock(); @@ -405,10 +426,15 @@ public: _flush(); } } + void flush_all() { _flush(); } + void sync() { + push_and_sync(this, &CommandQueueMT::_no_op); + } + void wait_and_flush() { ERR_FAIL_COND(pump_task_id == WorkerThreadPool::INVALID_TASK_ID); WorkerThreadPool::get_singleton()->wait_for_task_completion(pump_task_id); @@ -416,7 +442,9 @@ public: } void set_pump_task_id(WorkerThreadPool::TaskID p_task_id) { + lock(); pump_task_id = p_task_id; + unlock(); } CommandQueueMT(); diff --git a/core/templates/list.h b/core/templates/list.h index b4d4beb930..6663f06c30 100644 --- a/core/templates/list.h +++ b/core/templates/list.h @@ -139,54 +139,58 @@ public: typedef T ValueType; - struct Iterator { - _FORCE_INLINE_ T &operator*() const { + struct ConstIterator { + _FORCE_INLINE_ const T &operator*() const { return E->get(); } - _FORCE_INLINE_ T *operator->() const { return &E->get(); } - _FORCE_INLINE_ Iterator &operator++() { + _FORCE_INLINE_ const T *operator->() const { return &E->get(); } + _FORCE_INLINE_ ConstIterator &operator++() { E = E->next(); return *this; } - _FORCE_INLINE_ Iterator &operator--() { + _FORCE_INLINE_ ConstIterator &operator--() { E = E->prev(); return *this; } - _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } - Iterator(Element *p_E) { E = p_E; } - Iterator() {} - Iterator(const Iterator &p_it) { E = p_it.E; } + _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; } + _FORCE_INLINE_ ConstIterator() {} + _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; } private: - Element *E = nullptr; + const Element *E = nullptr; }; - struct ConstIterator { - _FORCE_INLINE_ const T &operator*() const { + struct Iterator { + _FORCE_INLINE_ T &operator*() const { return E->get(); } - _FORCE_INLINE_ const T *operator->() const { return &E->get(); } - _FORCE_INLINE_ ConstIterator &operator++() { + _FORCE_INLINE_ T *operator->() const { return &E->get(); } + _FORCE_INLINE_ Iterator &operator++() { E = E->next(); return *this; } - _FORCE_INLINE_ ConstIterator &operator--() { + _FORCE_INLINE_ Iterator &operator--() { E = E->prev(); return *this; } - _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } - _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; } - _FORCE_INLINE_ ConstIterator() {} - _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; } + Iterator(Element *p_E) { E = p_E; } + Iterator() {} + Iterator(const Iterator &p_it) { E = p_it.E; } + + operator ConstIterator() const { + return ConstIterator(E); + } private: - const Element *E = nullptr; + Element *E = nullptr; }; _FORCE_INLINE_ Iterator begin() { @@ -519,7 +523,9 @@ public: } } - T &operator[](int p_index) { + // Random access to elements, use with care, + // do not use for iteration. + T &get(int p_index) { CRASH_BAD_INDEX(p_index, size()); Element *I = front(); @@ -532,7 +538,9 @@ public: return I->get(); } - const T &operator[](int p_index) const { + // Random access to elements, use with care, + // do not use for iteration. + const T &get(int p_index) const { CRASH_BAD_INDEX(p_index, size()); const Element *I = front(); diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h index e0047e0782..c281d70d92 100644 --- a/core/templates/local_vector.h +++ b/core/templates/local_vector.h @@ -264,6 +264,10 @@ public: return -1; } + bool has(const T &p_val) const { + return find(p_val) != -1; + } + template <typename C> void sort_custom() { U len = count; diff --git a/core/templates/simple_type.h b/core/templates/simple_type.h index b2ae0110e2..197115ddb9 100644 --- a/core/templates/simple_type.h +++ b/core/templates/simple_type.h @@ -31,26 +31,9 @@ #ifndef SIMPLE_TYPE_H #define SIMPLE_TYPE_H -/* Batch of specializations to obtain the actual simple type */ +#include <type_traits> template <typename T> -struct GetSimpleTypeT { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T &> { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T const> { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T const &> { - typedef T type_t; -}; +using GetSimpleTypeT = typename std::remove_cv_t<std::remove_reference_t<T>>; #endif // SIMPLE_TYPE_H diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 0fe4518b0f..61b90e2a26 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -362,42 +362,42 @@ void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void template <typename T, typename... P, size_t... Is> void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { - (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename... P, size_t... Is> void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence<Is...>) { - (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename... P, size_t... Is> void call_with_validated_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, IndexSequence<Is...>) { - p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + p_method(p_instance, (VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename R, typename... P, size_t... Is> void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, p_method((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename... P, size_t... Is> void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { - p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + p_method((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename... P> diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index c8d1241d3d..1e10709b12 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -152,6 +152,7 @@ MAKE_PTRARG(PackedStringArray); MAKE_PTRARG(PackedVector2Array); MAKE_PTRARG(PackedVector3Array); MAKE_PTRARG(PackedColorArray); +MAKE_PTRARG(PackedVector4Array); MAKE_PTRARG_BY_REFERENCE(Variant); // This is for Object. diff --git a/core/variant/type_info.h b/core/variant/type_info.h index 15cb6c9c1a..d51c80eebe 100644 --- a/core/variant/type_info.h +++ b/core/variant/type_info.h @@ -142,6 +142,7 @@ MAKE_TYPE_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY) MAKE_TYPE_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPE_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPE_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY) +MAKE_TYPE_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) MAKE_TYPE_INFO(IPAddress, Variant::STRING) diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h index 0befd19864..e00947ed1e 100644 --- a/core/variant/typed_array.h +++ b/core/variant/typed_array.h @@ -134,6 +134,7 @@ MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY) MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY) +MAKE_TYPED_ARRAY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) MAKE_TYPED_ARRAY(IPAddress, Variant::STRING) template <typename T> @@ -235,6 +236,7 @@ MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY) MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING) #undef MAKE_TYPED_ARRAY diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 37eb16f9b2..8be00b1358 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -167,6 +167,9 @@ String Variant::get_type_name(Variant::Type p_type) { case PACKED_COLOR_ARRAY: { return "PackedColorArray"; } + case PACKED_VECTOR4_ARRAY: { + return "PackedVector4Array"; + } default: { } } @@ -404,6 +407,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { PACKED_COLOR_ARRAY, PACKED_VECTOR2_ARRAY, PACKED_VECTOR3_ARRAY, + PACKED_VECTOR4_ARRAY, NIL }; @@ -480,6 +484,14 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; + case PACKED_VECTOR4_ARRAY: { + static const Type valid[] = { + ARRAY, + NIL + }; + valid_types = valid; + + } break; default: { } } @@ -738,6 +750,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type PACKED_COLOR_ARRAY, PACKED_VECTOR2_ARRAY, PACKED_VECTOR3_ARRAY, + PACKED_VECTOR4_ARRAY, NIL }; @@ -814,6 +827,14 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; + case PACKED_VECTOR4_ARRAY: { + static const Type valid[] = { + ARRAY, + NIL + }; + valid_types = valid; + + } break; default: { } } @@ -980,6 +1001,9 @@ bool Variant::is_zero() const { case PACKED_COLOR_ARRAY: { return PackedArrayRef<Color>::get_array(_data.packed_array).size() == 0; } + case PACKED_VECTOR4_ARRAY: { + return PackedArrayRef<Vector4>::get_array(_data.packed_array).size() == 0; + } default: { } } @@ -1236,6 +1260,12 @@ void Variant::reference(const Variant &p_variant) { _data.packed_array = PackedArrayRef<Color>::create(); } } break; + case PACKED_VECTOR4_ARRAY: { + _data.packed_array = static_cast<PackedArrayRef<Vector4> *>(p_variant._data.packed_array)->reference(); + if (!_data.packed_array) { + _data.packed_array = PackedArrayRef<Vector4>::create(); + } + } break; default: { } } @@ -1410,9 +1440,12 @@ void Variant::_clear_internal() { case PACKED_COLOR_ARRAY: { PackedArrayRefBase::destroy(_data.packed_array); } break; + case PACKED_VECTOR4_ARRAY: { + PackedArrayRefBase::destroy(_data.packed_array); + } break; default: { // Not needed, there is no point. The following do not allocate memory: - // VECTOR2, VECTOR3, RECT2, PLANE, QUATERNION, COLOR. + // VECTOR2, VECTOR3, VECTOR4, RECT2, PLANE, QUATERNION, COLOR. } } } @@ -1759,6 +1792,9 @@ String Variant::stringify(int recursion_count) const { case PACKED_COLOR_ARRAY: { return stringify_vector(operator PackedColorArray(), recursion_count); } + case PACKED_VECTOR4_ARRAY: { + return stringify_vector(operator PackedVector4Array(), recursion_count); + } case PACKED_STRING_ARRAY: { return stringify_vector(operator PackedStringArray(), recursion_count); } @@ -2085,7 +2121,7 @@ Variant::operator ::RID() const { } #endif Callable::CallError ce; - Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce); + Variant ret = _get_obj().obj->callp(CoreStringName(get_rid), nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) { return ret; } @@ -2191,6 +2227,9 @@ inline DA _convert_array_from_variant(const Variant &p_variant) { case Variant::PACKED_COLOR_ARRAY: { return _convert_array<DA, PackedColorArray>(p_variant.operator PackedColorArray()); } + case Variant::PACKED_VECTOR4_ARRAY: { + return _convert_array<DA, PackedVector4Array>(p_variant.operator PackedVector4Array()); + } default: { return DA(); } @@ -2277,6 +2316,14 @@ Variant::operator PackedColorArray() const { } } +Variant::operator PackedVector4Array() const { + if (type == PACKED_VECTOR4_ARRAY) { + return static_cast<PackedArrayRef<Vector4> *>(_data.packed_array)->array; + } else { + return _convert_array_from_variant<PackedVector4Array>(*this); + } +} + /* helpers */ Variant::operator Vector<::RID>() const { @@ -2635,6 +2682,11 @@ Variant::Variant(const PackedColorArray &p_color_array) : _data.packed_array = PackedArrayRef<Color>::create(p_color_array); } +Variant::Variant(const PackedVector4Array &p_vector4_array) : + type(PACKED_VECTOR4_ARRAY) { + _data.packed_array = PackedArrayRef<Vector4>::create(p_vector4_array); +} + /* helpers */ Variant::Variant(const Vector<::RID> &p_array) : type(ARRAY) { @@ -2853,6 +2905,9 @@ void Variant::operator=(const Variant &p_variant) { case PACKED_COLOR_ARRAY: { _data.packed_array = PackedArrayRef<Color>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; + case PACKED_VECTOR4_ARRAY: { + _data.packed_array = PackedArrayRef<Vector4>::reference_from(_data.packed_array, p_variant._data.packed_array); + } break; default: { } } @@ -3175,6 +3230,25 @@ uint32_t Variant::recursive_hash(int recursion_count) const { return hash; } break; + case PACKED_VECTOR4_ARRAY: { + uint32_t hash = HASH_MURMUR3_SEED; + const PackedVector4Array &arr = PackedArrayRef<Vector4>::get_array(_data.packed_array); + int len = arr.size(); + + if (likely(len)) { + const Vector4 *r = arr.ptr(); + + for (int i = 0; i < len; i++) { + hash = hash_murmur3_one_real(r[i].x, hash); + hash = hash_murmur3_one_real(r[i].y, hash); + hash = hash_murmur3_one_real(r[i].z, hash); + hash = hash_murmur3_one_real(r[i].w, hash); + } + hash = hash_fmix32(hash); + } + + return hash; + } break; default: { } } @@ -3430,6 +3504,10 @@ bool Variant::hash_compare(const Variant &p_variant, int recursion_count, bool s hash_compare_packed_array(_data.packed_array, p_variant._data.packed_array, Color, hash_compare_color); } break; + case PACKED_VECTOR4_ARRAY: { + hash_compare_packed_array(_data.packed_array, p_variant._data.packed_array, Vector4, hash_compare_vector4); + } break; + default: bool v; Variant r; @@ -3468,7 +3546,8 @@ bool Variant::identity_compare(const Variant &p_variant) const { case PACKED_STRING_ARRAY: case PACKED_VECTOR2_ARRAY: case PACKED_VECTOR3_ARRAY: - case PACKED_COLOR_ARRAY: { + case PACKED_COLOR_ARRAY: + case PACKED_VECTOR4_ARRAY: { return _data.packed_array == p_variant._data.packed_array; } break; diff --git a/core/variant/variant.h b/core/variant/variant.h index 93953c4e0e..821edcfedf 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -75,6 +75,7 @@ typedef Vector<String> PackedStringArray; typedef Vector<Vector2> PackedVector2Array; typedef Vector<Vector3> PackedVector3Array; typedef Vector<Color> PackedColorArray; +typedef Vector<Vector4> PackedVector4Array; class Variant { public: @@ -126,6 +127,7 @@ public: PACKED_VECTOR2_ARRAY, PACKED_VECTOR3_ARRAY, PACKED_COLOR_ARRAY, + PACKED_VECTOR4_ARRAY, VARIANT_MAX }; @@ -297,6 +299,7 @@ private: true, //PACKED_VECTOR2_ARRAY, true, //PACKED_VECTOR3_ARRAY, true, //PACKED_COLOR_ARRAY, + true, //PACKED_VECTOR4_ARRAY, }; if (unlikely(needs_deinit[type])) { // Make it fast for types that don't need deinit. @@ -409,6 +412,7 @@ public: operator PackedVector3Array() const; operator PackedVector2Array() const; operator PackedColorArray() const; + operator PackedVector4Array() const; operator Vector<::RID>() const; operator Vector<Plane>() const; @@ -474,6 +478,7 @@ public: Variant(const PackedVector2Array &p_vector2_array); Variant(const PackedVector3Array &p_vector3_array); Variant(const PackedColorArray &p_color_array); + Variant(const PackedVector4Array &p_vector4_array); Variant(const Vector<::RID> &p_array); // helper Variant(const Vector<Plane> &p_array); // helper diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 4f510d1baa..9b7777f480 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1648,19 +1648,19 @@ static void _register_variant_builtin_methods() { bind_string_method(filenocasecmp_to, sarray("to"), varray()); bind_string_method(length, sarray(), varray()); bind_string_method(substr, sarray("from", "len"), varray(-1)); - bind_string_method(get_slice, sarray("delimiter", "slice"), varray()); + bind_string_methodv(get_slice, static_cast<String (String::*)(const String &, int) const>(&String::get_slice), sarray("delimiter", "slice"), varray()); bind_string_method(get_slicec, sarray("delimiter", "slice"), varray()); - bind_string_method(get_slice_count, sarray("delimiter"), varray()); + bind_string_methodv(get_slice_count, static_cast<int (String::*)(const String &) const>(&String::get_slice_count), sarray("delimiter"), varray()); bind_string_methodv(find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0)); - bind_string_method(count, sarray("what", "from", "to"), varray(0, 0)); - bind_string_method(countn, sarray("what", "from", "to"), varray(0, 0)); - bind_string_method(findn, sarray("what", "from"), varray(0)); - bind_string_method(rfind, sarray("what", "from"), varray(-1)); - bind_string_method(rfindn, sarray("what", "from"), varray(-1)); + bind_string_methodv(findn, static_cast<int (String::*)(const String &, int) const>(&String::findn), sarray("what", "from"), varray(0)); + bind_string_methodv(count, static_cast<int (String::*)(const String &, int, int) const>(&String::count), sarray("what", "from", "to"), varray(0, 0)); + bind_string_methodv(countn, static_cast<int (String::*)(const String &, int, int) const>(&String::countn), sarray("what", "from", "to"), varray(0, 0)); + bind_string_methodv(rfind, static_cast<int (String::*)(const String &, int) const>(&String::rfind), sarray("what", "from"), varray(-1)); + bind_string_methodv(rfindn, static_cast<int (String::*)(const String &, int) const>(&String::rfindn), sarray("what", "from"), varray(-1)); bind_string_method(match, sarray("expr"), varray()); bind_string_method(matchn, sarray("expr"), varray()); bind_string_methodv(begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray()); - bind_string_method(ends_with, sarray("text"), varray()); + bind_string_methodv(ends_with, static_cast<bool (String::*)(const String &) const>(&String::ends_with), sarray("text"), varray()); bind_string_method(is_subsequence_of, sarray("text"), varray()); bind_string_method(is_subsequence_ofn, sarray("text"), varray()); bind_string_method(bigrams, sarray(), varray()); @@ -1668,7 +1668,7 @@ static void _register_variant_builtin_methods() { bind_string_method(format, sarray("values", "placeholder"), varray("{_}")); bind_string_methodv(replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray()); - bind_string_method(replacen, sarray("what", "forwhat"), varray()); + bind_string_methodv(replacen, static_cast<String (String::*)(const String &, const String &) const>(&String::replacen), sarray("what", "forwhat"), varray()); bind_string_method(repeat, sarray("count"), varray()); bind_string_method(reverse, sarray(), varray()); bind_string_method(insert, sarray("position", "what"), varray()); @@ -1677,8 +1677,8 @@ static void _register_variant_builtin_methods() { bind_string_method(to_camel_case, sarray(), varray()); bind_string_method(to_pascal_case, sarray(), varray()); bind_string_method(to_snake_case, sarray(), varray()); - bind_string_method(split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); - bind_string_method(rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_methodv(split, static_cast<Vector<String> (String::*)(const String &, bool, int) const>(&String::split), sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_methodv(rsplit, static_cast<Vector<String> (String::*)(const String &, bool, int) const>(&String::rsplit), sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); bind_string_method(split_floats, sarray("delimiter", "allow_empty"), varray(true)); bind_string_method(join, sarray("parts"), varray()); @@ -1707,6 +1707,7 @@ static void _register_variant_builtin_methods() { bind_string_method(sha256_buffer, sarray(), varray()); bind_string_method(is_empty, sarray(), varray()); bind_string_methodv(contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray()); + bind_string_methodv(containsn, static_cast<bool (String::*)(const String &) const>(&String::containsn), sarray("what"), varray()); bind_string_method(is_absolute_path, sarray(), varray()); bind_string_method(is_relative_path, sarray(), varray()); @@ -1741,8 +1742,8 @@ static void _register_variant_builtin_methods() { bind_string_method(rpad, sarray("min_length", "character"), varray(" ")); bind_string_method(pad_decimals, sarray("digits"), varray()); bind_string_method(pad_zeros, sarray("digits"), varray()); - bind_string_method(trim_prefix, sarray("prefix"), varray()); - bind_string_method(trim_suffix, sarray("suffix"), varray()); + bind_string_methodv(trim_prefix, static_cast<String (String::*)(const String &) const>(&String::trim_prefix), sarray("prefix"), varray()); + bind_string_methodv(trim_suffix, static_cast<String (String::*)(const String &) const>(&String::trim_suffix), sarray("suffix"), varray()); bind_string_method(to_ascii_buffer, sarray(), varray()); bind_string_method(to_utf8_buffer, sarray(), varray()); @@ -1804,7 +1805,13 @@ static void _register_variant_builtin_methods() { bind_method(Vector2, abs, sarray(), varray()); bind_method(Vector2, sign, sarray(), varray()); bind_method(Vector2, clamp, sarray("min", "max"), varray()); + bind_method(Vector2, clampf, sarray("min", "max"), varray()); bind_method(Vector2, snapped, sarray("step"), varray()); + bind_method(Vector2, snappedf, sarray("step"), varray()); + bind_method(Vector2, min, sarray("with"), varray()); + bind_method(Vector2, minf, sarray("with"), varray()); + bind_method(Vector2, max, sarray("with"), varray()); + bind_method(Vector2, maxf, sarray("with"), varray()); bind_static_method(Vector2, from_angle, sarray("angle"), varray()); @@ -1820,7 +1827,13 @@ static void _register_variant_builtin_methods() { bind_method(Vector2i, sign, sarray(), varray()); bind_method(Vector2i, abs, sarray(), varray()); bind_method(Vector2i, clamp, sarray("min", "max"), varray()); + bind_method(Vector2i, clampi, sarray("min", "max"), varray()); bind_method(Vector2i, snapped, sarray("step"), varray()); + bind_method(Vector2i, snappedi, sarray("step"), varray()); + bind_method(Vector2i, min, sarray("with"), varray()); + bind_method(Vector2i, mini, sarray("with"), varray()); + bind_method(Vector2i, max, sarray("with"), varray()); + bind_method(Vector2i, maxi, sarray("with"), varray()); /* Rect2 */ @@ -1875,7 +1888,9 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, is_finite, sarray(), varray()); bind_method(Vector3, inverse, sarray(), varray()); bind_method(Vector3, clamp, sarray("min", "max"), varray()); + bind_method(Vector3, clampf, sarray("min", "max"), varray()); bind_method(Vector3, snapped, sarray("step"), varray()); + bind_method(Vector3, snappedf, sarray("step"), varray()); bind_method(Vector3, rotated, sarray("axis", "angle"), varray()); bind_method(Vector3, lerp, sarray("to", "weight"), varray()); bind_method(Vector3, slerp, sarray("to", "weight"), varray()); @@ -1899,6 +1914,10 @@ static void _register_variant_builtin_methods() { bind_method(Vector3, reflect, sarray("n"), varray()); bind_method(Vector3, sign, sarray(), varray()); bind_method(Vector3, octahedron_encode, sarray(), varray()); + bind_method(Vector3, min, sarray("with"), varray()); + bind_method(Vector3, minf, sarray("with"), varray()); + bind_method(Vector3, max, sarray("with"), varray()); + bind_method(Vector3, maxf, sarray("with"), varray()); bind_static_method(Vector3, octahedron_decode, sarray("uv"), varray()); /* Vector3i */ @@ -1912,7 +1931,13 @@ static void _register_variant_builtin_methods() { bind_method(Vector3i, sign, sarray(), varray()); bind_method(Vector3i, abs, sarray(), varray()); bind_method(Vector3i, clamp, sarray("min", "max"), varray()); + bind_method(Vector3i, clampi, sarray("min", "max"), varray()); bind_method(Vector3i, snapped, sarray("step"), varray()); + bind_method(Vector3i, snappedi, sarray("step"), varray()); + bind_method(Vector3i, min, sarray("with"), varray()); + bind_method(Vector3i, mini, sarray("with"), varray()); + bind_method(Vector3i, max, sarray("with"), varray()); + bind_method(Vector3i, maxi, sarray("with"), varray()); /* Vector4 */ @@ -1931,7 +1956,9 @@ static void _register_variant_builtin_methods() { bind_method(Vector4, posmod, sarray("mod"), varray()); bind_method(Vector4, posmodv, sarray("modv"), varray()); bind_method(Vector4, snapped, sarray("step"), varray()); + bind_method(Vector4, snappedf, sarray("step"), varray()); bind_method(Vector4, clamp, sarray("min", "max"), varray()); + bind_method(Vector4, clampf, sarray("min", "max"), varray()); bind_method(Vector4, normalized, sarray(), varray()); bind_method(Vector4, is_normalized, sarray(), varray()); bind_method(Vector4, direction_to, sarray("to"), varray()); @@ -1942,6 +1969,10 @@ static void _register_variant_builtin_methods() { bind_method(Vector4, is_equal_approx, sarray("to"), varray()); bind_method(Vector4, is_zero_approx, sarray(), varray()); bind_method(Vector4, is_finite, sarray(), varray()); + bind_method(Vector4, min, sarray("with"), varray()); + bind_method(Vector4, minf, sarray("with"), varray()); + bind_method(Vector4, max, sarray("with"), varray()); + bind_method(Vector4, maxf, sarray("with"), varray()); /* Vector4i */ @@ -1952,7 +1983,13 @@ static void _register_variant_builtin_methods() { bind_method(Vector4i, sign, sarray(), varray()); bind_method(Vector4i, abs, sarray(), varray()); bind_method(Vector4i, clamp, sarray("min", "max"), varray()); + bind_method(Vector4i, clampi, sarray("min", "max"), varray()); bind_method(Vector4i, snapped, sarray("step"), varray()); + bind_method(Vector4i, snappedi, sarray("step"), varray()); + bind_method(Vector4i, min, sarray("with"), varray()); + bind_method(Vector4i, mini, sarray("with"), varray()); + bind_method(Vector4i, max, sarray("with"), varray()); + bind_method(Vector4i, maxi, sarray("with"), varray()); bind_method(Vector4i, distance_to, sarray("to"), varray()); bind_method(Vector4i, distance_squared_to, sarray("to"), varray()); @@ -2532,6 +2569,30 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, rfind, sarray("value", "from"), varray(-1)); bind_method(PackedColorArray, count, sarray("value"), varray()); + /* Vector4 Array */ + + bind_method(PackedVector4Array, size, sarray(), varray()); + bind_method(PackedVector4Array, is_empty, sarray(), varray()); + bind_method(PackedVector4Array, set, sarray("index", "value"), varray()); + bind_method(PackedVector4Array, push_back, sarray("value"), varray()); + bind_method(PackedVector4Array, append, sarray("value"), varray()); + bind_method(PackedVector4Array, append_array, sarray("array"), varray()); + bind_method(PackedVector4Array, remove_at, sarray("index"), varray()); + bind_method(PackedVector4Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedVector4Array, fill, sarray("value"), varray()); + bind_methodv(PackedVector4Array, resize, &PackedVector4Array::resize_zeroed, sarray("new_size"), varray()); + bind_method(PackedVector4Array, clear, sarray(), varray()); + bind_method(PackedVector4Array, has, sarray("value"), varray()); + bind_method(PackedVector4Array, reverse, sarray(), varray()); + bind_method(PackedVector4Array, slice, sarray("begin", "end"), varray(INT_MAX)); + bind_method(PackedVector4Array, to_byte_array, sarray(), varray()); + bind_method(PackedVector4Array, sort, sarray(), varray()); + bind_method(PackedVector4Array, bsearch, sarray("value", "before"), varray(true)); + bind_method(PackedVector4Array, duplicate, sarray(), varray()); + bind_method(PackedVector4Array, find, sarray("value", "from"), varray(0)); + bind_method(PackedVector4Array, rfind, sarray("value", "from"), varray(-1)); + bind_method(PackedVector4Array, count, sarray("value"), varray()); + /* Register constants */ int ncc = Color::get_named_color_count(); diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp index b0ed49be5d..1edae407c2 100644 --- a/core/variant/variant_construct.cpp +++ b/core/variant/variant_construct.cpp @@ -211,6 +211,7 @@ void Variant::_register_variant_constructors() { add_constructor<VariantConstructorToArray<PackedVector2Array>>(sarray("from")); add_constructor<VariantConstructorToArray<PackedVector3Array>>(sarray("from")); add_constructor<VariantConstructorToArray<PackedColorArray>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedVector4Array>>(sarray("from")); add_constructor<VariantConstructNoArgs<PackedByteArray>>(sarray()); add_constructor<VariantConstructor<PackedByteArray, PackedByteArray>>(sarray("from")); @@ -247,6 +248,10 @@ void Variant::_register_variant_constructors() { add_constructor<VariantConstructNoArgs<PackedColorArray>>(sarray()); add_constructor<VariantConstructor<PackedColorArray, PackedColorArray>>(sarray("from")); add_constructor<VariantConstructorFromArray<PackedColorArray>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedVector4Array>>(sarray()); + add_constructor<VariantConstructor<PackedVector4Array, PackedVector4Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedVector4Array>>(sarray("from")); } void Variant::_unregister_variant_constructors() { diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h index a93723a910..82995620aa 100644 --- a/core/variant/variant_construct.h +++ b/core/variant/variant_construct.h @@ -97,6 +97,7 @@ MAKE_PTRCONSTRUCT(PackedStringArray); MAKE_PTRCONSTRUCT(PackedVector2Array); MAKE_PTRCONSTRUCT(PackedVector3Array); MAKE_PTRCONSTRUCT(PackedColorArray); +MAKE_PTRCONSTRUCT(PackedVector4Array); MAKE_PTRCONSTRUCT(Variant); template <typename T, typename... P> diff --git a/core/variant/variant_destruct.cpp b/core/variant/variant_destruct.cpp index c7455d5117..409f4bd07b 100644 --- a/core/variant/variant_destruct.cpp +++ b/core/variant/variant_destruct.cpp @@ -56,6 +56,7 @@ void Variant::_register_variant_destructors() { add_destructor<VariantDestruct<PackedVector2Array>>(); add_destructor<VariantDestruct<PackedVector3Array>>(); add_destructor<VariantDestruct<PackedColorArray>>(); + add_destructor<VariantDestruct<PackedVector4Array>>(); } void Variant::_unregister_variant_destructors() { diff --git a/core/variant/variant_destruct.h b/core/variant/variant_destruct.h index c496189c6d..d91d99b02e 100644 --- a/core/variant/variant_destruct.h +++ b/core/variant/variant_destruct.h @@ -65,6 +65,7 @@ MAKE_PTRDESTRUCT(PackedStringArray); MAKE_PTRDESTRUCT(PackedVector2Array); MAKE_PTRDESTRUCT(PackedVector3Array); MAKE_PTRDESTRUCT(PackedColorArray); +MAKE_PTRDESTRUCT(PackedVector4Array); #undef MAKE_PTRDESTRUCT diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index dbd4a6a7ad..c52ab6917b 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -114,6 +114,9 @@ public: case Variant::PACKED_COLOR_ARRAY: init_color_array(v); break; + case Variant::PACKED_VECTOR4_ARRAY: + init_vector4_array(v); + break; case Variant::OBJECT: init_object(v); break; @@ -205,6 +208,8 @@ public: _FORCE_INLINE_ static const PackedVector3Array *get_vector3_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector3> *>(v->_data.packed_array)->array; } _FORCE_INLINE_ static PackedColorArray *get_color_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } _FORCE_INLINE_ static const PackedColorArray *get_color_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedVector4Array *get_vector4_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Vector4> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedVector4Array *get_vector4_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector4> *>(v->_data.packed_array)->array; } _FORCE_INLINE_ static Object **get_object(Variant *v) { return (Object **)&v->_get_obj().obj; } _FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)&v->_get_obj().obj; } @@ -313,6 +318,10 @@ public: v->_data.packed_array = Variant::PackedArrayRef<Color>::create(Vector<Color>()); v->type = Variant::PACKED_COLOR_ARRAY; } + _FORCE_INLINE_ static void init_vector4_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<Vector4>::create(Vector<Vector4>()); + v->type = Variant::PACKED_VECTOR4_ARRAY; + } _FORCE_INLINE_ static void init_object(Variant *v) { object_assign_null(v); v->type = Variant::OBJECT; @@ -417,6 +426,8 @@ public: return get_vector3_array(v); case Variant::PACKED_COLOR_ARRAY: return get_color_array(v); + case Variant::PACKED_VECTOR4_ARRAY: + return get_vector4_array(v); case Variant::OBJECT: return get_object(v); case Variant::VARIANT_MAX: @@ -501,6 +512,8 @@ public: return get_vector3_array(v); case Variant::PACKED_COLOR_ARRAY: return get_color_array(v); + case Variant::PACKED_VECTOR4_ARRAY: + return get_vector4_array(v); case Variant::OBJECT: return get_object(v); case Variant::VARIANT_MAX: @@ -797,6 +810,12 @@ struct VariantGetInternalPtr<PackedColorArray> { static const PackedColorArray *get_ptr(const Variant *v) { return VariantInternal::get_color_array(v); } }; +template <> +struct VariantGetInternalPtr<PackedVector4Array> { + static PackedVector4Array *get_ptr(Variant *v) { return VariantInternal::get_vector4_array(v); } + static const PackedVector4Array *get_ptr(const Variant *v) { return VariantInternal::get_vector4_array(v); } +}; + template <typename T> struct VariantInternalAccessor { }; @@ -1058,6 +1077,12 @@ struct VariantInternalAccessor<PackedColorArray> { }; template <> +struct VariantInternalAccessor<PackedVector4Array> { + static _FORCE_INLINE_ const PackedVector4Array &get(const Variant *v) { return *VariantInternal::get_vector4_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedVector4Array &p_value) { *VariantInternal::get_vector4_array(v) = p_value; } +}; + +template <> struct VariantInternalAccessor<Object *> { static _FORCE_INLINE_ Object *get(const Variant *v) { return const_cast<Object *>(*VariantInternal::get_object(v)); } static _FORCE_INLINE_ void set(Variant *v, const Object *p_value) { VariantInternal::object_assign(v, p_value); } @@ -1297,6 +1322,11 @@ struct VariantInitializer<PackedColorArray> { }; template <> +struct VariantInitializer<PackedVector4Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector4_array(v); } +}; + +template <> struct VariantInitializer<Object *> { static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_object(v); } }; @@ -1490,6 +1520,11 @@ struct VariantDefaultInitializer<PackedColorArray> { static _FORCE_INLINE_ void init(Variant *v) { *VariantInternal::get_color_array(v) = PackedColorArray(); } }; +template <> +struct VariantDefaultInitializer<PackedVector4Array> { + static _FORCE_INLINE_ void init(Variant *v) { *VariantInternal::get_vector4_array(v) = PackedVector4Array(); } +}; + template <typename T> struct VariantTypeChanger { static _FORCE_INLINE_ void change(Variant *v) { @@ -1511,7 +1546,7 @@ struct VariantTypeChanger { template <typename T> struct VariantTypeAdjust { _FORCE_INLINE_ static void adjust(Variant *r_ret) { - VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret); + VariantTypeChanger<GetSimpleTypeT<T>>::change(r_ret); } }; diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index dcf4b287d1..d2c1cde970 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -274,6 +274,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAppendArray<Vector2>>(Variant::OP_ADD, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorAppendArray<Vector3>>(Variant::OP_ADD, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorAppendArray<Color>>(Variant::OP_ADD, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorAppendArray<Vector4>>(Variant::OP_ADD, Variant::PACKED_VECTOR4_ARRAY, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorSub<int64_t, int64_t, int64_t>>(Variant::OP_SUBTRACT, Variant::INT, Variant::INT); register_op<OperatorEvaluatorSub<double, int64_t, double>>(Variant::OP_SUBTRACT, Variant::INT, Variant::FLOAT); @@ -480,6 +481,7 @@ void Variant::_register_variant_operators() { register_string_modulo_op(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY); register_string_modulo_op(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY); register_string_modulo_op(PackedColorArray, Variant::PACKED_COLOR_ARRAY); + register_string_modulo_op(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT); register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT); @@ -561,6 +563,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorEqual<PackedVector2Array, PackedVector2Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorEqual<PackedColorArray, PackedColorArray>>(Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorEqual<PackedVector4Array, PackedVector4Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::BOOL, Variant::NIL>>(Variant::OP_EQUAL, Variant::BOOL, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::INT, Variant::NIL>>(Variant::OP_EQUAL, Variant::INT, Variant::NIL); @@ -598,6 +601,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::NIL>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::BOOL>>(Variant::OP_EQUAL, Variant::NIL, Variant::BOOL); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::INT>>(Variant::OP_EQUAL, Variant::NIL, Variant::INT); @@ -635,6 +639,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR4_ARRAY>>(Variant::OP_EQUAL, Variant::NIL, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL); register_op<OperatorEvaluatorNotEqual<bool, bool>>(Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::BOOL); @@ -680,6 +685,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNotEqual<PackedVector2Array, PackedVector2Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorNotEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorNotEqual<PackedColorArray, PackedColorArray>>(Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedVector4Array, PackedVector4Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::INT, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::NIL); @@ -717,6 +723,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::NIL); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR4_ARRAY, Variant::NIL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BOOL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::BOOL); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::INT>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::INT); @@ -754,6 +761,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR3_ARRAY); register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR4_ARRAY>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorLess<bool, bool>>(Variant::OP_LESS, Variant::BOOL, Variant::BOOL); register_op<OperatorEvaluatorLess<int64_t, int64_t>>(Variant::OP_LESS, Variant::INT, Variant::INT); @@ -944,6 +952,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNot<PackedVector2Array>>(Variant::OP_NOT, Variant::PACKED_VECTOR2_ARRAY, Variant::NIL); register_op<OperatorEvaluatorNot<PackedVector3Array>>(Variant::OP_NOT, Variant::PACKED_VECTOR3_ARRAY, Variant::NIL); register_op<OperatorEvaluatorNot<PackedColorArray>>(Variant::OP_NOT, Variant::PACKED_COLOR_ARRAY, Variant::NIL); + register_op<OperatorEvaluatorNot<PackedVector4Array>>(Variant::OP_NOT, Variant::PACKED_VECTOR4_ARRAY, Variant::NIL); register_string_op(OperatorEvaluatorInStringFind, Variant::OP_IN); @@ -986,6 +995,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInDictionaryHas<PackedVector2Array>>(Variant::OP_IN, Variant::PACKED_VECTOR2_ARRAY, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<PackedVector3Array>>(Variant::OP_IN, Variant::PACKED_VECTOR3_ARRAY, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<PackedColorArray>>(Variant::OP_IN, Variant::PACKED_COLOR_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedVector4Array>>(Variant::OP_IN, Variant::PACKED_VECTOR4_ARRAY, Variant::DICTIONARY); register_op<OperatorEvaluatorInArrayFindNil>(Variant::OP_IN, Variant::NIL, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<bool, Array>>(Variant::OP_IN, Variant::BOOL, Variant::ARRAY); @@ -1026,6 +1036,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInArrayFind<PackedVector2Array, Array>>(Variant::OP_IN, Variant::PACKED_VECTOR2_ARRAY, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<PackedVector3Array, Array>>(Variant::OP_IN, Variant::PACKED_VECTOR3_ARRAY, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<PackedColorArray, Array>>(Variant::OP_IN, Variant::PACKED_COLOR_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedVector4Array, Array>>(Variant::OP_IN, Variant::PACKED_VECTOR4_ARRAY, Variant::ARRAY); register_op<OperatorEvaluatorInArrayFind<int, PackedByteArray>>(Variant::OP_IN, Variant::INT, Variant::PACKED_BYTE_ARRAY); register_op<OperatorEvaluatorInArrayFind<float, PackedByteArray>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_BYTE_ARRAY); @@ -1047,8 +1058,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorInArrayFind<Vector2, PackedVector2Array>>(Variant::OP_IN, Variant::VECTOR2, Variant::PACKED_VECTOR2_ARRAY); register_op<OperatorEvaluatorInArrayFind<Vector3, PackedVector3Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::PACKED_VECTOR3_ARRAY); - register_op<OperatorEvaluatorInArrayFind<Color, PackedColorArray>>(Variant::OP_IN, Variant::COLOR, Variant::PACKED_COLOR_ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector4, PackedVector4Array>>(Variant::OP_IN, Variant::VECTOR4, Variant::PACKED_VECTOR4_ARRAY); register_op<OperatorEvaluatorObjectHasPropertyString>(Variant::OP_IN, Variant::STRING, Variant::OBJECT); register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT); diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 50f8007efa..9a0dd712ed 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1395,6 +1395,24 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; + } else if (id == "PackedVector4Array" || id == "PoolVector4Array" || id == "Vector4Array") { + Vector<real_t> args; + Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str); + if (err) { + return err; + } + + Vector<Vector4> arr; + { + int len = args.size() / 4; + arr.resize(len); + Vector4 *w = arr.ptrw(); + for (int i = 0; i < len; i++) { + w[i] = Vector4(args[i * 4 + 0], args[i * 4 + 1], args[i * 4 + 2], args[i * 4 + 3]); + } + } + + value = arr; } else if (id == "PackedColorArray" || id == "PoolColorArray" || id == "ColorArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); @@ -2248,6 +2266,21 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, ")"); } break; + case Variant::PACKED_VECTOR4_ARRAY: { + p_store_string_func(p_store_string_ud, "PackedVector4Array("); + Vector<Vector4> data = p_variant; + int len = data.size(); + const Vector4 *ptr = data.ptr(); + + for (int i = 0; i < len; i++) { + if (i > 0) { + p_store_string_func(p_store_string_ud, ", "); + } + p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].x) + ", " + rtos_fix(ptr[i].y) + ", " + rtos_fix(ptr[i].z) + ", " + rtos_fix(ptr[i].w)); + } + + p_store_string_func(p_store_string_ud, ")"); + } break; default: { ERR_PRINT("Unknown variant type"); diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index f49e9e54b3..48176163a1 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -856,6 +856,7 @@ INDEXED_SETGET_STRUCT_TYPED(PackedVector2Array, Vector2) INDEXED_SETGET_STRUCT_TYPED(PackedVector3Array, Vector3) INDEXED_SETGET_STRUCT_TYPED(PackedStringArray, String) INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color) +INDEXED_SETGET_STRUCT_TYPED(PackedVector4Array, Vector4) INDEXED_SETGET_STRUCT_DICT(Dictionary) @@ -923,6 +924,7 @@ void register_indexed_setters_getters() { REGISTER_INDEXED_MEMBER(PackedVector3Array); REGISTER_INDEXED_MEMBER(PackedStringArray); REGISTER_INDEXED_MEMBER(PackedColorArray); + REGISTER_INDEXED_MEMBER(PackedVector4Array); REGISTER_INDEXED_MEMBER(Array); REGISTER_INDEXED_MEMBER(Dictionary); @@ -1382,7 +1384,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { ref.push_back(r_iter); Variant vref = ref; const Variant *refp[] = { &vref }; - Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce); + Variant ret = _get_obj().obj->callp(CoreStringName(_iter_init), refp, 1, ce); if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { valid = false; @@ -1498,6 +1500,14 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return true; } break; + case PACKED_VECTOR4_ARRAY: { + const Vector<Vector4> *arr = &PackedArrayRef<Vector4>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + } break; default: { } } @@ -1609,7 +1619,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { ref.push_back(r_iter); Variant vref = ref; const Variant *refp[] = { &vref }; - Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce); + Variant ret = _get_obj().obj->callp(CoreStringName(_iter_next), refp, 1, ce); if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { valid = false; @@ -1747,6 +1757,16 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { r_iter = idx; return true; } break; + case PACKED_VECTOR4_ARRAY: { + const Vector<Vector4> *arr = &PackedArrayRef<Vector4>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; default: { } } @@ -1791,7 +1811,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { Callable::CallError ce; ce.error = Callable::CallError::CALL_OK; const Variant *refp[] = { &r_iter }; - Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce); + Variant ret = _get_obj().obj->callp(CoreStringName(_iter_get), refp, 1, ce); if (ce.error != Callable::CallError::CALL_OK) { r_valid = false; @@ -1921,6 +1941,17 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { #endif return arr->get(idx); } break; + case PACKED_VECTOR4_ARRAY: { + const Vector<Vector4> *arr = &PackedArrayRef<Vector4>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; default: { } } @@ -1968,6 +1999,8 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const { return operator Vector<Vector3>().duplicate(); case PACKED_COLOR_ARRAY: return operator Vector<Color>().duplicate(); + case PACKED_VECTOR4_ARRAY: + return operator Vector<Vector4>().duplicate(); default: return *this; } diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 916ba7aa2f..5522b5ba88 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -917,6 +917,8 @@ Variant VariantUtilityFunctions::type_convert(const Variant &p_variant, const Va return p_variant.operator PackedVector3Array(); case Variant::Type::PACKED_COLOR_ARRAY: return p_variant.operator PackedColorArray(); + case Variant::Type::PACKED_VECTOR4_ARRAY: + return p_variant.operator PackedVector4Array(); case Variant::Type::VARIANT_MAX: ERR_PRINT("Invalid type argument to type_convert(), use the TYPE_* constants. Returning the unconverted Variant."); } |