Merge branch 'godotengine:master' into master

pull/1495/head
Anthony 2024-06-15 23:39:28 -04:00 committed by GitHub
commit de727e1a1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
90 changed files with 22315 additions and 1379 deletions

View File

@ -4,6 +4,8 @@ on: [push, pull_request]
env:
# Only used for the cache key. Increment version to force clean build.
GODOT_BASE_BRANCH: master
# Used to select the version of Godot to run the tests with.
GODOT_TEST_VERSION: master
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}
@ -117,7 +119,7 @@ jobs:
- name: Web dependencies
if: ${{ matrix.platform == 'web' }}
uses: mymindstorm/setup-emsdk@v13
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
@ -134,26 +136,26 @@ jobs:
- name: Generate godot-cpp sources only
run: |
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
scons platform=${{ matrix.platform }} verbose=yes build_library=no ${{ matrix.flags }}
scons -c
- name: Build godot-cpp (debug)
run: |
scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }}
scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }}
- name: Build test without rebuilding godot-cpp (debug)
run: |
cd test
scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }} build_library=no
scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} build_library=no
- name: Build test and godot-cpp (release)
run: |
cd test
scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
scons platform=${{ matrix.platform }} verbose=yes target=template_release ${{ matrix.flags }}
- name: Download latest Godot artifacts
uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
if: ${{ matrix.run-tests }}
if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }}
with:
repo: godotengine/godot
branch: master
@ -166,15 +168,28 @@ jobs:
ensure_latest: true
path: godot-artifacts
- name: Prepare Godot artifacts for testing
if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }}
run: |
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV
- name: Download requested Godot version for testing
if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION != 'master' }}
run: |
wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip
unzip -a Godot.zip
chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64"
echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV
- name: Run tests
if: ${{ matrix.run-tests }}
run: |
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
$GODOT --headless --version
cd test
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
(cd project && (timeout 10 ../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
GODOT=../godot-artifacts/godot.linuxbsd.editor.x86_64.mono ./run-tests.sh
(cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true))
./run-tests.sh
- name: Upload artifact
uses: actions/upload-artifact@v3

View File

@ -37,7 +37,7 @@
# Todo
# Test build for Windows, Mac and mingw.
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.13)
project(godot-cpp LANGUAGES CXX)
option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON)

View File

@ -22,7 +22,7 @@ This repository contains the *C++ bindings* for the [**Godot Engine**](https://
- [**Compatibility**](#compatibility)
- [**Contributing**](#contributing)
- [**Getting started**](#getting-started)
- [**Included example**](#included-example)
- [**Examples and templates**](#examples-and-templates)
## Versioning
@ -132,7 +132,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ClassDB::register_class<Example>();
GDREGISTER_CLASS(Example);
}
```

View File

@ -309,6 +309,10 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
generate_utility_functions(api, target_dir)
CLASS_ALIASES = {
"ClassDB": "ClassDBSingleton",
}
builtin_classes = []
# Key is class name, value is boolean where True means the class is refcounted.
@ -541,6 +545,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("#include <godot_cpp/variant/vector2.hpp>")
if class_name == "PackedVector3Array":
result.append("#include <godot_cpp/variant/vector3.hpp>")
if class_name == "PackedVector4Array":
result.append("#include <godot_cpp/variant/vector4.hpp>")
if is_packed_array(class_name):
result.append("#include <godot_cpp/core/error_macros.hpp>")
@ -696,7 +702,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
vararg = method["is_vararg"]
if vararg:
result.append("\ttemplate<class... Args>")
result.append("\ttemplate<typename... Args>")
method_signature = "\t"
if "is_static" in method and method["is_static"]:
@ -727,9 +733,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
# Special cases.
if class_name == "String":
result.append("\tstatic String utf8(const char *from, int64_t len = -1);")
result.append("\tvoid parse_utf8(const char *from, int64_t len = -1);")
result.append("\tError parse_utf8(const char *from, int64_t len = -1);")
result.append("\tstatic String utf16(const char16_t *from, int64_t len = -1);")
result.append("\tvoid parse_utf16(const char16_t *from, int64_t len = -1);")
result.append("\tError parse_utf16(const char16_t *from, int64_t len = -1, bool default_little_endian = true);")
result.append("\tCharString utf8() const;")
result.append("\tCharString ascii() const;")
result.append("\tChar16String utf16() const;")
@ -795,7 +801,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("\tchar32_t *ptrw();")
if class_name == "Array":
result.append("\ttemplate <class... Args>")
result.append("\ttemplate <typename... Args>")
result.append("\tstatic Array make(Args... args) {")
result.append("\t\treturn helpers::append_all(Array(), args...);")
result.append("\t}")
@ -1256,9 +1262,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
# First create map of classes and singletons.
for class_api in api["classes"]:
# Generate code for the ClassDB singleton under a different name.
if class_api["name"] == "ClassDB":
class_api["name"] = "ClassDBSingleton"
class_api["alias_for"] = "ClassDB"
if class_api["name"] in CLASS_ALIASES:
class_api["alias_for"] = class_api["name"]
class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]:
if native_struct["name"] == "ObjectID":
@ -1268,9 +1274,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name.
if singleton["name"] == "ClassDB":
singleton["name"] = "ClassDBSingleton"
singleton["alias_for"] = "ClassDB"
if singleton["name"] in CLASS_ALIASES:
singleton["alias_for"] = singleton["name"]
singleton["name"] = CLASS_ALIASES[singleton["name"]]
singletons.append(singleton["name"])
for class_api in api["classes"]:
@ -1475,6 +1481,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("#include <type_traits>")
result.append("")
if class_name == "ClassDBSingleton":
result.append("#include <godot_cpp/core/binder_common.hpp>")
result.append("")
result.append("namespace godot {")
result.append("")
@ -1496,6 +1506,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append("")
if is_singleton:
result.append(f"\tstatic {class_name} *singleton;")
result.append("")
result.append("public:")
result.append("")
@ -1556,7 +1570,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("protected:")
# T is the custom class we want to register (from which the call initiates, going up the inheritance chain),
# B is its base class (can be a custom class too, that's why we pass it).
result.append("\ttemplate <class T, class B>")
result.append("\ttemplate <typename T, typename B>")
result.append("\tstatic void register_virtuals() {")
if class_name != "Object":
result.append(f"\t\t{inherits}::register_virtuals<T, B>();")
@ -1576,12 +1590,21 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("\t}")
result.append("")
if is_singleton:
result.append(f"\t~{class_name}();")
result.append("")
result.append("public:")
# Special cases.
if class_name == "XMLParser":
result.append("\tError _open_buffer(const uint8_t *p_buffer, size_t p_size);")
if class_name == "Image":
result.append("\tuint8_t *ptrw();")
result.append("\tconst uint8_t *ptr();")
if class_name == "FileAccess":
result.append("\tuint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;")
result.append("\tvoid store_buffer(const uint8_t *p_src, uint64_t p_length);")
@ -1602,16 +1625,16 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
if class_name == "Object":
result.append("")
result.append("\ttemplate<class T>")
result.append("\ttemplate<typename T>")
result.append("\tstatic T *cast_to(Object *p_object);")
result.append("\ttemplate<class T>")
result.append("\ttemplate<typename T>")
result.append("\tstatic const T *cast_to(const Object *p_object);")
result.append("\tvirtual ~Object() = default;")
elif use_template_get_node and class_name == "Node":
result.append("\ttemplate<class T>")
result.append("\ttemplate<typename T>")
result.append(
"\tT *get_node(const NodePath &p_path) const { return Object::cast_to<T>(get_node_internal(p_path)); }"
)
@ -1633,20 +1656,41 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
if class_name == "ClassDBSingleton":
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
if "enums" in class_api:
for enum_api in class_api["enums"]:
if enum_api["is_bitfield"]:
result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\')
else:
result.append(f'\tenum {enum_api["name"]} {{ \\')
for value in enum_api["values"]:
result.append(f'\t\t{value["name"]} = {value["value"]}, \\')
result.append("\t}; \\")
result.append("\t \\")
for method in class_api["methods"]:
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
if vararg:
continue
# ClassDBSingleton shouldn't have any static methods, but if some appear later, lets skip them.
if "is_static" in method and method["is_static"]:
continue
method_signature = "\tstatic "
vararg = "is_vararg" in method and method["is_vararg"]
if vararg:
method_signature = "\ttemplate<typename... Args> static "
else:
method_signature = "\tstatic "
return_type = None
if "return_type" in method:
method_signature += f'{correct_type(method["return_type"])} '
return_type = correct_type(method["return_type"].replace("ClassDBSingleton", "ClassDB"), None, False)
elif "return_value" in method:
method_signature += (
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
return_type = correct_type(
method["return_value"]["type"].replace("ClassDBSingleton", "ClassDB"),
method["return_value"].get("meta", None),
False,
)
if return_type is not None:
method_signature += return_type + " "
else:
method_signature += "void "
@ -1657,7 +1701,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
method_arguments = method["arguments"]
method_signature += make_function_parameters(
method_arguments, include_default=True, for_builtin=True, is_vararg=False
method_arguments, include_default=True, for_builtin=True, is_vararg=vararg
)
method_signature += ") { \\"
@ -1665,10 +1709,14 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(method_signature)
method_body = "\t\t"
if "return_type" in method or "return_value" in method:
if return_type is not None:
method_body += "return "
if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"):
method_body += f"({return_type})"
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
if vararg:
method_body += ", args..."
method_body += "); \\"
result.append(method_body)
@ -1676,6 +1724,18 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("\t;")
result.append("")
result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\")
if "enums" in class_api:
for enum_api in class_api["enums"]:
if enum_api["is_bitfield"]:
result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
else:
result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
result.append("\t;")
result.append("")
result.append(f"#endif // ! {header_guard}")
return "\n".join(result)
@ -1693,6 +1753,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
result.append("")
result.append("#include <godot_cpp/core/class_db.hpp>")
result.append("#include <godot_cpp/core/engine_ptrcall.hpp>")
result.append("#include <godot_cpp/core/error_macros.hpp>")
result.append("")
@ -1707,9 +1768,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append("")
if is_singleton:
result.append(f"{class_name} *{class_name}::singleton = nullptr;")
result.append("")
result.append(f"{class_name} *{class_name}::get_singleton() {{")
# We assume multi-threaded access is OK because each assignment will assign the same value every time
result.append(f"\tstatic {class_name} *singleton = nullptr;")
result.append("\tif (unlikely(singleton == nullptr)) {")
result.append(
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
@ -1723,11 +1785,22 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
result.append("#endif // DEBUG_ENABLED")
result.append("\t\tif (likely(singleton)) {")
result.append(f"\t\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);")
result.append("\t\t}")
result.append("\t}")
result.append("\treturn singleton;")
result.append("}")
result.append("")
result.append(f"{class_name}::~{class_name}() {{")
result.append("\tif (singleton == this) {")
result.append(f"\t\tClassDB::_unregister_engine_singleton({class_name}::get_class_static());")
result.append("\t\tsingleton = nullptr;")
result.append("\t}")
result.append("}")
result.append("")
if "methods" in class_api:
for method in class_api["methods"]:
if method["is_virtual"]:
@ -2245,7 +2318,7 @@ def make_varargs_template(
if with_public_declare:
function_signature = "public: "
function_signature += "template<class... Args> "
function_signature += "template<typename... Args> "
if static:
function_signature += "static "
@ -2291,9 +2364,9 @@ def make_varargs_template(
args_array = f"\tstd::array<Variant, {len(method_arguments)} + sizeof...(Args)> variant_args {{ "
for argument in method_arguments:
if argument["type"] == "Variant":
args_array += argument["name"]
args_array += escape_identifier(argument["name"])
else:
args_array += f'Variant({argument["name"]})'
args_array += f'Variant({escape_identifier(argument["name"])})'
args_array += ", "
args_array += "Variant(args)... };"
@ -2405,6 +2478,7 @@ def is_packed_array(type_name):
"PackedStringArray",
"PackedVector2Array",
"PackedVector3Array",
"PackedVector4Array",
]
@ -2493,6 +2567,7 @@ def correct_default_value(value, type_name):
"null": "nullptr",
'""': "String()",
'&""': "StringName()",
'^""': "NodePath()",
"[]": "Array()",
"{}": "Dictionary()",
"Transform2D(1, 0, 0, 1, 0, 0)": "Transform2D()", # Default transform.
@ -2504,6 +2579,10 @@ def correct_default_value(value, type_name):
return f"{type_name}()"
if value.startswith("Array["):
return f"{{}}"
if value.startswith("&"):
return value[1::]
if value.startswith("^"):
return value[1::]
return value
@ -2513,7 +2592,7 @@ def correct_typed_array(type_name):
return type_name
def correct_type(type_name, meta=None):
def correct_type(type_name, meta=None, use_alias=True):
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
if meta != None:
if "int" in meta:
@ -2529,11 +2608,15 @@ def correct_type(type_name, meta=None):
if is_enum(type_name):
if is_bitfield(type_name):
base_class = get_enum_class(type_name)
if use_alias and base_class in CLASS_ALIASES:
base_class = CLASS_ALIASES[base_class]
if base_class == "GlobalConstants":
return f"BitField<{get_enum_name(type_name)}>"
return f"BitField<{base_class}::{get_enum_name(type_name)}>"
else:
base_class = get_enum_class(type_name)
if use_alias and base_class in CLASS_ALIASES:
base_class = CLASS_ALIASES[base_class]
if base_class == "GlobalConstants":
return f"{get_enum_name(type_name)}"
return f"{base_class}::{get_enum_name(type_name)}"

File diff suppressed because it is too large Load Diff

View File

@ -96,6 +96,7 @@ typedef enum {
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY,
GDEXTENSION_VARIANT_TYPE_VARIANT_MAX
} GDExtensionVariantType;
@ -256,6 +257,7 @@ typedef struct {
typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef void (*GDExtensionClassFreePropertyList2)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count);
typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
typedef GDExtensionBool (*GDExtensionClassValidateProperty)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property);
@ -333,7 +335,7 @@ typedef struct {
GDExtensionClassSet set_func;
GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList free_property_list_func;
GDExtensionClassFreePropertyList2 free_property_list_func;
GDExtensionClassPropertyCanRevert property_can_revert_func;
GDExtensionClassPropertyGetRevert property_get_revert_func;
GDExtensionClassValidateProperty validate_property_func;
@ -535,6 +537,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList2)(GDExtensionScriptInstan
typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionInt (*GDExtensionScriptInstanceGetMethodArgumentCount)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid);
typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionScriptInstanceNotification2 instead.
typedef void (*GDExtensionScriptInstanceNotification2)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what, GDExtensionBool p_reversed);
@ -654,6 +658,8 @@ typedef struct {
GDExtensionScriptInstanceHasMethod has_method_func;
GDExtensionScriptInstanceGetMethodArgumentCount get_method_argument_count_func;
GDExtensionScriptInstanceCall call_func;
GDExtensionScriptInstanceNotification2 notification_func;
@ -1576,6 +1582,7 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUn
/**
* @name string_new_with_utf8_chars_and_len
* @since 4.1
* @deprecated in Godot 4.3. Use `string_new_with_utf8_chars_and_len2` instead.
*
* Creates a String from a UTF-8 encoded C string with the given length.
*
@ -1585,9 +1592,24 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUn
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
/**
* @name string_new_with_utf8_chars_and_len2
* @since 4.3
*
* Creates a String from a UTF-8 encoded C string with the given length.
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-8 encoded C string.
* @param p_size The number of bytes (not code units).
*
* @return Error code signifying if the operation successful.
*/
typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen2)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
/**
* @name string_new_with_utf16_chars_and_len
* @since 4.1
* @deprecated in Godot 4.3. Use `string_new_with_utf16_chars_and_len2` instead.
*
* Creates a String from a UTF-16 encoded C string with the given length.
*
@ -1597,6 +1619,21 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen)(GDExtensionUnin
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count);
/**
* @name string_new_with_utf16_chars_and_len2
* @since 4.3
*
* Creates a String from a UTF-16 encoded C string with the given length.
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-16 encoded C string.
* @param p_size The number of characters (not bytes).
* @param p_default_little_endian If true, UTF-16 use little endian.
*
* @return Error code signifying if the operation successful.
*/
typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen2)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count, GDExtensionBool p_default_little_endian);
/**
* @name string_new_with_utf32_chars_and_len
* @since 4.1
@ -1893,6 +1930,36 @@ typedef void (*GDExtensionInterfaceFileAccessStoreBuffer)(GDExtensionObjectPtr p
*/
typedef uint64_t (*GDExtensionInterfaceFileAccessGetBuffer)(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length);
/* INTERFACE: Image Utilities */
/**
* @name image_ptrw
* @since 4.3
*
* Returns writable pointer to internal Image buffer.
*
* @param p_instance A pointer to a Image object.
*
* @return Pointer to internal Image buffer.
*
* @see Image::ptrw()
*/
typedef uint8_t *(*GDExtensionInterfaceImagePtrw)(GDExtensionObjectPtr p_instance);
/**
* @name image_ptr
* @since 4.3
*
* Returns read only pointer to internal Image buffer.
*
* @param p_instance A pointer to a Image object.
*
* @return Pointer to internal Image buffer.
*
* @see Image::ptr()
*/
typedef const uint8_t *(*GDExtensionInterfaceImagePtr)(GDExtensionObjectPtr p_instance);
/* INTERFACE: WorkerThreadPool Utilities */
/**
@ -1958,32 +2025,6 @@ typedef uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndex)(GDExtension
*/
typedef const uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index
* @since 4.1
*
* Gets a pointer to a color in a PackedColorArray.
*
* @param p_self A pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index_const
* @since 4.1
*
* Gets a const pointer to a color in a PackedColorArray.
*
* @param p_self A const pointer to a const PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A const pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_float32_array_operator_index
* @since 4.1
@ -2166,6 +2207,58 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_vector4_array_operator_index
* @since 4.3
*
* Gets a pointer to a Vector4 in a PackedVector4Array.
*
* @param p_self A pointer to a PackedVector4Array object.
* @param p_index The index of the Vector4 to get.
*
* @return A pointer to the requested Vector4.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_vector4_array_operator_index_const
* @since 4.3
*
* Gets a const pointer to a Vector4 in a PackedVector4Array.
*
* @param p_self A const pointer to a PackedVector4Array object.
* @param p_index The index of the Vector4 to get.
*
* @return A const pointer to the requested Vector4.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index
* @since 4.1
*
* Gets a pointer to a color in a PackedColorArray.
*
* @param p_self A pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index_const
* @since 4.1
*
* Gets a const pointer to a color in a PackedColorArray.
*
* @param p_self A const pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A const pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name array_operator_index
* @since 4.1
@ -2352,6 +2445,9 @@ typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o,
*
* Gets the class name of an Object.
*
* If the GDExtension wraps the Godot object in an abstraction specific to its class, this is the
* function that should be used to determine which wrapper to use.
*
* @param p_object A pointer to the Object.
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param r_class_name A pointer to a String to receive the class name.
@ -2626,7 +2722,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class2` instead.
* @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@ -2642,6 +2738,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
/**
* @name classdb_register_extension_class2
* @since 4.2
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@ -2831,6 +2928,31 @@ typedef void (*GDExtensionInterfaceEditorAddPlugin)(GDExtensionConstStringNamePt
*/
typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNamePtr p_class_name);
/**
* @name editor_help_load_xml_from_utf8_chars
* @since 4.3
*
* Loads new XML-formatted documentation data in the editor.
*
* The provided pointer can be immediately freed once the function returns.
*
* @param p_data A pointer to a UTF-8 encoded C string (null terminated).
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *p_data);
/**
* @name editor_help_load_xml_from_utf8_chars_and_len
* @since 4.3
*
* Loads new XML-formatted documentation data in the editor.
*
* The provided pointer can be immediately freed once the function returns.
*
* @param p_data A pointer to a UTF-8 encoded C string.
* @param p_size The number of bytes (not code units).
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
#ifdef __cplusplus
}
#endif

View File

@ -47,11 +47,11 @@ public:
static void remove_plugin_class(const StringName &p_class_name);
static void deinitialize(GDExtensionInitializationLevel p_level);
template <class T>
template <typename T>
static void add_by_type() {
add_plugin_class(T::get_class_static());
}
template <class T>
template <typename T>
static void remove_by_type() {
remove_plugin_class(T::get_class_static());
}

View File

@ -45,7 +45,7 @@ namespace godot {
class RefCounted;
template <class T>
template <typename T>
class Ref {
T *reference = nullptr;
@ -108,7 +108,7 @@ public:
ref(p_from);
}
template <class T_Other>
template <typename T_Other>
void operator=(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@ -144,7 +144,7 @@ public:
}
}
template <class T_Other>
template <typename T_Other>
void reference_ptr(T_Other *p_ptr) {
if (reference == p_ptr) {
return;
@ -161,7 +161,7 @@ public:
ref(p_from);
}
template <class T_Other>
template <typename T_Other>
Ref(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@ -226,7 +226,7 @@ public:
}
};
template <class T>
template <typename T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
@ -248,7 +248,7 @@ struct PtrToArg<Ref<T>> {
}
};
template <class T>
template <typename T>
struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;
@ -259,20 +259,20 @@ struct PtrToArg<const Ref<T> &> {
}
};
template <class T>
template <typename T>
struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
}
};
template <class T>
template <typename T>
struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());

View File

@ -46,13 +46,31 @@ class ClassDB;
typedef void GodotObject;
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
_ALWAYS_INLINE_ void _pre_initialize();
// Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped {
friend class GDExtensionBinding;
friend class ClassDB;
friend void postinitialize_handler(Wrapped *);
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
friend _ALWAYS_INLINE_ void _pre_initialize();
thread_local static const StringName *_constructing_extension_class_name;
thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
template <typename T>
_ALWAYS_INLINE_ static void _set_construct_info() {
_constructing_extension_class_name = T::_get_extension_class_name();
_constructing_class_binding_callbacks = &T::_gde_binding_callbacks;
}
protected:
virtual bool _is_extension_class() const { return false; }
static const StringName *_get_extension_class_name(); // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
#ifdef HOT_RELOAD_ENABLED
struct RecreateInstance {
GDExtensionClassInstancePtr wrapper;
@ -62,9 +80,6 @@ protected:
inline static RecreateInstance *recreate_instance = nullptr;
#endif
virtual const StringName *_get_extension_class_name() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const = 0;
void _notification(int p_what) {}
bool _set(const StringName &p_name, const Variant &p_property) { return false; }
bool _get(const StringName &p_name, Variant &r_property) const { return false; }
@ -78,7 +93,7 @@ protected:
static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; }
static GDExtensionBool get_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { return nullptr; }
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) {}
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count) {}
static GDExtensionBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name) { return false; }
static GDExtensionBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { return false; }
@ -89,14 +104,15 @@ protected:
::godot::List<::godot::PropertyInfo> plist_owned;
void _postinitialize();
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
Wrapped(const StringName p_godot_class);
Wrapped(GodotObject *p_godot_object);
virtual ~Wrapped() {}
public:
static StringName &get_class_static() {
static StringName string_name = StringName("Wrapped");
static const StringName &get_class_static() {
static const StringName string_name = StringName("Wrapped");
return string_name;
}
@ -108,6 +124,11 @@ public:
GodotObject *_owner = nullptr;
};
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
_ALWAYS_INLINE_ void _pre_initialize() {
Wrapped::_set_construct_info<T>();
}
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr) {
}
@ -115,13 +136,13 @@ _FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p
arr.push_back(p_str);
}
template <class... P>
template <typename... 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>
template <typename... P>
_FORCE_INLINE_ Vector<StringName> snarray(P... p_args) {
Vector<StringName> arr;
snarray_add_str(arr, p_args...);
@ -138,7 +159,7 @@ void add_engine_class_registration_callback(EngineClassRegistrationCallback p_ca
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
void register_engine_classes();
template <class T>
template <typename T>
struct EngineClassRegistration {
EngineClassRegistration() {
add_engine_class_registration_callback(&EngineClassRegistration<T>::callback);
@ -160,15 +181,14 @@ struct EngineClassRegistration {
private: \
void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\
protected: \
virtual const ::godot::StringName *_get_extension_class_name() const override { \
static ::godot::StringName string_name = get_class_static(); \
return &string_name; \
} \
virtual bool _is_extension_class() const override { return true; } \
\
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &_gde_binding_callbacks; \
static const ::godot::StringName *_get_extension_class_name() { \
const ::godot::StringName &string_name = get_class_static(); \
return &string_name; \
} \
\
static void (*_get_bind_methods())() { \
@ -207,13 +227,14 @@ protected:
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \
\
template <class T, class B> \
template <typename T, typename B> \
static void register_virtuals() { \
m_inherits::register_virtuals<T, B>(); \
} \
\
public: \
typedef m_class self_type; \
typedef m_inherits parent_type; \
\
static void initialize_class() { \
static bool initialized = false; \
@ -228,12 +249,12 @@ public:
initialized = true; \
} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\
@ -291,11 +312,10 @@ public:
return ::godot::internal::create_c_property_list(plist_cpp, r_count); \
} \
\
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) { \
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count) { \
if (p_instance) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
cls->plist_owned.clear(); \
/* TODO `GDExtensionClassFreePropertyList` is ill-defined, we need a non-const pointer to free this. */ \
::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
} \
} \
@ -374,6 +394,11 @@ public:
_gde_binding_reference_callback, \
}; \
\
protected: \
virtual void _notificationv(int32_t p_what, bool p_reversed = false) override { \
m_class::notification_bind(this, p_what, p_reversed); \
} \
\
private:
// Don't use this for your classes, use GDCLASS() instead.
@ -381,15 +406,15 @@ private:
private: \
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\
protected: \
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &_gde_binding_callbacks; \
} \
\
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
\
static void _bind_methods() {} \
\
static void (*_get_bind_methods())() { \
return nullptr; \
} \
@ -432,15 +457,16 @@ protected:
\
public: \
typedef m_class self_type; \
typedef m_inherits parent_type; \
\
static void initialize_class() {} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\

View File

@ -83,7 +83,7 @@ namespace godot {
}; \
}
template <class T>
template <typename T>
struct VariantCaster {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@ -95,7 +95,7 @@ struct VariantCaster {
}
};
template <class T>
template <typename T>
struct VariantCaster<T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@ -107,7 +107,7 @@ struct VariantCaster<T &> {
}
};
template <class T>
template <typename T>
struct VariantCaster<const T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
@ -144,7 +144,7 @@ struct VariantObjectClassChecker<const Ref<T> &> {
}
};
template <class T>
template <typename T>
struct VariantCasterAndValidate {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
@ -159,7 +159,7 @@ struct VariantCasterAndValidate {
}
};
template <class T>
template <typename T>
struct VariantCasterAndValidate<T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
@ -174,7 +174,7 @@ struct VariantCasterAndValidate<T &> {
}
};
template <class T>
template <typename T>
struct VariantCasterAndValidate<const T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
@ -189,47 +189,47 @@ struct VariantCasterAndValidate<const T &> {
}
};
template <class T, class... P, size_t... Is>
template <typename T, typename... P, size_t... Is>
void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
}
template <class T, class... P, size_t... Is>
template <typename T, typename... P, size_t... Is>
void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
}
template <class T, class R, class... P, size_t... Is>
template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
template <class T, class R, class... P, size_t... Is>
template <typename T, typename R, typename... P, size_t... Is>
void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
template <class T, class... P>
template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class... P>
template <typename T, typename... P>
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) {
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret) {
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class... P, size_t... Is>
template <typename T, typename... P, size_t... Is>
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -241,7 +241,7 @@ void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), con
(void)(p_args); // Avoid warning.
}
template <class T, class... P, size_t... Is>
template <typename T, typename... P, size_t... Is>
void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -253,7 +253,7 @@ void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) con
(void)(p_args); // Avoid warning.
}
template <class T, class R, class... P, size_t... Is>
template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -264,7 +264,7 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
#endif
}
template <class T, class R, class... P, size_t... Is>
template <typename T, typename R, typename... P, size_t... Is>
void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -276,7 +276,7 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
(void)p_args;
}
template <class T, class... P>
template <typename T, typename... P>
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -294,7 +294,7 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -312,7 +312,7 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -330,7 +330,7 @@ void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, co
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class... P>
template <typename T, typename... P>
void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -365,7 +365,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class... P>
template <typename T, typename... P>
void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -400,7 +400,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -435,7 +435,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -477,7 +477,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif
template <class Q>
template <typename Q>
void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) {
if (p_arg == index) {
type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE);
@ -485,7 +485,7 @@ void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType
index++;
}
template <class... P>
template <typename... P>
GDExtensionVariantType call_get_argument_type(int p_arg) {
GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL;
int index = 0;
@ -497,7 +497,7 @@ GDExtensionVariantType call_get_argument_type(int p_arg) {
return type;
}
template <class Q>
template <typename Q>
void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) {
if (p_arg == index) {
info = GetTypeInfo<Q>::get_class_info();
@ -505,7 +505,7 @@ void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &inf
index++;
}
template <class... P>
template <typename... P>
void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
int index = 0;
// I think rocket science is simpler than modern C++.
@ -515,7 +515,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
(void)index; // Suppress GCC warning.
}
template <class Q>
template <typename Q>
void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) {
if (p_arg == index) {
md = GetTypeInfo<Q>::METADATA;
@ -523,7 +523,7 @@ void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMe
index++;
}
template <class... P>
template <typename... P>
GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
@ -536,7 +536,7 @@ GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
return md;
}
template <class... P, size_t... Is>
template <typename... P, size_t... Is>
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -547,7 +547,7 @@ void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_arg
#endif
}
template <class... P>
template <typename... P>
void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -582,17 +582,17 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class... P, size_t... Is>
template <typename... P, size_t... Is>
void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
p_method(PtrToArg<P>::convert(p_args[Is])...);
}
template <class... P>
template <typename... P>
void call_with_ptr_args_static_method(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args) {
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
template <class R, class... P>
template <typename R, typename... P>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -610,7 +610,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class... P>
template <typename... P>
void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -628,7 +628,7 @@ void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p
call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class R, class... P, size_t... Is>
template <typename R, typename... P, size_t... Is>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@ -639,7 +639,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
#endif
}
template <class R, class... P>
template <typename R, typename... P>
void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
@ -674,12 +674,12 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class R, class... P, size_t... Is>
template <typename R, typename... P, size_t... Is>
void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
template <class R, class... P>
template <typename R, typename... P>
void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) {
call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}

View File

@ -40,7 +40,7 @@ namespace godot {
namespace internal {
template <class O, class... Args>
template <typename O, typename... 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... } };
@ -51,13 +51,13 @@ O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GD
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
}
template <class... Args>
template <typename... Args>
void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
constructor(base, call_args.data());
}
template <class T, class... Args>
template <typename T, typename... Args>
T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
T ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
@ -65,20 +65,20 @@ T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExten
return ret;
}
template <class... Args>
template <typename... Args>
void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
method(base, call_args.data(), nullptr, sizeof...(Args));
}
template <class T>
template <typename T>
T _call_builtin_operator_ptr(const GDExtensionPtrOperatorEvaluator op, GDExtensionConstTypePtr left, GDExtensionConstTypePtr right) {
T ret;
op(left, right, &ret);
return ret;
}
template <class T>
template <typename T>
T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) {
T ret;
getter(base, &ret);

View File

@ -45,6 +45,7 @@
#include <godot_cpp/variant/callable_method_pointer.hpp>
#include <list>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
@ -104,15 +105,17 @@ private:
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
// Used to remember the custom class registration order.
static std::vector<StringName> class_register_order;
static std::unordered_map<StringName, Object *> engine_singletons;
static std::mutex engine_singletons_mutex;
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
static void initialize_class(const ClassInfo &cl);
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
template <class T, bool is_abstract>
template <typename T, bool is_abstract>
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false);
template <class T>
template <typename T>
static GDExtensionObjectPtr _create_instance_func(void *data) {
if constexpr (!std::is_abstract_v<T>) {
T *new_object = memnew(T);
@ -122,7 +125,7 @@ private:
}
}
template <class T>
template <typename T>
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED
@ -140,26 +143,41 @@ private:
}
public:
template <class T>
template <typename T>
static void register_class(bool p_virtual = false);
template <class T>
template <typename T>
static void register_abstract_class();
template <class T>
template <typename T>
static void register_internal_class();
template <class T>
template <typename T>
static void register_runtime_class();
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
instance_binding_callbacks[p_name] = p_callbacks;
}
template <class N, class M, typename... VarArgs>
static void _register_engine_singleton(const StringName &p_class_name, Object *p_singleton) {
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
std::unordered_map<StringName, Object *>::const_iterator i = engine_singletons.find(p_class_name);
if (i != engine_singletons.end()) {
ERR_FAIL_COND((*i).second != p_singleton);
return;
}
engine_singletons[p_class_name] = p_singleton;
}
static void _unregister_engine_singleton(const StringName &p_class_name) {
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
engine_singletons.erase(p_class_name);
}
template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
template <class N, class M, typename... VarArgs>
template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args);
template <class M>
template <typename M>
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix);
@ -200,9 +218,11 @@ public:
::godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
}
template <class T, bool is_abstract>
template <typename T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
static_assert(!FunctionsAreSame<T::self_type::_bind_methods, T::parent_type::_bind_methods>::value, "Class must declare 'static void _bind_methods'.");
static_assert(!std::is_abstract_v<T> || is_abstract, "Class is abstract, please use GDREGISTER_ABSTRACT_CLASS.");
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
// Register this class within our plugin
@ -227,7 +247,7 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
T::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
T::free_property_list_bind, // GDExtensionClassFreePropertyList free_property_list_func;
T::free_property_list_bind, // GDExtensionClassFreePropertyList2 free_property_list_func;
T::property_can_revert_bind, // GDExtensionClassPropertyCanRevert property_can_revert_func;
T::property_get_revert_bind, // GDExtensionClassPropertyGetRevert property_get_revert_func;
T::validate_property_bind, // GDExtensionClassValidateProperty validate_property_func;
@ -254,27 +274,27 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
initialize_class(classes[cl.name]);
}
template <class T>
template <typename T>
void ClassDB::register_class(bool p_virtual) {
ClassDB::_register_class<T, false>(p_virtual);
}
template <class T>
template <typename T>
void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>();
}
template <class T>
template <typename T>
void ClassDB::register_internal_class() {
ClassDB::_register_class<T, false>(false, false);
}
template <class T>
template <typename T>
void ClassDB::register_runtime_class() {
ClassDB::_register_class<T, false>(false, true, true);
}
template <class N, class M, typename... VarArgs>
template <typename N, typename M, typename... VarArgs>
MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@ -285,7 +305,7 @@ MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args)
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
}
template <class N, class M, typename... VarArgs>
template <typename N, typename M, typename... VarArgs>
MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
@ -297,7 +317,7 @@ MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p
return bind_methodfi(0, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
}
template <class M>
template <typename M>
MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_NULL_V(bind, nullptr);
@ -329,12 +349,14 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
return bind;
}
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
#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_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>();
#define GDREGISTER_RUNTIME_CLASS(m_class) ClassDB::register_runtime_class<m_class>();
#define GDREGISTER_CLASS(m_class) ::godot::ClassDB::register_class<m_class>();
#define GDREGISTER_VIRTUAL_CLASS(m_class) ::godot::ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ::godot::ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_INTERNAL_CLASS(m_class) ::godot::ClassDB::register_internal_class<m_class>();
#define GDREGISTER_RUNTIME_CLASS(m_class) ::godot::ClassDB::register_runtime_class<m_class>();
} // namespace godot
CLASSDB_SINGLETON_VARIANT_CAST;
#endif // GODOT_CLASS_DB_HPP

View File

@ -108,7 +108,7 @@ typedef float real_t;
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <class T>
template <typename T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;

View File

@ -43,7 +43,7 @@ namespace godot {
namespace internal {
template <class O, class... Args>
template <typename O, typename... Args>
O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
@ -54,7 +54,7 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
}
template <class R, class... Args>
template <typename R, typename... Args>
R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
R ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
@ -62,13 +62,13 @@ R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const A
return ret;
}
template <class... Args>
template <typename... Args>
void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
}
template <class R, class... Args>
template <typename R, typename... Args>
R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
R ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
@ -76,15 +76,15 @@ R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
return ret;
}
template <class... Args>
Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *instance, const Args &...args) {
template <typename... Args>
Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, const Args &...args) {
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(&ret, mb_args.data(), mb_args.size());
return (Object *)internal::get_object_instance_binding(ret);
}
template <class... Args>
template <typename... Args>
void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &...args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(nullptr, mb_args.data(), mb_args.size());

View File

@ -84,7 +84,7 @@ constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <class T>
template <typename T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;
@ -138,7 +138,7 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) {
return -1;
}
template <class T>
template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x;
@ -613,6 +613,14 @@ inline bool is_inf(double p_val) {
return std::isinf(p_val);
}
inline bool is_finite(float p_val) {
return std::isfinite(p_val);
}
inline bool is_finite(double p_val) {
return std::isfinite(p_val);
}
inline bool is_equal_approx(float a, float b) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {

View File

@ -82,9 +82,12 @@ public:
static void free_static(void *p_ptr, bool p_pad_align = false);
};
template <typename T, std::enable_if_t<!std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
_ALWAYS_INLINE_ void _pre_initialize() {}
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
template <class T>
template <typename T>
_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
postinitialize_handler(p_obj);
return p_obj;
@ -94,18 +97,18 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
#define memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
#define memfree(m_mem) ::godot::Memory::free_static(m_mem)
#define memnew(m_class) ::godot::_post_initialize(new ("", "") m_class)
#define memnew(m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", "") m_class))
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new ("", m_allocator::alloc) m_class)
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class)
#define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class))
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class))
// Generic comparator used in Map, List, etc.
template <class T>
template <typename T>
struct Comparator {
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
};
template <class T>
template <typename T>
void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) {
if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
@ -114,12 +117,12 @@ void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wra
Memory::free_static(p_class);
}
template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
template <typename T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
void memdelete(T *p_class) {
godot::internal::gdextension_interface_object_destroy(p_class->_owner);
}
template <class T, class A>
template <typename T, typename A>
void memdelete_allocator(T *p_class) {
if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
@ -134,10 +137,10 @@ public:
_ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); }
};
template <class T>
template <typename T>
class DefaultTypedAllocator {
public:
template <class... Args>
template <typename... Args>
_ALWAYS_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); }
_ALWAYS_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); }
};

View File

@ -147,7 +147,7 @@ public:
virtual ~MethodBind();
};
template <class Derived, class T, class R, bool should_returns>
template <typename Derived, typename T, typename R, bool should_returns>
class MethodBindVarArgBase : public MethodBind {
protected:
R(T::*method)
@ -208,7 +208,7 @@ private:
}
};
template <class T>
template <typename T>
class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
@ -231,14 +231,14 @@ private:
}
};
template <class T>
template <typename T>
MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
return a;
}
template <class T, class R>
template <typename T, typename R>
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
@ -260,7 +260,7 @@ private:
}
};
template <class T, class R>
template <typename T, typename R>
MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
@ -277,9 +277,9 @@ class _gde_UnexistingClass;
// No return, not const.
#ifdef TYPED_METHOD_BIND
template <class T, class... P>
template <typename T, typename... P>
#else
template <class... P>
template <typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindT : public MethodBind {
void (MB_T::*method)(P...);
@ -339,7 +339,7 @@ public:
}
};
template <class T, class... P>
template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
@ -353,9 +353,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
// No return, const.
#ifdef TYPED_METHOD_BIND
template <class T, class... P>
template <typename T, typename... P>
#else
template <class... P>
template <typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const;
@ -412,10 +412,11 @@ public:
method = p_method;
generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_const(true);
}
};
template <class T, class... P>
template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
@ -429,9 +430,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
// Return, not const.
#ifdef TYPED_METHOD_BIND
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
#else
template <class R, class... P>
template <typename R, typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindTR : public MethodBind {
R(MB_T::*method)
@ -498,7 +499,7 @@ public:
}
};
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
@ -512,9 +513,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) {
// Return, const.
#ifdef TYPED_METHOD_BIND
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
#else
template <class R, class... P>
template <typename R, typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindTRC : public MethodBind {
R(MB_T::*method)
@ -578,10 +579,11 @@ public:
generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_return(true);
set_const(true);
}
};
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
@ -596,7 +598,7 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
// no return
template <class... P>
template <typename... P>
class MethodBindTS : public MethodBind {
void (*function)(P...);
@ -652,7 +654,7 @@ public:
}
};
template <class... P>
template <typename... P>
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
return a;
@ -660,7 +662,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
// return
template <class R, class... P>
template <typename R, typename... P>
class MethodBindTRS : public MethodBind {
R(*function)
(P...);
@ -722,7 +724,7 @@ public:
}
};
template <class R, class... P>
template <typename R, typename... P>
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
return a;

View File

@ -39,7 +39,7 @@
namespace godot {
template <class T>
template <typename T>
struct PtrToArg {};
#define MAKE_PTRARG(m_type) \
@ -166,27 +166,27 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
// This is for Object.
template <class T>
template <typename T>
struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return likely(p_ptr) ? reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
}
};
template <class T>
template <typename T>
struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return likely(p_ptr) ? reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
}
};

View File

@ -80,31 +80,31 @@ struct MethodInfo {
MethodInfo();
MethodInfo(StringName p_name);
template <class... Args>
template <typename... Args>
MethodInfo(StringName p_name, const Args &...args);
MethodInfo(Variant::Type ret);
MethodInfo(Variant::Type ret, StringName p_name);
template <class... Args>
template <typename... Args>
MethodInfo(Variant::Type ret, StringName p_name, const Args &...args);
MethodInfo(const PropertyInfo &p_ret, StringName p_name);
template <class... Args>
template <typename... Args>
MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...);
};
template <class... Args>
template <typename... Args>
MethodInfo::MethodInfo(StringName p_name, const Args &...args) :
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... };
}
template <class... Args>
template <typename... Args>
MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) :
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
return_val.type = ret;
arguments = { args... };
}
template <class... Args>
template <typename... Args>
MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...args) :
name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... };
@ -121,7 +121,7 @@ public:
}
};
template <class T>
template <typename T>
T *Object::cast_to(Object *p_object) {
if (p_object == nullptr) {
return nullptr;
@ -134,7 +134,7 @@ T *Object::cast_to(Object *p_object) {
return dynamic_cast<T *>(internal::get_object_instance_binding(casted));
}
template <class T>
template <typename T>
const T *Object::cast_to(const Object *p_object) {
if (p_object == nullptr) {
return nullptr;

View File

@ -47,9 +47,9 @@ struct PropertyInfo {
Variant::Type type = Variant::NIL;
StringName name;
StringName class_name;
uint32_t hint = 0;
uint32_t hint = PROPERTY_HINT_NONE;
String hint_string;
uint32_t usage = 7;
uint32_t usage = PROPERTY_USAGE_DEFAULT;
PropertyInfo() = default;
@ -72,6 +72,40 @@ struct PropertyInfo {
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
operator Dictionary() const {
Dictionary dict;
dict["name"] = name;
dict["class_name"] = class_name;
dict["type"] = type;
dict["hint"] = hint;
dict["hint_string"] = hint_string;
dict["usage"] = usage;
return dict;
}
static PropertyInfo from_dict(const Dictionary &p_dict) {
PropertyInfo pi;
if (p_dict.has("type")) {
pi.type = Variant::Type(int(p_dict["type"]));
}
if (p_dict.has("name")) {
pi.name = p_dict["name"];
}
if (p_dict.has("class_name")) {
pi.class_name = p_dict["class_name"];
}
if (p_dict.has("hint")) {
pi.hint = PropertyHint(int(p_dict["hint"]));
}
if (p_dict.has("hint_string")) {
pi.hint_string = p_dict["hint_string"];
}
if (p_dict.has("usage")) {
pi.usage = p_dict["usage"];
}
return pi;
}
void _update(GDExtensionPropertyInfo *p_info) {
p_info->type = (GDExtensionVariantType)type;
*(reinterpret_cast<StringName *>(p_info->name)) = name;

View File

@ -58,6 +58,16 @@ struct TypesAreSame<A, A> {
static bool const value = true;
};
template <auto A, auto B>
struct FunctionsAreSame {
static bool const value = false;
};
template <auto A>
struct FunctionsAreSame<A, A> {
static bool const value = true;
};
template <typename B, typename D>
struct TypeInherits {
static D *get_d();
@ -90,7 +100,7 @@ static PropertyInfo make_property_info(Variant::Type p_type, const StringName &p
// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
template <class T, typename = void>
template <typename T, typename = void>
struct GetTypeInfo;
#define MAKE_TYPE_INFO(m_type, m_var_type) \
@ -198,8 +208,8 @@ struct GetTypeInfo<const Variant &> {
template <typename T>
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
}
@ -207,8 +217,8 @@ struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type>
template <typename T>
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
}
@ -226,8 +236,8 @@ inline String enum_qualified_name_to_class_info_name(const String &p_qualified_n
#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@ -248,7 +258,7 @@ inline StringName _gde_constant_get_enum_name(T param, StringName p_constant) {
return GetTypeInfo<T>::get_class_info().class_name;
}
template <class T>
template <typename T>
class BitField {
int64_t value = 0;
@ -264,8 +274,8 @@ public:
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@ -273,8 +283,8 @@ public:
}; \
template <> \
struct GetTypeInfo<BitField<m_impl>> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@ -295,7 +305,7 @@ inline StringName _gde_constant_get_bitfield_name(T param, StringName p_constant
return GetTypeInfo<BitField<T>>::get_class_info().class_name;
}
template <class T>
template <typename T>
struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
@ -306,7 +316,7 @@ struct PtrToArg<TypedArray<T>> {
}
};
template <class T>
template <typename T>
struct PtrToArg<const TypedArray<T> &> {
typedef Array EncodeT;
_FORCE_INLINE_ static TypedArray<T>

View File

@ -108,7 +108,9 @@ extern "C" GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_str
extern "C" GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars;
extern "C" GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2;
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2;
extern "C" GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len;
extern "C" GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars;
@ -148,6 +150,8 @@ extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_inter
extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index;
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
@ -160,6 +164,7 @@ extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destro
extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
extern "C" GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
@ -190,6 +195,15 @@ extern "C" GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_inter
extern "C" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len;
extern "C" GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw;
extern "C" GDExtensionInterfaceImagePtr gdextension_interface_image_ptr;
class DocDataRegistration {
public:
DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data);
};
} // namespace internal

View File

@ -43,13 +43,13 @@
namespace godot {
template <class T>
template <typename T>
class Vector;
template <class T, class V>
template <typename T, typename V>
class VMap;
template <class T>
template <typename T>
class CharStringT;
static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
@ -60,15 +60,15 @@ static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
#pragma GCC diagnostic ignored "-Wplacement-new"
#endif
template <class T>
template <typename T>
class CowData {
template <class TV>
template <typename TV>
friend class Vector;
template <class TV, class VV>
template <typename TV, typename VV>
friend class VMap;
template <class TS>
template <typename TS>
friend class CharStringT;
public:
@ -248,7 +248,7 @@ public:
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
};
template <class T>
template <typename T>
void CowData<T>::_unref(void *p_data) {
if (!p_data) {
return;
@ -275,7 +275,7 @@ void CowData<T>::_unref(void *p_data) {
Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false);
}
template <class T>
template <typename T>
typename CowData<T>::USize CowData<T>::_copy_on_write() {
if (!_ptr) {
return 0;
@ -315,7 +315,7 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() {
return rc;
}
template <class T>
template <typename T>
template <bool p_ensure_zero>
Error CowData<T>::resize(Size p_size) {
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
@ -407,7 +407,7 @@ Error CowData<T>::resize(Size p_size) {
return OK;
}
template <class T>
template <typename T>
typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
Size ret = -1;
@ -425,7 +425,7 @@ typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
return ret;
}
template <class T>
template <typename T>
typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
const Size s = size();
@ -444,7 +444,7 @@ typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
return -1;
}
template <class T>
template <typename T>
typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
Size amount = 0;
for (Size i = 0; i < size(); i++) {
@ -455,12 +455,12 @@ typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
return amount;
}
template <class T>
template <typename T>
void CowData<T>::_ref(const CowData *p_from) {
_ref(*p_from);
}
template <class T>
template <typename T>
void CowData<T>::_ref(const CowData &p_from) {
if (_ptr == p_from._ptr) {
return; // self assign, do nothing.
@ -478,7 +478,7 @@ void CowData<T>::_ref(const CowData &p_from) {
}
}
template <class T>
template <typename T>
CowData<T>::~CowData() {
_unref(_ptr);
}

View File

@ -52,7 +52,7 @@ namespace godot {
* The assignment operator copy the pairs from one map to the other.
*/
template <class TKey, class TValue>
template <typename TKey, typename TValue>
struct HashMapElement {
HashMapElement *next = nullptr;
HashMapElement *prev = nullptr;
@ -62,10 +62,10 @@ struct HashMapElement {
data(p_key, p_value) {}
};
template <class TKey, class TValue,
class Hasher = HashMapHasherDefault,
class Comparator = HashMapComparatorDefault<TKey>,
class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
template <typename TKey, typename TValue,
typename Hasher = HashMapHasherDefault,
typename Comparator = HashMapComparatorDefault<TKey>,
typename Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
class HashMap {
public:
const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.

View File

@ -48,9 +48,9 @@ namespace godot {
*
*/
template <class TKey,
class Hasher = HashMapHasherDefault,
class Comparator = HashMapComparatorDefault<TKey>>
template <typename TKey,
typename Hasher = HashMapHasherDefault,
typename Comparator = HashMapComparatorDefault<TKey>>
class HashSet {
public:
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.

View File

@ -253,7 +253,7 @@ static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev
return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
}
template <class T>
template <typename T>
static _FORCE_INLINE_ uint32_t hash_make_uint32_t(T p_in) {
union {
T t;
@ -286,7 +286,7 @@ static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev =
return ((p_prev << 5) + p_prev) ^ p_in;
}
template <class T>
template <typename T>
static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
union {
T t;
@ -298,15 +298,15 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
return _u._u64;
}
template <class T>
template <typename T>
class Ref;
struct HashMapHasherDefault {
// Generic hash function for any type.
template <class T>
template <typename T>
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); }
template <class T>
template <typename T>
static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); }
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }

View File

@ -45,7 +45,7 @@
namespace godot {
template <class T, class A = DefaultAllocator>
template <typename T, typename A = DefaultAllocator>
class List {
struct _Data;
@ -139,31 +139,6 @@ public:
typedef T ValueType;
struct Iterator {
_FORCE_INLINE_ T &operator*() const {
return E->get();
}
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
_FORCE_INLINE_ Iterator &operator++() {
E = E->next();
return *this;
}
_FORCE_INLINE_ Iterator &operator--() {
E = E->prev();
return *this;
}
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
Iterator(Element *p_E) { E = p_E; }
Iterator() {}
Iterator(const Iterator &p_it) { E = p_it.E; }
private:
Element *E = nullptr;
};
struct ConstIterator {
_FORCE_INLINE_ const T &operator*() const {
return E->get();
@ -189,6 +164,35 @@ public:
const Element *E = nullptr;
};
struct Iterator {
_FORCE_INLINE_ T &operator*() const {
return E->get();
}
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
_FORCE_INLINE_ Iterator &operator++() {
E = E->next();
return *this;
}
_FORCE_INLINE_ Iterator &operator--() {
E = E->prev();
return *this;
}
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
Iterator(Element *p_E) { E = p_E; }
Iterator() {}
Iterator(const Iterator &p_it) { E = p_it.E; }
operator ConstIterator() const {
return ConstIterator(E);
}
private:
Element *E = nullptr;
};
_FORCE_INLINE_ Iterator begin() {
return Iterator(front());
}
@ -410,7 +414,7 @@ public:
/**
* find an element in the list,
*/
template <class T_v>
template <typename T_v>
Element *find(const T_v &p_val) {
Element *it = front();
while (it) {
@ -519,7 +523,14 @@ public:
}
}
T &operator[](int p_index) {
// Index operator, kept for compatibility.
_FORCE_INLINE_ T &operator[](int p_index) {
return get(p_index);
}
// Random access to elements, use with care,
// do not use for iteration.
T &get(int p_index) {
CRASH_BAD_INDEX(p_index, size());
Element *I = front();
@ -532,7 +543,14 @@ public:
return I->get();
}
const T &operator[](int p_index) const {
// Index operator, kept for compatibility.
_FORCE_INLINE_ const T &operator[](int p_index) const {
return get(p_index);
}
// Random access to elements, use with care,
// do not use for iteration.
const T &get(int p_index) const {
CRASH_BAD_INDEX(p_index, size());
const Element *I = front();
@ -646,7 +664,7 @@ public:
sort_custom<Comparator<T>>();
}
template <class C>
template <typename C>
void sort_custom_inplace() {
if (size() < 2) {
return;
@ -693,7 +711,7 @@ public:
_data->last = to;
}
template <class C>
template <typename C>
struct AuxiliaryComparator {
C compare;
_FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const {
@ -701,7 +719,7 @@ public:
}
};
template <class C>
template <typename C>
void sort_custom() {
// this version uses auxiliary memory for speed.
// if you don't want to use auxiliary memory, use the in_place version

View File

@ -43,7 +43,7 @@ namespace godot {
// If tight, it grows strictly as much as needed.
// Otherwise, it grows exponentially (the default and what you want in most cases).
template <class T, class U = uint32_t, bool force_trivial = false, bool tight = false>
template <typename T, typename U = uint32_t, bool force_trivial = false, bool tight = false>
class LocalVector {
private:
U count = 0;
@ -257,7 +257,11 @@ public:
return -1;
}
template <class C>
bool has(const T &p_val) const {
return find(p_val) != -1;
}
template <typename C>
void sort_custom() {
U len = count;
if (len == 0) {
@ -331,7 +335,7 @@ public:
}
};
template <class T, class U = uint32_t, bool force_trivial = false>
template <typename T, typename U = uint32_t, bool force_trivial = false>
using TightLocalVector = LocalVector<T, U, force_trivial, true>;
} // namespace godot

View File

@ -33,7 +33,7 @@
namespace godot {
template <class F, class S>
template <typename F, typename S>
struct Pair {
F first;
S second;
@ -49,17 +49,17 @@ struct Pair {
}
};
template <class F, class S>
template <typename F, typename S>
bool operator==(const Pair<F, S> &pair, const Pair<F, S> &other) {
return (pair.first == other.first) && (pair.second == other.second);
}
template <class F, class S>
template <typename F, typename S>
bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
return (pair.first != other.first) || (pair.second != other.second);
}
template <class F, class S>
template <typename F, typename S>
struct PairSort {
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
if (A.first != B.first) {
@ -69,7 +69,7 @@ struct PairSort {
}
};
template <class K, class V>
template <typename K, typename V>
struct KeyValue {
const K key;
V value;
@ -85,17 +85,17 @@ struct KeyValue {
}
};
template <class K, class V>
template <typename K, typename V>
bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
return (pair.key == other.key) && (pair.value == other.value);
}
template <class K, class V>
template <typename K, typename V>
bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
return (pair.key != other.key) || (pair.value != other.value);
}
template <class K, class V>
template <typename K, typename V>
struct KeyValueSort {
bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const {
return A.key < B.key;

View File

@ -40,7 +40,7 @@ namespace godot {
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator>
template <typename K, typename V, typename C = Comparator<K>, typename A = DefaultAllocator>
class RBMap {
enum Color {
RED,

View File

@ -38,7 +38,7 @@
namespace godot {
template <class T, class C = Comparator<T>, class A = DefaultAllocator>
template <typename T, typename C = Comparator<T>, typename A = DefaultAllocator>
class RBSet {
enum Color {
RED,

View File

@ -42,7 +42,7 @@
namespace godot {
template <class T, bool THREAD_SAFE = false>
template <typename T, bool THREAD_SAFE = false>
class RID_Alloc {
T **chunks = nullptr;
uint32_t **free_list_chunks = nullptr;
@ -347,7 +347,7 @@ public:
}
};
template <class T, bool THREAD_SAFE = false>
template <typename T, bool THREAD_SAFE = false>
class RID_PtrOwner {
RID_Alloc<T *, THREAD_SAFE> alloc;
@ -406,7 +406,7 @@ public:
alloc(p_target_chunk_byte_size) {}
};
template <class T, bool THREAD_SAFE = false>
template <typename T, bool THREAD_SAFE = false>
class RID_Owner {
RID_Alloc<T, THREAD_SAFE> alloc;

View File

@ -57,7 +57,7 @@ namespace godot {
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
static_assert(alignof(SafeFlag) == alignof(bool));
template <class T>
template <typename T>
class SafeNumeric {
std::atomic<T> value;
@ -195,7 +195,7 @@ public:
#else
template <class T>
template <typename T>
class SafeNumeric {
protected:
T value;

View File

@ -35,7 +35,7 @@
namespace godot {
template <class T, class Comparator = _DefaultComparator<T>>
template <typename T, typename Comparator = _DefaultComparator<T>>
class SearchArray {
public:
Comparator compare;

View File

@ -36,7 +36,7 @@
namespace godot {
template <class T>
template <typename T>
class SelfList {
public:
class List {

View File

@ -41,7 +41,7 @@ namespace godot {
break; \
}
template <class T>
template <typename T>
struct _DefaultComparator {
_FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); }
};
@ -52,7 +52,7 @@ struct _DefaultComparator {
#define SORT_ARRAY_VALIDATE_ENABLED false
#endif
template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
template <typename T, typename Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
class SortArray {
enum {
INTROSORT_THRESHOLD = 16

View File

@ -52,7 +52,7 @@ class ThreadWorkPool {
virtual ~BaseWork() = default;
};
template <class C, class M, class U>
template <typename C, typename M, typename U>
struct Work : public BaseWork {
C *instance;
M method;
@ -94,7 +94,7 @@ class ThreadWorkPool {
}
public:
template <class C, class M, class U>
template <typename C, typename M, typename U>
void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
ERR_FAIL_NULL(threads); // Never initialized.
ERR_FAIL_COND(current_work != nullptr);
@ -145,7 +145,7 @@ public:
current_work = nullptr;
}
template <class C, class M, class U>
template <typename C, typename M, typename U>
void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
switch (p_elements) {
case 0:

View File

@ -47,7 +47,7 @@
namespace godot {
template <class T>
template <typename T>
class VectorWriteProxy {
public:
_FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) {
@ -57,7 +57,7 @@ public:
}
};
template <class T>
template <typename T>
class Vector {
friend class VectorWriteProxy<T>;
@ -110,7 +110,7 @@ public:
sort_custom<_DefaultComparator<T>>();
}
template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args>
template <typename Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, typename... Args>
void sort_custom(Args &&...args) {
Size len = _cowdata.size();
if (len == 0) {
@ -126,7 +126,7 @@ public:
return bsearch_custom<_DefaultComparator<T>>(p_value, p_before);
}
template <class Comparator, class Value, class... Args>
template <typename Comparator, typename Value, typename... Args>
Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
SearchArray<T, Comparator> search{ args... };
return search.bisect(ptrw(), size(), p_value, p_before);
@ -293,7 +293,7 @@ public:
_FORCE_INLINE_ ~Vector() {}
};
template <class T>
template <typename T>
void Vector<T>::reverse() {
for (Size i = 0; i < size() / 2; i++) {
T *p = ptrw();
@ -301,7 +301,7 @@ void Vector<T>::reverse() {
}
}
template <class T>
template <typename T>
void Vector<T>::append_array(Vector<T> p_other) {
const Size ds = p_other.size();
if (ds == 0) {
@ -314,7 +314,7 @@ void Vector<T>::append_array(Vector<T> p_other) {
}
}
template <class T>
template <typename T>
bool Vector<T>::push_back(T p_elem) {
Error err = resize(size() + 1);
ERR_FAIL_COND_V(err, true);
@ -323,7 +323,7 @@ bool Vector<T>::push_back(T p_elem) {
return false;
}
template <class T>
template <typename T>
void Vector<T>::fill(T p_elem) {
T *p = ptrw();
for (Size i = 0; i < size(); i++) {

View File

@ -35,7 +35,7 @@
namespace godot {
template <class T, class V>
template <typename T, typename V>
class VMap {
public:
struct Pair {

View File

@ -35,7 +35,7 @@
namespace godot {
template <class T>
template <typename T>
class VSet {
Vector<T> _data;

View File

@ -65,6 +65,7 @@ struct _NO_DISCARD_ AABB {
bool operator!=(const AABB &p_rval) const;
bool is_equal_approx(const AABB &p_aabb) const;
bool is_finite() const;
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
@ -102,7 +103,7 @@ struct _NO_DISCARD_ AABB {
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
_FORCE_INLINE_ AABB abs() const {
return AABB(Vector3(position.x + MIN(size.x, (real_t)0), position.y + MIN(size.y, (real_t)0), position.z + MIN(size.z, (real_t)0)), size.abs());
return AABB(position + size.minf(0), size.abs());
}
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;

View File

@ -128,6 +128,7 @@ struct _NO_DISCARD_ Basis {
}
bool is_equal_approx(const Basis &p_basis) const;
bool is_finite() const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;

View File

@ -60,7 +60,7 @@ Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_m
// No return value.
//
template <class T, class... P>
template <typename T, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@ -90,7 +90,7 @@ public:
}
};
template <class T, class... P>
template <typename T, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
typedef CallableCustomMethodPointer<T, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
@ -101,7 +101,7 @@ Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_meth
// With return value.
//
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@ -132,7 +132,7 @@ public:
}
};
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
@ -143,7 +143,7 @@ Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)
// Const with return value.
//
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@ -174,7 +174,7 @@ public:
}
};
template <class T, class R, class... P>
template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
@ -185,7 +185,7 @@ Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_m
// Static method with no return value.
//
template <class... P>
template <typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
void (*method)(P...);
@ -214,7 +214,7 @@ public:
}
};
template <class... P>
template <typename... P>
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointer<P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method));
@ -225,7 +225,7 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...))
// Static method with return value.
//
template <class R, class... P>
template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R(*method)
@ -254,7 +254,7 @@ public:
}
};
template <class R, class... P>
template <typename R, typename... P>
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method));

View File

@ -38,12 +38,12 @@
namespace godot {
template <class T>
template <typename T>
class CharStringT;
template <class T>
template <typename T>
class CharProxy {
template <class TS>
template <typename TS>
friend class CharStringT;
const int64_t _index;
@ -80,7 +80,7 @@ public:
}
};
template <class T>
template <typename T>
class CharStringT {
friend class String;

View File

@ -77,6 +77,7 @@ struct _NO_DISCARD_ Plane {
Plane operator-() const { return Plane(-normal, -d); }
bool is_equal_approx(const Plane &p_plane) const;
bool is_equal_approx_any_side(const Plane &p_plane) const;
bool is_finite() const;
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;

View File

@ -55,6 +55,7 @@ struct _NO_DISCARD_ Quaternion {
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Quaternion &p_quaternion) const;
bool is_finite() const;
real_t length() const;
void normalize();
Quaternion normalized() const;

View File

@ -154,14 +154,12 @@ struct _NO_DISCARD_ Rect2 {
return Rect2();
}
new_rect.position.x = Math::max(p_rect.position.x, position.x);
new_rect.position.y = Math::max(p_rect.position.y, position.y);
new_rect.position = p_rect.position.max(position);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
new_rect.size = p_rect_end.min(end) - new_rect.position;
return new_rect;
}
@ -174,11 +172,9 @@ struct _NO_DISCARD_ Rect2 {
#endif
Rect2 new_rect;
new_rect.position.x = Math::min(p_rect.position.x, position.x);
new_rect.position.y = Math::min(p_rect.position.y, position.y);
new_rect.position = p_rect.position.min(position);
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
@ -209,6 +205,7 @@ struct _NO_DISCARD_ Rect2 {
}
bool is_equal_approx(const Rect2 &p_rect) const;
bool is_finite() const;
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
@ -283,7 +280,7 @@ struct _NO_DISCARD_ Rect2 {
}
_FORCE_INLINE_ Rect2 abs() const {
return Rect2(Point2(position.x + Math::min(size.x, (real_t)0), position.y + Math::min(size.y, (real_t)0)), size.abs());
return Rect2(position + size.minf(0), size.abs());
}
Vector2 get_support(const Vector2 &p_normal) const {

View File

@ -97,14 +97,12 @@ struct _NO_DISCARD_ Rect2i {
return Rect2i();
}
new_rect.position.x = Math::max(p_rect.position.x, position.x);
new_rect.position.y = Math::max(p_rect.position.y, position.y);
new_rect.position = p_rect.position.max(position);
Point2i p_rect_end = p_rect.position + p_rect.size;
Point2i end = position + size;
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
new_rect.size = p_rect_end.min(end) - new_rect.position;
return new_rect;
}
@ -117,11 +115,9 @@ struct _NO_DISCARD_ Rect2i {
#endif
Rect2i new_rect;
new_rect.position.x = Math::min(p_rect.position.x, position.x);
new_rect.position.y = Math::min(p_rect.position.y, position.y);
new_rect.position = p_rect.position.min(position);
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
@ -219,7 +215,7 @@ struct _NO_DISCARD_ Rect2i {
}
_FORCE_INLINE_ Rect2i abs() const {
return Rect2i(Point2i(position.x + Math::min(size.x, 0), position.y + Math::min(size.y, 0)), size.abs());
return Rect2i(position + size.mini(0), size.abs());
}
_FORCE_INLINE_ void set_end(const Vector2i &p_end) {

View File

@ -99,6 +99,7 @@ struct _NO_DISCARD_ Transform2D {
void orthonormalize();
Transform2D orthonormalized() const;
bool is_equal_approx(const Transform2D &p_transform) const;
bool is_finite() const;
Transform2D looking_at(const Vector2 &p_target) const;

View File

@ -78,6 +78,7 @@ struct _NO_DISCARD_ Transform3D {
void orthogonalize();
Transform3D orthogonalized() const;
bool is_equal_approx(const Transform3D &p_transform) const;
bool is_finite() const;
bool operator==(const Transform3D &p_transform) const;
bool operator!=(const Transform3D &p_transform) const;

View File

@ -36,7 +36,7 @@
namespace godot {
template <class T>
template <typename T>
class TypedArray : public Array {
public:
_FORCE_INLINE_ void operator=(const Array &p_array) {

View File

@ -269,7 +269,7 @@ public:
void callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
template <class... Args>
template <typename... Args>
Variant call(const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs;
@ -284,7 +284,7 @@ public:
static void callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
template <class... Args>
template <typename... Args>
static Variant call_static(Variant::Type type, const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs;

View File

@ -91,10 +91,18 @@ struct _NO_DISCARD_ Vector2 {
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
}
Vector2 minf(real_t p_scalar) const {
return Vector2(MIN(x, p_scalar), MIN(y, p_scalar));
}
Vector2 max(const Vector2 &p_vector2) const {
return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y));
}
Vector2 maxf(real_t p_scalar) const {
return Vector2(MAX(x, p_scalar), MAX(y, p_scalar));
}
real_t distance_to(const Vector2 &p_vector2) const;
real_t distance_squared_to(const Vector2 &p_vector2) const;
real_t angle_to(const Vector2 &p_vector2) const;
@ -123,6 +131,7 @@ struct _NO_DISCARD_ Vector2 {
bool is_equal_approx(const Vector2 &p_v) const;
bool is_zero_approx() const;
bool is_finite() const;
Vector2 operator+(const Vector2 &p_v) const;
void operator+=(const Vector2 &p_v);
@ -168,7 +177,9 @@ struct _NO_DISCARD_ Vector2 {
Vector2 ceil() const;
Vector2 round() const;
Vector2 snapped(const Vector2 &p_by) const;
Vector2 snappedf(real_t p_by) const;
Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const;
Vector2 clampf(real_t p_min, real_t p_max) const;
real_t aspect() const { return width / height; }
operator String() const;

View File

@ -83,10 +83,18 @@ struct _NO_DISCARD_ Vector2i {
return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
}
Vector2i mini(int32_t p_scalar) const {
return Vector2i(MIN(x, p_scalar), MIN(y, p_scalar));
}
Vector2i max(const Vector2i &p_vector2i) const {
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y));
}
Vector2i maxi(int32_t p_scalar) const {
return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar));
}
Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const;
@ -123,7 +131,10 @@ struct _NO_DISCARD_ Vector2i {
real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
Vector2i snapped(const Vector2i &p_step) const;
Vector2i snappedi(int32_t p_step) const;
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
Vector2i clampi(int32_t p_min, int32_t p_max) const;
operator String() const;
operator Vector2() const;

View File

@ -82,10 +82,18 @@ struct _NO_DISCARD_ Vector3 {
return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z));
}
Vector3 minf(real_t p_scalar) const {
return Vector3(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
}
Vector3 max(const Vector3 &p_vector3) const {
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z));
}
Vector3 maxf(real_t p_scalar) const {
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
}
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;
@ -98,7 +106,9 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ void zero();
void snap(const Vector3 p_val);
void snapf(real_t p_val);
Vector3 snapped(const Vector3 p_val) const;
Vector3 snappedf(real_t p_val) const;
void rotate(const Vector3 &p_axis, const real_t p_angle);
Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const;
@ -128,6 +138,7 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ Vector3 round() const;
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
Vector3 clampf(real_t p_min, real_t p_max) const;
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
@ -146,6 +157,7 @@ struct _NO_DISCARD_ Vector3 {
bool is_equal_approx(const Vector3 &p_v) const;
bool is_zero_approx() const;
bool is_finite() const;
/* Operators */

View File

@ -75,10 +75,18 @@ struct _NO_DISCARD_ Vector3i {
return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z));
}
Vector3i mini(int32_t p_scalar) const {
return Vector3i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
}
Vector3i max(const Vector3i &p_vector3i) const {
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z));
}
Vector3i maxi(int32_t p_scalar) const {
return Vector3i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
@ -89,7 +97,10 @@ struct _NO_DISCARD_ Vector3i {
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
Vector3i snapped(const Vector3i &p_step) const;
Vector3i snappedi(int32_t p_step) const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */

View File

@ -74,13 +74,22 @@ struct _NO_DISCARD_ Vector4 {
return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w));
}
Vector4 minf(real_t p_scalar) const {
return Vector4(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
}
Vector4 max(const Vector4 &p_vector4) const {
return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w));
}
Vector4 maxf(real_t p_scalar) const {
return Vector4(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const;
bool is_zero_approx() const;
bool is_finite() const;
real_t length() const;
void normalize();
Vector4 normalized() const;
@ -102,8 +111,11 @@ struct _NO_DISCARD_ Vector4 {
Vector4 posmod(const real_t p_mod) const;
Vector4 posmodv(const Vector4 &p_modv) const;
void snap(const Vector4 &p_step);
void snapf(real_t p_step);
Vector4 snapped(const Vector4 &p_step) const;
Vector4 snappedf(real_t p_step) const;
Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
Vector4 clampf(real_t p_min, real_t p_max) const;
Vector4 inverse() const;
_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;

View File

@ -77,10 +77,18 @@ struct _NO_DISCARD_ Vector4i {
return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w));
}
Vector4i mini(int32_t p_scalar) const {
return Vector4i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
}
Vector4i max(const Vector4i &p_vector4i) const {
return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w));
}
Vector4i maxi(int32_t p_scalar) const {
return Vector4i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
@ -91,7 +99,10 @@ struct _NO_DISCARD_ Vector4i {
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i snapped(const Vector4i &p_step) const;
Vector4i snappedi(int32_t p_step) const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */

View File

@ -29,6 +29,7 @@
/**************************************************************************/
#include <godot_cpp/classes/file_access.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/worker_thread_pool.hpp>
#include <godot_cpp/classes/xml_parser.hpp>
@ -55,4 +56,12 @@ WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)
return (GroupID)internal::gdextension_interface_worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description);
}
uint8_t *Image::ptrw() {
return internal::gdextension_interface_image_ptrw(_owner);
}
const uint8_t *Image::ptr() {
return internal::gdextension_interface_image_ptr(_owner);
}
} // namespace godot

View File

@ -39,22 +39,17 @@
#include <godot_cpp/core/class_db.hpp>
namespace godot {
thread_local const StringName *Wrapped::_constructing_extension_class_name = nullptr;
thread_local const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
const StringName *Wrapped::_get_extension_class_name() const {
const StringName *Wrapped::_get_extension_class_name() {
return nullptr;
}
void Wrapped::_postinitialize() {
const StringName *extension_class = _get_extension_class_name();
if (extension_class) {
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
}
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
if (extension_class) {
Object *obj = dynamic_cast<Object *>(this);
if (obj) {
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
}
// Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (_is_extension_class()) {
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
}
}
@ -79,6 +74,19 @@ Wrapped::Wrapped(const StringName p_godot_class) {
}
#endif
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
if (_constructing_extension_class_name) {
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this);
_constructing_extension_class_name = nullptr;
}
if (likely(_constructing_class_binding_callbacks)) {
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _constructing_class_binding_callbacks);
_constructing_class_binding_callbacks = nullptr;
} else {
ERR_PRINT("BUG: create a Godot Object without binding callbacks.");
CRASH_NOW_MSG("BUG: create a Godot Object without binding callbacks.");
}
}
Wrapped::Wrapped(GodotObject *p_godot_object) {

View File

@ -43,6 +43,8 @@ namespace godot {
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
std::vector<StringName> ClassDB::class_register_order;
std::unordered_map<StringName, Object *> ClassDB::engine_singletons;
std::mutex ClassDB::engine_singletons_mutex;
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
MethodDefinition D_METHOD(StringName p_name) {
@ -351,7 +353,7 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
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++) {
for (uint32_t 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];
}
@ -419,6 +421,22 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
});
class_register_order.erase(it, class_register_order.end());
}
if (p_level == GDEXTENSION_INITIALIZATION_CORE) {
// Make a new list of the singleton objects, since freeing the instance bindings will lead to
// elements getting removed from engine_singletons.
std::vector<Object *> singleton_objects;
{
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
singleton_objects.reserve(engine_singletons.size());
for (const std::pair<const StringName, Object *> &pair : engine_singletons) {
singleton_objects.push_back(pair.second);
}
}
for (std::vector<Object *>::iterator i = singleton_objects.begin(); i != singleton_objects.end(); i++) {
internal::gdextension_interface_object_free_instance_binding((*i)->_owner, internal::token);
}
}
}
} // namespace godot

View File

@ -60,8 +60,66 @@ Object *get_object_instance_binding(GodotObject *p_engine_object) {
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
}
TypedArray<Dictionary> convert_property_list(const std::vector<PropertyInfo> &p_list) {
TypedArray<Dictionary> va;
for (const PropertyInfo &pi : p_list) {
va.push_back(Dictionary(pi));
}
return va;
}
} // namespace internal
MethodInfo::operator Dictionary() const {
Dictionary dict;
dict["name"] = name;
dict["args"] = internal::convert_property_list(arguments);
Array da;
for (size_t i = 0; i < default_arguments.size(); i++) {
da.push_back(default_arguments[i]);
}
dict["default_args"] = da;
dict["flags"] = flags;
dict["id"] = id;
Dictionary r = return_val;
dict["return"] = r;
return dict;
}
MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
MethodInfo mi;
if (p_dict.has("name")) {
mi.name = p_dict["name"];
}
Array args;
if (p_dict.has("args")) {
args = p_dict["args"];
}
for (int i = 0; i < args.size(); i++) {
Dictionary d = args[i];
mi.arguments.push_back(PropertyInfo::from_dict(d));
}
Array defargs;
if (p_dict.has("default_args")) {
defargs = p_dict["default_args"];
}
for (int i = 0; i < defargs.size(); i++) {
mi.default_arguments.push_back(defargs[i]);
}
if (p_dict.has("return")) {
mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
}
if (p_dict.has("flags")) {
mi.flags = p_dict["flags"];
}
return mi;
}
MethodInfo::MethodInfo() :
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}

View File

@ -114,7 +114,9 @@ GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_string_new_wit
GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars = nullptr;
GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2 = nullptr;
GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2 = nullptr;
GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len = nullptr;
GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars = nullptr;
@ -154,6 +156,8 @@ GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_interface_packed
GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index = nullptr;
GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr;
GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
@ -166,6 +170,7 @@ GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding = nullptr;
GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding = nullptr;
GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
@ -196,6 +201,40 @@ GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classd
GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr;
GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr;
GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin = nullptr;
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars = nullptr;
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len = nullptr;
GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw = nullptr;
GDExtensionInterfaceImagePtr gdextension_interface_image_ptr = nullptr;
struct DocData {
const char *hash = nullptr;
int uncompressed_size = 0;
int compressed_size = 0;
const unsigned char *data = nullptr;
inline bool is_valid() const {
return hash != nullptr && uncompressed_size > 0 && compressed_size > 0 && data != nullptr;
}
void load_data() const;
};
static DocData &get_doc_data() {
static DocData doc_data;
return doc_data;
}
DocDataRegistration::DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data) {
DocData &doc_data = get_doc_data();
if (doc_data.is_valid()) {
printf("ERROR: Attempting to register documentation data when we already have some - discarding.\n");
return;
}
doc_data.hash = p_hash;
doc_data.uncompressed_size = p_uncompressed_size;
doc_data.compressed_size = p_compressed_size;
doc_data.data = p_data;
}
} // namespace internal
@ -354,7 +393,9 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(string_new_with_wide_chars, GDExtensionInterfaceStringNewWithWideChars);
LOAD_PROC_ADDRESS(string_new_with_latin1_chars_and_len, GDExtensionInterfaceStringNewWithLatin1CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len, GDExtensionInterfaceStringNewWithUtf8CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len2, GDExtensionInterfaceStringNewWithUtf8CharsAndLen2);
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len, GDExtensionInterfaceStringNewWithUtf16CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len2, GDExtensionInterfaceStringNewWithUtf16CharsAndLen2);
LOAD_PROC_ADDRESS(string_new_with_utf32_chars_and_len, GDExtensionInterfaceStringNewWithUtf32CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_wide_chars_and_len, GDExtensionInterfaceStringNewWithWideCharsAndLen);
LOAD_PROC_ADDRESS(string_to_latin1_chars, GDExtensionInterfaceStringToLatin1Chars);
@ -394,6 +435,8 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(packed_vector2_array_operator_index_const, GDExtensionInterfacePackedVector2ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index, GDExtensionInterfacePackedVector3ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index_const, GDExtensionInterfacePackedVector3ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index, GDExtensionInterfacePackedVector4ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index_const, GDExtensionInterfacePackedVector4ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_operator_index, GDExtensionInterfaceArrayOperatorIndex);
LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef);
@ -406,6 +449,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding);
LOAD_PROC_ADDRESS(object_free_instance_binding, GDExtensionInterfaceObjectFreeInstanceBinding);
LOAD_PROC_ADDRESS(object_set_instance, GDExtensionInterfaceObjectSetInstance);
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
@ -436,6 +480,10 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(get_library_path, GDExtensionInterfaceGetLibraryPath);
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin);
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars);
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars_and_len, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen);
LOAD_PROC_ADDRESS(image_ptrw, GDExtensionInterfaceImagePtrw);
LOAD_PROC_ADDRESS(image_ptr, GDExtensionInterfaceImagePtr);
r_initialization->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level;
@ -465,6 +513,13 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ
ClassDB::initialize(p_level);
}
level_initialized[p_level]++;
if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
const internal::DocData &doc_data = internal::get_doc_data();
if (doc_data.is_valid()) {
doc_data.load_data();
}
}
}
void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
@ -531,4 +586,15 @@ GDExtensionBool GDExtensionBinding::InitObject::init() const {
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
}
void internal::DocData::load_data() const {
PackedByteArray compressed;
compressed.resize(compressed_size);
memcpy(compressed.ptrw(), data, compressed_size);
// FileAccess::COMPRESSION_DEFLATE = 1
PackedByteArray decompressed = compressed.decompress(uncompressed_size, 1);
internal::gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len(reinterpret_cast<const char *>(decompressed.ptr()), uncompressed_size);
}
} // namespace godot

View File

@ -78,6 +78,10 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
}
bool AABB::is_finite() const {
return position.is_finite() && size.is_finite();
}
AABB AABB::intersection(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {

View File

@ -692,6 +692,10 @@ bool Basis::is_equal_approx(const Basis &p_basis) const {
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
}
bool Basis::is_finite() const {
return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
}
bool Basis::operator==(const Basis &p_matrix) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {

View File

@ -65,7 +65,7 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
}
}
template <class T>
template <typename T>
bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
if (length() == 0) {
return p_right.length() != 0;
@ -74,7 +74,7 @@ bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
return is_str_less(get_data(), p_right.get_data());
}
template <class T>
template <typename T>
CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
const int64_t lhs_len = length();
resize(lhs_len + 2);
@ -86,7 +86,7 @@ CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
return *this;
}
template <class T>
template <typename T>
void CharStringT<T>::operator=(const T *p_cstr) {
copy_from(p_cstr);
}
@ -127,7 +127,7 @@ const wchar_t *CharStringT<wchar_t>::get_data() const {
}
}
template <class T>
template <typename T>
void CharStringT<T>::copy_from(const T *p_cstr) {
if (!p_cstr) {
resize(0);
@ -178,8 +178,8 @@ String String::utf8(const char *from, int64_t len) {
return ret;
}
void String::parse_utf8(const char *from, int64_t len) {
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
Error String::parse_utf8(const char *from, int64_t len) {
return (Error)internal::gdextension_interface_string_new_with_utf8_chars_and_len2(_native_ptr(), from, len);
}
String String::utf16(const char16_t *from, int64_t len) {
@ -188,8 +188,8 @@ String String::utf16(const char16_t *from, int64_t len) {
return ret;
}
void String::parse_utf16(const char16_t *from, int64_t len) {
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
Error String::parse_utf16(const char16_t *from, int64_t len, bool default_little_endian) {
return (Error)internal::gdextension_interface_string_new_with_utf16_chars_and_len2(_native_ptr(), from, len, default_little_endian);
}
String String::num_real(double p_num, bool p_trailing) {

View File

@ -43,6 +43,7 @@
#include <godot_cpp/variant/packed_string_array.hpp>
#include <godot_cpp/variant/packed_vector2_array.hpp>
#include <godot_cpp/variant/packed_vector3_array.hpp>
#include <godot_cpp/variant/packed_vector4_array.hpp>
namespace godot {
@ -198,6 +199,24 @@ Vector3 *PackedVector3Array::ptrw() {
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Vector4 &PackedVector4Array::operator[](int64_t p_index) const {
const Vector4 *vec = (const Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec;
}
Vector4 &PackedVector4Array::operator[](int64_t p_index) {
Vector4 *vec = (Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec;
}
const Vector4 *PackedVector4Array::ptr() const {
return (const Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Vector4 *PackedVector4Array::ptrw() {
return (Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Variant &Array::operator[](int64_t p_index) const {
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *var;

View File

@ -178,6 +178,10 @@ bool Plane::is_equal_approx(const Plane &p_plane) const {
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
}
bool Plane::is_finite() const {
return normal.is_finite() && Math::is_finite(d);
}
Plane::operator String() const {
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
}

View File

@ -136,7 +136,7 @@ Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intra
Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
Projection proj;
proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar);
proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_znear, p_zfar);
return proj;
}

View File

@ -81,6 +81,10 @@ bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
}
bool Quaternion::is_finite() const {
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w);
}
real_t Quaternion::length() const {
return Math::sqrt(length_squared());
}

View File

@ -40,6 +40,10 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
}
bool Rect2::is_finite() const {
return position.is_finite() && size.is_finite();
}
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {

View File

@ -170,6 +170,10 @@ bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
}
bool Transform2D::is_finite() const {
return columns[0].is_finite() && columns[1].is_finite() && columns[2].is_finite();
}
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
Vector2 target_position = affine_inverse().xform(p_target);

View File

@ -175,6 +175,10 @@ bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
}
bool Transform3D::is_finite() const {
return basis.is_finite() && origin.is_finite();
}
bool Transform3D::operator==(const Transform3D &p_transform) const {
return (basis == p_transform.basis && origin == p_transform.origin);
}

View File

@ -137,12 +137,24 @@ Vector2 Vector2::clamp(const Vector2 &p_min, const Vector2 &p_max) const {
CLAMP(y, p_min.y, p_max.y));
}
Vector2 Vector2::clampf(real_t p_min, real_t p_max) const {
return Vector2(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max));
}
Vector2 Vector2::snapped(const Vector2 &p_step) const {
return Vector2(
Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y));
}
Vector2 Vector2::snappedf(real_t p_step) const {
return Vector2(
Math::snapped(x, p_step),
Math::snapped(y, p_step));
}
Vector2 Vector2::limit_length(const real_t p_len) const {
const real_t l = length();
Vector2 v = *this;
@ -188,6 +200,10 @@ bool Vector2::is_zero_approx() const {
return Math::is_zero_approx(x) && Math::is_zero_approx(y);
}
bool Vector2::is_finite() const {
return Math::is_finite(x) && Math::is_finite(y);
}
Vector2::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
}

View File

@ -35,12 +35,30 @@
namespace godot {
Vector2i Vector2i::snapped(const Vector2i &p_step) const {
return Vector2i(
Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y));
}
Vector2i Vector2i::snappedi(int32_t p_step) const {
return Vector2i(
Math::snapped(x, p_step),
Math::snapped(y, p_step));
}
Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
return Vector2i(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y));
}
Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const {
return Vector2i(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max));
}
int64_t Vector2i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y;
}

View File

@ -54,18 +54,37 @@ Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
CLAMP(z, p_min.z, p_max.z));
}
Vector3 Vector3::clampf(real_t p_min, real_t p_max) const {
return Vector3(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max));
}
void Vector3::snap(const Vector3 p_step) {
x = Math::snapped(x, p_step.x);
y = Math::snapped(y, p_step.y);
z = Math::snapped(z, p_step.z);
}
void Vector3::snapf(real_t p_step) {
x = Math::snapped(x, p_step);
y = Math::snapped(y, p_step);
z = Math::snapped(z, p_step);
}
Vector3 Vector3::snapped(const Vector3 p_step) const {
Vector3 v = *this;
v.snap(p_step);
return v;
}
Vector3 Vector3::snappedf(real_t p_step) const {
Vector3 v = *this;
v.snapf(p_step);
return v;
}
Vector3 Vector3::limit_length(const real_t p_len) const {
const real_t l = length();
Vector3 v = *this;
@ -141,6 +160,10 @@ bool Vector3::is_zero_approx() const {
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z);
}
bool Vector3::is_finite() const {
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z);
}
Vector3::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
}

View File

@ -35,6 +35,20 @@
namespace godot {
Vector3i Vector3i::snapped(const Vector3i &p_step) const {
return Vector3i(
Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y),
Math::snapped(z, p_step.z));
}
Vector3i Vector3i::snappedi(int32_t p_step) const {
return Vector3i(
Math::snapped(x, p_step),
Math::snapped(y, p_step),
Math::snapped(z, p_step));
}
Vector3i::Axis Vector3i::min_axis_index() const {
return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z);
}
@ -50,6 +64,13 @@ Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const {
CLAMP(z, p_min.z, p_max.z));
}
Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const {
return Vector3i(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max));
}
Vector3i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")";
}

View File

@ -67,6 +67,10 @@ bool Vector4::is_zero_approx() const {
return Math::is_zero_approx(x) && Math::is_zero_approx(y) && Math::is_zero_approx(z) && Math::is_zero_approx(w);
}
bool Vector4::is_finite() const {
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w);
}
real_t Vector4::length() const {
return Math::sqrt(length_squared());
}
@ -169,12 +173,25 @@ void Vector4::snap(const Vector4 &p_step) {
w = Math::snapped(w, p_step.w);
}
void Vector4::snapf(real_t p_step) {
x = Math::snapped(x, p_step);
y = Math::snapped(y, p_step);
z = Math::snapped(z, p_step);
w = Math::snapped(w, p_step);
}
Vector4 Vector4::snapped(const Vector4 &p_step) const {
Vector4 v = *this;
v.snap(p_step);
return v;
}
Vector4 Vector4::snappedf(real_t p_step) const {
Vector4 v = *this;
v.snapf(p_step);
return v;
}
Vector4 Vector4::inverse() const {
return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w);
}
@ -187,6 +204,14 @@ Vector4 Vector4::clamp(const Vector4 &p_min, const Vector4 &p_max) const {
CLAMP(w, p_min.w, p_max.w));
}
Vector4 Vector4::clampf(real_t p_min, real_t p_max) const {
return Vector4(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max),
CLAMP(w, p_min, p_max));
}
Vector4::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
}

View File

@ -35,6 +35,22 @@
namespace godot {
Vector4i Vector4i::snapped(const Vector4i &p_step) const {
return Vector4i(
Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y),
Math::snapped(z, p_step.z),
Math::snapped(w, p_step.w));
}
Vector4i Vector4i::snappedi(int32_t p_step) const {
return Vector4i(
Math::snapped(x, p_step),
Math::snapped(y, p_step),
Math::snapped(z, p_step),
Math::snapped(w, p_step));
}
Vector4i::Axis Vector4i::min_axis_index() const {
uint32_t min_index = 0;
int32_t min_value = x;
@ -67,6 +83,14 @@ Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const {
CLAMP(w, p_min.w, p_max.w));
}
Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const {
return Vector4i(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max),
CLAMP(w, p_min, p_max));
}
Vector4i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")";
}

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(godot-cpp-test)
cmake_minimum_required(VERSION 3.6)
set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory")
set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings")

View File

@ -16,6 +16,10 @@ env = SConscript("../SConstruct")
env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp")
if env["target"] in ["editor", "template_debug"]:
doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
sources.append(doc_data)
if env["platform"] == "macos":
library = env.SharedLibrary(
"project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Example" inherits="Control" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/godotengine/godot/master/doc/class.xsd">
<brief_description>
A test control defined in GDExtension.
</brief_description>
<description>
A control used for the automated GDExtension tests.
</description>
<tutorials>
</tutorials>
<methods>
<method name="simple_func">
<return type="void" />
<description>
Tests a simple function call.
</description>
</method>
</methods>
<members>
</members>
<signals>
</signals>
<constants>
</constants>
</class>

View File

@ -29,8 +29,10 @@ android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so"
android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm"
web.debug.threads.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
web.release.threads.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm"
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.nothreads.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.nothreads.wasm"
[dependencies]
ios.debug = {

View File

@ -9,12 +9,15 @@ class TestClass:
func _ready():
var example: Example = $Example
# Timing of set instance binding.
assert_equal(example.is_object_binding_set_by_parent_constructor(), true)
# Signal.
example.emit_custom_signal("Button", 42)
assert_equal(custom_signal_emitted, ["Button", 42])
# To string.
assert_equal(example.to_string(),'Example:[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id())
assert_equal(example.to_string(),'[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id())
# It appears there's a bug with instance ids :-(
#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())
@ -191,6 +194,10 @@ func _ready():
control.queue_free()
sprite.queue_free()
# Test that passing null for objects works as expected too.
var example_null : Example = null
assert_equal(example.test_object_cast_to_node(example_null), false)
# Test conversions to and from Variant.
assert_equal(example.test_variant_vector2i_conversion(Vector2i(1, 1)), Vector2i(1, 1))
assert_equal(example.test_variant_vector2i_conversion(Vector2(1.0, 1.0)), Vector2i(1, 1))
@ -252,6 +259,9 @@ func _ready():
assert_equal(example.test_virtual_implemented_in_script("Virtual", 939), "Implemented")
assert_equal(custom_signal_emitted, ["Virtual", 939])
# Test that we can access an engine singleton.
assert_equal(example.test_use_engine_singleton(), OS.get_name())
# Test that notifications happen on both parent and child classes.
var example_child = $ExampleChild
assert_equal(example_child.get_value1(), 11)

View File

@ -12,7 +12,7 @@ config_version=5
config/name="GDExtension Test Project"
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.2")
config/features=PackedStringArray("4.3")
config/icon="res://icon.png"
[native_extensions]

View File

@ -11,6 +11,7 @@
#include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/multiplayer_api.hpp>
#include <godot_cpp/classes/multiplayer_peer.hpp>
#include <godot_cpp/classes/os.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
@ -192,6 +193,8 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("return_extended_ref"), &Example::return_extended_ref);
ClassDB::bind_method(D_METHOD("extended_ref_checks", "ref"), &Example::extended_ref_checks);
ClassDB::bind_method(D_METHOD("is_object_binding_set_by_parent_constructor"), &Example::is_object_binding_set_by_parent_constructor);
ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray);
@ -238,6 +241,9 @@ void Example::_bind_methods() {
GDVIRTUAL_BIND(_do_something_virtual, "name", "value");
ClassDB::bind_method(D_METHOD("test_virtual_implemented_in_script"), &Example::test_virtual_implemented_in_script);
GDVIRTUAL_BIND(_do_something_virtual_with_control, "control");
ClassDB::bind_method(D_METHOD("test_use_engine_singleton"), &Example::test_use_engine_singleton);
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);
@ -287,7 +293,17 @@ void Example::_bind_methods() {
BIND_ENUM_CONSTANT(OUTSIDE_OF_CLASS);
}
Example::Example() {
bool Example::has_object_instance_binding() const {
return internal::gdextension_interface_object_get_instance_binding(_owner, internal::token, nullptr);
}
Example::Example() :
object_instance_binding_set_by_parent_constructor(has_object_instance_binding()) {
// Test conversion, to ensure users can use all parent calss functions at this time.
// It would crash if instance binding still not be initialized.
Variant v = Variant(this);
Object *o = (Object *)v;
//UtilityFunctions::print("Constructor.");
}
@ -367,6 +383,10 @@ void Example::emit_custom_signal(const String &name, int value) {
emit_signal("custom_signal", name, value);
}
bool Example::is_object_binding_set_by_parent_constructor() const {
return object_instance_binding_set_by_parent_constructor;
}
Array Example::test_array() const {
Array arr;
@ -671,6 +691,10 @@ String Example::test_virtual_implemented_in_script(const String &p_name, int p_v
return "Unimplemented";
}
String Example::test_use_engine_singleton() const {
return OS::get_singleton()->get_name();
}
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);

View File

@ -82,6 +82,9 @@ private:
Vector2 dprop[3];
int last_rpc_arg = 0;
const bool object_instance_binding_set_by_parent_constructor;
bool has_object_instance_binding() const;
public:
// Constants.
enum Constants {
@ -120,6 +123,8 @@ public:
void emit_custom_signal(const String &name, int value);
int def_args(int p_a = 100, int p_b = 200);
bool is_object_binding_set_by_parent_constructor() const;
Array test_array() const;
int test_tarray_arg(const TypedArray<int64_t> &p_array);
TypedArray<Vector2> test_tarray() const;
@ -186,6 +191,9 @@ public:
GDVIRTUAL2R(String, _do_something_virtual, String, int);
String test_virtual_implemented_in_script(const String &p_name, int p_value);
GDVIRTUAL1(_do_something_virtual_with_control, Control *);
String test_use_engine_singleton() const;
};
VARIANT_ENUM_CAST(Example::Constants);

View File

@ -21,15 +21,15 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
return;
}
ClassDB::register_class<ExampleRef>();
ClassDB::register_class<ExampleMin>();
ClassDB::register_class<Example>();
ClassDB::register_class<ExampleVirtual>(true);
ClassDB::register_abstract_class<ExampleAbstractBase>();
ClassDB::register_class<ExampleConcrete>();
ClassDB::register_class<ExampleBase>();
ClassDB::register_class<ExampleChild>();
ClassDB::register_runtime_class<ExampleRuntime>();
GDREGISTER_CLASS(ExampleRef);
GDREGISTER_CLASS(ExampleMin);
GDREGISTER_CLASS(Example);
GDREGISTER_VIRTUAL_CLASS(ExampleVirtual);
GDREGISTER_ABSTRACT_CLASS(ExampleAbstractBase);
GDREGISTER_CLASS(ExampleConcrete);
GDREGISTER_CLASS(ExampleBase);
GDREGISTER_CLASS(ExampleChild);
GDREGISTER_RUNTIME_CLASS(ExampleRuntime);
}
void uninitialize_example_module(ModuleInitializationLevel p_level) {

View File

@ -3,6 +3,7 @@ import os, sys, platform
from SCons.Variables import EnumVariable, PathVariable, BoolVariable
from SCons.Variables.BoolVariable import _text2bool
from SCons.Tool import Tool
from SCons.Action import Action
from SCons.Builder import Builder
from SCons.Errors import UserError
from SCons.Script import ARGUMENTS
@ -66,6 +67,67 @@ def get_custom_platforms(env):
return platforms
def no_verbose(env):
colors = {}
# Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it will not contain color codes
if sys.stdout.isatty():
colors["blue"] = "\033[0;94m"
colors["bold_blue"] = "\033[1;94m"
colors["reset"] = "\033[0m"
else:
colors["blue"] = ""
colors["bold_blue"] = ""
colors["reset"] = ""
# There is a space before "..." to ensure that source file names can be
# Ctrl + clicked in the VS Code terminal.
compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
java_compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
compile_shared_source_message = "{}Compiling shared {}$SOURCE{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_program_message = "{}Linking Program {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_library_message = "{}Linking Static Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
ranlib_library_message = "{}Ranlib Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_shared_library_message = "{}Linking Shared Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
generated_file_message = "{}Generating {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
env.Append(CXXCOMSTR=[compile_source_message])
env.Append(CCCOMSTR=[compile_source_message])
env.Append(SHCCCOMSTR=[compile_shared_source_message])
env.Append(SHCXXCOMSTR=[compile_shared_source_message])
env.Append(ARCOMSTR=[link_library_message])
env.Append(RANLIBCOMSTR=[ranlib_library_message])
env.Append(SHLINKCOMSTR=[link_shared_library_message])
env.Append(LINKCOMSTR=[link_program_message])
env.Append(JARCOMSTR=[java_library_message])
env.Append(JAVACCOMSTR=[java_compile_source_message])
env.Append(RCCOMSTR=[compiled_resource_message])
env.Append(GENCOMSTR=[generated_file_message])
platforms = ["linux", "macos", "windows", "android", "ios", "web"]
# CPU architecture options.
@ -204,6 +266,8 @@ def options(opts, env):
)
)
opts.Add(BoolVariable(key="threads", help="Enable threading support", default=env.get("threads", True)))
# compiledb
opts.Add(
BoolVariable(
@ -254,6 +318,7 @@ def options(opts, env):
)
opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True))
opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
# Add platform options (custom tools can override platforms)
for pl in sorted(set(platforms + custom_platforms)):
@ -262,6 +327,51 @@ def options(opts, env):
tool.options(opts)
def make_doc_source(target, source, env):
import zlib
dst = str(target[0])
g = open(dst, "w", encoding="utf-8")
buf = ""
docbegin = ""
docend = ""
for src in source:
src_path = str(src)
if not src_path.endswith(".xml"):
continue
with open(src_path, "r", encoding="utf-8") as f:
content = f.read()
buf += content
buf = (docbegin + buf + docend).encode("utf-8")
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("\n")
g.write("#include <godot_cpp/godot.hpp>\n")
g.write("\n")
g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n')
g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const unsigned char _doc_data_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + str(buf[i]) + ",\n")
g.write("};\n")
g.write("\n")
g.write(
"static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n"
)
g.write("\n")
g.close()
def generate(env):
# Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden
@ -330,6 +440,9 @@ def generate(env):
tool.generate(env)
if env["threads"]:
env.Append(CPPDEFINES=["THREADS_ENABLED"])
if env.use_hot_reload:
env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"])
@ -373,6 +486,8 @@ def generate(env):
suffix += "." + env["arch"]
if env["ios_simulator"]:
suffix += ".simulator"
if not env["threads"]:
suffix += ".nothreads"
env["suffix"] = suffix # Exposed when included from another project
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
@ -381,8 +496,17 @@ def generate(env):
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env)))
# Formatting
if not env["verbose"]:
no_verbose(env)
# Builders
env.Append(BUILDERS={"GodotCPPBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
env.Append(
BUILDERS={
"GodotCPPBindings": Builder(action=Action(scons_generate_bindings, "$GENCOMSTR"), emitter=scons_emit_files),
"GodotCPPDocData": Builder(action=make_doc_source),
}
)
env.AddMethod(_godot_cpp, "GodotCPP")

View File

@ -35,8 +35,9 @@ def generate(env):
env["SHLIBSUFFIX"] = ".wasm"
# Thread support (via SharedArrayBuffer).
env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"])
env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"])
if env["threads"]:
env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"])
env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"])
# Build as side module (shared library).
env.Append(CPPFLAGS=["-s", "SIDE_MODULE=1"])