feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CALLABLE_METHOD_POINTER_H
|
||||
#define CALLABLE_METHOD_POINTER_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/object.h"
|
||||
#include "core/variant/binder_common.h"
|
||||
|
|
@ -82,8 +81,7 @@ class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
|||
struct Data {
|
||||
T *instance;
|
||||
uint64_t object_id;
|
||||
R(T::*method)
|
||||
(P...);
|
||||
R (T::*method)(P...);
|
||||
} data;
|
||||
|
||||
public:
|
||||
|
|
@ -152,8 +150,7 @@ class CallableCustomMethodPointerC : public CallableCustomMethodPointerBase {
|
|||
struct Data {
|
||||
T *instance;
|
||||
uint64_t object_id;
|
||||
R(T::*method)
|
||||
(P...) const;
|
||||
R (T::*method)(P...) const;
|
||||
} data;
|
||||
|
||||
public:
|
||||
|
|
@ -226,8 +223,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
|
|||
template <typename R, typename... P>
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
R(*method)
|
||||
(P...);
|
||||
R (*method)(P...);
|
||||
} data;
|
||||
|
||||
public:
|
||||
|
|
@ -292,5 +288,3 @@ Callable create_custom_callable_static_function_pointer(
|
|||
#else
|
||||
#define callable_mp_static(M) create_custom_callable_static_function_pointer(M)
|
||||
#endif
|
||||
|
||||
#endif // CALLABLE_METHOD_POINTER_H
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
#include "core/object/script_language.h"
|
||||
#include "core/version.h"
|
||||
|
||||
#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
|
||||
#define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
MethodDefinition D_METHODP(const char *p_name, const char *const **p_args, uint32_t p_argcount) {
|
||||
|
|
@ -238,13 +235,13 @@ bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_in
|
|||
}
|
||||
|
||||
bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
return _is_parent_class(p_class, p_inherits);
|
||||
}
|
||||
|
||||
void ClassDB::get_class_list(List<StringName> *p_classes) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
p_classes->push_back(E.key);
|
||||
|
|
@ -255,7 +252,7 @@ void ClassDB::get_class_list(List<StringName> *p_classes) {
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void ClassDB::get_extensions_class_list(List<StringName> *p_classes) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) {
|
||||
|
|
@ -268,7 +265,7 @@ void ClassDB::get_extensions_class_list(List<StringName> *p_classes) {
|
|||
}
|
||||
|
||||
void ClassDB::get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) {
|
||||
|
|
@ -284,28 +281,28 @@ void ClassDB::get_extension_class_list(const Ref<GDExtension> &p_extension, List
|
|||
}
|
||||
#endif
|
||||
|
||||
void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
|
||||
OBJTYPE_RLOCK;
|
||||
void ClassDB::get_inheriters_from_class(const StringName &p_class, LocalVector<StringName> &p_classes) {
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
if (E.key != p_class && _is_parent_class(E.key, p_class)) {
|
||||
p_classes->push_back(E.key);
|
||||
p_classes.push_back(E.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
if (E.key != p_class && _get_parent_class(E.key) == p_class) {
|
||||
if (E.value.inherits == p_class) {
|
||||
p_classes->push_back(E.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
if (!ti) {
|
||||
|
|
@ -315,7 +312,7 @@ StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
|
|||
}
|
||||
|
||||
bool ClassDB::get_inheritance_chain_nocheck(const StringName &p_class, Vector<StringName> &r_result) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *start = classes.getptr(p_class);
|
||||
if (!start) {
|
||||
|
|
@ -356,13 +353,13 @@ StringName ClassDB::_get_parent_class(const StringName &p_class) {
|
|||
}
|
||||
|
||||
StringName ClassDB::get_parent_class(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
return _get_parent_class(p_class);
|
||||
}
|
||||
|
||||
ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -372,13 +369,13 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
|
|||
|
||||
uint32_t ClassDB::get_api_hash(APIType p_api) {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
if (api_hashes_cache.has(p_api)) {
|
||||
return api_hashes_cache[p_api];
|
||||
}
|
||||
|
||||
uint64_t hash = hash_murmur3_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
|
||||
uint64_t hash = hash_murmur3_one_64(HashMapHasherDefault::hash(GODOT_VERSION_FULL_CONFIG));
|
||||
|
||||
List<StringName> class_list;
|
||||
for (const KeyValue<StringName, ClassInfo> &E : classes) {
|
||||
|
|
@ -520,12 +517,12 @@ uint32_t ClassDB::get_api_hash(APIType p_api) {
|
|||
}
|
||||
|
||||
bool ClassDB::class_exists(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
return classes.has(p_class);
|
||||
}
|
||||
|
||||
void ClassDB::add_compatibility_class(const StringName &p_class, const StringName &p_fallback) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
compat_classes[p_class] = p_fallback;
|
||||
}
|
||||
|
||||
|
|
@ -536,18 +533,21 @@ StringName ClassDB::get_compatibility_class(const StringName &p_class) {
|
|||
return StringName();
|
||||
}
|
||||
|
||||
Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class, bool p_notify_postinitialize) {
|
||||
Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class, bool p_notify_postinitialize, bool p_exposed_only) {
|
||||
ClassInfo *ti;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ti = classes.getptr(p_class);
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (!_can_instantiate(ti, p_exposed_only)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
ti = classes.getptr(compat_classes[p_class]);
|
||||
}
|
||||
}
|
||||
ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
|
||||
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
|
||||
if (p_exposed_only) {
|
||||
ERR_FAIL_COND_V_MSG(!ti->exposed, nullptr, vformat("Class '%s' isn't exposed.", String(p_class)));
|
||||
}
|
||||
ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, vformat("Class '%s' or its base class cannot be instantiated.", String(p_class)));
|
||||
}
|
||||
|
||||
|
|
@ -599,11 +599,15 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require
|
|||
}
|
||||
}
|
||||
|
||||
bool ClassDB::_can_instantiate(ClassInfo *p_class_info) {
|
||||
bool ClassDB::_can_instantiate(ClassInfo *p_class_info, bool p_exposed_only) {
|
||||
if (!p_class_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_exposed_only && !p_class_info->exposed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_class_info->disabled || !p_class_info->creation_func) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -645,7 +649,7 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class)
|
|||
|
||||
ClassInfo *ti;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ti = classes.getptr(p_class);
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
|
|
@ -730,7 +734,7 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
|
|||
ERR_FAIL_NULL(p_object);
|
||||
ClassInfo *ti;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ti = classes.getptr(p_class);
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
|
|
@ -755,7 +759,7 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
|
|||
bool ClassDB::can_instantiate(const StringName &p_class) {
|
||||
String script_path;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
if (!ti) {
|
||||
|
|
@ -781,7 +785,7 @@ use_script:
|
|||
bool ClassDB::is_abstract(const StringName &p_class) {
|
||||
String script_path;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
if (!ti) {
|
||||
|
|
@ -813,7 +817,7 @@ use_script:
|
|||
bool ClassDB::is_virtual(const StringName &p_class) {
|
||||
String script_path;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
if (!ti) {
|
||||
|
|
@ -836,8 +840,8 @@ use_script:
|
|||
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
|
||||
}
|
||||
|
||||
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
|
||||
OBJTYPE_WLOCK;
|
||||
void ClassDB::_add_class(const StringName &p_class, const StringName &p_inherits) {
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
const StringName &name = p_class;
|
||||
|
||||
|
|
@ -880,7 +884,7 @@ static MethodInfo info_from_bind(MethodBind *p_method) {
|
|||
}
|
||||
|
||||
void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -926,7 +930,7 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met
|
|||
}
|
||||
|
||||
void ClassDB::get_method_list_with_compatibility(const StringName &p_class, List<Pair<MethodInfo, uint32_t>> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -986,7 +990,7 @@ void ClassDB::get_method_list_with_compatibility(const StringName &p_class, List
|
|||
}
|
||||
|
||||
bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance, bool p_exclude_from_properties) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1036,7 +1040,7 @@ bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_met
|
|||
}
|
||||
|
||||
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_name) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1051,7 +1055,7 @@ MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_n
|
|||
}
|
||||
|
||||
Vector<uint32_t> ClassDB::get_method_compatibility_hashes(const StringName &p_class, const StringName &p_name) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1070,7 +1074,7 @@ Vector<uint32_t> ClassDB::get_method_compatibility_hashes(const StringName &p_cl
|
|||
}
|
||||
|
||||
MethodBind *ClassDB::get_method_with_compatibility(const StringName &p_class, const StringName &p_name, uint64_t p_hash, bool *r_method_exists, bool *r_is_deprecated) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1105,7 +1109,7 @@ MethodBind *ClassDB::get_method_with_compatibility(const StringName &p_class, co
|
|||
}
|
||||
|
||||
void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1142,7 +1146,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
|
|||
}
|
||||
|
||||
void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1167,7 +1171,7 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List<String>
|
|||
}
|
||||
|
||||
int64_t ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1191,7 +1195,7 @@ int64_t ClassDB::get_integer_constant(const StringName &p_class, const StringNam
|
|||
}
|
||||
|
||||
bool ClassDB::has_integer_constant(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1210,7 +1214,7 @@ bool ClassDB::has_integer_constant(const StringName &p_class, const StringName &
|
|||
}
|
||||
|
||||
StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1234,7 +1238,7 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S
|
|||
}
|
||||
|
||||
void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1252,7 +1256,7 @@ void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums
|
|||
}
|
||||
|
||||
void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1275,7 +1279,7 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_
|
|||
|
||||
void ClassDB::set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values) {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
ERR_FAIL_NULL(type);
|
||||
|
|
@ -1286,7 +1290,7 @@ void ClassDB::set_method_error_return_values(const StringName &p_class, const St
|
|||
|
||||
Vector<Error> ClassDB::get_method_error_return_values(const StringName &p_class, const StringName &p_method) {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
ERR_FAIL_NULL_V(type, Vector<Error>());
|
||||
|
|
@ -1301,7 +1305,7 @@ Vector<Error> ClassDB::get_method_error_return_values(const StringName &p_class,
|
|||
}
|
||||
|
||||
bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1320,7 +1324,7 @@ bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool
|
|||
}
|
||||
|
||||
bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1339,7 +1343,7 @@ bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_na
|
|||
}
|
||||
|
||||
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
|
@ -1358,7 +1362,7 @@ void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal)
|
|||
}
|
||||
|
||||
void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
|
@ -1379,7 +1383,7 @@ void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_sig
|
|||
}
|
||||
|
||||
bool ClassDB::has_signal(const StringName &p_class, const StringName &p_signal, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ClassInfo *check = type;
|
||||
while (check) {
|
||||
|
|
@ -1396,7 +1400,7 @@ bool ClassDB::has_signal(const StringName &p_class, const StringName &p_signal,
|
|||
}
|
||||
|
||||
bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ClassInfo *check = type;
|
||||
while (check) {
|
||||
|
|
@ -1413,7 +1417,7 @@ bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal,
|
|||
}
|
||||
|
||||
void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
|
|
@ -1426,7 +1430,7 @@ void ClassDB::add_property_group(const StringName &p_class, const String &p_name
|
|||
}
|
||||
|
||||
void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
|
|
@ -1443,7 +1447,7 @@ void ClassDB::add_property_array_count(const StringName &p_class, const String &
|
|||
}
|
||||
|
||||
void ClassDB::add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
|
|
@ -1452,9 +1456,9 @@ void ClassDB::add_property_array(const StringName &p_class, const StringName &p_
|
|||
|
||||
// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end.
|
||||
void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
|
||||
lock.read_lock();
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
lock.read_unlock();
|
||||
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
|
|
@ -1486,8 +1490,6 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
|
|||
ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), vformat("Object '%s' already has property '%s'.", p_class, p_pinfo.name));
|
||||
#endif
|
||||
|
||||
OBJTYPE_WLOCK
|
||||
|
||||
type->property_list.push_back(p_pinfo);
|
||||
type->property_map[p_pinfo.name] = p_pinfo;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
|
@ -1518,7 +1520,7 @@ void ClassDB::set_property_default_value(const StringName &p_class, const String
|
|||
|
||||
void ClassDB::add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL(type);
|
||||
|
||||
|
|
@ -1534,7 +1536,7 @@ void ClassDB::add_linked_property(const StringName &p_class, const String &p_pro
|
|||
}
|
||||
|
||||
void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ClassInfo *check = type;
|
||||
|
|
@ -1577,7 +1579,7 @@ void ClassDB::get_linked_properties_info(const StringName &p_class, const String
|
|||
}
|
||||
|
||||
bool ClassDB::get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *check = classes.getptr(p_class);
|
||||
while (check) {
|
||||
|
|
@ -1800,7 +1802,7 @@ bool ClassDB::has_property(const StringName &p_class, const StringName &p_proper
|
|||
}
|
||||
|
||||
void ClassDB::set_method_flags(const StringName &p_class, const StringName &p_method, int p_flags) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
ClassInfo *check = type;
|
||||
ERR_FAIL_NULL(check);
|
||||
|
|
@ -1825,7 +1827,7 @@ bool ClassDB::has_method(const StringName &p_class, const StringName &p_method,
|
|||
}
|
||||
|
||||
int ClassDB::get_method_argument_count(const StringName &p_class, const StringName &p_method, bool *r_is_valid, bool p_no_inheritance) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -1864,7 +1866,7 @@ void ClassDB::_bind_compatibility(ClassInfo *type, MethodBind *p_method) {
|
|||
}
|
||||
|
||||
void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
StringName method_name = p_method->get_name();
|
||||
|
||||
|
|
@ -1933,7 +1935,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_
|
|||
StringName mdname = StaticCString::create(method_name);
|
||||
#endif
|
||||
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
ERR_FAIL_NULL_V(p_bind, nullptr);
|
||||
p_bind->set_name(mdname);
|
||||
|
||||
|
|
@ -1996,7 +1998,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_
|
|||
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
|
||||
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
|
||||
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
MethodInfo mi = p_method;
|
||||
|
|
@ -2011,9 +2013,8 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
|
|||
if (p_arg_names.size() != mi.arguments.size()) {
|
||||
WARN_PRINT(vformat("Mismatch argument name count for virtual method: '%s::%s'.", String(p_class), p_method.name));
|
||||
} else {
|
||||
List<PropertyInfo>::Iterator itr = mi.arguments.begin();
|
||||
for (int i = 0; i < p_arg_names.size(); ++itr, ++i) {
|
||||
itr->name = p_arg_names[i];
|
||||
for (int64_t i = 0; i < p_arg_names.size(); ++i) {
|
||||
mi.arguments.write[i].name = p_arg_names[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2031,7 +2032,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
|
|||
void ClassDB::add_virtual_compatibility_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
|
||||
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
|
||||
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
HashMap<StringName, Vector<uint32_t>> &virtual_methods_compat = classes[p_class].virtual_methods_compat;
|
||||
|
||||
|
|
@ -2066,7 +2067,7 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p
|
|||
}
|
||||
|
||||
Vector<uint32_t> ClassDB::get_virtual_method_compatibility_hashes(const StringName &p_class, const StringName &p_name) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *type = classes.getptr(p_class);
|
||||
|
||||
|
|
@ -2107,14 +2108,14 @@ void ClassDB::add_extension_class_virtual_method(const StringName &p_class, cons
|
|||
}
|
||||
|
||||
void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) {
|
||||
OBJTYPE_WLOCK;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
|
||||
classes[p_class].disabled = !p_enable;
|
||||
}
|
||||
|
||||
bool ClassDB::is_class_enabled(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
if (!ti || !ti->creation_func) {
|
||||
|
|
@ -2128,7 +2129,7 @@ bool ClassDB::is_class_enabled(const StringName &p_class) {
|
|||
}
|
||||
|
||||
bool ClassDB::is_class_exposed(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
|
||||
|
|
@ -2136,7 +2137,7 @@ bool ClassDB::is_class_exposed(const StringName &p_class) {
|
|||
}
|
||||
|
||||
bool ClassDB::is_class_reloadable(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
|
||||
|
|
@ -2144,7 +2145,7 @@ bool ClassDB::is_class_reloadable(const StringName &p_class) {
|
|||
}
|
||||
|
||||
bool ClassDB::is_class_runtime(const StringName &p_class) {
|
||||
OBJTYPE_RLOCK;
|
||||
Locker::Lock lock(Locker::STATE_READ);
|
||||
|
||||
ClassInfo *ti = classes.getptr(p_class);
|
||||
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
|
||||
|
|
@ -2342,7 +2343,9 @@ uint64_t ClassDB::get_native_struct_size(const StringName &p_name) {
|
|||
return native_structs[p_name].struct_size;
|
||||
}
|
||||
|
||||
RWLock ClassDB::lock;
|
||||
Object *ClassDB::_instantiate_allow_unexposed(const StringName &p_class) {
|
||||
return _instantiate_internal(p_class, false, true, false);
|
||||
}
|
||||
|
||||
void ClassDB::cleanup_defaults() {
|
||||
default_values.clear();
|
||||
|
|
@ -2379,3 +2382,32 @@ bool ClassDB::is_default_array_arg(const Array &p_array) {
|
|||
}
|
||||
|
||||
//
|
||||
|
||||
ClassDB::Locker::Lock::Lock(Locker::State p_state) {
|
||||
DEV_ASSERT(p_state != STATE_UNLOCKED);
|
||||
if (p_state == STATE_READ) {
|
||||
if (Locker::thread_state == STATE_UNLOCKED) {
|
||||
state = STATE_READ;
|
||||
Locker::thread_state = STATE_READ;
|
||||
Locker::lock.read_lock();
|
||||
}
|
||||
} else if (p_state == STATE_WRITE) {
|
||||
if (Locker::thread_state == STATE_UNLOCKED) {
|
||||
state = STATE_WRITE;
|
||||
Locker::thread_state = STATE_WRITE;
|
||||
Locker::lock.write_lock();
|
||||
} else if (Locker::thread_state == STATE_READ) {
|
||||
CRASH_NOW_MSG("Lock can't be upgraded from read to write.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClassDB::Locker::Lock::~Lock() {
|
||||
if (state == STATE_READ) {
|
||||
Locker::lock.read_unlock();
|
||||
Locker::thread_state = STATE_UNLOCKED;
|
||||
} else if (state == STATE_WRITE) {
|
||||
Locker::lock.write_unlock();
|
||||
Locker::thread_state = STATE_UNLOCKED;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CLASS_DB_H
|
||||
#define CLASS_DB_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/method_bind.h"
|
||||
#include "core/object/object.h"
|
||||
|
|
@ -79,6 +78,8 @@ MethodDefinition D_METHOD(const char *p_name, const VarArgs... p_args) {
|
|||
#endif
|
||||
|
||||
class ClassDB {
|
||||
friend class Object;
|
||||
|
||||
public:
|
||||
enum APIType {
|
||||
API_CORE,
|
||||
|
|
@ -153,7 +154,30 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static RWLock lock;
|
||||
// We need a recursive r/w lock because there are various code paths
|
||||
// that may in turn invoke other entry points with require locking.
|
||||
class Locker {
|
||||
public:
|
||||
enum State {
|
||||
STATE_UNLOCKED,
|
||||
STATE_READ,
|
||||
STATE_WRITE,
|
||||
};
|
||||
|
||||
private:
|
||||
inline static RWLock lock;
|
||||
inline thread_local static State thread_state = STATE_UNLOCKED;
|
||||
|
||||
public:
|
||||
class Lock {
|
||||
State state = STATE_UNLOCKED;
|
||||
|
||||
public:
|
||||
explicit Lock(State p_state);
|
||||
~Lock();
|
||||
};
|
||||
};
|
||||
|
||||
static HashMap<StringName, ClassInfo> classes;
|
||||
static HashMap<StringName, StringName> resource_base_extensions;
|
||||
static HashMap<StringName, StringName> compat_classes;
|
||||
|
|
@ -171,7 +195,7 @@ public:
|
|||
static APIType current_api;
|
||||
static HashMap<APIType, uint32_t> api_hashes_cache;
|
||||
|
||||
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
|
||||
static void _add_class(const StringName &p_class, const StringName &p_inherits);
|
||||
|
||||
static HashMap<StringName, HashMap<StringName, Variant>> default_values;
|
||||
static HashSet<StringName> default_values_cached;
|
||||
|
|
@ -194,20 +218,14 @@ private:
|
|||
static MethodBind *_bind_vararg_method(MethodBind *p_bind, const StringName &p_name, const Vector<Variant> &p_default_args, bool p_compatibility);
|
||||
static void _bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility);
|
||||
|
||||
static Object *_instantiate_internal(const StringName &p_class, bool p_require_real_class = false, bool p_notify_postinitialize = true);
|
||||
static Object *_instantiate_internal(const StringName &p_class, bool p_require_real_class = false, bool p_notify_postinitialize = true, bool p_exposed_only = true);
|
||||
|
||||
static bool _can_instantiate(ClassInfo *p_class_info);
|
||||
static bool _can_instantiate(ClassInfo *p_class_info, bool p_exposed_only = true);
|
||||
|
||||
public:
|
||||
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
|
||||
template <typename T>
|
||||
static void _add_class() {
|
||||
_add_class2(T::get_class_static(), T::get_parent_class_static());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void register_class(bool p_virtual = false) {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
static_assert(std::is_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
|
|
@ -222,7 +240,7 @@ public:
|
|||
|
||||
template <typename T>
|
||||
static void register_abstract_class() {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
static_assert(std::is_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
|
|
@ -235,7 +253,7 @@ public:
|
|||
|
||||
template <typename T>
|
||||
static void register_internal_class() {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
static_assert(std::is_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
|
|
@ -250,7 +268,7 @@ public:
|
|||
|
||||
template <typename T>
|
||||
static void register_runtime_class() {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
static_assert(std::is_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
|
|
@ -275,7 +293,7 @@ public:
|
|||
|
||||
template <typename T>
|
||||
static void register_custom_instance_class() {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
static_assert(std::is_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
|
|
@ -293,7 +311,7 @@ public:
|
|||
static void get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes);
|
||||
static ObjectGDExtension *get_placeholder_extension(const StringName &p_class);
|
||||
#endif
|
||||
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
|
||||
static void get_inheriters_from_class(const StringName &p_class, LocalVector<StringName> &p_classes);
|
||||
static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
|
||||
static StringName get_parent_class_nocheck(const StringName &p_class);
|
||||
static bool get_inheritance_chain_nocheck(const StringName &p_class, Vector<StringName> &r_result);
|
||||
|
|
@ -391,7 +409,7 @@ public:
|
|||
|
||||
template <typename M>
|
||||
static MethodBind *bind_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
|
||||
ERR_FAIL_NULL_V(bind, nullptr);
|
||||
|
|
@ -404,7 +422,7 @@ public:
|
|||
|
||||
template <typename M>
|
||||
static MethodBind *bind_compatibility_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
Locker::Lock lock(Locker::STATE_WRITE);
|
||||
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
|
||||
ERR_FAIL_NULL_V(bind, nullptr);
|
||||
|
|
@ -498,6 +516,8 @@ public:
|
|||
static void get_native_struct_list(List<StringName> *r_names);
|
||||
static String get_native_struct_code(const StringName &p_name);
|
||||
static uint64_t get_native_struct_size(const StringName &p_name); // Used for asserting
|
||||
|
||||
static Object *_instantiate_allow_unexposed(const StringName &p_class); // Used to create unexposed classes from GDExtension, typically for unexposed EditorPlugin.
|
||||
};
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
|
|
@ -563,7 +583,3 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
|
|||
}
|
||||
|
||||
#define GDREGISTER_NATIVE_STRUCT(m_class, m_code) ClassDB::register_native_struct(#m_class, m_code, sizeof(m_class))
|
||||
|
||||
#include "core/disabled_classes.gen.h"
|
||||
|
||||
#endif // CLASS_DB_H
|
||||
|
|
|
|||
|
|
@ -15,57 +15,65 @@ script_has_method = """ScriptInstance *_script_instance = ((Object *)(this))->ge
|
|||
}"""
|
||||
|
||||
proto = """#define GDVIRTUAL$VER($ALIAS $RET m_name $ARG)\\
|
||||
StringName _gdvirtual_##$VARNAME##_sn = #m_name;\\
|
||||
mutable bool _gdvirtual_##$VARNAME##_initialized = false;\\
|
||||
mutable void *_gdvirtual_##$VARNAME = nullptr;\\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##$VARNAME##_call($CALLARGS) $CONST {\\
|
||||
static const StringName _gdvirtual_##$VARNAME##_sn = _scs_create(#m_name, true);\\
|
||||
$SCRIPTCALL\\
|
||||
if (unlikely(_get_extension() && !_gdvirtual_##$VARNAME##_initialized)) {\\
|
||||
MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\
|
||||
uint32_t hash = mi.get_compatibility_hash();\\
|
||||
_gdvirtual_##$VARNAME = nullptr;\\
|
||||
if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\
|
||||
_gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
} else if (_get_extension()->get_virtual2) {\\
|
||||
_gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
if (_get_extension()) {\\
|
||||
if (unlikely(!_gdvirtual_##$VARNAME)) {\\
|
||||
MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\
|
||||
uint32_t hash = mi.get_compatibility_hash();\\
|
||||
_gdvirtual_##$VARNAME = nullptr;\\
|
||||
if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\
|
||||
_gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
} else if (_get_extension()->get_virtual2) {\\
|
||||
_gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
}\\
|
||||
_GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\
|
||||
_GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME);\\
|
||||
if (_gdvirtual_##$VARNAME == nullptr) {\\
|
||||
_gdvirtual_##$VARNAME = reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR);\\
|
||||
}\\
|
||||
}\\
|
||||
_GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\
|
||||
_GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_initialized);\\
|
||||
_gdvirtual_##$VARNAME##_initialized = true;\\
|
||||
}\\
|
||||
if (_gdvirtual_##$VARNAME) {\\
|
||||
$CALLPTRARGS\\
|
||||
$CALLPTRRETDEF\\
|
||||
if (_get_extension()->call_virtual_with_data) {\\
|
||||
_get_extension()->call_virtual_with_data(_get_extension_instance(), &_gdvirtual_##$VARNAME##_sn, _gdvirtual_##$VARNAME, $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
||||
$CALLPTRRET\\
|
||||
} else {\\
|
||||
((GDExtensionClassCallVirtual)_gdvirtual_##$VARNAME)(_get_extension_instance(), $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
||||
$CALLPTRRET\\
|
||||
if (_gdvirtual_##$VARNAME != reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\
|
||||
$CALLPTRARGS\\
|
||||
$CALLPTRRETDEF\\
|
||||
if (_get_extension()->call_virtual_with_data) {\\
|
||||
_get_extension()->call_virtual_with_data(_get_extension_instance(), &_gdvirtual_##$VARNAME##_sn, _gdvirtual_##$VARNAME, $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
||||
$CALLPTRRET\\
|
||||
} else {\\
|
||||
((GDExtensionClassCallVirtual)_gdvirtual_##$VARNAME)(_get_extension_instance(), $CALLPTRARGPASS, $CALLPTRRETPASS);\\
|
||||
$CALLPTRRET\\
|
||||
}\\
|
||||
return true;\\
|
||||
}\\
|
||||
return true;\\
|
||||
}\\
|
||||
$REQCHECK\\
|
||||
$RVOID\\
|
||||
return false;\\
|
||||
}\\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##$VARNAME##_overridden() const {\\
|
||||
static const StringName _gdvirtual_##$VARNAME##_sn = _scs_create(#m_name, true);\\
|
||||
$SCRIPTHASMETHOD\\
|
||||
if (unlikely(_get_extension() && !_gdvirtual_##$VARNAME##_initialized)) {\\
|
||||
MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\
|
||||
uint32_t hash = mi.get_compatibility_hash();\\
|
||||
_gdvirtual_##$VARNAME = nullptr;\\
|
||||
if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\
|
||||
_gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
} else if (_get_extension()->get_virtual2) {\\
|
||||
_gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
if (_get_extension()) {\\
|
||||
if (unlikely(!_gdvirtual_##$VARNAME)) {\\
|
||||
MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\
|
||||
uint32_t hash = mi.get_compatibility_hash();\\
|
||||
_gdvirtual_##$VARNAME = nullptr;\\
|
||||
if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\
|
||||
_gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
} else if (_get_extension()->get_virtual2) {\\
|
||||
_gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\
|
||||
}\\
|
||||
_GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\
|
||||
_GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME);\\
|
||||
if (_gdvirtual_##$VARNAME == nullptr) {\\
|
||||
_gdvirtual_##$VARNAME = reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR);\\
|
||||
}\\
|
||||
}\\
|
||||
if (_gdvirtual_##$VARNAME != reinterpret_cast<void*>(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\
|
||||
return true;\\
|
||||
}\\
|
||||
_GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\
|
||||
_GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_initialized);\\
|
||||
_gdvirtual_##$VARNAME##_initialized = true;\\
|
||||
}\\
|
||||
if (_gdvirtual_##$VARNAME) {\\
|
||||
return true;\\
|
||||
}\\
|
||||
return false;\\
|
||||
}\\
|
||||
|
|
@ -207,24 +215,22 @@ def run(target, source, env):
|
|||
max_versions = 12
|
||||
|
||||
txt = """/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||
#ifndef GDVIRTUAL_GEN_H
|
||||
#define GDVIRTUAL_GEN_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/script_instance.h"
|
||||
|
||||
#include <utility>
|
||||
inline constexpr uintptr_t _INVALID_GDVIRTUAL_FUNC_ADDR = static_cast<uintptr_t>(-1);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#define _GDVIRTUAL_TRACK(m_virtual, m_initialized)\\
|
||||
#define _GDVIRTUAL_TRACK(m_virtual)\\
|
||||
if (_get_extension()->reloadable) {\\
|
||||
VirtualMethodTracker *tracker = memnew(VirtualMethodTracker);\\
|
||||
tracker->method = (void **)&m_virtual;\\
|
||||
tracker->initialized = &m_initialized;\\
|
||||
tracker->next = virtual_method_list;\\
|
||||
virtual_method_list = tracker;\\
|
||||
}
|
||||
#else
|
||||
#define _GDVIRTUAL_TRACK(m_virtual, m_initialized)
|
||||
#define _GDVIRTUAL_TRACK(m_virtual)
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
|
|
@ -257,7 +263,5 @@ def run(target, source, env):
|
|||
txt += generate_version(i, True, False, False, True)
|
||||
txt += generate_version(i, True, True, False, True)
|
||||
|
||||
txt += "#endif // GDVIRTUAL_GEN_H\n"
|
||||
|
||||
with open(str(target[0]), "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(txt)
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ void CallQueue::_call_function(const Callable &p_callable, const Variant *p_args
|
|||
Error CallQueue::flush() {
|
||||
LOCK_MUTEX;
|
||||
|
||||
if (pages.size() == 0) {
|
||||
if (pages.is_empty()) {
|
||||
// Never allocated
|
||||
UNLOCK_MUTEX;
|
||||
return OK; // Do nothing.
|
||||
|
|
@ -308,7 +308,7 @@ Error CallQueue::flush() {
|
|||
void CallQueue::clear() {
|
||||
LOCK_MUTEX;
|
||||
|
||||
if (pages.size() == 0) {
|
||||
if (pages.is_empty()) {
|
||||
UNLOCK_MUTEX;
|
||||
return; // Nothing to clear.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MESSAGE_QUEUE_H
|
||||
#define MESSAGE_QUEUE_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/object_id.h"
|
||||
#include "core/os/thread_safe.h"
|
||||
|
|
@ -171,5 +170,3 @@ public:
|
|||
MessageQueue();
|
||||
~MessageQueue();
|
||||
};
|
||||
|
||||
#endif // MESSAGE_QUEUE_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef METHOD_BIND_H
|
||||
#define METHOD_BIND_H
|
||||
#pragma once
|
||||
|
||||
#include "core/variant/binder_common.h"
|
||||
|
||||
|
|
@ -143,8 +142,7 @@ public:
|
|||
template <typename Derived, typename T, typename R, bool should_returns>
|
||||
class MethodBindVarArgBase : public MethodBind {
|
||||
protected:
|
||||
R(T::*method)
|
||||
(const Variant **, int, Callable::CallError &);
|
||||
R (T::*method)(const Variant **, int, Callable::CallError &);
|
||||
MethodInfo method_info;
|
||||
|
||||
public:
|
||||
|
|
@ -152,7 +150,7 @@ public:
|
|||
if (p_arg < 0) {
|
||||
return _gen_return_type_info();
|
||||
} else if (p_arg < method_info.arguments.size()) {
|
||||
return method_info.arguments.get(p_arg);
|
||||
return method_info.arguments[p_arg];
|
||||
} else {
|
||||
return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
}
|
||||
|
|
@ -193,11 +191,10 @@ public:
|
|||
Vector<StringName> names;
|
||||
names.resize(method_info.arguments.size());
|
||||
#endif
|
||||
int i = 0;
|
||||
for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
|
||||
at[i + 1] = itr->type;
|
||||
for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
|
||||
at[i + 1] = method_info.arguments[i].type;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
names.write[i] = itr->name;
|
||||
names.write[i] = method_info.arguments[i].name;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -259,11 +256,8 @@ class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>,
|
|||
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
|
||||
|
||||
public:
|
||||
#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
|
||||
// Workaround GH-66343 raised only with UBSAN, seems to be a false positive.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wmaybe-uninitialized") // Workaround GH-66343 raised only with UBSAN, seems to be a false positive.
|
||||
|
||||
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
|
||||
#ifdef TOOLS_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(p_object && p_object->is_extension_placeholder() && p_object->get_class_name() == MethodBind::get_instance_class(), Variant(), vformat("Cannot call method bind '%s' on placeholder instance.", MethodBind::get_name()));
|
||||
|
|
@ -271,9 +265,7 @@ public:
|
|||
return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error);
|
||||
}
|
||||
|
||||
#if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
GODOT_GCC_WARNING_POP
|
||||
|
||||
MethodBindVarArgTR(
|
||||
R (T::*p_method)(const Variant **, int, Callable::CallError &),
|
||||
|
|
@ -480,8 +472,7 @@ template <typename T, typename R, typename... P>
|
|||
template <typename R, typename... P>
|
||||
#endif
|
||||
class MethodBindTR : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
(P...);
|
||||
R (MB_T::*method)(P...);
|
||||
|
||||
protected:
|
||||
virtual Variant::Type _gen_argument_type(int p_arg) const override {
|
||||
|
|
@ -576,8 +567,7 @@ template <typename T, typename R, typename... P>
|
|||
template <typename R, typename... P>
|
||||
#endif
|
||||
class MethodBindTRC : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
(P...) const;
|
||||
R (MB_T::*method)(P...) const;
|
||||
|
||||
protected:
|
||||
virtual Variant::Type _gen_argument_type(int p_arg) const override {
|
||||
|
|
@ -728,8 +718,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
|
|||
|
||||
template <typename R, typename... P>
|
||||
class MethodBindTRS : public MethodBind {
|
||||
R(*function)
|
||||
(P...);
|
||||
R (*function)(P...);
|
||||
|
||||
protected:
|
||||
virtual Variant::Type _gen_argument_type(int p_arg) const override {
|
||||
|
|
@ -790,5 +779,3 @@ MethodBind *create_static_method_bind(R (*p_method)(P...)) {
|
|||
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif // METHOD_BIND_H
|
||||
|
|
|
|||
|
|
@ -115,10 +115,19 @@ TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list) {
|
|||
return va;
|
||||
}
|
||||
|
||||
TypedArray<Dictionary> convert_property_list(const Vector<PropertyInfo> &p_vector) {
|
||||
TypedArray<Dictionary> va;
|
||||
for (const PropertyInfo &E : p_vector) {
|
||||
va.push_back(Dictionary(E));
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
||||
|
||||
MethodInfo::operator Dictionary() const {
|
||||
Dictionary d;
|
||||
d["name"] = name;
|
||||
d["args"] = convert_property_list(&arguments);
|
||||
d["args"] = convert_property_list(arguments);
|
||||
Array da;
|
||||
for (int i = 0; i < default_arguments.size(); i++) {
|
||||
da.push_back(default_arguments[i]);
|
||||
|
|
@ -240,21 +249,15 @@ void Object::cancel_free() {
|
|||
}
|
||||
|
||||
void Object::_initialize() {
|
||||
_class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after _initialize.
|
||||
// Cache the class name in the object for quick reference.
|
||||
_class_name_ptr = _get_class_namev();
|
||||
_initialize_classv();
|
||||
_class_name_ptr = nullptr; // May have been called from a constructor.
|
||||
}
|
||||
|
||||
void Object::_postinitialize() {
|
||||
notification(NOTIFICATION_POSTINITIALIZE);
|
||||
}
|
||||
|
||||
void Object::get_valid_parents_static(List<String> *p_parents) {
|
||||
}
|
||||
|
||||
void Object::_get_valid_parents_static(List<String> *p_parents) {
|
||||
}
|
||||
|
||||
void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
|
|
@ -902,18 +905,14 @@ Variant Object::call_const(const StringName &p_method, const Variant **p_args, i
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Object::notification(int p_notification, bool p_reversed) {
|
||||
if (p_reversed) {
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, p_reversed);
|
||||
}
|
||||
} else {
|
||||
_notificationv(p_notification, p_reversed);
|
||||
}
|
||||
void Object::_notification_forward(int p_notification) {
|
||||
// Notify classes starting with Object and ending with most derived subclass.
|
||||
// e.g. Object -> Node -> Node3D
|
||||
_notification_forwardv(p_notification);
|
||||
|
||||
if (_extension) {
|
||||
if (_extension->notification2) {
|
||||
_extension->notification2(_extension_instance, p_notification, static_cast<GDExtensionBool>(p_reversed));
|
||||
_extension->notification2(_extension_instance, p_notification, static_cast<GDExtensionBool>(false));
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
} else if (_extension->notification) {
|
||||
_extension->notification(_extension_instance, p_notification);
|
||||
|
|
@ -921,13 +920,29 @@ void Object::notification(int p_notification, bool p_reversed) {
|
|||
}
|
||||
}
|
||||
|
||||
if (p_reversed) {
|
||||
_notificationv(p_notification, p_reversed);
|
||||
} else {
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, p_reversed);
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::_notification_backward(int p_notification) {
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, true);
|
||||
}
|
||||
|
||||
if (_extension) {
|
||||
if (_extension->notification2) {
|
||||
_extension->notification2(_extension_instance, p_notification, static_cast<GDExtensionBool>(true));
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
} else if (_extension->notification) {
|
||||
_extension->notification(_extension_instance, p_notification);
|
||||
#endif // DISABLE_DEPRECATED
|
||||
}
|
||||
}
|
||||
|
||||
// Notify classes starting with most derived subclass and ending in Object.
|
||||
// e.g. Node3D -> Node -> Object
|
||||
_notification_backwardv(p_notification);
|
||||
}
|
||||
|
||||
String Object::to_string() {
|
||||
|
|
@ -1080,8 +1095,8 @@ TypedArray<Dictionary> Object::_get_method_list_bind() const {
|
|||
get_method_list(&ml);
|
||||
TypedArray<Dictionary> ret;
|
||||
|
||||
for (List<MethodInfo>::Element *E = ml.front(); E; E = E->next()) {
|
||||
Dictionary d = E->get();
|
||||
for (const MethodInfo &mi : ml) {
|
||||
Dictionary d = mi;
|
||||
//va.push_back(d);
|
||||
ret.push_back(d);
|
||||
}
|
||||
|
|
@ -1575,7 +1590,7 @@ void Object::initialize_class() {
|
|||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
ClassDB::_add_class<Object>();
|
||||
_add_class_to_classdb(get_class_static(), StringName());
|
||||
_bind_methods();
|
||||
_bind_compatibility_methods();
|
||||
initialized = true;
|
||||
|
|
@ -1640,12 +1655,10 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
|
|||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_var;
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
|
||||
for (const Variant &E : keys) {
|
||||
_clear_internal_resource_paths(E);
|
||||
_clear_internal_resource_paths(d[E]);
|
||||
for (const KeyValue<Variant, Variant> &kv : d) {
|
||||
_clear_internal_resource_paths(kv.key);
|
||||
_clear_internal_resource_paths(kv.value);
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
|
|
@ -1653,9 +1666,20 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
|
|||
}
|
||||
}
|
||||
|
||||
void Object::_add_class_to_classdb(const StringName &p_class, const StringName &p_inherits) {
|
||||
ClassDB::_add_class(p_class, p_inherits);
|
||||
}
|
||||
|
||||
void Object::_get_property_list_from_classdb(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
|
||||
ClassDB::get_property_list(p_class, p_list, p_no_inheritance, p_validator);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded) {
|
||||
set_edited(true);
|
||||
void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded, bool p_initializing) {
|
||||
if (!p_initializing) {
|
||||
set_edited(true);
|
||||
}
|
||||
|
||||
if (p_unfolded) {
|
||||
editor_section_folding.insert(p_section);
|
||||
} else {
|
||||
|
|
@ -1878,7 +1902,7 @@ Variant::Type Object::get_static_property_type(const StringName &p_property, boo
|
|||
}
|
||||
|
||||
Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const {
|
||||
if (p_path.size() == 0) {
|
||||
if (p_path.is_empty()) {
|
||||
if (r_valid) {
|
||||
*r_valid = false;
|
||||
}
|
||||
|
|
@ -1945,6 +1969,20 @@ uint32_t Object::get_edited_version() const {
|
|||
}
|
||||
#endif
|
||||
|
||||
const StringName &Object::get_class_name() const {
|
||||
if (_extension) {
|
||||
// Can't put inside the unlikely as constructor can run it.
|
||||
return _extension->class_name;
|
||||
}
|
||||
|
||||
if (unlikely(!_class_name_ptr)) {
|
||||
// While class is initializing / deinitializing, constructors and destructors
|
||||
// need access to the proper class at the proper stage.
|
||||
return *_get_class_namev();
|
||||
}
|
||||
return *_class_name_ptr;
|
||||
}
|
||||
|
||||
StringName Object::get_class_name_for_extension(const GDExtension *p_library) const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
// If this is the library this extension comes from and it's a placeholder, we
|
||||
|
|
@ -2092,7 +2130,6 @@ void Object::clear_internal_extension() {
|
|||
// Clear the virtual methods.
|
||||
while (virtual_method_list) {
|
||||
(*virtual_method_list->method) = nullptr;
|
||||
(*virtual_method_list->initialized) = false;
|
||||
virtual_method_list = virtual_method_list->next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
#pragma once
|
||||
|
||||
#include "core/disabled_classes.gen.h"
|
||||
#include "core/extension/gdextension_interface.h"
|
||||
#include "core/object/message_queue.h"
|
||||
#include "core/object/object_id.h"
|
||||
|
|
@ -47,6 +47,9 @@
|
|||
template <typename T>
|
||||
class TypedArray;
|
||||
|
||||
template <typename T>
|
||||
class Ref;
|
||||
|
||||
enum PropertyHint {
|
||||
PROPERTY_HINT_NONE, ///< no hint provided.
|
||||
PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_less][,hide_slider][,radians_as_degrees][,degrees][,exp][,suffix:<keyword>] range.
|
||||
|
|
@ -129,6 +132,9 @@ enum PropertyUsageFlags {
|
|||
PROPERTY_USAGE_NO_EDITOR = PROPERTY_USAGE_STORAGE,
|
||||
};
|
||||
|
||||
// Respective values are defined by disabled_classes.gen.h
|
||||
#define GD_IS_CLASS_ENABLED(m_class) m_class::_class_is_enabled
|
||||
|
||||
#define ADD_SIGNAL(m_signal) ::ClassDB::add_signal(get_class_static(), m_signal)
|
||||
#define ADD_PROPERTY(m_property, m_setter, m_getter) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter))
|
||||
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
|
||||
|
|
@ -209,6 +215,7 @@ struct PropertyInfo {
|
|||
};
|
||||
|
||||
TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list);
|
||||
TypedArray<Dictionary> convert_property_list(const Vector<PropertyInfo> &p_vector);
|
||||
|
||||
enum MethodFlags {
|
||||
METHOD_FLAG_NORMAL = 1,
|
||||
|
|
@ -227,7 +234,7 @@ struct MethodInfo {
|
|||
PropertyInfo return_val;
|
||||
uint32_t flags = METHOD_FLAGS_DEFAULT;
|
||||
int id = 0;
|
||||
List<PropertyInfo> arguments;
|
||||
Vector<PropertyInfo> arguments;
|
||||
Vector<Variant> default_arguments;
|
||||
int return_val_metadata = 0;
|
||||
Vector<int> arguments_metadata;
|
||||
|
|
@ -256,8 +263,8 @@ struct MethodInfo {
|
|||
return_val(PropertyInfo(pinfo.return_value)),
|
||||
flags(pinfo.flags),
|
||||
id(pinfo.id) {
|
||||
for (uint32_t j = 0; j < pinfo.argument_count; j++) {
|
||||
arguments.push_back(PropertyInfo(pinfo.arguments[j]));
|
||||
for (uint32_t i = 0; i < pinfo.argument_count; i++) {
|
||||
arguments.push_back(PropertyInfo(pinfo.arguments[i]));
|
||||
}
|
||||
const Variant *def_values = (const Variant *)pinfo.default_arguments;
|
||||
for (uint32_t j = 0; j < pinfo.default_argument_count; j++) {
|
||||
|
|
@ -265,22 +272,12 @@ struct MethodInfo {
|
|||
}
|
||||
}
|
||||
|
||||
void _push_params(const PropertyInfo &p_param) {
|
||||
arguments.push_back(p_param);
|
||||
}
|
||||
|
||||
template <typename... VarArgs>
|
||||
void _push_params(const PropertyInfo &p_param, VarArgs... p_params) {
|
||||
arguments.push_back(p_param);
|
||||
_push_params(p_params...);
|
||||
}
|
||||
|
||||
MethodInfo(const String &p_name) { name = p_name; }
|
||||
|
||||
template <typename... VarArgs>
|
||||
MethodInfo(const String &p_name, VarArgs... p_params) {
|
||||
name = p_name;
|
||||
_push_params(p_params...);
|
||||
arguments = Vector<PropertyInfo>{ p_params... };
|
||||
}
|
||||
|
||||
MethodInfo(Variant::Type ret) { return_val.type = ret; }
|
||||
|
|
@ -293,7 +290,7 @@ struct MethodInfo {
|
|||
MethodInfo(Variant::Type ret, const String &p_name, VarArgs... p_params) {
|
||||
name = p_name;
|
||||
return_val.type = ret;
|
||||
_push_params(p_params...);
|
||||
arguments = Vector<PropertyInfo>{ p_params... };
|
||||
}
|
||||
|
||||
MethodInfo(const PropertyInfo &p_ret, const String &p_name) {
|
||||
|
|
@ -305,7 +302,7 @@ struct MethodInfo {
|
|||
MethodInfo(const PropertyInfo &p_ret, const String &p_name, VarArgs... p_params) {
|
||||
return_val = p_ret;
|
||||
name = p_name;
|
||||
_push_params(p_params...);
|
||||
arguments = Vector<PropertyInfo>{ p_params... };
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -396,57 +393,46 @@ struct ObjectGDExtension {
|
|||
* much alone defines the object model.
|
||||
*/
|
||||
|
||||
// This is a barebones version of GDCLASS,
|
||||
// only intended for simple classes deriving from Object
|
||||
// so that they can support the `Object::cast_to()` method.
|
||||
#define GDSOFTCLASS(m_class, m_inherits) \
|
||||
public: \
|
||||
using self_type = m_class; \
|
||||
using super_type = m_inherits; \
|
||||
static _FORCE_INLINE_ void *get_class_ptr_static() { \
|
||||
static int ptr; \
|
||||
return &ptr; \
|
||||
} \
|
||||
virtual bool is_class_ptr(void *p_ptr) const override { \
|
||||
return (p_ptr == get_class_ptr_static()) || m_inherits::is_class_ptr(p_ptr); \
|
||||
} \
|
||||
\
|
||||
private:
|
||||
|
||||
#define GDCLASS(m_class, m_inherits) \
|
||||
GDSOFTCLASS(m_class, m_inherits) \
|
||||
private: \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
friend class ::ClassDB; \
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
static constexpr bool _class_is_enabled = !bool(GD_IS_DEFINED(ClassDB_Disable_##m_class)) && m_inherits::_class_is_enabled; \
|
||||
virtual String get_class() const override { \
|
||||
if (_get_extension()) { \
|
||||
return _get_extension()->class_name.operator String(); \
|
||||
} \
|
||||
return String(#m_class); \
|
||||
} \
|
||||
virtual const StringName *_get_class_namev() const override { \
|
||||
return &get_class_static(); \
|
||||
} \
|
||||
static const StringName &get_class_static() { \
|
||||
static StringName _class_name_static; \
|
||||
if (unlikely(!_class_name_static)) { \
|
||||
StringName::assign_static_unique_class_name(&_class_name_static, #m_class); \
|
||||
} \
|
||||
return &_class_name_static; \
|
||||
} \
|
||||
static _FORCE_INLINE_ void *get_class_ptr_static() { \
|
||||
static int ptr; \
|
||||
return &ptr; \
|
||||
} \
|
||||
static _FORCE_INLINE_ String get_class_static() { \
|
||||
return String(#m_class); \
|
||||
} \
|
||||
static _FORCE_INLINE_ String get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
static void get_inheritance_list_static(List<String> *p_inheritance_list) { \
|
||||
m_inherits::get_inheritance_list_static(p_inheritance_list); \
|
||||
p_inheritance_list->push_back(String(#m_class)); \
|
||||
return _class_name_static; \
|
||||
} \
|
||||
virtual bool is_class(const String &p_class) const override { \
|
||||
if (_get_extension() && _get_extension()->is_class(p_class)) { \
|
||||
return true; \
|
||||
} \
|
||||
return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \
|
||||
} \
|
||||
virtual bool is_class_ptr(void *p_ptr) const override { \
|
||||
return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); \
|
||||
} \
|
||||
\
|
||||
static void get_valid_parents_static(List<String> *p_parents) { \
|
||||
if (m_class::_get_valid_parents_static != m_inherits::_get_valid_parents_static) { \
|
||||
m_class::_get_valid_parents_static(p_parents); \
|
||||
} \
|
||||
\
|
||||
m_inherits::get_valid_parents_static(p_parents); \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
|
|
@ -464,7 +450,7 @@ public:
|
|||
return; \
|
||||
} \
|
||||
m_inherits::initialize_class(); \
|
||||
::ClassDB::_add_class<m_class>(); \
|
||||
_add_class_to_classdb(get_class_static(), super_type::get_class_static()); \
|
||||
if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \
|
||||
_bind_methods(); \
|
||||
} \
|
||||
|
|
@ -479,7 +465,7 @@ protected:
|
|||
initialize_class(); \
|
||||
} \
|
||||
_FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &) const { \
|
||||
return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_get; \
|
||||
return (bool (Object::*)(const StringName &, Variant &) const) & m_class::_get; \
|
||||
} \
|
||||
virtual bool _getv(const StringName &p_name, Variant &r_ret) const override { \
|
||||
if (m_class::_get_get() != m_inherits::_get_get()) { \
|
||||
|
|
@ -490,7 +476,7 @@ protected:
|
|||
return m_inherits::_getv(p_name, r_ret); \
|
||||
} \
|
||||
_FORCE_INLINE_ bool (Object::*_get_set() const)(const StringName &p_name, const Variant &p_property) { \
|
||||
return (bool(Object::*)(const StringName &, const Variant &)) & m_class::_set; \
|
||||
return (bool (Object::*)(const StringName &, const Variant &)) & m_class::_set; \
|
||||
} \
|
||||
virtual bool _setv(const StringName &p_name, const Variant &p_property) override { \
|
||||
if (m_inherits::_setv(p_name, p_property)) { \
|
||||
|
|
@ -502,14 +488,14 @@ protected:
|
|||
return false; \
|
||||
} \
|
||||
_FORCE_INLINE_ void (Object::*_get_get_property_list() const)(List<PropertyInfo> * p_list) const { \
|
||||
return (void(Object::*)(List<PropertyInfo> *) const) & m_class::_get_property_list; \
|
||||
return (void (Object::*)(List<PropertyInfo> *) const) & m_class::_get_property_list; \
|
||||
} \
|
||||
virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const override { \
|
||||
if (!p_reversed) { \
|
||||
m_inherits::_get_property_listv(p_list, p_reversed); \
|
||||
} \
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, get_class_static(), PROPERTY_HINT_NONE, get_class_static(), PROPERTY_USAGE_CATEGORY)); \
|
||||
::ClassDB::get_property_list(#m_class, p_list, true, this); \
|
||||
_get_property_list_from_classdb(#m_class, p_list, true, this); \
|
||||
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
|
||||
_get_property_list(p_list); \
|
||||
} \
|
||||
|
|
@ -518,7 +504,7 @@ protected:
|
|||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ void (Object::*_get_validate_property() const)(PropertyInfo & p_property) const { \
|
||||
return (void(Object::*)(PropertyInfo &) const) & m_class::_validate_property; \
|
||||
return (void (Object::*)(PropertyInfo &) const) & m_class::_validate_property; \
|
||||
} \
|
||||
virtual void _validate_propertyv(PropertyInfo &p_property) const override { \
|
||||
m_inherits::_validate_propertyv(p_property); \
|
||||
|
|
@ -527,7 +513,7 @@ protected:
|
|||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ bool (Object::*_get_property_can_revert() const)(const StringName &p_name) const { \
|
||||
return (bool(Object::*)(const StringName &) const) & m_class::_property_can_revert; \
|
||||
return (bool (Object::*)(const StringName &) const) & m_class::_property_can_revert; \
|
||||
} \
|
||||
virtual bool _property_can_revertv(const StringName &p_name) const override { \
|
||||
if (m_class::_get_property_can_revert() != m_inherits::_get_property_can_revert()) { \
|
||||
|
|
@ -538,7 +524,7 @@ protected:
|
|||
return m_inherits::_property_can_revertv(p_name); \
|
||||
} \
|
||||
_FORCE_INLINE_ bool (Object::*_get_property_get_revert() const)(const StringName &p_name, Variant &) const { \
|
||||
return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_property_get_revert; \
|
||||
return (bool (Object::*)(const StringName &, Variant &) const) & m_class::_property_get_revert; \
|
||||
} \
|
||||
virtual bool _property_get_revertv(const StringName &p_name, Variant &r_ret) const override { \
|
||||
if (m_class::_get_property_get_revert() != m_inherits::_get_property_get_revert()) { \
|
||||
|
|
@ -549,18 +535,19 @@ protected:
|
|||
return m_inherits::_property_get_revertv(p_name, r_ret); \
|
||||
} \
|
||||
_FORCE_INLINE_ void (Object::*_get_notification() const)(int) { \
|
||||
return (void(Object::*)(int)) & m_class::_notification; \
|
||||
return (void (Object::*)(int)) & m_class::_notification; \
|
||||
} \
|
||||
virtual void _notificationv(int p_notification, bool p_reversed) override { \
|
||||
if (!p_reversed) { \
|
||||
m_inherits::_notificationv(p_notification, p_reversed); \
|
||||
} \
|
||||
virtual void _notification_forwardv(int p_notification) override { \
|
||||
m_inherits::_notification_forwardv(p_notification); \
|
||||
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||
_notification(p_notification); \
|
||||
} \
|
||||
if (p_reversed) { \
|
||||
m_inherits::_notificationv(p_notification, p_reversed); \
|
||||
} \
|
||||
virtual void _notification_backwardv(int p_notification) override { \
|
||||
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||
_notification(p_notification); \
|
||||
} \
|
||||
m_inherits::_notification_backwardv(p_notification); \
|
||||
} \
|
||||
\
|
||||
private:
|
||||
|
|
@ -704,7 +691,11 @@ protected:
|
|||
virtual void _validate_propertyv(PropertyInfo &p_property) const {}
|
||||
virtual bool _property_can_revertv(const StringName &p_name) const { return false; }
|
||||
virtual bool _property_get_revertv(const StringName &p_name, Variant &r_property) const { return false; }
|
||||
virtual void _notificationv(int p_notification, bool p_reversed) {}
|
||||
|
||||
void _notification_forward(int p_notification);
|
||||
void _notification_backward(int p_notification);
|
||||
virtual void _notification_forwardv(int p_notification) {}
|
||||
virtual void _notification_backwardv(int p_notification) {}
|
||||
|
||||
static void _bind_methods();
|
||||
static void _bind_compatibility_methods() {}
|
||||
|
|
@ -743,18 +734,12 @@ protected:
|
|||
_FORCE_INLINE_ void (Object::*_get_notification() const)(int) {
|
||||
return &Object::_notification;
|
||||
}
|
||||
static void get_valid_parents_static(List<String> *p_parents);
|
||||
static void _get_valid_parents_static(List<String> *p_parents);
|
||||
|
||||
Variant _call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||
Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||
|
||||
virtual const StringName *_get_class_namev() const {
|
||||
static StringName _class_name_static;
|
||||
if (unlikely(!_class_name_static)) {
|
||||
StringName::assign_static_unique_class_name(&_class_name_static, "Object");
|
||||
}
|
||||
return &_class_name_static;
|
||||
return &get_class_static();
|
||||
}
|
||||
|
||||
TypedArray<StringName> _get_meta_list_bind() const;
|
||||
|
|
@ -766,12 +751,14 @@ protected:
|
|||
friend class ClassDB;
|
||||
friend class PlaceholderExtensionInstance;
|
||||
|
||||
static void _add_class_to_classdb(const StringName &p_class, const StringName &p_inherits);
|
||||
static void _get_property_list_from_classdb(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator);
|
||||
|
||||
bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
struct VirtualMethodTracker {
|
||||
void **method;
|
||||
bool *initialized;
|
||||
VirtualMethodTracker *next;
|
||||
};
|
||||
|
||||
|
|
@ -797,12 +784,18 @@ public:
|
|||
|
||||
template <typename T>
|
||||
static T *cast_to(Object *p_object) {
|
||||
return p_object ? dynamic_cast<T *>(p_object) : nullptr;
|
||||
// This is like dynamic_cast, but faster.
|
||||
// The reason is that we can assume no virtual and multiple inheritance.
|
||||
static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
|
||||
static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
|
||||
return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<T *>(p_object) : nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static const T *cast_to(const Object *p_object) {
|
||||
return p_object ? dynamic_cast<const T *>(p_object) : nullptr;
|
||||
static_assert(std::is_base_of_v<Object, T>, "T must be derived from Object");
|
||||
static_assert(std::is_same_v<std::decay_t<T>, typename T::self_type>, "T must use GDCLASS or GDSOFTCLASS");
|
||||
return p_object && p_object->is_class_ptr(T::get_class_ptr_static()) ? static_cast<const T *>(p_object) : nullptr;
|
||||
}
|
||||
|
||||
enum {
|
||||
|
|
@ -814,17 +807,16 @@ public:
|
|||
};
|
||||
|
||||
/* TYPE API */
|
||||
static void get_inheritance_list_static(List<String> *p_inheritance_list) { p_inheritance_list->push_back("Object"); }
|
||||
|
||||
static String get_class_static() { return "Object"; }
|
||||
static String get_parent_class_static() { return String(); }
|
||||
|
||||
virtual String get_class() const {
|
||||
if (_extension) {
|
||||
return _extension->class_name.operator String();
|
||||
static const StringName &get_class_static() {
|
||||
static StringName _class_name_static;
|
||||
if (unlikely(!_class_name_static)) {
|
||||
StringName::assign_static_unique_class_name(&_class_name_static, "Object");
|
||||
}
|
||||
return "Object";
|
||||
return _class_name_static;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ String get_class() const { return get_class_name(); }
|
||||
|
||||
virtual String get_save_class() const { return get_class(); } //class stored when saving
|
||||
|
||||
virtual bool is_class(const String &p_class) const {
|
||||
|
|
@ -835,19 +827,7 @@ public:
|
|||
}
|
||||
virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; }
|
||||
|
||||
_FORCE_INLINE_ const StringName &get_class_name() const {
|
||||
if (_extension) {
|
||||
// Can't put inside the unlikely as constructor can run it
|
||||
return _extension->class_name;
|
||||
}
|
||||
|
||||
if (unlikely(!_class_name_ptr)) {
|
||||
// While class is initializing / deinitializing, constructors and destructurs
|
||||
// need access to the proper class at the proper stage.
|
||||
return *_get_class_namev();
|
||||
}
|
||||
return *_class_name_ptr;
|
||||
}
|
||||
const StringName &get_class_name() const;
|
||||
|
||||
StringName get_class_name_for_extension(const GDExtension *p_library) const;
|
||||
|
||||
|
|
@ -882,7 +862,17 @@ public:
|
|||
return (cerr.error == Callable::CallError::CALL_OK) ? ret : Variant();
|
||||
}
|
||||
|
||||
void notification(int p_notification, bool p_reversed = false);
|
||||
// Depending on the boolean, we call either the virtual function _notification_backward or _notification_forward.
|
||||
// - Forward calls subclasses in descending order (e.g. Object -> Node -> Node3D -> extension -> script).
|
||||
// Backward calls subclasses in descending order (e.g. script -> extension -> Node3D -> Node -> Object).
|
||||
_FORCE_INLINE_ void notification(int p_notification, bool p_reversed = false) {
|
||||
if (p_reversed) {
|
||||
_notification_backward(p_notification);
|
||||
} else {
|
||||
_notification_forward(p_notification);
|
||||
}
|
||||
}
|
||||
|
||||
virtual String to_string();
|
||||
|
||||
// Used mainly by script, get and set all INCLUDING string.
|
||||
|
|
@ -974,7 +964,7 @@ public:
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
|
||||
void editor_set_section_unfold(const String &p_section, bool p_unfolded);
|
||||
void editor_set_section_unfold(const String &p_section, bool p_unfolded, bool p_initializing = false);
|
||||
bool editor_is_section_unfolded(const String &p_section);
|
||||
const HashSet<String> &editor_get_section_folding() const { return editor_section_folding; }
|
||||
void editor_clear_section_folding() { editor_section_folding.clear(); }
|
||||
|
|
@ -1062,8 +1052,15 @@ public:
|
|||
|
||||
return object;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
_ALWAYS_INLINE_ static T *get_instance(ObjectID p_instance_id) {
|
||||
return Object::cast_to<T>(get_instance(p_instance_id));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
_ALWAYS_INLINE_ static Ref<T> get_ref(ObjectID p_instance_id); // Defined in ref_counted.h
|
||||
|
||||
static void debug_objects(DebugFunc p_func);
|
||||
static int get_object_count();
|
||||
};
|
||||
|
||||
#endif // OBJECT_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef OBJECT_ID_H
|
||||
#define OBJECT_ID_H
|
||||
#pragma once
|
||||
|
||||
#include "core/typedefs.h"
|
||||
|
||||
|
|
@ -60,4 +59,5 @@ public:
|
|||
_ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
|
||||
};
|
||||
|
||||
#endif // OBJECT_ID_H
|
||||
template <>
|
||||
struct is_zero_constructible<ObjectID> : std::true_type {};
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef REF_COUNTED_H
|
||||
#define REF_COUNTED_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/templates/safe_refcount.h"
|
||||
|
|
@ -86,6 +85,10 @@ class Ref {
|
|||
|
||||
//virtual RefCounted * get_reference() const { return reference; }
|
||||
public:
|
||||
static _FORCE_INLINE_ String get_class_static() {
|
||||
return T::get_class_static();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const T *p_ptr) const {
|
||||
return reference == p_ptr;
|
||||
}
|
||||
|
|
@ -128,6 +131,15 @@ public:
|
|||
ref(p_from);
|
||||
}
|
||||
|
||||
void operator=(Ref &&p_from) {
|
||||
if (reference == p_from.reference) {
|
||||
return;
|
||||
}
|
||||
unref();
|
||||
reference = p_from.reference;
|
||||
p_from.reference = nullptr;
|
||||
}
|
||||
|
||||
template <typename T_Other>
|
||||
void operator=(const Ref<T_Other> &p_from) {
|
||||
ref_pointer<false>(Object::cast_to<T>(p_from.ptr()));
|
||||
|
|
@ -160,6 +172,11 @@ public:
|
|||
this->operator=(p_from);
|
||||
}
|
||||
|
||||
Ref(Ref &&p_from) {
|
||||
reference = p_from.reference;
|
||||
p_from.reference = nullptr;
|
||||
}
|
||||
|
||||
template <typename T_Other>
|
||||
Ref(const Ref<T_Other> &p_from) {
|
||||
this->operator=(p_from);
|
||||
|
|
@ -181,10 +198,15 @@ public:
|
|||
// do a lot of referencing on references and stuff
|
||||
// mutexes will avoid more crashes?
|
||||
|
||||
if (reference && reference->unreference()) {
|
||||
memdelete(reference);
|
||||
if (reference) {
|
||||
// NOTE: `reinterpret_cast` is "safe" here because we know `T` has simple linear
|
||||
// inheritance to `RefCounted`. This guarantees that `T * == `RefCounted *`, which
|
||||
// allows us to declare `Ref<T>` with forward declared `T` types.
|
||||
if (reinterpret_cast<RefCounted *>(reference)->unreference()) {
|
||||
memdelete(reinterpret_cast<RefCounted *>(reference));
|
||||
}
|
||||
reference = nullptr;
|
||||
}
|
||||
reference = nullptr;
|
||||
}
|
||||
|
||||
template <typename... VarArgs>
|
||||
|
|
@ -233,19 +255,6 @@ struct PtrToArg<Ref<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct PtrToArg<const Ref<T> &> {
|
||||
typedef Ref<T> EncodeT;
|
||||
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
if (p_ptr == nullptr) {
|
||||
return Ref<T>();
|
||||
}
|
||||
// p_ptr points to a RefCounted object
|
||||
return Ref<T>(*((T *const *)p_ptr));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<Ref<T>> {
|
||||
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
|
||||
|
|
@ -256,26 +265,17 @@ struct GetTypeInfo<Ref<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<const Ref<T> &> {
|
||||
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
|
||||
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
|
||||
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VariantInternalAccessor<Ref<T>> {
|
||||
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
|
||||
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::object_assign(v, p_ref); }
|
||||
};
|
||||
|
||||
// Zero-constructing Ref initializes reference to nullptr (and thus empty).
|
||||
template <typename T>
|
||||
struct VariantInternalAccessor<const Ref<T> &> {
|
||||
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
|
||||
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::object_assign(v, p_ref); }
|
||||
};
|
||||
struct is_zero_constructible<Ref<T>> : std::true_type {};
|
||||
|
||||
#endif // REF_COUNTED_H
|
||||
template <typename T>
|
||||
Ref<T> ObjectDB::get_ref(ObjectID p_instance_id) {
|
||||
return Ref<T>(get_instance(p_instance_id));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCRIPT_INSTANCE_H
|
||||
#define SCRIPT_INSTANCE_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
|
|
@ -96,5 +95,3 @@ public:
|
|||
virtual ScriptLanguage *get_language() = 0;
|
||||
virtual ~ScriptInstance();
|
||||
};
|
||||
|
||||
#endif // SCRIPT_INSTANCE_H
|
||||
|
|
|
|||
|
|
@ -633,6 +633,7 @@ void ScriptLanguage::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_PASCAL_CASE);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_SNAKE_CASE);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_KEBAB_CASE);
|
||||
BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_CAMEL_CASE);
|
||||
}
|
||||
|
||||
bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCRIPT_LANGUAGE_H
|
||||
#define SCRIPT_LANGUAGE_H
|
||||
#pragma once
|
||||
|
||||
#include "core/doc_data.h"
|
||||
#include "core/io/resource.h"
|
||||
|
|
@ -247,6 +246,7 @@ public:
|
|||
SCRIPT_NAME_CASING_PASCAL_CASE,
|
||||
SCRIPT_NAME_CASING_SNAKE_CASE,
|
||||
SCRIPT_NAME_CASING_KEBAB_CASE,
|
||||
SCRIPT_NAME_CASING_CAMEL_CASE,
|
||||
};
|
||||
|
||||
struct ScriptTemplate {
|
||||
|
|
@ -505,5 +505,3 @@ public:
|
|||
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
|
||||
~PlaceHolderScriptInstance();
|
||||
};
|
||||
|
||||
#endif // SCRIPT_LANGUAGE_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCRIPT_LANGUAGE_EXTENSION_H
|
||||
#define SCRIPT_LANGUAGE_EXTENSION_H
|
||||
#pragma once
|
||||
|
||||
#include "core/extension/ext_wrappers.gen.inc"
|
||||
#include "core/object/gdvirtual.gen.inc"
|
||||
|
|
@ -193,10 +192,8 @@ public:
|
|||
virtual void get_constants(HashMap<StringName, Variant> *p_constants) override {
|
||||
Dictionary constants;
|
||||
GDVIRTUAL_CALL(_get_constants, constants);
|
||||
List<Variant> keys;
|
||||
constants.get_key_list(&keys);
|
||||
for (const Variant &K : keys) {
|
||||
p_constants->insert(K, constants[K]);
|
||||
for (const KeyValue<Variant, Variant> &kv : constants) {
|
||||
p_constants->insert(kv.key, kv.value);
|
||||
}
|
||||
}
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<StringName>, _get_members)
|
||||
|
|
@ -516,7 +513,7 @@ public:
|
|||
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_CALL(_debug_get_stack_level_locals, p_level, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
if (ret.is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (p_locals != nullptr && ret.has("locals")) {
|
||||
|
|
@ -536,7 +533,7 @@ public:
|
|||
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_CALL(_debug_get_stack_level_members, p_level, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
if (ret.is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (p_members != nullptr && ret.has("members")) {
|
||||
|
|
@ -563,7 +560,7 @@ public:
|
|||
virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_CALL(_debug_get_globals, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
if (ret.is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (p_globals != nullptr && ret.has("globals")) {
|
||||
|
|
@ -714,11 +711,7 @@ public:
|
|||
|
||||
GDExtensionScriptInstanceDataPtr instance = nullptr;
|
||||
|
||||
// There should not be warnings on explicit casts.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#endif
|
||||
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wignored-qualifiers") // There should not be warnings on explicit casts.
|
||||
|
||||
virtual bool set(const StringName &p_name, const Variant &p_value) override {
|
||||
if (native_info->set_func) {
|
||||
|
|
@ -966,9 +959,5 @@ public:
|
|||
#endif // DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
GODOT_GCC_WARNING_POP
|
||||
};
|
||||
|
||||
#endif // SCRIPT_LANGUAGE_EXTENSION_H
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef UNDO_REDO_H
|
||||
#define UNDO_REDO_H
|
||||
#pragma once
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
|
|
@ -151,5 +150,3 @@ public:
|
|||
};
|
||||
|
||||
VARIANT_ENUM_CAST(UndoRedo::MergeMode);
|
||||
|
||||
#endif // UNDO_REDO_H
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
WorkerThreadPool::Task *const WorkerThreadPool::ThreadData::YIELDING = (Task *)1;
|
||||
|
||||
HashMap<StringName, WorkerThreadPool *> WorkerThreadPool::named_pools;
|
||||
|
||||
void WorkerThreadPool::Task::free_template_userdata() {
|
||||
ERR_FAIL_NULL(template_userdata);
|
||||
ERR_FAIL_NULL(native_func_userdata);
|
||||
|
|
@ -184,26 +186,34 @@ void WorkerThreadPool::_thread_function(void *p_user) {
|
|||
while (true) {
|
||||
Task *task_to_process = nullptr;
|
||||
{
|
||||
MutexLock lock(singleton->task_mutex);
|
||||
// Create the lock outside the inner loop so it isn't needlessly unlocked and relocked
|
||||
// when no task was found to process, and the loop is re-entered.
|
||||
MutexLock lock(thread_data->pool->task_mutex);
|
||||
|
||||
bool exit = singleton->_handle_runlevel(thread_data, lock);
|
||||
if (unlikely(exit)) {
|
||||
while (true) {
|
||||
bool exit = thread_data->pool->_handle_runlevel(thread_data, lock);
|
||||
if (unlikely(exit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread_data->signaled = false;
|
||||
|
||||
if (!thread_data->pool->task_queue.first()) {
|
||||
// There wasn't a task available yet.
|
||||
// Let's wait for the next notification, then recheck.
|
||||
thread_data->cond_var.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Got a task to process! Remove it from the queue, then break into the task handling section.
|
||||
task_to_process = thread_data->pool->task_queue.first()->self();
|
||||
thread_data->pool->task_queue.remove(thread_data->pool->task_queue.first());
|
||||
break;
|
||||
}
|
||||
|
||||
thread_data->signaled = false;
|
||||
|
||||
if (singleton->task_queue.first()) {
|
||||
task_to_process = singleton->task_queue.first()->self();
|
||||
singleton->task_queue.remove(singleton->task_queue.first());
|
||||
} else {
|
||||
thread_data->cond_var.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (task_to_process) {
|
||||
singleton->_process_task(task_to_process);
|
||||
}
|
||||
DEV_ASSERT(task_to_process);
|
||||
thread_data->pool->_process_task(task_to_process);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +221,7 @@ void WorkerThreadPool::_post_tasks(Task **p_tasks, uint32_t p_count, bool p_high
|
|||
// Fall back to processing on the calling thread if there are no worker threads.
|
||||
// Separated into its own variable to make it easier to extend this logic
|
||||
// in custom builds.
|
||||
bool process_on_calling_thread = threads.size() == 0;
|
||||
bool process_on_calling_thread = threads.is_empty();
|
||||
if (process_on_calling_thread) {
|
||||
p_lock.temp_unlock();
|
||||
for (uint32_t i = 0; i < p_count; i++) {
|
||||
|
|
@ -497,7 +507,7 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
}
|
||||
}
|
||||
|
||||
if (singleton->task_queue.first()) {
|
||||
if (p_caller_pool_thread->pool->task_queue.first()) {
|
||||
task_to_process = task_queue.first()->self();
|
||||
task_queue.remove(task_queue.first());
|
||||
}
|
||||
|
|
@ -505,7 +515,9 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
if (!task_to_process) {
|
||||
p_caller_pool_thread->awaited_task = p_task;
|
||||
|
||||
_unlock_unlockable_mutexes();
|
||||
if (this == singleton) {
|
||||
_unlock_unlockable_mutexes();
|
||||
}
|
||||
relock_unlockables = true;
|
||||
|
||||
p_caller_pool_thread->cond_var.wait(lock);
|
||||
|
|
@ -514,7 +526,7 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
}
|
||||
}
|
||||
|
||||
if (relock_unlockables) {
|
||||
if (relock_unlockables && this == singleton) {
|
||||
_lock_unlockable_mutexes();
|
||||
}
|
||||
|
||||
|
|
@ -690,9 +702,13 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
|
|||
{
|
||||
Group *group = *groupp;
|
||||
|
||||
_unlock_unlockable_mutexes();
|
||||
if (this == singleton) {
|
||||
_unlock_unlockable_mutexes();
|
||||
}
|
||||
group->done_semaphore.wait();
|
||||
_lock_unlockable_mutexes();
|
||||
if (this == singleton) {
|
||||
_lock_unlockable_mutexes();
|
||||
}
|
||||
|
||||
uint32_t max_users = group->tasks_used + 1; // Add 1 because the thread waiting for it is also user. Read before to avoid another thread freeing task after increment.
|
||||
uint32_t finished_users = group->finished.increment(); // fetch happens before inc, so increment later.
|
||||
|
|
@ -709,15 +725,15 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int WorkerThreadPool::get_thread_index() {
|
||||
int WorkerThreadPool::get_thread_index() const {
|
||||
Thread::ID tid = Thread::get_caller_id();
|
||||
return singleton->thread_ids.has(tid) ? singleton->thread_ids[tid] : -1;
|
||||
return thread_ids.has(tid) ? thread_ids[tid] : -1;
|
||||
}
|
||||
|
||||
WorkerThreadPool::TaskID WorkerThreadPool::get_caller_task_id() {
|
||||
WorkerThreadPool::TaskID WorkerThreadPool::get_caller_task_id() const {
|
||||
int th_index = get_thread_index();
|
||||
if (th_index != -1 && singleton->threads[th_index].current_task) {
|
||||
return singleton->threads[th_index].current_task->self;
|
||||
if (th_index != -1 && threads[th_index].current_task) {
|
||||
return threads[th_index].current_task->self;
|
||||
} else {
|
||||
return INVALID_TASK_ID;
|
||||
}
|
||||
|
|
@ -764,15 +780,29 @@ void WorkerThreadPool::init(int p_thread_count, float p_low_priority_task_ratio)
|
|||
|
||||
threads.resize(p_thread_count);
|
||||
|
||||
Thread::Settings settings;
|
||||
#ifdef __APPLE__
|
||||
// The default stack size for new threads on Apple platforms is 512KiB.
|
||||
// This is insufficient when using a library like SPIRV-Cross,
|
||||
// which can generate deep stacks and result in a stack overflow.
|
||||
#ifdef DEV_ENABLED
|
||||
// Debug builds need an even larger stack size.
|
||||
settings.stack_size = 2 * 1024 * 1024; // 2 MiB
|
||||
#else
|
||||
settings.stack_size = 1 * 1024 * 1024; // 1 MiB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < threads.size(); i++) {
|
||||
threads[i].index = i;
|
||||
threads[i].thread.start(&WorkerThreadPool::_thread_function, &threads[i]);
|
||||
threads[i].pool = this;
|
||||
threads[i].thread.start(&WorkerThreadPool::_thread_function, &threads[i], settings);
|
||||
thread_ids.insert(threads[i].thread.get_id(), i);
|
||||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::exit_languages_threads() {
|
||||
if (threads.size() == 0) {
|
||||
if (threads.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -792,7 +822,7 @@ void WorkerThreadPool::exit_languages_threads() {
|
|||
}
|
||||
|
||||
void WorkerThreadPool::finish() {
|
||||
if (threads.size() == 0) {
|
||||
if (threads.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -832,10 +862,33 @@ void WorkerThreadPool::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("wait_for_group_task_completion", "group_id"), &WorkerThreadPool::wait_for_group_task_completion);
|
||||
}
|
||||
|
||||
WorkerThreadPool::WorkerThreadPool() {
|
||||
singleton = this;
|
||||
WorkerThreadPool *WorkerThreadPool::get_named_pool(const StringName &p_name) {
|
||||
WorkerThreadPool **pool_ptr = named_pools.getptr(p_name);
|
||||
if (pool_ptr) {
|
||||
return *pool_ptr;
|
||||
} else {
|
||||
WorkerThreadPool *pool = memnew(WorkerThreadPool(false));
|
||||
pool->init();
|
||||
named_pools[p_name] = pool;
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
||||
WorkerThreadPool::WorkerThreadPool(bool p_singleton) {
|
||||
if (p_singleton) {
|
||||
singleton = this;
|
||||
}
|
||||
}
|
||||
|
||||
WorkerThreadPool::~WorkerThreadPool() {
|
||||
finish();
|
||||
|
||||
if (this == singleton) {
|
||||
singleton = nullptr;
|
||||
for (KeyValue<StringName, WorkerThreadPool *> &E : named_pools) {
|
||||
E.value->finish();
|
||||
memdelete(E.value);
|
||||
}
|
||||
named_pools.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef WORKER_THREAD_POOL_H
|
||||
#define WORKER_THREAD_POOL_H
|
||||
#pragma once
|
||||
|
||||
#include "core/os/condition_variable.h"
|
||||
#include "core/os/memory.h"
|
||||
|
|
@ -119,6 +118,7 @@ private:
|
|||
Task *current_task = nullptr;
|
||||
Task *awaited_task = nullptr; // Null if not awaiting the condition variable, or special value (YIELDING).
|
||||
ConditionVariable cond_var;
|
||||
WorkerThreadPool *pool = nullptr;
|
||||
|
||||
ThreadData() :
|
||||
signaled(false),
|
||||
|
|
@ -166,6 +166,8 @@ private:
|
|||
|
||||
uint64_t last_task = 1;
|
||||
|
||||
static HashMap<StringName, WorkerThreadPool *> named_pools;
|
||||
|
||||
static void _thread_function(void *p_user);
|
||||
|
||||
void _process_task(Task *task);
|
||||
|
|
@ -266,9 +268,12 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
// Note: Do not use this unless you know what you are doing, and it is absolutely necessary. Main thread pool (`get_singleton()`) should be preferred instead.
|
||||
static WorkerThreadPool *get_named_pool(const StringName &p_name);
|
||||
|
||||
static WorkerThreadPool *get_singleton() { return singleton; }
|
||||
static int get_thread_index();
|
||||
static TaskID get_caller_task_id();
|
||||
int get_thread_index() const;
|
||||
TaskID get_caller_task_id() const;
|
||||
|
||||
#ifdef THREADS_ENABLED
|
||||
_ALWAYS_INLINE_ static uint32_t thread_enter_unlock_allowance_zone(const MutexLock<BinaryMutex> &p_lock) { return _thread_enter_unlock_allowance_zone(p_lock._get_lock()); }
|
||||
|
|
@ -285,8 +290,6 @@ public:
|
|||
void init(int p_thread_count = -1, float p_low_priority_task_ratio = 0.3);
|
||||
void exit_languages_threads();
|
||||
void finish();
|
||||
WorkerThreadPool();
|
||||
WorkerThreadPool(bool p_singleton = true);
|
||||
~WorkerThreadPool();
|
||||
};
|
||||
|
||||
#endif // WORKER_THREAD_POOL_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue