diff options
Diffstat (limited to 'core/object')
-rw-r--r-- | core/object/class_db.h | 84 | ||||
-rw-r--r-- | core/object/method_bind.cpp | 4 | ||||
-rw-r--r-- | core/object/method_bind.h | 142 | ||||
-rw-r--r-- | core/object/object.cpp | 70 | ||||
-rw-r--r-- | core/object/object.h | 4 |
5 files changed, 214 insertions, 90 deletions
diff --git a/core/object/class_db.h b/core/object/class_db.h index 32e4bf7644..4211601d15 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -227,75 +227,27 @@ public: static uint64_t get_api_hash(APIType p_api); - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method) { - MethodBind *bind = create_method_bind(p_method); - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, nullptr, 0); //use static function, much smaller binary usage - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[1] = { &p_def1 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[2] = { &p_def1, &p_def2 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6); - } - - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7) { + template <class N, class M, typename... VarArgs> + static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args) { + Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. + const Variant *argptrs[sizeof...(p_args) + 1]; + for (uint32_t i = 0; i < sizeof...(p_args); i++) { + argptrs[i] = &args[i]; + } MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[7] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 7); + return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } - template <class N, class M> - static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7, const Variant &p_def8) { - MethodBind *bind = create_method_bind(p_method); - const Variant *ptr[8] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7, &p_def8 }; - - return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 8); + template <class N, class M, typename... VarArgs> + static MethodBind *bind_static_method(const StringName &p_class, N p_method_name, M p_method, VarArgs... p_args) { + Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. + const Variant *argptrs[sizeof...(p_args) + 1]; + for (uint32_t i = 0; i < sizeof...(p_args); i++) { + argptrs[i] = &args[i]; + } + MethodBind *bind = create_static_method_bind(p_method); + bind->set_instance_class(p_class); + return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args)); } template <class M> diff --git a/core/object/method_bind.cpp b/core/object/method_bind.cpp index 32269b5f19..a79adb7c6c 100644 --- a/core/object/method_bind.cpp +++ b/core/object/method_bind.cpp @@ -83,6 +83,10 @@ void MethodBind::_set_const(bool p_const) { _const = p_const; } +void MethodBind::_set_static(bool p_static) { + _static = p_static; +} + void MethodBind::_set_returns(bool p_returns) { _returns = p_returns; } diff --git a/core/object/method_bind.h b/core/object/method_bind.h index 02b73fa273..1518c8d793 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -60,6 +60,7 @@ class MethodBind { int default_argument_count = 0; int argument_count = 0; + bool _static = false; bool _const = false; bool _returns = false; @@ -69,6 +70,7 @@ protected: Vector<StringName> arg_names; #endif void _set_const(bool p_const); + void _set_static(bool p_static); void _set_returns(bool p_returns); virtual Variant::Type _gen_argument_type(int p_arg) const = 0; virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; @@ -116,7 +118,7 @@ public: #endif void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } - uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } + uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0) | (is_static() ? METHOD_FLAG_STATIC : 0); } _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; } @@ -129,6 +131,7 @@ public: void set_name(const StringName &p_name); _FORCE_INLINE_ int get_method_id() const { return method_id; } _FORCE_INLINE_ bool is_const() const { return _const; } + _FORCE_INLINE_ bool is_static() const { return _static; } _FORCE_INLINE_ bool has_return() const { return _returns; } virtual bool is_vararg() const { return false; } @@ -308,7 +311,7 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) { return a; } -// no return, not const +// no return, const #ifdef TYPED_METHOD_BIND template <class T, class... P> @@ -558,4 +561,139 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) { return a; } +/* STATIC BINDS */ + +// no return + +template <class... P> +class MethodBindTS : public MethodBind { + void (*function)(P...); + +protected: +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return Variant::NIL; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + return call_get_argument_metadata<P...>(p_arg); + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + (void)p_object; // unused + call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments()); + return Variant(); + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + (void)p_object; + (void)r_ret; + call_with_ptr_args_static_method(function, p_args); + } + + MethodBindTS(void (*p_function)(P...)) { + function = p_function; + _generate_argument_types(sizeof...(P)); + set_argument_count(sizeof...(P)); + _set_static(true); + } +}; + +template <class... P> +MethodBind *create_static_method_bind(void (*p_method)(P...)) { + MethodBind *a = memnew((MethodBindTS<P...>)(p_method)); + return a; +} + +// return + +template <class R, class... P> +class MethodBindTRS : public MethodBind { + R(*function) + (P...); + +protected: +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return GetTypeInfo<R>::VARIANT_TYPE; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } else { + return GetTypeInfo<R>::get_class_info(); + } + } + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + if (p_arg >= 0) { + return call_get_argument_metadata<P...>(p_arg); + } else { + return GetTypeInfo<R>::METADATA; + } + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + Variant ret; + call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments()); + return ret; + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + (void)p_object; + call_with_ptr_args_static_method_ret(function, p_args, r_ret); + } + + MethodBindTRS(R (*p_function)(P...)) { + function = p_function; + _generate_argument_types(sizeof...(P)); + set_argument_count(sizeof...(P)); + _set_static(true); + _set_returns(true); + } +}; + +template <class R, class... P> +MethodBind *create_static_method_bind(R (*p_method)(P...)) { + MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method)); + return a; +} + #endif // METHOD_BIND_H diff --git a/core/object/object.cpp b/core/object/object.cpp index 096edd4e60..226d3ef0b8 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -416,12 +416,22 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid } return; - } else if (p_name == CoreStringNames::get_singleton()->_meta) { - metadata = p_value.duplicate(); - if (r_valid) { - *r_valid = true; + } else { + OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); + if (E) { + E->get() = p_value; + if (r_valid) { + *r_valid = true; + } + return; + } else if (p_name.operator String().begins_with("metadata/")) { + // Must exist, otherwise duplicate() will not work. + set_meta(p_name.operator String().replace_first("metadata/", ""), p_value); + if (r_valid) { + *r_valid = true; + } + return; } - return; } // Something inside the object... :| @@ -496,9 +506,12 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { *r_valid = true; } return ret; + } + + const OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name); - } else if (p_name == CoreStringNames::get_singleton()->_meta) { - ret = metadata; + if (E) { + ret = E->get(); if (r_valid) { *r_valid = true; } @@ -648,13 +661,20 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons if (!is_class("Script")) { // can still be set, but this is for user-friendliness p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } - if (!metadata.is_empty()) { - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); - } + if (script_instance && !p_reversed) { p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); } + + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + PropertyInfo pi = PropertyInfo(K.value().get_type(), "metadata/" + K.key().operator String()); + if (K.value().get_type() == Variant::OBJECT) { + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Resource"; + } + p_list->push_back(pi); + } } void Object::_validate_property(PropertyInfo &property) const { @@ -915,11 +935,23 @@ bool Object::has_meta(const StringName &p_name) const { void Object::set_meta(const StringName &p_name, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { - metadata.erase(p_name); + if (metadata.has(p_name)) { + metadata.erase(p_name); + metadata_properties.erase("metadata/" + p_name.operator String()); + notify_property_list_changed(); + } return; } - metadata[p_name] = p_value; + OrderedHashMap<StringName, Variant>::Element E = metadata.find(p_name); + if (E) { + E.value() = p_value; + } else { + ERR_FAIL_COND(!p_name.operator String().is_valid_identifier()); + E = metadata.insert(p_name, p_value); + metadata_properties["metadata/" + p_name.operator String()] = E; + notify_property_list_changed(); + } } Variant Object::get_meta(const StringName &p_name) const { @@ -928,7 +960,7 @@ Variant Object::get_meta(const StringName &p_name) const { } void Object::remove_meta(const StringName &p_name) { - metadata.erase(p_name); + set_meta(p_name, Variant()); } Array Object::_get_property_list_bind() const { @@ -954,20 +986,16 @@ Array Object::_get_method_list_bind() const { Vector<StringName> Object::_get_meta_list_bind() const { Vector<StringName> _metaret; - List<Variant> keys; - metadata.get_key_list(&keys); - for (const Variant &E : keys) { - _metaret.push_back(E); + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + _metaret.push_back(K.key()); } return _metaret; } void Object::get_meta_list(List<StringName> *p_list) const { - List<Variant> keys; - metadata.get_key_list(&keys); - for (const Variant &E : keys) { - p_list->push_back(E); + for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) { + p_list->push_back(K.key()); } } diff --git a/core/object/object.h b/core/object/object.h index 6b4f1c81e6..41365cfe51 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -39,6 +39,7 @@ #include "core/templates/hash_map.h" #include "core/templates/list.h" #include "core/templates/map.h" +#include "core/templates/ordered_hash_map.h" #include "core/templates/safe_refcount.h" #include "core/templates/set.h" #include "core/templates/vmap.h" @@ -530,7 +531,8 @@ private: #endif ScriptInstance *script_instance = nullptr; Variant script; // Reference does not exist yet, store it in a Variant. - Dictionary metadata; + OrderedHashMap<StringName, Variant> metadata; + HashMap<StringName, OrderedHashMap<StringName, Variant>::Element> metadata_properties; mutable StringName _class_name; mutable const StringName *_class_ptr = nullptr; |