diff options
Diffstat (limited to 'core')
26 files changed, 204 insertions, 214 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 57833fe42f..562cbbdd27 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -49,12 +49,11 @@ ProjectSettings *ProjectSettings::get_singleton() { } String ProjectSettings::get_project_data_dir_name() const { - return ".godot"; + return project_data_dir_name; } String ProjectSettings::get_project_data_path() const { - String project_data_dir_name = get_project_data_dir_name(); - return "res://" + project_data_dir_name; + return "res://" + get_project_data_dir_name(); } String ProjectSettings::get_resource_path() const { @@ -520,6 +519,10 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo _load_settings_text(custom_settings); } } + + // Updating the default value after the project settings have loaded. + project_data_dir_name = GLOBAL_GET("application/config/project_data_dir_name"); + // Using GLOBAL_GET on every block for compressing can be slow, so assigning here. Compression::zstd_long_distance_matching = GLOBAL_GET("compression/formats/zstd/long_distance_matching"); Compression::zstd_level = GLOBAL_GET("compression/formats/zstd/compression_level"); @@ -1091,6 +1094,7 @@ ProjectSettings::ProjectSettings() { custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res"); GLOBAL_DEF("application/run/disable_stdout", false); GLOBAL_DEF("application/run/disable_stderr", false); + project_data_dir_name = GLOBAL_DEF_RST("application/config/project_data_dir_name", ".godot"); GLOBAL_DEF("application/config/use_custom_user_dir", false); GLOBAL_DEF("application/config/custom_user_dir_name", ""); GLOBAL_DEF("application/config/project_settings_override", ""); diff --git a/core/config/project_settings.h b/core/config/project_settings.h index b642051402..82f04b94df 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -93,6 +93,8 @@ protected: OrderedHashMap<StringName, AutoloadInfo> autoloads; + String project_data_dir_name; + bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; diff --git a/core/core_bind.cpp b/core/core_bind.cpp index f630adc39e..e11d9ab9c1 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1771,6 +1771,7 @@ void Thread::_start_func(void *ud) { Object *target_instance = t->target_callable.get_object(); if (!target_instance) { + t->running.clear(); ERR_FAIL_MSG(vformat("Could not call function '%s' on previously freed instance to start thread %s.", t->target_callable.get_method(), t->get_id())); } @@ -1813,19 +1814,22 @@ void Thread::_start_func(void *ud) { t->target_callable.call(arg, argc, t->ret, ce); if (ce.error != Callable::CallError::CALL_OK) { + t->running.clear(); ERR_FAIL_MSG("Could not call function '" + t->target_callable.get_method().operator String() + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, arg, argc, ce) + "."); } + + t->running.clear(); } Error Thread::start(const Callable &p_callable, const Variant &p_userdata, Priority p_priority) { - ERR_FAIL_COND_V_MSG(active.is_set(), ERR_ALREADY_IN_USE, "Thread already started."); + ERR_FAIL_COND_V_MSG(is_started(), ERR_ALREADY_IN_USE, "Thread already started."); ERR_FAIL_COND_V(p_callable.is_null(), ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_priority, PRIORITY_MAX, ERR_INVALID_PARAMETER); ret = Variant(); target_callable = p_callable; userdata = p_userdata; - active.set(); + running.set(); Ref<Thread> *ud = memnew(Ref<Thread>(this)); @@ -1840,15 +1844,18 @@ String Thread::get_id() const { return itos(thread.get_id()); } -bool Thread::is_active() const { - return active.is_set(); +bool Thread::is_started() const { + return thread.is_started(); +} + +bool Thread::is_alive() const { + return running.is_set(); } Variant Thread::wait_to_finish() { - ERR_FAIL_COND_V_MSG(!active.is_set(), Variant(), "Thread must be active to wait for its completion."); + ERR_FAIL_COND_V_MSG(!is_started(), Variant(), "Thread must have been started to wait for its completion."); thread.wait_to_finish(); Variant r = ret; - active.clear(); target_callable = Callable(); userdata = Variant(); @@ -1858,7 +1865,8 @@ Variant Thread::wait_to_finish() { void Thread::_bind_methods() { ClassDB::bind_method(D_METHOD("start", "callable", "userdata", "priority"), &Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL)); ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id); - ClassDB::bind_method(D_METHOD("is_active"), &Thread::is_active); + ClassDB::bind_method(D_METHOD("is_started"), &Thread::is_started); + ClassDB::bind_method(D_METHOD("is_alive"), &Thread::is_alive); ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish); BIND_ENUM_CONSTANT(PRIORITY_LOW); diff --git a/core/core_bind.h b/core/core_bind.h index 84a284f948..4eab085dda 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -538,7 +538,7 @@ class Thread : public RefCounted { protected: Variant ret; Variant userdata; - SafeFlag active; + SafeFlag running; Callable target_callable; ::Thread thread; static void _bind_methods(); @@ -554,7 +554,8 @@ public: Error start(const Callable &p_callable, const Variant &p_userdata = Variant(), Priority p_priority = PRIORITY_NORMAL); String get_id() const; - bool is_active() const; + bool is_started() const; + bool is_alive() const; Variant wait_to_finish(); }; diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 73f78bde54..8f8cb5a3e0 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -182,11 +182,11 @@ typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_in typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference); -struct GDNativeInstanceBindingCallbacks { +typedef struct { GDNativeInstanceBindingCreateCallback create_callback; GDNativeInstanceBindingFreeCallback free_callback; GDNativeInstanceBindingReferenceCallback reference_callback; -}; +} GDNativeInstanceBindingCallbacks; /* EXTENSION CLASSES */ diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index e54c947340..df631053b8 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -233,7 +233,7 @@ uint64_t FileAccessCompressed::get_position() const { if (writing) { return write_pos; } else { - return read_block * block_size + read_pos; + return (uint64_t)read_block * block_size + read_pos; } } diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index b5c882e9ce..53bf7456e6 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -99,7 +99,7 @@ static int godot_testerror(voidpf opaque, voidpf stream) { } static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { - return memalloc(items * size); + return memalloc((size_t)items * size); } static void godot_free(voidpf opaque, voidpf address) { diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index fb4c76aa7a..24808cc8d6 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -100,7 +100,7 @@ int zipio_testerror(voidpf opaque, voidpf stream) { } voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) { - voidpf ptr = memalloc(items * size); + voidpf ptr = memalloc((size_t)items * size); memset(ptr, 0, items * size); return ptr; } diff --git a/core/math/bvh.h b/core/math/bvh.h index cefbc9b0db..65b8b102a3 100644 --- a/core/math/bvh.h +++ b/core/math/bvh.h @@ -200,7 +200,7 @@ public: // use in conjunction with activate if you have deferred the collision check, and // set pairable has never been called. - // (deferred collision checks are a workaround for visual server for historical reasons) + // (deferred collision checks are a workaround for rendering server for historical reasons) void force_collision_check(BVHHandle p_handle) { if (USE_PAIRS) { // the aabb should already be up to date in the BVH diff --git a/core/multiplayer/multiplayer.h b/core/multiplayer/multiplayer.h index 31b7bf0043..be398f02c8 100644 --- a/core/multiplayer/multiplayer.h +++ b/core/multiplayer/multiplayer.h @@ -52,7 +52,7 @@ enum RPCMode { struct RPCConfig { StringName name; RPCMode rpc_mode = RPC_MODE_DISABLED; - bool sync = false; + bool call_local = false; TransferMode transfer_mode = TRANSFER_MODE_RELIABLE; int channel = 0; diff --git a/core/multiplayer/multiplayer_replicator.cpp b/core/multiplayer/multiplayer_replicator.cpp index a4ea74327c..6604510394 100644 --- a/core/multiplayer/multiplayer_replicator.cpp +++ b/core/multiplayer/multiplayer_replicator.cpp @@ -572,7 +572,7 @@ Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object * args[0] = p_peer; args[1] = p_scene_id; args[2] = p_obj; - args[3] = true; + args[3] = p_spawn; const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] }; Callable::CallError ce; Variant ret; diff --git a/core/multiplayer/rpc_manager.cpp b/core/multiplayer/rpc_manager.cpp index 20ab7a25bb..d8e875c3e6 100644 --- a/core/multiplayer/rpc_manager.cpp +++ b/core/multiplayer/rpc_manager.cpp @@ -476,9 +476,9 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c vformat("Unable to get the RPC configuration for the function \"%s\" at path: \"%s\". This happens when the method is not marked for RPCs.", p_method, p_node->get_path())); if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { if (rpc_id & (1 << 15)) { - call_local_native = config.sync; + call_local_native = config.call_local; } else { - call_local_script = config.sync; + call_local_script = config.call_local; } } @@ -521,5 +521,5 @@ void RPCManager::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, c } } - ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.sync, "RPC '" + p_method + "' on yourself is not allowed by selected mode."); + ERR_FAIL_COND_MSG(p_peer_id == node_id && !config.call_local, "RPC '" + p_method + "' on yourself is not allowed by selected mode."); } diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index d5509c50f1..4b3c8b123f 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -37,8 +37,6 @@ #define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock); #define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock); -#ifdef DEBUG_METHODS_ENABLED - MethodDefinition D_METHOD(const char *p_name) { MethodDefinition md; md.name = StaticCString::create(p_name); @@ -226,8 +224,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ return md; } -#endif - ClassDB::APIType ClassDB::current_api = API_CORE; void ClassDB::set_current_api(APIType p_api) { @@ -589,7 +585,6 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit } } -#ifdef DEBUG_METHODS_ENABLED static MethodInfo info_from_bind(MethodBind *p_method) { MethodInfo minfo; minfo.name = p_method->get_name(); @@ -610,7 +605,6 @@ static MethodInfo info_from_bind(MethodBind *p_method) { return minfo; } -#endif void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) { OBJTYPE_RLOCK; @@ -650,9 +644,8 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met while ((K = type->method_map.next(K))) { MethodBind *m = type->method_map[*K]; - MethodInfo mi; - mi.name = m->get_name(); - p_methods->push_back(mi); + MethodInfo minfo = info_from_bind(m); + p_methods->push_back(minfo); } #endif @@ -698,9 +691,8 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met if (type->method_map.has(p_method)) { if (r_info) { MethodBind *m = type->method_map[p_method]; - MethodInfo mi; - mi.name = m->get_name(); - *r_info = mi; + MethodInfo minfo = info_from_bind(m); + *r_info = minfo; } return true; } @@ -1411,13 +1403,8 @@ void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method type->method_map[p_method->get_name()] = p_method; } -#ifdef DEBUG_METHODS_ENABLED MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname = method_name.name; -#else -MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) { - StringName mdname = StaticCString::create(method_name); -#endif OBJTYPE_WLOCK; ERR_FAIL_COND_V(!p_bind, nullptr); diff --git a/core/object/class_db.h b/core/object/class_db.h index 3a1cbf8559..d9eec4e4a8 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -45,8 +45,6 @@ #define DEFVAL(m_defval) (m_defval) -#ifdef DEBUG_METHODS_ENABLED - struct MethodDefinition { StringName name; Vector<StringName> args; @@ -72,26 +70,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13); -#else - -//#define NO_VARIADIC_MACROS - -#ifdef NO_VARIADIC_MACROS - -static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) { - return m_name; -} - -#else - -// When DEBUG_METHODS_ENABLED is set this will let the engine know -// the argument names for easier debugging. -#define D_METHOD(m_c, ...) m_c - -#endif - -#endif - class ClassDB { public: enum APIType { @@ -156,11 +134,7 @@ public: static HashMap<StringName, StringName> resource_base_extensions; static HashMap<StringName, StringName> compat_classes; -#ifdef DEBUG_METHODS_ENABLED static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount); -#else - static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount); -#endif static APIType current_api; @@ -190,6 +164,7 @@ public: t->creation_func = &creator<T>; t->exposed = true; t->class_ptr = T::get_class_ptr_static(); + t->api = current_api; T::register_custom_data_to_otdb(); } @@ -201,6 +176,7 @@ public: ERR_FAIL_COND(!t); t->exposed = true; t->class_ptr = T::get_class_ptr_static(); + t->api = current_api; //nothing } @@ -221,6 +197,7 @@ public: t->creation_func = &_create_ptr_func<T>; t->exposed = true; t->class_ptr = T::get_class_ptr_static(); + t->api = current_api; T::register_custom_data_to_otdb(); } diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp index c53104fe3f..d1d8b075fe 100644 --- a/core/object/method_bind.cpp +++ b/core/object/method_bind.cpp @@ -63,12 +63,15 @@ uint32_t MethodBind::get_hash() const { return hash; } -#ifdef DEBUG_METHODS_ENABLED PropertyInfo MethodBind::get_argument_info(int p_argument) const { ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo()); PropertyInfo info = _gen_argument_type_info(p_argument); +#ifdef DEBUG_METHODS_ENABLED info.name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); +#else + info.name = String("arg" + itos(p_argument)); +#endif return info; } @@ -76,7 +79,6 @@ PropertyInfo MethodBind::get_return_info() const { return _gen_argument_type_info(-1); } -#endif void MethodBind::_set_const(bool p_const) { _const = p_const; } @@ -109,7 +111,6 @@ void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) { default_argument_count = default_arguments.size(); } -#ifdef DEBUG_METHODS_ENABLED void MethodBind::_generate_argument_types(int p_count) { set_argument_count(p_count); @@ -123,8 +124,6 @@ void MethodBind::_generate_argument_types(int p_count) { argument_types = argt; } -#endif - MethodBind::MethodBind() { static int last_id = 0; method_id = last_id++; diff --git a/core/object/method_bind.h b/core/object/method_bind.h index b0b379873e..ee003099a0 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -64,18 +64,16 @@ class MethodBind { bool _returns = false; protected: -#ifdef DEBUG_METHODS_ENABLED Variant::Type *argument_types = nullptr; +#ifdef DEBUG_METHODS_ENABLED Vector<StringName> arg_names; #endif void _set_const(bool p_const); void _set_returns(bool p_returns); -#ifdef DEBUG_METHODS_ENABLED virtual Variant::Type _gen_argument_type(int p_arg) const = 0; virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; void _generate_argument_types(int p_count); -#endif void set_argument_count(int p_count) { argument_count = p_count; } public: @@ -102,7 +100,6 @@ public: } } -#ifdef DEBUG_METHODS_ENABLED _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); return argument_types[p_argument + 1]; @@ -111,6 +108,7 @@ public: PropertyInfo get_argument_info(int p_argument) const; PropertyInfo get_return_info() const; +#ifdef DEBUG_METHODS_ENABLED void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise. Vector<StringName> get_argument_names() const; @@ -149,12 +147,9 @@ public: protected: NativeCall call_method = nullptr; -#ifdef DEBUG_METHODS_ENABLED MethodInfo arguments; -#endif public: -#ifdef DEBUG_METHODS_ENABLED virtual PropertyInfo _gen_argument_type_info(int p_arg) const { if (p_arg < 0) { return arguments.return_val; @@ -169,13 +164,10 @@ public: return _gen_argument_type_info(p_arg).type; } +#ifdef DEBUG_METHODS_ENABLED virtual GodotTypeInfo::Metadata get_argument_meta(int) const { return GodotTypeInfo::METADATA_NONE; } -#else - virtual Variant::Type _gen_argument_type(int p_arg) const { - return Variant::NIL; - } #endif virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { @@ -185,25 +177,29 @@ public: void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) { set_argument_count(p_info.arguments.size()); -#ifdef DEBUG_METHODS_ENABLED Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1); at[0] = p_info.return_val.type; if (p_info.arguments.size()) { +#ifdef DEBUG_METHODS_ENABLED Vector<StringName> names; names.resize(p_info.arguments.size()); +#endif for (int i = 0; i < p_info.arguments.size(); i++) { at[i + 1] = p_info.arguments[i].type; +#ifdef DEBUG_METHODS_ENABLED names.write[i] = p_info.arguments[i].name; +#endif } +#ifdef DEBUG_METHODS_ENABLED set_argument_names(names); +#endif } argument_types = at; arguments = p_info; if (p_return_nil_is_variant) { arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; } -#endif } virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { @@ -248,7 +244,6 @@ class MethodBindT : public MethodBind { void (MB_T::*method)(P...); protected: -#ifdef DEBUG_METHODS_ENABLED // GCC raises warnings in the case P = {} as the comparison is always false... #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -270,7 +265,6 @@ protected: call_get_argument_type_info<P...>(p_arg, pi); return pi; } -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -298,9 +292,7 @@ public: MethodBindT(void (MB_T::*p_method)(P...)) { method = p_method; -#ifdef DEBUG_METHODS_ENABLED _generate_argument_types(sizeof...(P)); -#endif set_argument_count(sizeof...(P)); } }; @@ -327,7 +319,6 @@ class MethodBindTC : public MethodBind { void (MB_T::*method)(P...) const; protected: -#ifdef DEBUG_METHODS_ENABLED // GCC raises warnings in the case P = {} as the comparison is always false... #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -349,7 +340,6 @@ protected: call_get_argument_type_info<P...>(p_arg, pi); return pi; } -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -378,9 +368,7 @@ public: MethodBindTC(void (MB_T::*p_method)(P...) const) { method = p_method; _set_const(true); -#ifdef DEBUG_METHODS_ENABLED _generate_argument_types(sizeof...(P)); -#endif set_argument_count(sizeof...(P)); } }; @@ -408,7 +396,6 @@ class MethodBindTR : public MethodBind { (P...); protected: -#ifdef DEBUG_METHODS_ENABLED // GCC raises warnings in the case P = {} as the comparison is always false... #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -434,7 +421,6 @@ protected: #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -468,9 +454,7 @@ public: MethodBindTR(R (MB_T::*p_method)(P...)) { method = p_method; _set_returns(true); -#ifdef DEBUG_METHODS_ENABLED _generate_argument_types(sizeof...(P)); -#endif set_argument_count(sizeof...(P)); } }; @@ -499,7 +483,6 @@ class MethodBindTRC : public MethodBind { (P...) const; protected: -#ifdef DEBUG_METHODS_ENABLED // GCC raises warnings in the case P = {} as the comparison is always false... #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -525,7 +508,6 @@ protected: #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif -#endif public: #ifdef DEBUG_METHODS_ENABLED @@ -560,9 +542,7 @@ public: method = p_method; _set_returns(true); _set_const(true); -#ifdef DEBUG_METHODS_ENABLED _generate_argument_types(sizeof...(P)); -#endif set_argument_count(sizeof...(P)); } }; diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp index b7d2bac96d..289caf5247 100644 --- a/core/object/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -32,6 +32,7 @@ #include "core/io/resource.h" #include "core/os/os.h" +#include "core/templates/local_vector.h" void UndoRedo::_discard_redo() { if (current_action == actions.size() - 1) { @@ -85,10 +86,17 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { current_action = actions.size() - 2; if (p_mode == MERGE_ENDS) { - // Clear all do ops from last action, and delete all object references - List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); + // Clear all do ops from last action if they are not forced kept + LocalVector<List<Operation>::Element *> to_remove; + for (List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); E; E = E->next()) { + if (!E->get().force_keep_in_merge_ends) { + to_remove.push_back(E); + } + } - while (E) { + for (unsigned int i = 0; i < to_remove.size(); i++) { + List<Operation>::Element *E = to_remove[i]; + // Delete all object references if (E->get().type == Operation::TYPE_REFERENCE) { Object *obj = ObjectDB::get_instance(E->get().object); @@ -96,27 +104,26 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { memdelete(obj); } } - - E = E->next(); - actions.write[current_action + 1].do_ops.pop_front(); + E->erase(); } } actions.write[actions.size() - 1].last_tick = ticks; - merge_mode = p_mode; merging = true; } else { Action new_action; new_action.name = p_name; new_action.last_tick = ticks; actions.push_back(new_action); - - merge_mode = MERGE_DISABLE; } + + merge_mode = p_mode; } action_level++; + + force_keep_in_merge_ends = false; } void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { @@ -146,7 +153,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -157,6 +164,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR } undo_op.type = Operation::TYPE_METHOD; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; undo_op.name = p_method; for (int i = 0; i < VARIANT_ARG_MAX; i++) { @@ -187,7 +195,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -198,6 +206,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, } undo_op.type = Operation::TYPE_PROPERTY; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; undo_op.name = p_property; undo_op.args[0] = p_value; actions.write[current_action + 1].undo_ops.push_back(undo_op); @@ -223,7 +232,7 @@ void UndoRedo::add_undo_reference(Object *p_object) { ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -234,9 +243,24 @@ void UndoRedo::add_undo_reference(Object *p_object) { } undo_op.type = Operation::TYPE_REFERENCE; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; actions.write[current_action + 1].undo_ops.push_back(undo_op); } +void UndoRedo::start_force_keep_in_merge_ends() { + ERR_FAIL_COND(action_level <= 0); + ERR_FAIL_COND((current_action + 1) >= actions.size()); + + force_keep_in_merge_ends = true; +} + +void UndoRedo::end_force_keep_in_merge_ends() { + ERR_FAIL_COND(action_level <= 0); + ERR_FAIL_COND((current_action + 1) >= actions.size()); + + force_keep_in_merge_ends = false; +} + void UndoRedo::_pop_history_tail() { _discard_redo(); @@ -538,6 +562,9 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference); ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference); + ClassDB::bind_method(D_METHOD("start_force_keep_in_merge_ends"), &UndoRedo::start_force_keep_in_merge_ends); + ClassDB::bind_method(D_METHOD("end_force_keep_in_merge_ends"), &UndoRedo::end_force_keep_in_merge_ends); + ClassDB::bind_method(D_METHOD("get_history_count"), &UndoRedo::get_history_count); ClassDB::bind_method(D_METHOD("get_current_action"), &UndoRedo::get_current_action); ClassDB::bind_method(D_METHOD("get_action_name", "id"), &UndoRedo::get_action_name); diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h index d1ce252d86..a757d154e2 100644 --- a/core/object/undo_redo.h +++ b/core/object/undo_redo.h @@ -61,6 +61,7 @@ private: }; Type type; + bool force_keep_in_merge_ends; Ref<RefCounted> ref; ObjectID object; StringName name; @@ -76,6 +77,7 @@ private: Vector<Action> actions; int current_action = -1; + bool force_keep_in_merge_ends = false; int action_level = 0; MergeMode merge_mode = MERGE_DISABLE; bool merging = false; @@ -109,6 +111,9 @@ public: void add_do_reference(Object *p_object); void add_undo_reference(Object *p_object); + void start_force_keep_in_merge_ends(); + void end_force_keep_in_merge_ends(); + bool is_committing_action() const; void commit_action(bool p_execute = true); diff --git a/core/templates/hash_map.h b/core/templates/hash_map.h index 1257b54449..b5bb0d7396 100644 --- a/core/templates/hash_map.h +++ b/core/templates/hash_map.h @@ -62,7 +62,9 @@ public: TKey key; TData data; - Pair() {} + Pair(const TKey &p_key) : + key(p_key), + data() {} Pair(const TKey &p_key, const TData &p_data) : key(p_key), data(p_data) { @@ -90,6 +92,11 @@ public: const TData &value() const { return pair.value(); } + + Element(const TKey &p_key) : + pair(p_key) {} + Element(const Element &p_other) : + pair(p_other.pair.key, p_other.pair.data) {} }; private: @@ -192,14 +199,12 @@ private: Element *create_element(const TKey &p_key) { /* if element doesn't exist, create it */ - Element *e = memnew(Element); + Element *e = memnew(Element(p_key)); ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory."); uint32_t hash = Hasher::hash(p_key); uint32_t index = hash & ((1 << hash_table_power) - 1); e->next = hash_table[index]; e->hash = hash; - e->pair.key = p_key; - e->pair.data = TData(); hash_table[index] = e; elements++; @@ -228,9 +233,7 @@ private: const Element *e = p_t.hash_table[i]; while (e) { - Element *le = memnew(Element); /* local element */ - - *le = *e; /* copy data */ + Element *le = memnew(Element(*e)); /* local element */ /* add to list and reassign pointers */ le->next = hash_table[i]; diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 3b2c837096..8592a1dc62 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -563,13 +563,11 @@ void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), con // GCC raises "parameter 'p_args' set but not used" when P = {}, // it's not clever enough to treat other P values as making this branch valid. -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #endif -#ifdef DEBUG_METHODS_ENABLED - template <class Q> void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) { if (p_arg == index) { @@ -608,6 +606,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) { (void)index; // Suppress GCC warning. } +#ifdef DEBUG_METHODS_ENABLED template <class Q> void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) { if (p_arg == index) { @@ -629,13 +628,6 @@ GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) { return md; } -#else - -template <class... P> -Variant::Type call_get_argument_type(int p_arg) { - return Variant::NIL; -} - #endif // DEBUG_METHODS_ENABLED ////////////////////// @@ -915,7 +907,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_ call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); } -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 0dbeb6e4cb..3214fc125d 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -1624,6 +1624,19 @@ Variant::operator String() const { return stringify(stack); } +template <class T> +String stringify_vector(const T &vec, List<const void *> &stack) { + String str("["); + for (int i = 0; i < vec.size(); i++) { + if (i > 0) { + str += ", "; + } + str = str + Variant(vec[i]).stringify(stack); + } + str += "]"; + return str; +} + String Variant::stringify(List<const void *> &stack) const { switch (type) { case NIL: @@ -1703,88 +1716,31 @@ String Variant::stringify(List<const void *> &stack) const { return str; } break; case PACKED_VECTOR2_ARRAY: { - Vector<Vector2> vec = operator Vector<Vector2>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + Variant(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<Vector2>(), stack); } break; case PACKED_VECTOR3_ARRAY: { - Vector<Vector3> vec = operator Vector<Vector3>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + Variant(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<Vector3>(), stack); + } break; + case PACKED_COLOR_ARRAY: { + return stringify_vector(operator Vector<Color>(), stack); } break; case PACKED_STRING_ARRAY: { - Vector<String> vec = operator Vector<String>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + vec[i]; - } - str += "]"; - return str; + return stringify_vector(operator Vector<String>(), stack); + } break; + case PACKED_BYTE_ARRAY: { + return stringify_vector(operator Vector<uint8_t>(), stack); } break; case PACKED_INT32_ARRAY: { - Vector<int32_t> vec = operator Vector<int32_t>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + itos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<int32_t>(), stack); } break; case PACKED_INT64_ARRAY: { - Vector<int64_t> vec = operator Vector<int64_t>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + itos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<int64_t>(), stack); } break; case PACKED_FLOAT32_ARRAY: { - Vector<float> vec = operator Vector<float>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + rtos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<float>(), stack); } break; case PACKED_FLOAT64_ARRAY: { - Vector<double> vec = operator Vector<double>(); - String str("["); - for (int i = 0; i < vec.size(); i++) { - if (i > 0) { - str += ", "; - } - str = str + rtos(vec[i]); - } - str += "]"; - return str; + return stringify_vector(operator Vector<double>(), stack); } break; case ARRAY: { Array arr = operator Array(); @@ -1793,16 +1749,8 @@ String Variant::stringify(List<const void *> &stack) const { } stack.push_back(arr.id()); - String str("["); - for (int i = 0; i < arr.size(); i++) { - if (i) { - str += ", "; - } - - str += arr[i].stringify(stack); - } + String str = stringify_vector(arr, stack); - str += "]"; stack.erase(arr.id()); return str; @@ -3145,10 +3093,18 @@ bool Variant::hash_compare(const Variant &p_variant) const { } switch (type) { + case INT: { + return _data._int == p_variant._data._int; + } break; + case FLOAT: { return hash_compare_scalar(_data._float, p_variant._data._float); } break; + case STRING: { + return *reinterpret_cast<const String *>(_data._mem) == *reinterpret_cast<const String *>(p_variant._data._mem); + } break; + case VECTOR2: { const Vector2 *l = reinterpret_cast<const Vector2 *>(_data._mem); const Vector2 *r = reinterpret_cast<const Vector2 *>(p_variant._data._mem); diff --git a/core/variant/variant.h b/core/variant/variant.h index 9ec131a1b8..d3f694e7ca 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -641,6 +641,7 @@ public: static UtilityFunctionType get_utility_function_type(const StringName &p_name); + static MethodInfo get_utility_function_info(const StringName &p_name); static int get_utility_function_argument_count(const StringName &p_name); static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg); static String get_utility_function_argument_name(const StringName &p_name, int p_arg); diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index b94588f480..b85ece338c 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -641,7 +641,10 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorNotFloat>(Variant::OP_NOT, Variant::FLOAT, Variant::NIL); register_op<OperatorEvaluatorNotObject>(Variant::OP_NOT, Variant::OBJECT, Variant::NIL); - register_op<OperatorEvaluatorInStringFind>(Variant::OP_IN, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorInStringFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorInStringFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING); + register_op<OperatorEvaluatorInStringNameFind<String>>(Variant::OP_IN, Variant::STRING, Variant::STRING_NAME); + register_op<OperatorEvaluatorInStringNameFind<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::STRING_NAME); register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY); register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY); diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index 3c9f849a4f..353524469a 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -1213,22 +1213,44 @@ public: //// +template <class Left> class OperatorEvaluatorInStringFind { public: static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { - const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left); const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right); *r_ret = str_b.find(str_a) != -1; r_valid = true; } static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { - const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left); + const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left); const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1; } static void ptr_evaluate(const void *left, const void *right, void *r_ret) { - PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret); + PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<Left>::convert(left)) != -1, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class Left> +class OperatorEvaluatorInStringNameFind { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(&p_left); + const String str_b = VariantGetInternalPtr<StringName>::get_ptr(&p_right)->operator String(); + + *r_ret = str_b.find(str_a) != -1; + r_valid = true; + } + static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Left &str_a = *VariantGetInternalPtr<Left>::get_ptr(left); + const String str_b = VariantGetInternalPtr<StringName>::get_ptr(right)->operator String(); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<StringName>::convert(right).operator String().find(PtrToArg<Left>::convert(left)) != -1, r_ret); } static Variant::Type get_return_type() { return Variant::BOOL; } }; diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index 3bba68d75e..4abb51ca7c 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -239,7 +239,8 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool *v = p_value; r_valid = true; } else { - r_valid = false; + VariantGetInternalPtr<Dictionary>::get_ptr(this)->operator[](p_member) = p_value; + r_valid = true; } } else { diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 55c1376031..666b582e39 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -1333,6 +1333,28 @@ Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName return bfi->type; } +MethodInfo Variant::get_utility_function_info(const StringName &p_name) { + MethodInfo info; + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (bfi) { + info.name = p_name; + if (bfi->returns_value && bfi->return_type == Variant::NIL) { + info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } + info.return_val.type = bfi->return_type; + if (bfi->is_vararg) { + info.flags |= METHOD_FLAG_VARARG; + } + for (int i = 0; i < bfi->argnames.size(); ++i) { + PropertyInfo arg; + arg.type = bfi->get_arg_type(i); + arg.name = bfi->argnames[i]; + info.arguments.push_back(arg); + } + } + return info; +} + int Variant::get_utility_function_argument_count(const StringName &p_name) { const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); if (!bfi) { |