Compare commits

..

1 Commits

Author SHA1 Message Date
David Snopek 2e0fb69144 Allow registering "gameplay classes" 2024-01-02 16:26:20 -06:00
33 changed files with 254 additions and 748 deletions

View File

@ -58,7 +58,7 @@ first-party `godot-cpp` extension.
Some compatibility breakage is to be expected as GDExtension and `godot-cpp` Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
get more used, documented, and critical issues get resolved. See the get more used, documented, and critical issues get resolved. See the
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension) [Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues) and the [godot-cpp issue tracker](https://github.com/godotengine/godot/issues)
for a list of known issues, and be sure to provide feedback on issues and PRs for a list of known issues, and be sure to provide feedback on issues and PRs
which affect your use of this extension. which affect your use of this extension.
@ -74,10 +74,7 @@ so formatting is done before your changes are submitted.
## Getting started ## Getting started
You need the same C++ pre-requisites installed that are required for the `godot` repository. Follow the [official build instructions for your target platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/index.html#building-for-target-platforms). It's a bit similar to what it was for 3.x but also a bit different.
Getting started with GDExtensions is a bit similar to what it was for 3.x but also a bit different.
This new approach is much more akin to how core Godot modules are structured. This new approach is much more akin to how core Godot modules are structured.
Compiling this repository generates a static library to be linked with your shared lib, Compiling this repository generates a static library to be linked with your shared lib,

View File

@ -70,136 +70,6 @@ def generate_wrappers(target):
f.write(txt) f.write(txt)
def generate_virtual_version(argcount, const=False, returns=False):
s = """#define GDVIRTUAL$VER($RET m_name $ARG)\\
StringName _gdvirtual_##m_name##_sn = #m_name;\\
template <bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST {\\
if (::godot::internal::gdextension_interface_object_has_script_method(_owner, &_gdvirtual_##m_name##_sn)) { \\
GDExtensionCallError ce;\\
$CALLSIARGS\\
$CALLSIBEGIN::godot::internal::gdextension_interface_object_call_script_method(_owner, &_gdvirtual_##m_name##_sn, $CALLSIARGPASS, $CALLSIRETPASS, &ce);\\
if (ce.error == GDEXTENSION_CALL_OK) {\\
$CALLSIRET\\
return true;\\
}\\
}\\
if (required) {\\
ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");\\
$RVOID\\
}\\
return false;\\
}\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const {\\
return godot::internal::gdextension_interface_object_has_script_method(_owner, &_gdvirtual_##m_name##_sn); \\
}\\
_FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() {\\
MethodInfo method_info;\\
method_info.name = #m_name;\\
method_info.flags = $METHOD_FLAGS;\\
$FILL_METHOD_INFO\\
return method_info;\\
}
"""
sproto = str(argcount)
method_info = ""
if returns:
sproto += "R"
s = s.replace("$RET", "m_ret,")
s = s.replace("$RVOID", "(void)r_ret;") # If required, may lead to uninitialized errors
method_info += "method_info.return_val = GetTypeInfo<m_ret>::get_class_info();\\\n"
method_info += "\t\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;"
else:
s = s.replace("$RET ", "")
s = s.replace("\t\t\t$RVOID\\\n", "")
if const:
sproto += "C"
s = s.replace("$CONST", "const")
s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL | METHOD_FLAG_CONST")
else:
s = s.replace("$CONST ", "")
s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL")
s = s.replace("$VER", sproto)
argtext = ""
callargtext = ""
callsiargs = ""
callsiargptrs = ""
if argcount > 0:
argtext += ", "
callsiargs = f"Variant vargs[{argcount}] = {{ "
callsiargptrs = f"\t\t\tconst Variant *vargptrs[{argcount}] = {{ "
for i in range(argcount):
if i > 0:
argtext += ", "
callargtext += ", "
callsiargs += ", "
callsiargptrs += ", "
argtext += f"m_type{i + 1}"
callargtext += f"m_type{i + 1} arg{i + 1}"
callsiargs += f"Variant(arg{i + 1})"
callsiargptrs += f"&vargs[{i}]"
if method_info:
method_info += "\\\n\t\t"
method_info += f"method_info.arguments.push_back(GetTypeInfo<m_type{i + 1}>::get_class_info());\\\n"
method_info += f"\t\tmethod_info.arguments_metadata.push_back(GetTypeInfo<m_type{i + 1}>::METADATA);"
if argcount:
callsiargs += " };\\\n"
callsiargptrs += " };"
s = s.replace("$CALLSIARGS", callsiargs + callsiargptrs)
s = s.replace("$CALLSIARGPASS", f"(const GDExtensionConstVariantPtr *)vargptrs, {argcount}")
else:
s = s.replace("\t\t\t$CALLSIARGS\\\n", "")
s = s.replace("$CALLSIARGPASS", "nullptr, 0")
if returns:
if argcount > 0:
callargtext += ", "
callargtext += "m_ret &r_ret"
s = s.replace("$CALLSIBEGIN", "Variant ret;\\\n\t\t\t")
s = s.replace("$CALLSIRETPASS", "&ret")
s = s.replace("$CALLSIRET", "r_ret = VariantCaster<m_ret>::cast(ret);")
else:
s = s.replace("$CALLSIBEGIN", "")
s = s.replace("$CALLSIRETPASS", "nullptr")
s = s.replace("\t\t\t\t$CALLSIRET\\\n", "")
s = s.replace(" $ARG", argtext)
s = s.replace("$CALLARGS", callargtext)
if method_info:
s = s.replace("$FILL_METHOD_INFO", method_info)
else:
s = s.replace("\t\t$FILL_METHOD_INFO\\\n", method_info)
return s
def generate_virtuals(target):
max_versions = 12
txt = """/* THIS FILE IS GENERATED DO NOT EDIT */
#ifndef GDEXTENSION_GDVIRTUAL_GEN_H
#define GDEXTENSION_GDVIRTUAL_GEN_H
"""
for i in range(max_versions + 1):
txt += f"/* {i} Arguments */\n\n"
txt += generate_virtual_version(i, False, False)
txt += generate_virtual_version(i, False, True)
txt += generate_virtual_version(i, True, False)
txt += generate_virtual_version(i, True, True)
txt += "#endif // GDEXTENSION_GDVIRTUAL_GEN_H\n"
with open(target, "w", encoding="utf-8") as f:
f.write(txt)
def get_file_list(api_filepath, output_dir, headers=False, sources=False): def get_file_list(api_filepath, output_dir, headers=False, sources=False):
api = {} api = {}
files = [] files = []
@ -211,7 +81,6 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
source_gen_folder = Path(output_dir) / "gen" / "src" source_gen_folder = Path(output_dir) / "gen" / "src"
files.append(str((core_gen_folder / "ext_wrappers.gen.inc").as_posix())) files.append(str((core_gen_folder / "ext_wrappers.gen.inc").as_posix()))
files.append(str((core_gen_folder / "gdvirtual.gen.inc").as_posix()))
for builtin_class in api["builtin_classes"]: for builtin_class in api["builtin_classes"]:
if is_pod_type(builtin_class["name"]): if is_pod_type(builtin_class["name"]):
@ -335,7 +204,6 @@ def generate_builtin_bindings(api, output_dir, build_config):
source_gen_folder.mkdir(parents=True, exist_ok=True) source_gen_folder.mkdir(parents=True, exist_ok=True)
generate_wrappers(core_gen_folder / "ext_wrappers.gen.inc") generate_wrappers(core_gen_folder / "ext_wrappers.gen.inc")
generate_virtuals(core_gen_folder / "gdvirtual.gen.inc")
# Store types beforehand. # Store types beforehand.
for builtin_api in api["builtin_classes"]: for builtin_api in api["builtin_classes"]:
@ -720,17 +588,17 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
# Special cases. # Special cases.
if class_name == "String": if class_name == "String":
result.append("\tstatic String utf8(const char *from, int64_t len = -1);") result.append("\tstatic String utf8(const char *from, int len = -1);")
result.append("\tvoid parse_utf8(const char *from, int64_t len = -1);") result.append("\tvoid parse_utf8(const char *from, int len = -1);")
result.append("\tstatic String utf16(const char16_t *from, int64_t len = -1);") result.append("\tstatic String utf16(const char16_t *from, int len = -1);")
result.append("\tvoid parse_utf16(const char16_t *from, int64_t len = -1);") result.append("\tvoid parse_utf16(const char16_t *from, int len = -1);")
result.append("\tCharString utf8() const;") result.append("\tCharString utf8() const;")
result.append("\tCharString ascii() const;") result.append("\tCharString ascii() const;")
result.append("\tChar16String utf16() const;") result.append("\tChar16String utf16() const;")
result.append("\tChar32String utf32() const;") result.append("\tChar32String utf32() const;")
result.append("\tCharWideString wide_string() const;") result.append("\tCharWideString wide_string() const;")
result.append("\tstatic String num_real(double p_num, bool p_trailing = true);") result.append("\tstatic String num_real(double p_num, bool p_trailing = true);")
result.append("\tError resize(int64_t p_size);") result.append("\tError resize(int p_size);")
if "members" in builtin_api: if "members" in builtin_api:
for member in builtin_api["members"]: for member in builtin_api["members"]:
@ -783,8 +651,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("\tString &operator+=(const wchar_t *p_str);") result.append("\tString &operator+=(const wchar_t *p_str);")
result.append("\tString &operator+=(const char32_t *p_str);") result.append("\tString &operator+=(const char32_t *p_str);")
result.append("\tconst char32_t &operator[](int64_t p_index) const;") result.append("\tconst char32_t &operator[](int p_index) const;")
result.append("\tchar32_t &operator[](int64_t p_index);") result.append("\tchar32_t &operator[](int p_index);")
result.append("\tconst char32_t *ptr() const;") result.append("\tconst char32_t *ptr() const;")
result.append("\tchar32_t *ptrw();") result.append("\tchar32_t *ptrw();")
@ -802,8 +670,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
return_type = "int32_t" return_type = "int32_t"
elif class_name == "PackedFloat32Array": elif class_name == "PackedFloat32Array":
return_type = "float" return_type = "float"
result.append(f"\tconst {return_type} &operator[](int64_t p_index) const;") result.append(f"\tconst {return_type} &operator[](int p_index) const;")
result.append(f"\t{return_type} &operator[](int64_t p_index);") result.append(f"\t{return_type} &operator[](int p_index);")
result.append(f"\tconst {return_type} *ptr() const;") result.append(f"\tconst {return_type} *ptr() const;")
result.append(f"\t{return_type} *ptrw();") result.append(f"\t{return_type} *ptrw();")
iterators = """ iterators = """
@ -874,8 +742,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append(iterators.replace("$TYPE", return_type)) result.append(iterators.replace("$TYPE", return_type))
if class_name == "Array": if class_name == "Array":
result.append("\tconst Variant &operator[](int64_t p_index) const;") result.append("\tconst Variant &operator[](int p_index) const;")
result.append("\tVariant &operator[](int64_t p_index);") result.append("\tVariant &operator[](int p_index);")
result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);") result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);")
result.append("\tvoid _ref(const Array &p_from) const;") result.append("\tvoid _ref(const Array &p_from) const;")
@ -1096,19 +964,8 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append(method_signature + "{") result.append(method_signature + "{")
method_call = "\t" method_call = "\t"
is_ref = False
if "return_type" in method: if "return_type" in method:
return_type = method["return_type"] method_call += f'return internal::_call_builtin_method_ptr_ret<{correct_type(method["return_type"])}>('
if is_enum(return_type):
method_call += f"return ({get_gdextension_type(correct_type(return_type))})internal::_call_builtin_method_ptr_ret<int64_t>("
elif is_pod_type(return_type) or is_variant(return_type):
method_call += f"return internal::_call_builtin_method_ptr_ret<{get_gdextension_type(correct_type(return_type))}>("
elif is_refcounted(return_type):
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(internal::_call_builtin_method_ptr_ret_obj<{return_type}>("
is_ref = True
else:
method_call += f"return internal::_call_builtin_method_ptr_ret_obj<{return_type}>("
else: else:
method_call += "internal::_call_builtin_method_ptr_no_ret(" method_call += "internal::_call_builtin_method_ptr_no_ret("
method_call += f'_method_bindings.method_{method["name"]}, ' method_call += f'_method_bindings.method_{method["name"]}, '
@ -1129,9 +986,6 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result += encode result += encode
arguments.append(arg_name) arguments.append(arg_name)
method_call += ", ".join(arguments) method_call += ", ".join(arguments)
if is_ref:
method_call += ")" # Close Ref<> constructor.
method_call += ");" method_call += ");"
result.append(method_call) result.append(method_call)
@ -1842,7 +1696,7 @@ def generate_global_constants(api, output_dir):
header.append("") header.append("")
for constant in api["global_constants"]: for constant in api["global_constants"]:
header.append(f'\tconst int64_t {escape_identifier(constant["name"])} = {constant["value"]};') header.append(f'\tconst int {escape_identifier(constant["name"])} = {constant["value"]};')
header.append("") header.append("")
@ -1924,9 +1778,9 @@ def generate_global_constant_binds(api, output_dir):
continue continue
if enum_def["is_bitfield"]: if enum_def["is_bitfield"]:
header.append(f'VARIANT_BITFIELD_CAST({enum_def["name"]});') header.append(f'VARIANT_BITFIELD_CAST(godot::{enum_def["name"]});')
else: else:
header.append(f'VARIANT_ENUM_CAST({enum_def["name"]});') header.append(f'VARIANT_ENUM_CAST(godot::{enum_def["name"]});')
# Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file. # Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file.
header.append(f"VARIANT_ENUM_CAST(godot::Variant::Type);") header.append(f"VARIANT_ENUM_CAST(godot::Variant::Type);")
@ -2579,7 +2433,6 @@ def get_operator_id_name(op):
"unary-": "negate", "unary-": "negate",
"unary+": "positive", "unary+": "positive",
"%": "module", "%": "module",
"**": "power",
"<<": "shift_left", "<<": "shift_left",
">>": "shift_right", ">>": "shift_right",
"&": "bit_and", "&": "bit_and",

View File

@ -329,7 +329,7 @@ typedef struct {
GDExtensionBool is_virtual; GDExtensionBool is_virtual;
GDExtensionBool is_abstract; GDExtensionBool is_abstract;
GDExtensionBool is_exposed; GDExtensionBool is_exposed;
GDExtensionBool is_runtime; GDExtensionBool is_gameplay;
GDExtensionClassSet set_func; GDExtensionClassSet set_func;
GDExtensionClassGet get_func; GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func; GDExtensionClassGetPropertyList get_property_list_func;
@ -398,18 +398,13 @@ typedef struct {
GDExtensionClassMethodPtrCall ptrcall_func; GDExtensionClassMethodPtrCall ptrcall_func;
uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`. uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`.
/* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. /* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */
*
* @todo Consider dropping `has_return_value` and making the other two properties match `GDExtensionMethodInfo` and `GDExtensionClassVirtualMethod` for consistency in future version of this struct.
*/
GDExtensionBool has_return_value; GDExtensionBool has_return_value;
GDExtensionPropertyInfo *return_value_info; GDExtensionPropertyInfo *return_value_info;
GDExtensionClassMethodArgumentMetadata return_value_metadata; GDExtensionClassMethodArgumentMetadata return_value_metadata;
/* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`. /* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`.
* Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. * Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies.
*
* @todo Consider renaming `arguments_info` to `arguments` for consistency in future version of this struct.
*/ */
uint32_t argument_count; uint32_t argument_count;
GDExtensionPropertyInfo *arguments_info; GDExtensionPropertyInfo *arguments_info;
@ -420,18 +415,6 @@ typedef struct {
GDExtensionVariantPtr *default_arguments; GDExtensionVariantPtr *default_arguments;
} GDExtensionClassMethodInfo; } GDExtensionClassMethodInfo;
typedef struct {
GDExtensionStringNamePtr name;
uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`.
GDExtensionPropertyInfo return_value;
GDExtensionClassMethodArgumentMetadata return_value_metadata;
uint32_t argument_count;
GDExtensionPropertyInfo *arguments;
GDExtensionClassMethodArgumentMetadata *arguments_metadata;
} GDExtensionClassVirtualMethodInfo;
typedef void (*GDExtensionCallableCustomCall)(void *callable_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); typedef void (*GDExtensionCallableCustomCall)(void *callable_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
typedef GDExtensionBool (*GDExtensionCallableCustomIsValid)(void *callable_userdata); typedef GDExtensionBool (*GDExtensionCallableCustomIsValid)(void *callable_userdata);
typedef void (*GDExtensionCallableCustomFree)(void *callable_userdata); typedef void (*GDExtensionCallableCustomFree)(void *callable_userdata);
@ -2319,34 +2302,6 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceObjectGetInstanceFromId)(GDOb
*/ */
typedef GDObjectInstanceID (*GDExtensionInterfaceObjectGetInstanceId)(GDExtensionConstObjectPtr p_object); typedef GDObjectInstanceID (*GDExtensionInterfaceObjectGetInstanceId)(GDExtensionConstObjectPtr p_object);
/**
* @name object_has_script_method
* @since 4.3
*
* Checks if this object has a script with the given method.
*
* @param p_object A pointer to the Object.
* @param p_method A pointer to a StringName identifying the method.
*
* @returns true if the object has a script and that script has a method with the given name. Returns false if the object has no script.
*/
typedef GDExtensionBool (*GDExtensionInterfaceObjectHasScriptMethod)(GDExtensionConstObjectPtr p_object, GDExtensionConstStringNamePtr p_method);
/**
* @name object_call_script_method
* @since 4.3
*
* Call the given script method on this object.
*
* @param p_object A pointer to the Object.
* @param p_method A pointer to a StringName identifying the method.
* @param p_args A pointer to a C array of Variant.
* @param p_argument_count The number of arguments.
* @param r_return A pointer a Variant which will be assigned the return value.
* @param r_error A pointer the structure which will hold error information.
*/
typedef void (*GDExtensionInterfaceObjectCallScriptMethod)(GDExtensionObjectPtr p_object, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error);
/* INTERFACE: Reference */ /* INTERFACE: Reference */
/** /**
@ -2577,20 +2532,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionCl
*/ */
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassMethod)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassMethod)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
/**
* @name classdb_register_extension_class_virtual_method
* @since 4.3
*
* Registers a virtual method on an extension class in ClassDB, that can be implemented by scripts or other extensions.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_method_info A pointer to a GDExtensionClassMethodInfo struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassVirtualMethodInfo *p_method_info);
/** /**
* @name classdb_register_extension_class_integer_constant * @name classdb_register_extension_class_integer_constant
* @since 4.1 * @since 4.1

View File

@ -36,7 +36,6 @@
#include <godot_cpp/core/property_info.hpp> #include <godot_cpp/core/property_info.hpp>
#include <godot_cpp/templates/list.hpp> #include <godot_cpp/templates/list.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/godot.hpp> #include <godot_cpp/godot.hpp>
@ -49,7 +48,6 @@ typedef void GodotObject;
// Base for all engine classes, to contain the pointer to the engine instance. // Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped { class Wrapped {
friend class GDExtensionBinding; friend class GDExtensionBinding;
friend class ClassDB;
friend void postinitialize_handler(Wrapped *); friend void postinitialize_handler(Wrapped *);
protected: protected:
@ -108,26 +106,6 @@ public:
GodotObject *_owner = nullptr; GodotObject *_owner = nullptr;
}; };
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr) {
}
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str) {
arr.push_back(p_str);
}
template <class... P>
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str, P... p_args) {
arr.push_back(p_str);
snarray_add_str(arr, p_args...);
}
template <class... P>
_FORCE_INLINE_ Vector<StringName> snarray(P... p_args) {
Vector<StringName> arr;
snarray_add_str(arr, p_args...);
return arr;
}
namespace internal { namespace internal {
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size); GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size);
@ -153,6 +131,17 @@ struct EngineClassRegistration {
} // namespace godot } // namespace godot
#ifdef HOT_RELOAD_ENABLED
#define _GDCLASS_RECREATE(m_class, m_inherits) \
m_class *new_instance = (m_class *)memalloc(sizeof(m_class)); \
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance }; \
Wrapped::recreate_instance = &recreate_data; \
memnew_placement(new_instance, m_class); \
return new_instance;
#else
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
#endif
// Use this on top of your own classes. // Use this on top of your own classes.
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes // Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
// every line of the macro different // every line of the macro different
@ -237,6 +226,15 @@ public:
return m_inherits::get_class_static(); \ return m_inherits::get_class_static(); \
} \ } \
\ \
static GDExtensionObjectPtr create(void *data) { \
m_class *new_object = memnew(m_class); \
return new_object->_owner; \
} \
\
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
_GDCLASS_RECREATE(m_class, m_inherits); \
} \
\
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \ static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
if (p_instance && m_class::_get_notification()) { \ if (p_instance && m_class::_get_notification()) { \
if (m_class::_get_notification() != m_inherits::_get_notification()) { \ if (m_class::_get_notification() != m_inherits::_get_notification()) { \
@ -439,6 +437,14 @@ public:
return m_inherits::get_class_static(); \ return m_inherits::get_class_static(); \
} \ } \
\ \
static GDExtensionObjectPtr create(void *data) { \
return nullptr; \
} \
\
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
return nullptr; \
} \
\
static void free(void *data, GDExtensionClassInstancePtr ptr) { \ static void free(void *data, GDExtensionClassInstancePtr ptr) { \
} \ } \
\ \
@ -466,14 +472,4 @@ private:
// Don't use this for your classes, use GDCLASS() instead. // Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits) #define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_BIND(m_name, ...) ::godot::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), ::godot::snarray(__VA_ARGS__));
#define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden()
#define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden()
#endif // GODOT_WRAPPED_HPP #endif // GODOT_WRAPPED_HPP

View File

@ -281,13 +281,13 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
if ((size_t)p_argcount < sizeof...(P)) { if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -299,13 +299,13 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
if ((size_t)p_argcount < sizeof...(P)) { if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -317,13 +317,13 @@ void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, co
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
if ((size_t)p_argcount < sizeof...(P)) { if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -335,7 +335,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -346,7 +346,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -370,7 +370,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -381,7 +381,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -405,7 +405,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -416,7 +416,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -440,7 +440,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -451,7 +451,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -552,7 +552,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = sizeof...(P); r_error.argument = sizeof...(P);
return; return;
} }
#endif #endif
@ -563,7 +563,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = sizeof...(P); r_error.argument = sizeof...(P);
return; return;
} }
#endif #endif
@ -597,13 +597,13 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
if ((size_t)p_argcount < sizeof...(P)) { if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -615,13 +615,13 @@ void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
if ((size_t)p_argcount < sizeof...(P)) { if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P); r_error.argument = (int32_t)sizeof...(P);
return; return;
} }
#endif #endif
@ -644,7 +644,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = sizeof...(P); r_error.argument = sizeof...(P);
return; return;
} }
#endif #endif
@ -655,7 +655,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (missing > dvs) { if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = sizeof...(P); r_error.argument = sizeof...(P);
return; return;
} }
#endif #endif

View File

@ -32,7 +32,6 @@
#define GODOT_BUILTIN_PTRCALL_HPP #define GODOT_BUILTIN_PTRCALL_HPP
#include <gdextension_interface.h> #include <gdextension_interface.h>
#include <godot_cpp/core/object.hpp>
#include <array> #include <array>
@ -40,17 +39,6 @@ namespace godot {
namespace internal { namespace internal {
template <class O, class... Args>
O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) {
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
method(base, call_args.data(), &ret, sizeof...(Args));
if (ret == nullptr) {
return nullptr;
}
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
}
template <class... Args> template <class... Args>
void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) { void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };

View File

@ -110,34 +110,7 @@ private:
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method); static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
template <class T, bool is_abstract> template <class T, bool is_abstract>
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false); static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_gameplay = false);
template <class T>
static GDExtensionObjectPtr _create_instance_func(void *data) {
if constexpr (!std::is_abstract_v<T>) {
T *new_object = memnew(T);
return new_object->_owner;
} else {
return nullptr;
}
}
template <class T>
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED
T *new_instance = (T *)memalloc(sizeof(T));
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
Wrapped::recreate_instance = &recreate_data;
memnew_placement(new_instance, T);
return new_instance;
#else
return nullptr;
#endif
} else {
return nullptr;
}
}
public: public:
template <class T> template <class T>
@ -147,7 +120,7 @@ public:
template <class T> template <class T>
static void register_internal_class(); static void register_internal_class();
template <class T> template <class T>
static void register_runtime_class(); static void register_gameplay_class();
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { _FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
instance_binding_callbacks[p_name] = p_callbacks; instance_binding_callbacks[p_name] = p_callbacks;
@ -167,10 +140,7 @@ public:
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1); static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void add_signal(const StringName &p_class, const MethodInfo &p_signal); static void add_signal(const StringName &p_class, const MethodInfo &p_signal);
static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield = false); static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield = false);
// Binds an implementation of a virtual method defined in Godot.
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call); static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call);
// Add a new virtual method that can be implemented by scripts.
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names = Vector<StringName>());
static MethodBind *get_method(const StringName &p_class, const StringName &p_method); static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
@ -201,7 +171,7 @@ public:
} }
template <class T, bool is_abstract> template <class T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) { void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_gameplay) {
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS."); static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks; instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
@ -223,7 +193,7 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
p_virtual, // GDExtensionBool is_virtual; p_virtual, // GDExtensionBool is_virtual;
is_abstract, // GDExtensionBool is_abstract; is_abstract, // GDExtensionBool is_abstract;
p_exposed, // GDExtensionBool is_exposed; p_exposed, // GDExtensionBool is_exposed;
p_runtime, // GDExtensionBool is_runtime; p_gameplay, // GDExtensionBool is_gameplay;
T::set_bind, // GDExtensionClassSet set_func; T::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func; T::get_bind, // GDExtensionClassGet get_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func; T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
@ -235,9 +205,9 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
T::to_string_bind, // GDExtensionClassToString to_string_func; T::to_string_bind, // GDExtensionClassToString to_string_func;
nullptr, // GDExtensionClassReference reference_func; nullptr, // GDExtensionClassReference reference_func;
nullptr, // GDExtensionClassUnreference unreference_func; nullptr, // GDExtensionClassUnreference unreference_func;
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
&_recreate_instance_func<T>, // GDExtensionClassRecreateInstance recreate_instance_func; T::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func; &ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func; nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func; nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
@ -270,7 +240,7 @@ void ClassDB::register_internal_class() {
} }
template <class T> template <class T>
void ClassDB::register_runtime_class() { void ClassDB::register_gameplay_class() {
ClassDB::_register_class<T, false>(false, true, true); ClassDB::_register_class<T, false>(false, true, true);
} }
@ -333,7 +303,7 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true); #define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>(); #define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>(); #define GDREGISTER_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>();
#define GDREGISTER_RUNTIME_CLASS(m_class) ClassDB::register_runtime_class<m_class>(); #define GDREGISTER_GAMEPLAY_CLASS(m_class) ClassDB::register_gameplay_class<m_class>();
} // namespace godot } // namespace godot

View File

@ -68,8 +68,6 @@ struct MethodInfo {
int id = 0; int id = 0;
std::vector<PropertyInfo> arguments; std::vector<PropertyInfo> arguments;
std::vector<Variant> default_arguments; std::vector<Variant> default_arguments;
GDExtensionClassMethodArgumentMetadata return_val_metadata;
std::vector<GDExtensionClassMethodArgumentMetadata> arguments_metadata;
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; } inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); } inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }

View File

@ -80,17 +80,6 @@ struct PropertyInfo {
p_info->usage = usage; p_info->usage = usage;
*(reinterpret_cast<StringName *>(p_info->class_name)) = class_name; *(reinterpret_cast<StringName *>(p_info->class_name)) = class_name;
} }
GDExtensionPropertyInfo _to_gdextension() const {
return {
(GDExtensionVariantType)type,
name._native_ptr(),
class_name._native_ptr(),
hint,
hint_string._native_ptr(),
usage,
};
}
}; };
} // namespace godot } // namespace godot

View File

@ -370,14 +370,11 @@ MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3) MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I) MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D) MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY_INFO(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE) MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION) MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB) MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS) MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D) MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY_INFO(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR) MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME) MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH) MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
@ -396,11 +393,8 @@ MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY) MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
*/ */
#undef MAKE_TYPED_ARRAY_INFO
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info()) #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
} // namespace godot } // namespace godot

View File

@ -165,8 +165,6 @@ extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_g
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to; extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id; extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id; extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
extern "C" GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method;
extern "C" GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method;
extern "C" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create; extern "C" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create;
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata; extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object; extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
@ -179,7 +177,6 @@ extern "C" GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classd
extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag; extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3; extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method; extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant; extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property; extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed; extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed;

View File

@ -52,8 +52,6 @@ class VMap;
template <class T> template <class T>
class CharStringT; class CharStringT;
SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint64_t)
// Silence a false positive warning (see GH-52119). // Silence a false positive warning (see GH-52119).
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -71,71 +69,52 @@ class CowData {
template <class TS> template <class TS>
friend class CharStringT; friend class CharStringT;
public:
typedef int64_t Size;
typedef uint64_t USize;
static constexpr USize MAX_INT = INT64_MAX;
private: private:
// Function to find the next power of 2 to an integer.
static _FORCE_INLINE_ USize next_po2(USize x) {
if (x == 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
if (sizeof(USize) == 8) {
x |= x >> 32;
}
return ++x;
}
static constexpr USize ALLOC_PAD = sizeof(USize) * 2; // For size and atomic refcount.
mutable T *_ptr = nullptr; mutable T *_ptr = nullptr;
// internal helpers // internal helpers
_FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const { _FORCE_INLINE_ SafeNumeric<uint32_t> *_get_refcount() const {
if (!_ptr) { if (!_ptr) {
return nullptr; return nullptr;
} }
return reinterpret_cast<SafeNumeric<USize> *>(_ptr) - 2; return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2;
} }
_FORCE_INLINE_ USize *_get_size() const { _FORCE_INLINE_ uint32_t *_get_size() const {
if (!_ptr) { if (!_ptr) {
return nullptr; return nullptr;
} }
return reinterpret_cast<USize *>(_ptr) - 1; return reinterpret_cast<uint32_t *>(_ptr) - 1;
} }
_FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const { _FORCE_INLINE_ T *_get_data() const {
return next_po2(p_elements * sizeof(T)); if (!_ptr) {
return nullptr;
}
return reinterpret_cast<T *>(_ptr);
} }
_FORCE_INLINE_ bool _get_alloc_size_checked(USize p_elements, USize *out) const { _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
return next_power_of_2(p_elements * sizeof(T));
}
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
if (unlikely(p_elements == 0)) { if (unlikely(p_elements == 0)) {
*out = 0; *out = 0;
return true; return true;
} }
#if defined(__GNUC__) && defined(IS_32_BIT) #if defined(__GNUC__)
USize o; size_t o;
USize p; size_t p;
if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) { if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) {
*out = 0; *out = 0;
return false; return false;
} }
*out = next_po2(o); *out = next_power_of_2(o);
if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) { if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) {
return false; // No longer allocated here. return false; // No longer allocated here.
} }
#else #else
@ -149,22 +128,22 @@ private:
void _unref(void *p_data); void _unref(void *p_data);
void _ref(const CowData *p_from); void _ref(const CowData *p_from);
void _ref(const CowData &p_from); void _ref(const CowData &p_from);
USize _copy_on_write(); uint32_t _copy_on_write();
public: public:
void operator=(const CowData<T> &p_from) { _ref(p_from); } void operator=(const CowData<T> &p_from) { _ref(p_from); }
_FORCE_INLINE_ T *ptrw() { _FORCE_INLINE_ T *ptrw() {
_copy_on_write(); _copy_on_write();
return _ptr; return (T *)_get_data();
} }
_FORCE_INLINE_ const T *ptr() const { _FORCE_INLINE_ const T *ptr() const {
return _ptr; return _get_data();
} }
_FORCE_INLINE_ Size size() const { _FORCE_INLINE_ int size() const {
USize *size = (USize *)_get_size(); uint32_t *size = (uint32_t *)_get_size();
if (size) { if (size) {
return *size; return *size;
} else { } else {
@ -175,42 +154,41 @@ public:
_FORCE_INLINE_ void clear() { resize(0); } _FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; } _FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; }
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _FORCE_INLINE_ void set(int p_index, const T &p_elem) {
ERR_FAIL_INDEX(p_index, size()); ERR_FAIL_INDEX(p_index, size());
_copy_on_write(); _copy_on_write();
_ptr[p_index] = p_elem; _get_data()[p_index] = p_elem;
} }
_FORCE_INLINE_ T &get_m(Size p_index) { _FORCE_INLINE_ T &get_m(int p_index) {
CRASH_BAD_INDEX(p_index, size()); CRASH_BAD_INDEX(p_index, size());
_copy_on_write(); _copy_on_write();
return _ptr[p_index]; return _get_data()[p_index];
} }
_FORCE_INLINE_ const T &get(Size p_index) const { _FORCE_INLINE_ const T &get(int p_index) const {
CRASH_BAD_INDEX(p_index, size()); CRASH_BAD_INDEX(p_index, size());
return _ptr[p_index]; return _get_data()[p_index];
} }
template <bool p_ensure_zero = false> Error resize(int p_size);
Error resize(Size p_size);
_FORCE_INLINE_ void remove_at(Size p_index) { _FORCE_INLINE_ void remove_at(int p_index) {
ERR_FAIL_INDEX(p_index, size()); ERR_FAIL_INDEX(p_index, size());
T *p = ptrw(); T *p = ptrw();
Size len = size(); int len = size();
for (Size i = p_index; i < len - 1; i++) { for (int i = p_index; i < len - 1; i++) {
p[i] = p[i + 1]; p[i] = p[i + 1];
} }
resize(len - 1); resize(len - 1);
} }
Error insert(Size p_pos, const T &p_val) { Error insert(int p_pos, const T &p_val) {
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
resize(size() + 1); resize(size() + 1);
for (Size i = (size() - 1); i > p_pos; i--) { for (int i = (size() - 1); i > p_pos; i--) {
set(i, get(i - 1)); set(i, get(i - 1));
} }
set(p_pos, p_val); set(p_pos, p_val);
@ -218,13 +196,11 @@ public:
return OK; return OK;
} }
Size find(const T &p_val, Size p_from = 0) const; int find(const T &p_val, int p_from = 0) const;
Size rfind(const T &p_val, Size p_from = -1) const;
Size count(const T &p_val) const;
_FORCE_INLINE_ CowData() {} _FORCE_INLINE_ CowData() {}
_FORCE_INLINE_ ~CowData(); _FORCE_INLINE_ ~CowData();
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }; _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }
}; };
template <class T> template <class T>
@ -233,45 +209,44 @@ void CowData<T>::_unref(void *p_data) {
return; return;
} }
SafeNumeric<USize> *refc = _get_refcount(); SafeNumeric<uint32_t> *refc = _get_refcount();
if (refc->decrement() > 0) { if (refc->decrement() > 0) {
return; // still in use return; // still in use
} }
// clean up
// clean up
if (!std::is_trivially_destructible<T>::value) { if (!std::is_trivially_destructible<T>::value) {
USize *count = _get_size(); uint32_t *count = _get_size();
T *data = (T *)(count + 1); T *data = (T *)(count + 1);
for (USize i = 0; i < *count; ++i) { for (uint32_t i = 0; i < *count; ++i) {
// call destructors // call destructors
data[i].~T(); data[i].~T();
} }
} }
// free mem // free mem
Memory::free_static(((uint8_t *)p_data) - ALLOC_PAD, false); Memory::free_static((uint8_t *)p_data, true);
} }
template <class T> template <class T>
typename CowData<T>::USize CowData<T>::_copy_on_write() { uint32_t CowData<T>::_copy_on_write() {
if (!_ptr) { if (!_ptr) {
return 0; return 0;
} }
SafeNumeric<USize> *refc = _get_refcount(); SafeNumeric<uint32_t> *refc = _get_refcount();
USize rc = refc->get(); uint32_t rc = refc->get();
if (unlikely(rc > 1)) { if (unlikely(rc > 1)) {
/* in use by more than me */ /* in use by more than me */
USize current_size = *_get_size(); uint32_t current_size = *_get_size();
USize *mem_new = (USize *)Memory::alloc_static(_get_alloc_size(current_size) + ALLOC_PAD, false); uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
mem_new += 2;
new (mem_new - 2) SafeNumeric<USize>(1); //refcount new (mem_new - 2) SafeNumeric<uint32_t>(1); // refcount
*(mem_new - 1) = current_size; //size *(mem_new - 1) = current_size; // size
T *_data = (T *)(mem_new); T *_data = (T *)(mem_new);
@ -280,8 +255,8 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() {
memcpy(mem_new, _ptr, current_size * sizeof(T)); memcpy(mem_new, _ptr, current_size * sizeof(T));
} else { } else {
for (USize i = 0; i < current_size; i++) { for (uint32_t i = 0; i < current_size; i++) {
memnew_placement(&_data[i], T(_ptr[i])); memnew_placement(&_data[i], T(_get_data()[i]));
} }
} }
@ -294,11 +269,10 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() {
} }
template <class T> template <class T>
template <bool p_ensure_zero> Error CowData<T>::resize(int p_size) {
Error CowData<T>::resize(Size p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
Size current_size = size(); int current_size = size();
if (p_size == current_size) { if (p_size == current_size) {
return OK; return OK;
@ -312,29 +286,27 @@ Error CowData<T>::resize(Size p_size) {
} }
// possibly changing size, copy on write // possibly changing size, copy on write
USize rc = _copy_on_write(); uint32_t rc = _copy_on_write();
USize current_alloc_size = _get_alloc_size(current_size); size_t current_alloc_size = _get_alloc_size(current_size);
USize alloc_size; size_t alloc_size;
ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
if (p_size > current_size) { if (p_size > current_size) {
if (alloc_size != current_alloc_size) { if (alloc_size != current_alloc_size) {
if (current_size == 0) { if (current_size == 0) {
// alloc from scratch // alloc from scratch
USize *ptr = (USize *)Memory::alloc_static(alloc_size + ALLOC_PAD, false); uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
ptr += 2;
ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY); ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY);
*(ptr - 1) = 0; //size, currently none *(ptr - 1) = 0; // size, currently none
new (ptr - 2) SafeNumeric<USize>(1); //refcount new (ptr - 2) SafeNumeric<uint32_t>(1); // refcount
_ptr = (T *)ptr; _ptr = (T *)ptr;
} else { } else {
USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
_ptrnew += 2; new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount
_ptr = (T *)(_ptrnew); _ptr = (T *)(_ptrnew);
} }
@ -343,11 +315,11 @@ Error CowData<T>::resize(Size p_size) {
// construct the newly created elements // construct the newly created elements
if (!std::is_trivially_constructible<T>::value) { if (!std::is_trivially_constructible<T>::value) {
for (Size i = *_get_size(); i < p_size; i++) { T *elems = _get_data();
memnew_placement(&_ptr[i], T);
for (int i = *_get_size(); i < p_size; i++) {
memnew_placement(&elems[i], T);
} }
} else if (p_ensure_zero) {
memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T));
} }
*_get_size() = p_size; *_get_size() = p_size;
@ -355,17 +327,16 @@ Error CowData<T>::resize(Size p_size) {
} else if (p_size < current_size) { } else if (p_size < current_size) {
if (!std::is_trivially_destructible<T>::value) { if (!std::is_trivially_destructible<T>::value) {
// deinitialize no longer needed elements // deinitialize no longer needed elements
for (USize i = p_size; i < *_get_size(); i++) { for (uint32_t i = p_size; i < *_get_size(); i++) {
T *t = &_ptr[i]; T *t = &_get_data()[i];
t->~T(); t->~T();
} }
} }
if (alloc_size != current_alloc_size) { if (alloc_size != current_alloc_size) {
USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
_ptrnew += 2; new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount
_ptr = (T *)(_ptrnew); _ptr = (T *)(_ptrnew);
} }
@ -377,14 +348,14 @@ Error CowData<T>::resize(Size p_size) {
} }
template <class T> template <class T>
typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const { int CowData<T>::find(const T &p_val, int p_from) const {
Size ret = -1; int ret = -1;
if (p_from < 0 || size() == 0) { if (p_from < 0 || size() == 0) {
return ret; return ret;
} }
for (Size i = p_from; i < size(); i++) { for (int i = p_from; i < size(); i++) {
if (get(i) == p_val) { if (get(i) == p_val) {
ret = i; ret = i;
break; break;
@ -394,36 +365,6 @@ typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
return ret; return ret;
} }
template <class T>
typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
const Size s = size();
if (p_from < 0) {
p_from = s + p_from;
}
if (p_from < 0 || p_from >= s) {
p_from = s - 1;
}
for (Size i = p_from; i >= 0; i--) {
if (get(i) == p_val) {
return i;
}
}
return -1;
}
template <class T>
typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
Size amount = 0;
for (Size i = 0; i < size(); i++) {
if (get(i) == p_val) {
amount++;
}
}
return amount;
}
template <class T> template <class T>
void CowData<T>::_ref(const CowData *p_from) { void CowData<T>::_ref(const CowData *p_from) {
_ref(*p_from); _ref(*p_from);

View File

@ -48,15 +48,6 @@ namespace godot {
// value and, as an important benefit, you can be sure the value is properly synchronized // value and, as an important benefit, you can be sure the value is properly synchronized
// even with threads that are already running. // even with threads that are already running.
// These are used in very specific areas of the engine where it's critical that these guarantees are held
#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \
static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \
static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value);
#define SAFE_FLAG_TYPE_PUN_GUARANTEES \
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
static_assert(alignof(SafeFlag) == alignof(bool));
template <class T> template <class T>
class SafeNumeric { class SafeNumeric {
std::atomic<T> value; std::atomic<T> value;

View File

@ -50,7 +50,7 @@ namespace godot {
template <class T> template <class T>
class VectorWriteProxy { class VectorWriteProxy {
public: public:
_FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) { _FORCE_INLINE_ T &operator[](int p_index) {
CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size()); CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size());
return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index]; return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index];
@ -63,26 +63,22 @@ class Vector {
public: public:
VectorWriteProxy<T> write; VectorWriteProxy<T> write;
typedef typename CowData<T>::Size Size;
private: private:
CowData<T> _cowdata; CowData<T> _cowdata;
public: public:
bool push_back(T p_elem); bool push_back(T p_elem);
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias _FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } // alias
void fill(T p_elem); void fill(T p_elem);
void remove_at(Size p_index) { _cowdata.remove_at(p_index); } void remove_at(int p_index) { _cowdata.remove_at(p_index); }
_FORCE_INLINE_ bool erase(const T &p_val) { void erase(const T &p_val) {
Size idx = find(p_val); int idx = find(p_val);
if (idx >= 0) { if (idx >= 0) {
remove_at(idx); remove_at(idx);
return true;
} }
return false;
} }
void reverse(); void reverse();
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
@ -90,45 +86,37 @@ public:
_FORCE_INLINE_ void clear() { resize(0); } _FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); } _FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); }
_FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); } _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); }
_FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ Size size() const { return _cowdata.size(); } _FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(Size p_size) { return _cowdata.resize(p_size); } Error resize(int p_size) { return _cowdata.resize(p_size); }
Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); } _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); } Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); }
Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); }
Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); }
Size count(const T &p_val) const { return _cowdata.count(p_val); }
void append_array(Vector<T> p_other); void append_array(Vector<T> p_other);
_FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; } _FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; }
void sort() { template <class C>
sort_custom<_DefaultComparator<T>>(); void sort_custom() {
} int len = _cowdata.size();
template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args>
void sort_custom(Args &&...args) {
Size len = _cowdata.size();
if (len == 0) { if (len == 0) {
return; return;
} }
T *data = ptrw(); T *data = ptrw();
SortArray<T, Comparator, Validate> sorter{ args... }; SortArray<T, C> sorter;
sorter.sort(data, len); sorter.sort(data, len);
} }
Size bsearch(const T &p_value, bool p_before) { void sort() {
return bsearch_custom<_DefaultComparator<T>>(p_value, p_before); sort_custom<_DefaultComparator<T>>();
} }
template <class Comparator, class Value, class... Args> int bsearch(const T &p_value, bool p_before) {
Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) { SearchArray<T> search;
SearchArray<T, Comparator> search{ args... };
return search.bisect(ptrw(), size(), p_value, p_before); return search.bisect(ptrw(), size(), p_value, p_before);
} }
@ -137,7 +125,7 @@ public:
} }
void ordered_insert(const T &p_val) { void ordered_insert(const T &p_val) {
Size i; int i;
for (i = 0; i < _cowdata.size(); i++) { for (i = 0; i < _cowdata.size(); i++) {
if (p_val < operator[](i)) { if (p_val < operator[](i)) {
break; break;
@ -152,36 +140,33 @@ public:
Vector<uint8_t> to_byte_array() const { Vector<uint8_t> to_byte_array() const {
Vector<uint8_t> ret; Vector<uint8_t> ret;
if (is_empty()) {
return ret;
}
ret.resize(size() * sizeof(T)); ret.resize(size() * sizeof(T));
memcpy(ret.ptrw(), ptr(), sizeof(T) * size()); memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
return ret; return ret;
} }
Vector<T> slice(Size p_begin, Size p_end = CowData<T>::MAX_INT) const { Vector<T> slice(int p_begin, int p_end = INT_MAX) const {
Vector<T> result; Vector<T> result;
const Size s = size(); const int s = size();
Size begin = CLAMP(p_begin, -s, s); int begin = Math::clamp(p_begin, -s, s);
if (begin < 0) { if (begin < 0) {
begin += s; begin += s;
} }
Size end = CLAMP(p_end, -s, s); int end = Math::clamp(p_end, -s, s);
if (end < 0) { if (end < 0) {
end += s; end += s;
} }
ERR_FAIL_COND_V(begin > end, result); ERR_FAIL_COND_V(begin > end, result);
Size result_size = end - begin; int result_size = end - begin;
result.resize(result_size); result.resize(result_size);
const T *const r = ptr(); const T *const r = ptr();
T *const w = result.ptrw(); T *const w = result.ptrw();
for (Size i = 0; i < result_size; ++i) { for (int i = 0; i < result_size; ++i) {
w[i] = r[begin + i]; w[i] = r[begin + i];
} }
@ -189,11 +174,11 @@ public:
} }
bool operator==(const Vector<T> &p_arr) const { bool operator==(const Vector<T> &p_arr) const {
Size s = size(); int s = size();
if (s != p_arr.size()) { if (s != p_arr.size()) {
return false; return false;
} }
for (Size i = 0; i < s; i++) { for (int i = 0; i < s; i++) {
if (operator[](i) != p_arr[i]) { if (operator[](i) != p_arr[i]) {
return false; return false;
} }
@ -202,11 +187,11 @@ public:
} }
bool operator!=(const Vector<T> &p_arr) const { bool operator!=(const Vector<T> &p_arr) const {
Size s = size(); int s = size();
if (s != p_arr.size()) { if (s != p_arr.size()) {
return true; return true;
} }
for (Size i = 0; i < s; i++) { for (int i = 0; i < s; i++) {
if (operator[](i) != p_arr[i]) { if (operator[](i) != p_arr[i]) {
return true; return true;
} }
@ -283,7 +268,7 @@ public:
Error err = _cowdata.resize(p_init.size()); Error err = _cowdata.resize(p_init.size());
ERR_FAIL_COND(err); ERR_FAIL_COND(err);
Size i = 0; int i = 0;
for (const T &element : p_init) { for (const T &element : p_init) {
_cowdata.set(i++, element); _cowdata.set(i++, element);
} }
@ -295,7 +280,7 @@ public:
template <class T> template <class T>
void Vector<T>::reverse() { void Vector<T>::reverse() {
for (Size i = 0; i < size() / 2; i++) { for (int i = 0; i < size() / 2; i++) {
T *p = ptrw(); T *p = ptrw();
SWAP(p[i], p[size() - i - 1]); SWAP(p[i], p[size() - i - 1]);
} }
@ -303,13 +288,13 @@ void Vector<T>::reverse() {
template <class T> template <class T>
void Vector<T>::append_array(Vector<T> p_other) { void Vector<T>::append_array(Vector<T> p_other) {
const Size ds = p_other.size(); const int ds = p_other.size();
if (ds == 0) { if (ds == 0) {
return; return;
} }
const Size bs = size(); const int bs = size();
resize(bs + ds); resize(bs + ds);
for (Size i = 0; i < ds; ++i) { for (int i = 0; i < ds; ++i) {
ptrw()[bs + i] = p_other[i]; ptrw()[bs + i] = p_other[i];
} }
} }
@ -326,7 +311,7 @@ bool Vector<T>::push_back(T p_elem) {
template <class T> template <class T>
void Vector<T>::fill(T p_elem) { void Vector<T>::fill(T p_elem) {
T *p = ptrw(); T *p = ptrw();
for (Size i = 0; i < size(); i++) { for (int i = 0; i < size(); i++) {
p[i] = p_elem; p[i] = p_elem;
} }
} }

View File

@ -201,11 +201,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
return ( return (
(src_min.x <= dst_min.x) && (src_min.x <= dst_min.x) &&
(src_max.x >= dst_max.x) && (src_max.x > dst_max.x) &&
(src_min.y <= dst_min.y) && (src_min.y <= dst_min.y) &&
(src_max.y >= dst_max.y) && (src_max.y > dst_max.y) &&
(src_min.z <= dst_min.z) && (src_min.z <= dst_min.z) &&
(src_max.z >= dst_max.z)); (src_max.z > dst_max.z));
} }
Vector3 AABB::get_support(const Vector3 &p_normal) const { Vector3 AABB::get_support(const Vector3 &p_normal) const {

View File

@ -46,11 +46,11 @@ class CharProxy {
template <class TS> template <class TS>
friend class CharStringT; friend class CharStringT;
const int64_t _index; const int _index;
CowData<T> &_cowdata; CowData<T> &_cowdata;
static inline const T _null = 0; static inline const T _null = 0;
_FORCE_INLINE_ CharProxy(const int64_t &p_index, CowData<T> &p_cowdata) : _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
_index(p_index), _index(p_index),
_cowdata(p_cowdata) {} _cowdata(p_cowdata) {}
@ -90,19 +90,19 @@ class CharStringT {
public: public:
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
_FORCE_INLINE_ int64_t size() const { return _cowdata.size(); } _FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(int64_t p_size) { return _cowdata.resize(p_size); } Error resize(int p_size) { return _cowdata.resize(p_size); }
_FORCE_INLINE_ T get(int64_t p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int64_t p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ const T &operator[](int64_t p_index) const { _FORCE_INLINE_ const T &operator[](int p_index) const {
if (unlikely(p_index == _cowdata.size())) { if (unlikely(p_index == _cowdata.size())) {
return _null; return _null;
} }
return _cowdata.get(p_index); return _cowdata.get(p_index);
} }
_FORCE_INLINE_ CharProxy<T> operator[](int64_t p_index) { return CharProxy<T>(p_index, _cowdata); } _FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }
_FORCE_INLINE_ CharStringT() {} _FORCE_INLINE_ CharStringT() {}
_FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); } _FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
@ -112,7 +112,7 @@ public:
void operator=(const T *p_cstr); void operator=(const T *p_cstr);
bool operator<(const CharStringT<T> &p_right) const; bool operator<(const CharStringT<T> &p_right) const;
CharStringT<T> &operator+=(T p_char); CharStringT<T> &operator+=(T p_char);
int64_t length() const { return size() ? size() - 1 : 0; } int length() const { return size() ? size() - 1 : 0; }
const T *get_data() const; const T *get_data() const;
operator const T *() const { return get_data(); }; operator const T *() const { return get_data(); };

View File

@ -75,8 +75,6 @@ public:
} \ } \
}; };
// All Variant::OBJECT types are intentionally omitted from this list because they are handled by
// the unspecialized TypedArray definition.
MAKE_TYPED_ARRAY(bool, Variant::BOOL) MAKE_TYPED_ARRAY(bool, Variant::BOOL)
MAKE_TYPED_ARRAY(uint8_t, Variant::INT) MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY(int8_t, Variant::INT) MAKE_TYPED_ARRAY(int8_t, Variant::INT)
@ -96,14 +94,11 @@ MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3) MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I) MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D) MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE) MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION) MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB) MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS) MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D) MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY(Color, Variant::COLOR) MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME) MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH) MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
@ -121,10 +116,6 @@ MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY) MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
// If the IPAddress struct is added to godot-cpp, the following could also be added:
//MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
#undef MAKE_TYPED_ARRAY
} // namespace godot } // namespace godot

View File

@ -122,7 +122,6 @@ public:
OP_NEGATE, OP_NEGATE,
OP_POSITIVE, OP_POSITIVE,
OP_MODULE, OP_MODULE,
OP_POWER,
// bitwise // bitwise
OP_SHIFT_LEFT, OP_SHIFT_LEFT,
OP_SHIFT_RIGHT, OP_SHIFT_RIGHT,

View File

@ -117,9 +117,6 @@ struct _NO_DISCARD_ Vector2i {
int64_t length_squared() const; int64_t length_squared() const;
double length() const; double length() const;
int64_t distance_squared_to(const Vector2i &p_to) const;
double distance_to(const Vector2i &p_to) const;
real_t aspect() const { return width / (real_t)height; } real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }

View File

@ -82,9 +82,6 @@ struct _NO_DISCARD_ Vector3i {
_FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const; _FORCE_INLINE_ double length() const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
_FORCE_INLINE_ void zero(); _FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i abs() const;
@ -139,14 +136,6 @@ double Vector3i::length() const {
return Math::sqrt((double)length_squared()); return Math::sqrt((double)length_squared());
} }
int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector3i::distance_to(const Vector3i &p_to) const {
return (p_to - *this).length();
}
Vector3i Vector3i::abs() const { Vector3i Vector3i::abs() const {
return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z)); return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
} }

View File

@ -84,9 +84,6 @@ struct _NO_DISCARD_ Vector4i {
_FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const; _FORCE_INLINE_ double length() const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
_FORCE_INLINE_ void zero(); _FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i abs() const;
@ -143,14 +140,6 @@ double Vector4i::length() const {
return Math::sqrt((double)length_squared()); return Math::sqrt((double)length_squared());
} }
int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector4i::distance_to(const Vector4i &p_to) const {
return (p_to - *this).length();
}
Vector4i Vector4i::abs() const { Vector4i Vector4i::abs() const {
return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w)); return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
} }

View File

@ -32,7 +32,6 @@
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/godot.hpp> #include <godot_cpp/godot.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/core/memory.hpp> #include <godot_cpp/core/memory.hpp>
@ -338,46 +337,6 @@ void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p
type.virtual_methods[p_method] = p_call; type.virtual_methods[p_method] = p_call;
} }
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names) {
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
GDExtensionClassVirtualMethodInfo mi;
mi.name = (GDExtensionStringNamePtr)&p_method.name;
mi.method_flags = p_method.flags;
mi.return_value = p_method.return_val._to_gdextension();
mi.return_value_metadata = p_method.return_val_metadata;
mi.argument_count = p_method.arguments.size();
if (mi.argument_count > 0) {
mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count);
mi.arguments_metadata = (GDExtensionClassMethodArgumentMetadata *)memalloc(sizeof(GDExtensionClassMethodArgumentMetadata) * mi.argument_count);
for (int i = 0; i < mi.argument_count; i++) {
mi.arguments[i] = p_method.arguments[i]._to_gdextension();
mi.arguments_metadata[i] = p_method.arguments_metadata[i];
}
} else {
mi.arguments = nullptr;
mi.arguments_metadata = nullptr;
}
if (p_arg_names.size() != mi.argument_count) {
WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name);
} else {
for (int i = 0; i < p_arg_names.size(); i++) {
mi.arguments[i].name = (GDExtensionStringNamePtr)&p_arg_names[i];
}
}
internal::gdextension_interface_classdb_register_extension_class_virtual_method(internal::library, &p_class, &mi);
if (mi.arguments) {
memfree(mi.arguments);
}
if (mi.arguments_metadata) {
memfree(mi.arguments_metadata);
}
}
void ClassDB::initialize_class(const ClassInfo &p_cl) { void ClassDB::initialize_class(const ClassInfo &p_cl) {
} }

View File

@ -171,8 +171,6 @@ GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_na
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr; GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr; GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr; GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method = nullptr;
GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method = nullptr;
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr; GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr; GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr; GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
@ -185,7 +183,6 @@ GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_metho
GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr; GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3 = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3 = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr;
@ -411,8 +408,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo); LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId); LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId); LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
LOAD_PROC_ADDRESS(object_has_script_method, GDExtensionInterfaceObjectHasScriptMethod);
LOAD_PROC_ADDRESS(object_call_script_method, GDExtensionInterfaceObjectCallScriptMethod);
LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate); LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate);
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData); LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject); LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
@ -425,7 +420,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag); LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag);
LOAD_PROC_ADDRESS(classdb_register_extension_class3, GDExtensionInterfaceClassdbRegisterExtensionClass3); LOAD_PROC_ADDRESS(classdb_register_extension_class3, GDExtensionInterfaceClassdbRegisterExtensionClass3);
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod); LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
LOAD_PROC_ADDRESS(classdb_register_extension_class_virtual_method, GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod);
LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant); LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty); LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed); LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed);

View File

@ -76,7 +76,7 @@ bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
template <class T> template <class T>
CharStringT<T> &CharStringT<T>::operator+=(T p_char) { CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
const int64_t lhs_len = length(); const int lhs_len = length();
resize(lhs_len + 2); resize(lhs_len + 2);
T *dst = ptrw(); T *dst = ptrw();
@ -172,23 +172,23 @@ String::String(const char32_t *from) {
internal::gdextension_interface_string_new_with_utf32_chars(_native_ptr(), from); internal::gdextension_interface_string_new_with_utf32_chars(_native_ptr(), from);
} }
String String::utf8(const char *from, int64_t len) { String String::utf8(const char *from, int len) {
String ret; String ret;
ret.parse_utf8(from, len); ret.parse_utf8(from, len);
return ret; return ret;
} }
void String::parse_utf8(const char *from, int64_t len) { void String::parse_utf8(const char *from, int len) {
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len); internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
} }
String String::utf16(const char16_t *from, int64_t len) { String String::utf16(const char16_t *from, int len) {
String ret; String ret;
ret.parse_utf16(from, len); ret.parse_utf16(from, len);
return ret; return ret;
} }
void String::parse_utf16(const char16_t *from, int64_t len) { void String::parse_utf16(const char16_t *from, int len) {
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len); internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
} }
@ -230,8 +230,8 @@ String rtoss(double p_val) {
} }
CharString String::utf8() const { CharString String::utf8() const {
int64_t length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0); int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
int64_t size = length + 1; int size = length + 1;
CharString str; CharString str;
str.resize(size); str.resize(size);
internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length); internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length);
@ -242,8 +242,8 @@ CharString String::utf8() const {
} }
CharString String::ascii() const { CharString String::ascii() const {
int64_t length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0); int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
int64_t size = length + 1; int size = length + 1;
CharString str; CharString str;
str.resize(size); str.resize(size);
internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length); internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length);
@ -254,8 +254,8 @@ CharString String::ascii() const {
} }
Char16String String::utf16() const { Char16String String::utf16() const {
int64_t length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0); int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
int64_t size = length + 1; int size = length + 1;
Char16String str; Char16String str;
str.resize(size); str.resize(size);
internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length); internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length);
@ -266,8 +266,8 @@ Char16String String::utf16() const {
} }
Char32String String::utf32() const { Char32String String::utf32() const {
int64_t length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0); int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
int64_t size = length + 1; int size = length + 1;
Char32String str; Char32String str;
str.resize(size); str.resize(size);
internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length); internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length);
@ -278,8 +278,8 @@ Char32String String::utf32() const {
} }
CharWideString String::wide_string() const { CharWideString String::wide_string() const {
int64_t length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0); int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
int64_t size = length + 1; int size = length + 1;
CharWideString str; CharWideString str;
str.resize(size); str.resize(size);
internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length); internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length);
@ -289,7 +289,7 @@ CharWideString String::wide_string() const {
return str; return str;
} }
Error String::resize(int64_t p_size) { Error String::resize(int p_size) {
return (Error)internal::gdextension_interface_string_resize(_native_ptr(), p_size); return (Error)internal::gdextension_interface_string_resize(_native_ptr(), p_size);
} }
@ -390,11 +390,11 @@ String &String::operator+=(const char32_t *p_str) {
return *this; return *this;
} }
const char32_t &String::operator[](int64_t p_index) const { const char32_t &String::operator[](int p_index) const {
return *internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, p_index); return *internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, p_index);
} }
char32_t &String::operator[](int64_t p_index) { char32_t &String::operator[](int p_index) {
return *internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, p_index); return *internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, p_index);
} }

View File

@ -46,11 +46,11 @@
namespace godot { namespace godot {
const uint8_t &PackedByteArray::operator[](int64_t p_index) const { const uint8_t &PackedByteArray::operator[](int p_index) const {
return *internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
} }
uint8_t &PackedByteArray::operator[](int64_t p_index) { uint8_t &PackedByteArray::operator[](int p_index) {
return *internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index);
} }
@ -62,12 +62,12 @@ uint8_t *PackedByteArray::ptrw() {
return internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0); return internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const Color &PackedColorArray::operator[](int64_t p_index) const { const Color &PackedColorArray::operator[](int p_index) const {
const Color *color = (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const Color *color = (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *color; return *color;
} }
Color &PackedColorArray::operator[](int64_t p_index) { Color &PackedColorArray::operator[](int p_index) {
Color *color = (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index); Color *color = (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *color; return *color;
} }
@ -80,11 +80,11 @@ Color *PackedColorArray::ptrw() {
return (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, 0); return (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const float &PackedFloat32Array::operator[](int64_t p_index) const { const float &PackedFloat32Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
} }
float &PackedFloat32Array::operator[](int64_t p_index) { float &PackedFloat32Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index);
} }
@ -96,11 +96,11 @@ float *PackedFloat32Array::ptrw() {
return internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0); return internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const double &PackedFloat64Array::operator[](int64_t p_index) const { const double &PackedFloat64Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
} }
double &PackedFloat64Array::operator[](int64_t p_index) { double &PackedFloat64Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index);
} }
@ -112,11 +112,11 @@ double *PackedFloat64Array::ptrw() {
return internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0); return internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const int32_t &PackedInt32Array::operator[](int64_t p_index) const { const int32_t &PackedInt32Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
} }
int32_t &PackedInt32Array::operator[](int64_t p_index) { int32_t &PackedInt32Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index);
} }
@ -128,11 +128,11 @@ int32_t *PackedInt32Array::ptrw() {
return internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0); return internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const int64_t &PackedInt64Array::operator[](int64_t p_index) const { const int64_t &PackedInt64Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
} }
int64_t &PackedInt64Array::operator[](int64_t p_index) { int64_t &PackedInt64Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index); return *internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index);
} }
@ -144,12 +144,12 @@ int64_t *PackedInt64Array::ptrw() {
return internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0); return internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const String &PackedStringArray::operator[](int64_t p_index) const { const String &PackedStringArray::operator[](int p_index) const {
const String *string = (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const String *string = (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *string; return *string;
} }
String &PackedStringArray::operator[](int64_t p_index) { String &PackedStringArray::operator[](int p_index) {
String *string = (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index); String *string = (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *string; return *string;
} }
@ -162,12 +162,12 @@ String *PackedStringArray::ptrw() {
return (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, 0); return (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const Vector2 &PackedVector2Array::operator[](int64_t p_index) const { const Vector2 &PackedVector2Array::operator[](int p_index) const {
const Vector2 *vec = (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const Vector2 *vec = (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec; return *vec;
} }
Vector2 &PackedVector2Array::operator[](int64_t p_index) { Vector2 &PackedVector2Array::operator[](int p_index) {
Vector2 *vec = (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index); Vector2 *vec = (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec; return *vec;
} }
@ -180,12 +180,12 @@ Vector2 *PackedVector2Array::ptrw() {
return (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0); return (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const Vector3 &PackedVector3Array::operator[](int64_t p_index) const { const Vector3 &PackedVector3Array::operator[](int p_index) const {
const Vector3 *vec = (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const Vector3 *vec = (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec; return *vec;
} }
Vector3 &PackedVector3Array::operator[](int64_t p_index) { Vector3 &PackedVector3Array::operator[](int p_index) {
Vector3 *vec = (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index); Vector3 *vec = (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec; return *vec;
} }
@ -198,12 +198,12 @@ Vector3 *PackedVector3Array::ptrw() {
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0); return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const Variant &Array::operator[](int64_t p_index) const { const Variant &Array::operator[](int p_index) const {
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *var; return *var;
} }
Variant &Array::operator[](int64_t p_index) { Variant &Array::operator[](int p_index) {
Variant *var = (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, p_index); Variant *var = (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *var; return *var;
} }

View File

@ -49,14 +49,6 @@ double Vector2i::length() const {
return Math::sqrt((double)length_squared()); return Math::sqrt((double)length_squared());
} }
int64_t Vector2i::distance_squared_to(const Vector2i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector2i::distance_to(const Vector2i &p_to) const {
return (p_to - *this).length();
}
Vector2i Vector2i::operator+(const Vector2i &p_v) const { Vector2i Vector2i::operator+(const Vector2i &p_v) const {
return Vector2i(x + p_v.x, y + p_v.y); return Vector2i(x + p_v.x, y + p_v.y);
} }

View File

@ -1,5 +0,0 @@
extends Example
func _do_something_virtual(p_name, p_value):
custom_signal.emit(p_name, p_value)
return "Implemented"

View File

@ -241,10 +241,6 @@ func _ready():
assert_equal(new_example_ref.was_post_initialized(), true) assert_equal(new_example_ref.was_post_initialized(), true)
assert_equal(example.test_post_initialize(), true) assert_equal(example.test_post_initialize(), true)
# Test a virtual method defined in GDExtension and implemented in script.
assert_equal(example.test_virtual_implemented_in_script("Virtual", 939), "Implemented")
assert_equal(custom_signal_emitted, ["Virtual", 939])
exit_with_status() exit_with_status()
func _on_Example_custom_signal(signal_name, value): func _on_Example_custom_signal(signal_name, value):

View File

@ -1,13 +1,11 @@
[gd_scene load_steps=3 format=3 uid="uid://dmx2xuigcpvt4"] [gd_scene load_steps=2 format=3 uid="uid://dmx2xuigcpvt4"]
[ext_resource type="Script" path="res://main.gd" id="1_qesh5"] [ext_resource type="Script" path="res://main.gd" id="1_qesh5"]
[ext_resource type="Script" path="res://example.gd" id="2_jju25"]
[node name="Node" type="Node"] [node name="Node" type="Node"]
script = ExtResource("1_qesh5") script = ExtResource("1_qesh5")
[node name="Example" type="Example" parent="."] [node name="Example" type="Example" parent="."]
script = ExtResource("2_jju25")
[node name="ExampleMin" type="ExampleMin" parent="Example"] [node name="ExampleMin" type="ExampleMin" parent="Example"]
layout_mode = 0 layout_mode = 0

View File

@ -230,9 +230,6 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind); ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize); ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
GDVIRTUAL_BIND(_do_something_virtual, "name", "value");
ClassDB::bind_method(D_METHOD("test_virtual_implemented_in_script"), &Example::test_virtual_implemented_in_script);
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static); ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2); ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
@ -630,30 +627,22 @@ void Example::_input(const Ref<InputEvent> &event) {
} }
} }
String Example::test_virtual_implemented_in_script(const String &p_name, int p_value) { void ExampleGameplay::_bind_methods() {
String ret; ClassDB::bind_method(D_METHOD("set_prop_value", "value"), &ExampleGameplay::set_prop_value);
if (GDVIRTUAL_CALL(_do_something_virtual, p_name, p_value, ret)) { ClassDB::bind_method(D_METHOD("get_prop_value"), &ExampleGameplay::get_prop_value);
return ret;
}
return "Unimplemented";
}
void ExampleRuntime::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_prop_value", "value"), &ExampleRuntime::set_prop_value);
ClassDB::bind_method(D_METHOD("get_prop_value"), &ExampleRuntime::get_prop_value);
ADD_PROPERTY(PropertyInfo(Variant::INT, "prop_value"), "set_prop_value", "get_prop_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "prop_value"), "set_prop_value", "get_prop_value");
} }
void ExampleRuntime::set_prop_value(int p_prop_value) { void ExampleGameplay::set_prop_value(int p_prop_value) {
prop_value = p_prop_value; prop_value = p_prop_value;
} }
int ExampleRuntime::get_prop_value() const { int ExampleGameplay::get_prop_value() const {
return prop_value; return prop_value;
} }
ExampleRuntime::ExampleRuntime() { ExampleGameplay::ExampleGameplay() {
} }
ExampleRuntime::~ExampleRuntime() { ExampleGameplay::~ExampleGameplay() {
} }

View File

@ -24,7 +24,6 @@
#include <godot_cpp/variant/variant.hpp> #include <godot_cpp/variant/variant.hpp>
#include <godot_cpp/core/binder_common.hpp> #include <godot_cpp/core/binder_common.hpp>
#include <godot_cpp/core/gdvirtual.gen.inc>
using namespace godot; using namespace godot;
@ -182,9 +181,6 @@ public:
// Virtual function override (no need to bind manually). // Virtual function override (no need to bind manually).
virtual bool _has_point(const Vector2 &point) const override; virtual bool _has_point(const Vector2 &point) const override;
virtual void _input(const Ref<InputEvent> &event) override; virtual void _input(const Ref<InputEvent> &event) override;
GDVIRTUAL2R(String, _do_something_virtual, String, int);
String test_virtual_implemented_in_script(const String &p_name, int p_value);
}; };
VARIANT_ENUM_CAST(Example::Constants); VARIANT_ENUM_CAST(Example::Constants);
@ -202,26 +198,15 @@ protected:
static void _bind_methods() {} static void _bind_methods() {}
}; };
class ExampleAbstractBase : public Object { class ExampleAbstract : public Object {
GDCLASS(ExampleAbstractBase, Object); GDCLASS(ExampleAbstract, Object);
protected: protected:
static void _bind_methods() {} static void _bind_methods() {}
virtual int test_function() = 0;
}; };
class ExampleConcrete : public ExampleAbstractBase { class ExampleGameplay : public Node {
GDCLASS(ExampleConcrete, ExampleAbstractBase); GDCLASS(ExampleGameplay, Node);
protected:
static void _bind_methods() {}
virtual int test_function() override { return 25; }
};
class ExampleRuntime : public Node {
GDCLASS(ExampleRuntime, Node);
int prop_value = 12; int prop_value = 12;
@ -232,8 +217,8 @@ public:
void set_prop_value(int p_prop_value); void set_prop_value(int p_prop_value);
int get_prop_value() const; int get_prop_value() const;
ExampleRuntime(); ExampleGameplay();
~ExampleRuntime(); ~ExampleGameplay();
}; };
#endif // EXAMPLE_CLASS_H #endif // EXAMPLE_CLASS_H

View File

@ -25,9 +25,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
ClassDB::register_class<ExampleMin>(); ClassDB::register_class<ExampleMin>();
ClassDB::register_class<Example>(); ClassDB::register_class<Example>();
ClassDB::register_class<ExampleVirtual>(true); ClassDB::register_class<ExampleVirtual>(true);
ClassDB::register_abstract_class<ExampleAbstractBase>(); ClassDB::register_abstract_class<ExampleAbstract>();
ClassDB::register_class<ExampleConcrete>(); ClassDB::register_gameplay_class<ExampleGameplay>();
ClassDB::register_runtime_class<ExampleRuntime>();
} }
void uninitialize_example_module(ModuleInitializationLevel p_level) { void uninitialize_example_module(ModuleInitializationLevel p_level) {

View File

@ -64,12 +64,6 @@ def generate(env):
elif sys.platform == "darwin": elif sys.platform == "darwin":
toolchain += "darwin-x86_64" toolchain += "darwin-x86_64"
env.Append(LINKFLAGS=["-shared"]) env.Append(LINKFLAGS=["-shared"])
if not os.path.exists(toolchain):
print("ERROR: Could not find NDK toolchain at " + toolchain + ".")
print("Make sure NDK version " + get_ndk_version() + " is installed.")
env.Exit(1)
env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
# Get architecture info # Get architecture info