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

View File

@ -37,7 +37,7 @@
# Todo # Todo
# Test build for Windows, Mac and mingw. # Test build for Windows, Mac and mingw.
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.13)
project(godot-cpp LANGUAGES CXX) project(godot-cpp LANGUAGES CXX)
option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON) 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) - [**Compatibility**](#compatibility)
- [**Contributing**](#contributing) - [**Contributing**](#contributing)
- [**Getting started**](#getting-started) - [**Getting started**](#getting-started)
- [**Included example**](#included-example) - [**Examples and templates**](#examples-and-templates)
## Versioning ## Versioning
@ -132,7 +132,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return; 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) generate_utility_functions(api, target_dir)
CLASS_ALIASES = {
"ClassDB": "ClassDBSingleton",
}
builtin_classes = [] builtin_classes = []
# Key is class name, value is boolean where True means the class is refcounted. # 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>") result.append("#include <godot_cpp/variant/vector2.hpp>")
if class_name == "PackedVector3Array": if class_name == "PackedVector3Array":
result.append("#include <godot_cpp/variant/vector3.hpp>") 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): if is_packed_array(class_name):
result.append("#include <godot_cpp/core/error_macros.hpp>") 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"] vararg = method["is_vararg"]
if vararg: if vararg:
result.append("\ttemplate<class... Args>") result.append("\ttemplate<typename... Args>")
method_signature = "\t" method_signature = "\t"
if "is_static" in method and method["is_static"]: 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. # Special cases.
if class_name == "String": if class_name == "String":
result.append("\tstatic String utf8(const char *from, int64_t len = -1);") result.append("\tstatic String utf8(const char *from, 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("\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 utf8() const;")
result.append("\tCharString ascii() const;") result.append("\tCharString ascii() const;")
result.append("\tChar16String utf16() 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();") result.append("\tchar32_t *ptrw();")
if class_name == "Array": if class_name == "Array":
result.append("\ttemplate <class... Args>") result.append("\ttemplate <typename... Args>")
result.append("\tstatic Array make(Args... args) {") result.append("\tstatic Array make(Args... args) {")
result.append("\t\treturn helpers::append_all(Array(), args...);") result.append("\t\treturn helpers::append_all(Array(), args...);")
result.append("\t}") 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. # First create map of classes and singletons.
for class_api in api["classes"]: for class_api in api["classes"]:
# Generate code for the ClassDB singleton under a different name. # Generate code for the ClassDB singleton under a different name.
if class_api["name"] == "ClassDB": if class_api["name"] in CLASS_ALIASES:
class_api["name"] = "ClassDBSingleton" class_api["alias_for"] = class_api["name"]
class_api["alias_for"] = "ClassDB" class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
engine_classes[class_api["name"]] = class_api["is_refcounted"] engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]: for native_struct in api["native_structures"]:
if native_struct["name"] == "ObjectID": 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"]: for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name. # Generate code for the ClassDB singleton under a different name.
if singleton["name"] == "ClassDB": if singleton["name"] in CLASS_ALIASES:
singleton["name"] = "ClassDBSingleton" singleton["alias_for"] = singleton["name"]
singleton["alias_for"] = "ClassDB" singleton["name"] = CLASS_ALIASES[singleton["name"]]
singletons.append(singleton["name"]) singletons.append(singleton["name"])
for class_api in api["classes"]: 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("#include <type_traits>")
result.append("") result.append("")
if class_name == "ClassDBSingleton":
result.append("#include <godot_cpp/core/binder_common.hpp>")
result.append("")
result.append("namespace godot {") result.append("namespace godot {")
result.append("") 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(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append("") result.append("")
if is_singleton:
result.append(f"\tstatic {class_name} *singleton;")
result.append("")
result.append("public:") result.append("public:")
result.append("") result.append("")
@ -1556,7 +1570,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("protected:") result.append("protected:")
# T is the custom class we want to register (from which the call initiates, going up the inheritance chain), # 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). # 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() {") result.append("\tstatic void register_virtuals() {")
if class_name != "Object": if class_name != "Object":
result.append(f"\t\t{inherits}::register_virtuals<T, B>();") 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("\t}")
result.append("") result.append("")
if is_singleton:
result.append(f"\t~{class_name}();")
result.append("")
result.append("public:") result.append("public:")
# Special cases. # Special cases.
if class_name == "XMLParser": if class_name == "XMLParser":
result.append("\tError _open_buffer(const uint8_t *p_buffer, size_t p_size);") 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": if class_name == "FileAccess":
result.append("\tuint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;") 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);") 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": if class_name == "Object":
result.append("") result.append("")
result.append("\ttemplate<class T>") result.append("\ttemplate<typename T>")
result.append("\tstatic T *cast_to(Object *p_object);") 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("\tstatic const T *cast_to(const Object *p_object);")
result.append("\tvirtual ~Object() = default;") result.append("\tvirtual ~Object() = default;")
elif use_template_get_node and class_name == "Node": elif use_template_get_node and class_name == "Node":
result.append("\ttemplate<class T>") result.append("\ttemplate<typename T>")
result.append( result.append(
"\tT *get_node(const NodePath &p_path) const { return Object::cast_to<T>(get_node_internal(p_path)); }" "\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": if class_name == "ClassDBSingleton":
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\") 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"]: for method in class_api["methods"]:
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them. # ClassDBSingleton shouldn't have any static methods, but if some appear later, lets skip them.
if vararg:
continue
if "is_static" in method and method["is_static"]: if "is_static" in method and method["is_static"]:
continue 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: 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: elif "return_value" in method:
method_signature += ( return_type = correct_type(
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " " 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: else:
method_signature += "void " 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_arguments = method["arguments"]
method_signature += make_function_parameters( 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 += ") { \\" method_signature += ") { \\"
@ -1665,10 +1709,14 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(method_signature) result.append(method_signature)
method_body = "\t\t" method_body = "\t\t"
if "return_type" in method or "return_value" in method: if return_type is not None:
method_body += "return " 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 += f'ClassDBSingleton::get_singleton()->{method["name"]}('
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments)) method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
if vararg:
method_body += ", args..."
method_body += "); \\" method_body += "); \\"
result.append(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("\t;")
result.append("") 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}") result.append(f"#endif // ! {header_guard}")
return "\n".join(result) 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(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
result.append("") 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/engine_ptrcall.hpp>")
result.append("#include <godot_cpp/core/error_macros.hpp>") result.append("#include <godot_cpp/core/error_macros.hpp>")
result.append("") result.append("")
@ -1707,9 +1768,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append("") result.append("")
if is_singleton: if is_singleton:
result.append(f"{class_name} *{class_name}::singleton = nullptr;")
result.append("")
result.append(f"{class_name} *{class_name}::get_singleton() {{") 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 # 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("\tif (unlikely(singleton == nullptr)) {")
result.append( result.append(
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());" 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("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);") result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
result.append("#endif // DEBUG_ENABLED") 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("\t}")
result.append("\treturn singleton;") result.append("\treturn singleton;")
result.append("}") result.append("}")
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: if "methods" in class_api:
for method in class_api["methods"]: for method in class_api["methods"]:
if method["is_virtual"]: if method["is_virtual"]:
@ -2245,7 +2318,7 @@ def make_varargs_template(
if with_public_declare: if with_public_declare:
function_signature = "public: " function_signature = "public: "
function_signature += "template<class... Args> " function_signature += "template<typename... Args> "
if static: if static:
function_signature += "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 {{ " args_array = f"\tstd::array<Variant, {len(method_arguments)} + sizeof...(Args)> variant_args {{ "
for argument in method_arguments: for argument in method_arguments:
if argument["type"] == "Variant": if argument["type"] == "Variant":
args_array += argument["name"] args_array += escape_identifier(argument["name"])
else: else:
args_array += f'Variant({argument["name"]})' args_array += f'Variant({escape_identifier(argument["name"])})'
args_array += ", " args_array += ", "
args_array += "Variant(args)... };" args_array += "Variant(args)... };"
@ -2405,6 +2478,7 @@ def is_packed_array(type_name):
"PackedStringArray", "PackedStringArray",
"PackedVector2Array", "PackedVector2Array",
"PackedVector3Array", "PackedVector3Array",
"PackedVector4Array",
] ]
@ -2493,6 +2567,7 @@ def correct_default_value(value, type_name):
"null": "nullptr", "null": "nullptr",
'""': "String()", '""': "String()",
'&""': "StringName()", '&""': "StringName()",
'^""': "NodePath()",
"[]": "Array()", "[]": "Array()",
"{}": "Dictionary()", "{}": "Dictionary()",
"Transform2D(1, 0, 0, 1, 0, 0)": "Transform2D()", # Default transform. "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}()" return f"{type_name}()"
if value.startswith("Array["): if value.startswith("Array["):
return f"{{}}" return f"{{}}"
if value.startswith("&"):
return value[1::]
if value.startswith("^"):
return value[1::]
return value return value
@ -2513,7 +2592,7 @@ def correct_typed_array(type_name):
return 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"} type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
if meta != None: if meta != None:
if "int" in meta: if "int" in meta:
@ -2529,11 +2608,15 @@ def correct_type(type_name, meta=None):
if is_enum(type_name): if is_enum(type_name):
if is_bitfield(type_name): if is_bitfield(type_name):
base_class = get_enum_class(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": if base_class == "GlobalConstants":
return f"BitField<{get_enum_name(type_name)}>" return f"BitField<{get_enum_name(type_name)}>"
return f"BitField<{base_class}::{get_enum_name(type_name)}>" return f"BitField<{base_class}::{get_enum_name(type_name)}>"
else: else:
base_class = get_enum_class(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": if base_class == "GlobalConstants":
return f"{get_enum_name(type_name)}" return f"{get_enum_name(type_name)}"
return f"{base_class}::{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_VECTOR2_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY, GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY,
GDEXTENSION_VARIANT_TYPE_VARIANT_MAX GDEXTENSION_VARIANT_TYPE_VARIANT_MAX
} GDExtensionVariantType; } GDExtensionVariantType;
@ -256,6 +257,7 @@ typedef struct {
typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list); 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 (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
typedef GDExtensionBool (*GDExtensionClassValidateProperty)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property); typedef GDExtensionBool (*GDExtensionClassValidateProperty)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property);
@ -333,7 +335,7 @@ typedef struct {
GDExtensionClassSet set_func; GDExtensionClassSet set_func;
GDExtensionClassGet get_func; GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func; GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList free_property_list_func; GDExtensionClassFreePropertyList2 free_property_list_func;
GDExtensionClassPropertyCanRevert property_can_revert_func; GDExtensionClassPropertyCanRevert property_can_revert_func;
GDExtensionClassPropertyGetRevert property_get_revert_func; GDExtensionClassPropertyGetRevert property_get_revert_func;
GDExtensionClassValidateProperty validate_property_func; GDExtensionClassValidateProperty validate_property_func;
@ -535,6 +537,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList2)(GDExtensionScriptInstan
typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name); 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 (*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 (*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); typedef void (*GDExtensionScriptInstanceNotification2)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what, GDExtensionBool p_reversed);
@ -654,6 +658,8 @@ typedef struct {
GDExtensionScriptInstanceHasMethod has_method_func; GDExtensionScriptInstanceHasMethod has_method_func;
GDExtensionScriptInstanceGetMethodArgumentCount get_method_argument_count_func;
GDExtensionScriptInstanceCall call_func; GDExtensionScriptInstanceCall call_func;
GDExtensionScriptInstanceNotification2 notification_func; GDExtensionScriptInstanceNotification2 notification_func;
@ -1576,6 +1582,7 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUn
/** /**
* @name string_new_with_utf8_chars_and_len * @name string_new_with_utf8_chars_and_len
* @since 4.1 * @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. * 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); 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 * @name string_new_with_utf16_chars_and_len
* @since 4.1 * @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. * 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); 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 * @name string_new_with_utf32_chars_and_len
* @since 4.1 * @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); 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 */ /* INTERFACE: WorkerThreadPool Utilities */
/** /**
@ -1958,32 +2025,6 @@ typedef uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndex)(GDExtension
*/ */
typedef const uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); 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 * @name packed_float32_array_operator_index
* @since 4.1 * @since 4.1
@ -2166,6 +2207,58 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex
*/ */
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); 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 * @name array_operator_index
* @since 4.1 * @since 4.1
@ -2352,6 +2445,9 @@ typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o,
* *
* Gets the class name of an Object. * 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_object A pointer to the Object.
* @param p_library A pointer the library received by the GDExtension's entry point function. * @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. * @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 * @name classdb_register_extension_class
* @since 4.1 * @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. * Registers an extension class in the ClassDB.
* *
@ -2642,6 +2738,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
/** /**
* @name classdb_register_extension_class2 * @name classdb_register_extension_class2
* @since 4.2 * @since 4.2
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
* *
* Registers an extension class in the ClassDB. * Registers an extension class in the ClassDB.
* *
@ -2831,6 +2928,31 @@ typedef void (*GDExtensionInterfaceEditorAddPlugin)(GDExtensionConstStringNamePt
*/ */
typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNamePtr p_class_name); 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 #ifdef __cplusplus
} }
#endif #endif

View File

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

View File

@ -45,7 +45,7 @@ namespace godot {
class RefCounted; class RefCounted;
template <class T> template <typename T>
class Ref { class Ref {
T *reference = nullptr; T *reference = nullptr;
@ -108,7 +108,7 @@ public:
ref(p_from); ref(p_from);
} }
template <class T_Other> template <typename T_Other>
void operator=(const Ref<T_Other> &p_from) { void operator=(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr())); RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) { if (!refb) {
@ -144,7 +144,7 @@ public:
} }
} }
template <class T_Other> template <typename T_Other>
void reference_ptr(T_Other *p_ptr) { void reference_ptr(T_Other *p_ptr) {
if (reference == p_ptr) { if (reference == p_ptr) {
return; return;
@ -161,7 +161,7 @@ public:
ref(p_from); ref(p_from);
} }
template <class T_Other> template <typename T_Other>
Ref(const Ref<T_Other> &p_from) { Ref(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr())); RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) { if (!refb) {
@ -226,7 +226,7 @@ public:
} }
}; };
template <class T> template <typename T>
struct PtrToArg<Ref<T>> { struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = (GDExtensionRefPtr)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> &> { struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT; 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> { struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() { static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 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> { struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() { static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 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; 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. // Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped { class Wrapped {
friend class GDExtensionBinding; friend class GDExtensionBinding;
friend class ClassDB; friend class ClassDB;
friend void postinitialize_handler(Wrapped *); 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: 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 #ifdef HOT_RELOAD_ENABLED
struct RecreateInstance { struct RecreateInstance {
GDExtensionClassInstancePtr wrapper; GDExtensionClassInstancePtr wrapper;
@ -62,9 +80,6 @@ protected:
inline static RecreateInstance *recreate_instance = nullptr; inline static RecreateInstance *recreate_instance = nullptr;
#endif #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) {} void _notification(int p_what) {}
bool _set(const StringName &p_name, const Variant &p_property) { return false; } bool _set(const StringName &p_name, const Variant &p_property) { return false; }
bool _get(const StringName &p_name, Variant &r_property) const { 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 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 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 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_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 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; } static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { return false; }
@ -89,14 +104,15 @@ protected:
::godot::List<::godot::PropertyInfo> plist_owned; ::godot::List<::godot::PropertyInfo> plist_owned;
void _postinitialize(); void _postinitialize();
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
Wrapped(const StringName p_godot_class); Wrapped(const StringName p_godot_class);
Wrapped(GodotObject *p_godot_object); Wrapped(GodotObject *p_godot_object);
virtual ~Wrapped() {} virtual ~Wrapped() {}
public: public:
static StringName &get_class_static() { static const StringName &get_class_static() {
static StringName string_name = StringName("Wrapped"); static const StringName string_name = StringName("Wrapped");
return string_name; return string_name;
} }
@ -108,6 +124,11 @@ public:
GodotObject *_owner = nullptr; 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) { _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); 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) { _FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str, P... p_args) {
arr.push_back(p_str); arr.push_back(p_str);
snarray_add_str(arr, p_args...); snarray_add_str(arr, p_args...);
} }
template <class... P> template <typename... P>
_FORCE_INLINE_ Vector<StringName> snarray(P... p_args) { _FORCE_INLINE_ Vector<StringName> snarray(P... p_args) {
Vector<StringName> arr; Vector<StringName> arr;
snarray_add_str(arr, p_args...); 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_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
void register_engine_classes(); void register_engine_classes();
template <class T> template <typename T>
struct EngineClassRegistration { struct EngineClassRegistration {
EngineClassRegistration() { EngineClassRegistration() {
add_engine_class_registration_callback(&EngineClassRegistration<T>::callback); add_engine_class_registration_callback(&EngineClassRegistration<T>::callback);
@ -160,15 +181,14 @@ struct EngineClassRegistration {
private: \ private: \
void operator=(const m_class &p_rval) {} \ void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \ friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\ \
protected: \ protected: \
virtual const ::godot::StringName *_get_extension_class_name() const override { \ virtual bool _is_extension_class() const override { return true; } \
static ::godot::StringName string_name = get_class_static(); \
return &string_name; \
} \
\ \
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \ static const ::godot::StringName *_get_extension_class_name() { \
return &_gde_binding_callbacks; \ const ::godot::StringName &string_name = get_class_static(); \
return &string_name; \
} \ } \
\ \
static void (*_get_bind_methods())() { \ static void (*_get_bind_methods())() { \
@ -207,13 +227,14 @@ protected:
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \ return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \ } \
\ \
template <class T, class B> \ template <typename T, typename B> \
static void register_virtuals() { \ static void register_virtuals() { \
m_inherits::register_virtuals<T, B>(); \ m_inherits::register_virtuals<T, B>(); \
} \ } \
\ \
public: \ public: \
typedef m_class self_type; \ typedef m_class self_type; \
typedef m_inherits parent_type; \
\ \
static void initialize_class() { \ static void initialize_class() { \
static bool initialized = false; \ static bool initialized = false; \
@ -228,12 +249,12 @@ public:
initialized = true; \ initialized = true; \
} \ } \
\ \
static ::godot::StringName &get_class_static() { \ static const ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_class); \ static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
return string_name; \ return string_name; \
} \ } \
\ \
static ::godot::StringName &get_parent_class_static() { \ static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \ return m_inherits::get_class_static(); \
} \ } \
\ \
@ -291,11 +312,10 @@ public:
return ::godot::internal::create_c_property_list(plist_cpp, r_count); \ 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) { \ if (p_instance) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \ m_class *cls = reinterpret_cast<m_class *>(p_instance); \
cls->plist_owned.clear(); \ 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)); \ ::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
} \ } \
} \ } \
@ -374,6 +394,11 @@ public:
_gde_binding_reference_callback, \ _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: private:
// Don't use this for your classes, use GDCLASS() instead. // Don't use this for your classes, use GDCLASS() instead.
@ -381,15 +406,15 @@ private:
private: \ private: \
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \ inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
void operator=(const m_class &p_rval) {} \ void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\ \
protected: \ 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(const char *p_godot_class) : m_inherits(p_godot_class) {} \
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \ m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
\ \
static void _bind_methods() {} \
\
static void (*_get_bind_methods())() { \ static void (*_get_bind_methods())() { \
return nullptr; \ return nullptr; \
} \ } \
@ -432,15 +457,16 @@ protected:
\ \
public: \ public: \
typedef m_class self_type; \ typedef m_class self_type; \
typedef m_inherits parent_type; \
\ \
static void initialize_class() {} \ static void initialize_class() {} \
\ \
static ::godot::StringName &get_class_static() { \ static const ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \ static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \ return string_name; \
} \ } \
\ \
static ::godot::StringName &get_parent_class_static() { \ static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \ return m_inherits::get_class_static(); \
} \ } \
\ \

View File

@ -83,7 +83,7 @@ namespace godot {
}; \ }; \
} }
template <class T> template <typename T>
struct VariantCaster { struct VariantCaster {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>; using TStripped = std::remove_pointer_t<T>;
@ -95,7 +95,7 @@ struct VariantCaster {
} }
}; };
template <class T> template <typename T>
struct VariantCaster<T &> { struct VariantCaster<T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>; using TStripped = std::remove_pointer_t<T>;
@ -107,7 +107,7 @@ struct VariantCaster<T &> {
} }
}; };
template <class T> template <typename T>
struct VariantCaster<const T &> { struct VariantCaster<const T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>; using TStripped = std::remove_pointer_t<T>;
@ -144,7 +144,7 @@ struct VariantObjectClassChecker<const Ref<T> &> {
} }
}; };
template <class T> template <typename T>
struct VariantCasterAndValidate { struct VariantCasterAndValidate {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
@ -159,7 +159,7 @@ struct VariantCasterAndValidate {
} }
}; };
template <class T> template <typename T>
struct VariantCasterAndValidate<T &> { struct VariantCasterAndValidate<T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
@ -174,7 +174,7 @@ struct VariantCasterAndValidate<T &> {
} }
}; };
template <class T> template <typename T>
struct VariantCasterAndValidate<const T &> { struct VariantCasterAndValidate<const T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); 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...>) { 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])...); (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...>) { 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])...); (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...>) { 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); 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...>) { 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); 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*/) { 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)>{}); 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*/) { 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)>{}); 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) { 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)>{}); 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) { 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)>{}); 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...>) { 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; 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. (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...>) { 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; 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. (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...>) { 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; 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 #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...>) { 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; 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; (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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif #endif
template <class Q> template <typename Q>
void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) { void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) {
if (p_arg == index) { if (p_arg == index) {
type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE); type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE);
@ -485,7 +485,7 @@ void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType
index++; index++;
} }
template <class... P> template <typename... P>
GDExtensionVariantType call_get_argument_type(int p_arg) { GDExtensionVariantType call_get_argument_type(int p_arg) {
GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL; GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL;
int index = 0; int index = 0;
@ -497,7 +497,7 @@ GDExtensionVariantType call_get_argument_type(int p_arg) {
return type; return type;
} }
template <class Q> template <typename Q>
void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) {
if (p_arg == index) { if (p_arg == index) {
info = GetTypeInfo<Q>::get_class_info(); 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++; index++;
} }
template <class... P> template <typename... P>
void call_get_argument_type_info(int p_arg, PropertyInfo &info) { void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
int index = 0; int index = 0;
// I think rocket science is simpler than modern C++. // 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. (void)index; // Suppress GCC warning.
} }
template <class Q> template <typename Q>
void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) { void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) {
if (p_arg == index) { if (p_arg == index) {
md = GetTypeInfo<Q>::METADATA; md = GetTypeInfo<Q>::METADATA;
@ -523,7 +523,7 @@ void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMe
index++; index++;
} }
template <class... P> template <typename... P>
GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) { GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
@ -536,7 +536,7 @@ GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
return md; 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...>) { 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; 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 #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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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...>) { 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])...); 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) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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...>) { 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; 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 #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) { 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 #ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) { 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)>{}); 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...>) { 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); 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) { 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)>{}); 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 { 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) { O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) {
GodotObject *ret = nullptr; GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; 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)); 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) { void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
constructor(base, call_args.data()); 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 _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
T ret; T ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; 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; return ret;
} }
template <class... Args> template <typename... Args>
void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) { void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
method(base, call_args.data(), nullptr, sizeof...(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 _call_builtin_operator_ptr(const GDExtensionPtrOperatorEvaluator op, GDExtensionConstTypePtr left, GDExtensionConstTypePtr right) {
T ret; T ret;
op(left, right, &ret); op(left, right, &ret);
return ret; return ret;
} }
template <class T> template <typename T>
T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) { T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) {
T ret; T ret;
getter(base, &ret); getter(base, &ret);

View File

@ -45,6 +45,7 @@
#include <godot_cpp/variant/callable_method_pointer.hpp> #include <godot_cpp/variant/callable_method_pointer.hpp>
#include <list> #include <list>
#include <mutex>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -104,15 +105,17 @@ private:
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks; static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
// Used to remember the custom class registration order. // Used to remember the custom class registration order.
static std::vector<StringName> class_register_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 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 initialize_class(const ClassInfo &cl);
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method); static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
template <class T, bool is_abstract> template <typename T, bool is_abstract>
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false); static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false);
template <class T> template <typename T>
static GDExtensionObjectPtr _create_instance_func(void *data) { static GDExtensionObjectPtr _create_instance_func(void *data) {
if constexpr (!std::is_abstract_v<T>) { if constexpr (!std::is_abstract_v<T>) {
T *new_object = memnew(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) { static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) { if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED #ifdef HOT_RELOAD_ENABLED
@ -140,26 +143,41 @@ private:
} }
public: public:
template <class T> template <typename T>
static void register_class(bool p_virtual = false); static void register_class(bool p_virtual = false);
template <class T> template <typename T>
static void register_abstract_class(); static void register_abstract_class();
template <class T> template <typename T>
static void register_internal_class(); static void register_internal_class();
template <class T> template <typename T>
static void register_runtime_class(); static void register_runtime_class();
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { _FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
instance_binding_callbacks[p_name] = p_callbacks; instance_binding_callbacks[p_name] = p_callbacks;
} }
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); 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); 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 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); 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); \ ::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) { 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(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; instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
// Register this class within our plugin // 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::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func; T::get_bind, // GDExtensionClassGet get_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func; T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
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_can_revert_bind, // GDExtensionClassPropertyCanRevert property_can_revert_func;
T::property_get_revert_bind, // GDExtensionClassPropertyGetRevert property_get_revert_func; T::property_get_revert_bind, // GDExtensionClassPropertyGetRevert property_get_revert_func;
T::validate_property_bind, // GDExtensionClassValidateProperty validate_property_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]); initialize_class(classes[cl.name]);
} }
template <class T> template <typename T>
void ClassDB::register_class(bool p_virtual) { void ClassDB::register_class(bool p_virtual) {
ClassDB::_register_class<T, false>(p_virtual); ClassDB::_register_class<T, false>(p_virtual);
} }
template <class T> template <typename T>
void ClassDB::register_abstract_class() { void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>(); ClassDB::_register_class<T, true>();
} }
template <class T> template <typename T>
void ClassDB::register_internal_class() { void ClassDB::register_internal_class() {
ClassDB::_register_class<T, false>(false, false); ClassDB::_register_class<T, false>(false, false);
} }
template <class T> template <typename T>
void ClassDB::register_runtime_class() { void ClassDB::register_runtime_class() {
ClassDB::_register_class<T, false>(false, true, true); 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) { 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. 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]; 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)); 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) { 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. 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]; 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)); 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 *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); MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
ERR_FAIL_NULL_V(bind, nullptr); 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; return bind;
} }
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>(); #define GDREGISTER_CLASS(m_class) ::godot::ClassDB::register_class<m_class>();
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true); #define GDREGISTER_VIRTUAL_CLASS(m_class) ::godot::ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>(); #define GDREGISTER_ABSTRACT_CLASS(m_class) ::godot::ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>(); #define GDREGISTER_INTERNAL_CLASS(m_class) ::godot::ClassDB::register_internal_class<m_class>();
#define GDREGISTER_RUNTIME_CLASS(m_class) ClassDB::register_runtime_class<m_class>(); #define GDREGISTER_RUNTIME_CLASS(m_class) ::godot::ClassDB::register_runtime_class<m_class>();
} // namespace godot } // namespace godot
CLASSDB_SINGLETON_VARIANT_CAST;
#endif // GODOT_CLASS_DB_HPP #endif // GODOT_CLASS_DB_HPP

View File

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

View File

@ -43,7 +43,7 @@ namespace godot {
namespace internal { 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) { O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
GodotObject *ret = nullptr; GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; 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)); 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 _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
R ret; R ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; 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; return ret;
} }
template <class... Args> template <typename... Args>
void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr); 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 _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
R ret; R ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
@ -76,15 +76,15 @@ R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
return ret; return ret;
} }
template <class... Args> template <typename... Args>
Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *instance, const Args &...args) { Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, const Args &...args) {
GodotObject *ret = nullptr; GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(&ret, mb_args.data(), mb_args.size()); func(&ret, mb_args.data(), mb_args.size());
return (Object *)internal::get_object_instance_binding(ret); 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) { void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &...args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(nullptr, mb_args.data(), mb_args.size()); 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. // Generic swap template.
#ifndef SWAP #ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y)) #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) { inline void __swap_tmpl(T &x, T &y) {
T aux = x; T aux = x;
x = y; x = y;
@ -138,7 +138,7 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) {
return -1; return -1;
} }
template <class T> template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x; --x;
@ -613,6 +613,14 @@ inline bool is_inf(double p_val) {
return std::isinf(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) { inline bool is_equal_approx(float a, float b) {
// Check for exact equality first, required to handle "infinity" values. // Check for exact equality first, required to handle "infinity" values.
if (a == b) { if (a == b) {

View File

@ -82,9 +82,12 @@ public:
static void free_static(void *p_ptr, bool p_pad_align = false); 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 *) {} _ALWAYS_INLINE_ void postinitialize_handler(void *) {}
template <class T> template <typename T>
_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
postinitialize_handler(p_obj); postinitialize_handler(p_obj);
return 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 memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
#define memfree(m_mem) ::godot::Memory::free_static(m_mem) #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_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::_post_initialize(new ("", m_placement, sizeof(m_class), "") 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. // Generic comparator used in Map, List, etc.
template <class T> template <typename T>
struct Comparator { struct Comparator {
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); } _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) { 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>) { if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~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); 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) { void memdelete(T *p_class) {
godot::internal::gdextension_interface_object_destroy(p_class->_owner); 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) { void memdelete_allocator(T *p_class) {
if constexpr (!std::is_trivially_destructible_v<T>) { if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T(); p_class->~T();
@ -134,10 +137,10 @@ public:
_ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); } _ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); }
}; };
template <class T> template <typename T>
class DefaultTypedAllocator { class DefaultTypedAllocator {
public: public:
template <class... Args> template <typename... Args>
_ALWAYS_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_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); } _ALWAYS_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); }
}; };

View File

@ -147,7 +147,7 @@ public:
virtual ~MethodBind(); 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 { class MethodBindVarArgBase : public MethodBind {
protected: protected:
R(T::*method) R(T::*method)
@ -208,7 +208,7 @@ private:
} }
}; };
template <class T> template <typename T>
class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> { class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
friend class 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 *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)); MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static()); a->set_instance_class(T::get_class_static());
return a; return a;
} }
template <class T, class R> template <typename T, typename R>
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> { class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
friend class 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 *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)); MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static()); a->set_instance_class(T::get_class_static());
@ -277,9 +277,9 @@ class _gde_UnexistingClass;
// No return, not const. // No return, not const.
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
template <class T, class... P> template <typename T, typename... P>
#else #else
template <class... P> template <typename... P>
#endif // TYPED_METHOD_BIND #endif // TYPED_METHOD_BIND
class MethodBindT : public MethodBind { class MethodBindT : public MethodBind {
void (MB_T::*method)(P...); 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...)) { MethodBind *create_method_bind(void (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method)); MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
@ -353,9 +353,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
// No return, const. // No return, const.
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
template <class T, class... P> template <typename T, typename... P>
#else #else
template <class... P> template <typename... P>
#endif // TYPED_METHOD_BIND #endif // TYPED_METHOD_BIND
class MethodBindTC : public MethodBind { class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const; void (MB_T::*method)(P...) const;
@ -412,10 +412,11 @@ public:
method = p_method; method = p_method;
generate_argument_types(sizeof...(P)); generate_argument_types(sizeof...(P));
set_argument_count(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) { MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method)); 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. // Return, not const.
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
template <class T, class R, class... P> template <typename T, typename R, typename... P>
#else #else
template <class R, class... P> template <typename R, typename... P>
#endif // TYPED_METHOD_BIND #endif // TYPED_METHOD_BIND
class MethodBindTR : public MethodBind { class MethodBindTR : public MethodBind {
R(MB_T::*method) 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...)) { MethodBind *create_method_bind(R (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method)); MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
@ -512,9 +513,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) {
// Return, const. // Return, const.
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
template <class T, class R, class... P> template <typename T, typename R, typename... P>
#else #else
template <class R, class... P> template <typename R, typename... P>
#endif // TYPED_METHOD_BIND #endif // TYPED_METHOD_BIND
class MethodBindTRC : public MethodBind { class MethodBindTRC : public MethodBind {
R(MB_T::*method) R(MB_T::*method)
@ -578,10 +579,11 @@ public:
generate_argument_types(sizeof...(P)); generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P)); set_argument_count(sizeof...(P));
set_return(true); 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) { MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND #ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method)); 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 // no return
template <class... P> template <typename... P>
class MethodBindTS : public MethodBind { class MethodBindTS : public MethodBind {
void (*function)(P...); void (*function)(P...);
@ -652,7 +654,7 @@ public:
} }
}; };
template <class... P> template <typename... P>
MethodBind *create_static_method_bind(void (*p_method)(P...)) { MethodBind *create_static_method_bind(void (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTS<P...>)(p_method)); MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
return a; return a;
@ -660,7 +662,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
// return // return
template <class R, class... P> template <typename R, typename... P>
class MethodBindTRS : public MethodBind { class MethodBindTRS : public MethodBind {
R(*function) R(*function)
(P...); (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 *create_static_method_bind(R (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method)); MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
return a; return a;

View File

@ -39,7 +39,7 @@
namespace godot { namespace godot {
template <class T> template <typename T>
struct PtrToArg {}; struct PtrToArg {};
#define MAKE_PTRARG(m_type) \ #define MAKE_PTRARG(m_type) \
@ -166,27 +166,27 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
// This is for Object. // This is for Object.
template <class T> template <typename T>
struct PtrToArg<T *> { struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object"); 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) { _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; typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) { _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 *> { struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object"); 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) { _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; typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) { _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();
MethodInfo(StringName p_name); MethodInfo(StringName p_name);
template <class... Args> template <typename... Args>
MethodInfo(StringName p_name, const Args &...args); MethodInfo(StringName p_name, const Args &...args);
MethodInfo(Variant::Type ret); MethodInfo(Variant::Type ret);
MethodInfo(Variant::Type ret, StringName p_name); MethodInfo(Variant::Type ret, StringName p_name);
template <class... Args> template <typename... Args>
MethodInfo(Variant::Type ret, StringName p_name, const Args &...args); MethodInfo(Variant::Type ret, StringName p_name, const Args &...args);
MethodInfo(const PropertyInfo &p_ret, StringName p_name); MethodInfo(const PropertyInfo &p_ret, StringName p_name);
template <class... Args> template <typename... Args>
MethodInfo(const PropertyInfo &p_ret, StringName p_name, const 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) : MethodInfo::MethodInfo(StringName p_name, const Args &...args) :
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... }; arguments = { args... };
} }
template <class... Args> template <typename... Args>
MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) : MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) :
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
return_val.type = ret; return_val.type = ret;
arguments = { args... }; arguments = { args... };
} }
template <class... Args> template <typename... Args>
MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...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) { name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... }; arguments = { args... };
@ -121,7 +121,7 @@ public:
} }
}; };
template <class T> template <typename T>
T *Object::cast_to(Object *p_object) { T *Object::cast_to(Object *p_object) {
if (p_object == nullptr) { if (p_object == nullptr) {
return nullptr; return nullptr;
@ -134,7 +134,7 @@ T *Object::cast_to(Object *p_object) {
return dynamic_cast<T *>(internal::get_object_instance_binding(casted)); 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) { const T *Object::cast_to(const Object *p_object) {
if (p_object == nullptr) { if (p_object == nullptr) {
return nullptr; return nullptr;

View File

@ -47,9 +47,9 @@ struct PropertyInfo {
Variant::Type type = Variant::NIL; Variant::Type type = Variant::NIL;
StringName name; StringName name;
StringName class_name; StringName class_name;
uint32_t hint = 0; uint32_t hint = PROPERTY_HINT_NONE;
String hint_string; String hint_string;
uint32_t usage = 7; uint32_t usage = PROPERTY_USAGE_DEFAULT;
PropertyInfo() = default; PropertyInfo() = default;
@ -72,6 +72,40 @@ struct PropertyInfo {
PropertyInfo(const GDExtensionPropertyInfo *p_info) : 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)) {} 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) { void _update(GDExtensionPropertyInfo *p_info) {
p_info->type = (GDExtensionVariantType)type; p_info->type = (GDExtensionVariantType)type;
*(reinterpret_cast<StringName *>(p_info->name)) = name; *(reinterpret_cast<StringName *>(p_info->name)) = name;

View File

@ -58,6 +58,16 @@ struct TypesAreSame<A, A> {
static bool const value = true; 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> template <typename B, typename D>
struct TypeInherits { struct TypeInherits {
static D *get_d(); 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 // 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. // 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; struct GetTypeInfo;
#define MAKE_TYPE_INFO(m_type, m_var_type) \ #define MAKE_TYPE_INFO(m_type, m_var_type) \
@ -198,8 +208,8 @@ struct GetTypeInfo<const Variant &> {
template <typename T> template <typename T>
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() { static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 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> template <typename T>
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() { static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 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) \ #define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
template <> \ template <> \
struct GetTypeInfo<m_impl> { \ struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \ static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \ static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \ 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)); \ 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; return GetTypeInfo<T>::get_class_info().class_name;
} }
template <class T> template <typename T>
class BitField { class BitField {
int64_t value = 0; int64_t value = 0;
@ -264,8 +274,8 @@ public:
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \ #define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
template <> \ template <> \
struct GetTypeInfo<m_impl> { \ struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \ static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \ static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ 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)); \ enum_qualified_name_to_class_info_name(#m_enum)); \
@ -273,8 +283,8 @@ public:
}; \ }; \
template <> \ template <> \
struct GetTypeInfo<BitField<m_impl>> { \ struct GetTypeInfo<BitField<m_impl>> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \ static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \ static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \ static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \ 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)); \ 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; return GetTypeInfo<BitField<T>>::get_class_info().class_name;
} }
template <class T> template <typename T>
struct PtrToArg<TypedArray<T>> { struct PtrToArg<TypedArray<T>> {
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
return TypedArray<T>(*reinterpret_cast<const Array *>(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> &> { struct PtrToArg<const TypedArray<T> &> {
typedef Array EncodeT; typedef Array EncodeT;
_FORCE_INLINE_ static TypedArray<T> _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" GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars;
extern "C" GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len; 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" 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" 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" GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len; extern "C" GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len;
extern "C" GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars; 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" GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index; extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const; 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" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const; extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref; 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" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding; extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_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" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name; extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to; 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" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin; extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_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 } // namespace internal

View File

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

View File

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

View File

@ -48,9 +48,9 @@ namespace godot {
* *
*/ */
template <class TKey, template <typename TKey,
class Hasher = HashMapHasherDefault, typename Hasher = HashMapHasherDefault,
class Comparator = HashMapComparatorDefault<TKey>> typename Comparator = HashMapComparatorDefault<TKey>>
class HashSet { class HashSet {
public: public:
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. 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); 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) { static _FORCE_INLINE_ uint32_t hash_make_uint32_t(T p_in) {
union { union {
T t; 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; 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) { static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
union { union {
T t; T t;
@ -298,15 +298,15 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
return _u._u64; return _u._u64;
} }
template <class T> template <typename T>
class Ref; class Ref;
struct HashMapHasherDefault { struct HashMapHasherDefault {
// Generic hash function for any type. // 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); } 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 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(); } static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }

View File

@ -45,7 +45,7 @@
namespace godot { namespace godot {
template <class T, class A = DefaultAllocator> template <typename T, typename A = DefaultAllocator>
class List { class List {
struct _Data; struct _Data;
@ -139,31 +139,6 @@ public:
typedef T ValueType; 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 { struct ConstIterator {
_FORCE_INLINE_ const T &operator*() const { _FORCE_INLINE_ const T &operator*() const {
return E->get(); return E->get();
@ -189,6 +164,35 @@ public:
const Element *E = nullptr; 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() { _FORCE_INLINE_ Iterator begin() {
return Iterator(front()); return Iterator(front());
} }
@ -410,7 +414,7 @@ public:
/** /**
* find an element in the list, * find an element in the list,
*/ */
template <class T_v> template <typename T_v>
Element *find(const T_v &p_val) { Element *find(const T_v &p_val) {
Element *it = front(); Element *it = front();
while (it) { 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()); CRASH_BAD_INDEX(p_index, size());
Element *I = front(); Element *I = front();
@ -532,7 +543,14 @@ public:
return I->get(); 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()); CRASH_BAD_INDEX(p_index, size());
const Element *I = front(); const Element *I = front();
@ -646,7 +664,7 @@ public:
sort_custom<Comparator<T>>(); sort_custom<Comparator<T>>();
} }
template <class C> template <typename C>
void sort_custom_inplace() { void sort_custom_inplace() {
if (size() < 2) { if (size() < 2) {
return; return;
@ -693,7 +711,7 @@ public:
_data->last = to; _data->last = to;
} }
template <class C> template <typename C>
struct AuxiliaryComparator { struct AuxiliaryComparator {
C compare; C compare;
_FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const { _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() { void sort_custom() {
// this version uses auxiliary memory for speed. // this version uses auxiliary memory for speed.
// if you don't want to use auxiliary memory, use the in_place version // 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. // If tight, it grows strictly as much as needed.
// Otherwise, it grows exponentially (the default and what you want in most cases). // 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 { class LocalVector {
private: private:
U count = 0; U count = 0;
@ -257,7 +257,11 @@ public:
return -1; return -1;
} }
template <class C> bool has(const T &p_val) const {
return find(p_val) != -1;
}
template <typename C>
void sort_custom() { void sort_custom() {
U len = count; U len = count;
if (len == 0) { 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>; using TightLocalVector = LocalVector<T, U, force_trivial, true>;
} // namespace godot } // namespace godot

View File

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

View File

@ -40,7 +40,7 @@ namespace godot {
// based on the very nice implementation of rb-trees by: // 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 // 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 { class RBMap {
enum Color { enum Color {
RED, RED,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,6 +65,7 @@ struct _NO_DISCARD_ AABB {
bool operator!=(const AABB &p_rval) const; bool operator!=(const AABB &p_rval) const;
bool is_equal_approx(const AABB &p_aabb) 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(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 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 _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_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
_FORCE_INLINE_ AABB abs() const { _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; 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_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;
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. // No return value.
// //
template <class T, class... P> template <typename T, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase { class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data { struct Data {
T *instance; 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...)) { Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
typedef CallableCustomMethodPointer<T, P...> CCMP; typedef CallableCustomMethodPointer<T, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_instance, p_method)); 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. // With return value.
// //
template <class T, class R, class... P> template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data { struct Data {
T *instance; 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...)) { Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise. typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method)); 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. // Const with return value.
// //
template <class T, class R, class... P> template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase { class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data { struct Data {
T *instance; 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) { 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. typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method)); 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. // Static method with no return value.
// //
template <class... P> template <typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase { class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data { struct Data {
void (*method)(P...); 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...)) { Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointer<P...> CCMP; typedef CallableCustomStaticMethodPointer<P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method)); 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. // Static method with return value.
// //
template <class R, class... P> template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase { class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data { struct Data {
R(*method) 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...)) { Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP; typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method)); CCMP *ccmp = memnew(CCMP(p_method));

View File

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

View File

@ -77,6 +77,7 @@ struct _NO_DISCARD_ Plane {
Plane operator-() const { return Plane(-normal, -d); } Plane operator-() const { return Plane(-normal, -d); }
bool is_equal_approx(const Plane &p_plane) const; bool is_equal_approx(const Plane &p_plane) const;
bool is_equal_approx_any_side(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;
_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; _FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Quaternion &p_quaternion) const; bool is_equal_approx(const Quaternion &p_quaternion) const;
bool is_finite() const;
real_t length() const; real_t length() const;
void normalize(); void normalize();
Quaternion normalized() const; Quaternion normalized() const;

View File

@ -154,14 +154,12 @@ struct _NO_DISCARD_ Rect2 {
return Rect2(); return Rect2();
} }
new_rect.position.x = Math::max(p_rect.position.x, position.x); new_rect.position = p_rect.position.max(position);
new_rect.position.y = Math::max(p_rect.position.y, position.y);
Point2 p_rect_end = p_rect.position + p_rect.size; Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size; Point2 end = position + size;
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x; new_rect.size = p_rect_end.min(end) - new_rect.position;
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
return new_rect; return new_rect;
} }
@ -174,11 +172,9 @@ struct _NO_DISCARD_ Rect2 {
#endif #endif
Rect2 new_rect; Rect2 new_rect;
new_rect.position.x = Math::min(p_rect.position.x, position.x); new_rect.position = p_rect.position.min(position);
new_rect.position.y = Math::min(p_rect.position.y, position.y);
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x); new_rect.size = (p_rect.position + p_rect.size).max(position + size);
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = new_rect.size - new_rect.position; // Make relative again. 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_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; }
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 { _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 { Vector2 get_support(const Vector2 &p_normal) const {

View File

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

View File

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

View File

@ -78,6 +78,7 @@ struct _NO_DISCARD_ Transform3D {
void orthogonalize(); void orthogonalize();
Transform3D orthogonalized() const; Transform3D orthogonalized() const;
bool is_equal_approx(const Transform3D &p_transform) 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;
bool operator!=(const Transform3D &p_transform) const; bool operator!=(const Transform3D &p_transform) const;

View File

@ -36,7 +36,7 @@
namespace godot { namespace godot {
template <class T> template <typename T>
class TypedArray : public Array { class TypedArray : public Array {
public: public:
_FORCE_INLINE_ void operator=(const Array &p_array) { _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); 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) { Variant call(const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... }; std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs; 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); 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) { static Variant call_static(Variant::Type type, const StringName &method, Args... args) {
std::array<Variant, sizeof...(args)> vargs = { args... }; std::array<Variant, sizeof...(args)> vargs = { args... };
std::array<const Variant *, sizeof...(args)> argptrs; 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)); 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 { Vector2 max(const Vector2 &p_vector2) const {
return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y)); 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_to(const Vector2 &p_vector2) const;
real_t distance_squared_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; 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_equal_approx(const Vector2 &p_v) const;
bool is_zero_approx() const; bool is_zero_approx() const;
bool is_finite() const;
Vector2 operator+(const Vector2 &p_v) const; Vector2 operator+(const Vector2 &p_v) const;
void operator+=(const Vector2 &p_v); void operator+=(const Vector2 &p_v);
@ -168,7 +177,9 @@ struct _NO_DISCARD_ Vector2 {
Vector2 ceil() const; Vector2 ceil() const;
Vector2 round() const; Vector2 round() const;
Vector2 snapped(const Vector2 &p_by) 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 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; } real_t aspect() const { return width / height; }
operator String() const; 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)); 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 { Vector2i max(const Vector2i &p_vector2i) const {
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y)); 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; Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v); void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const; Vector2i operator-(const Vector2i &p_v) const;
@ -123,7 +131,10 @@ struct _NO_DISCARD_ Vector2i {
real_t aspect() const { return width / (real_t)height; } real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
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 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 String() const;
operator Vector2() 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)); 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 { Vector3 max(const Vector3 &p_vector3) const {
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z)); 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() const;
_FORCE_INLINE_ real_t length_squared() const; _FORCE_INLINE_ real_t length_squared() const;
@ -98,7 +106,9 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ void zero(); _FORCE_INLINE_ void zero();
void snap(const Vector3 p_val); void snap(const Vector3 p_val);
void snapf(real_t p_val);
Vector3 snapped(const Vector3 p_val) const; 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); void rotate(const Vector3 &p_axis, const real_t p_angle);
Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const; 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 ceil() const;
_FORCE_INLINE_ Vector3 round() const; _FORCE_INLINE_ Vector3 round() const;
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) 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_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_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_equal_approx(const Vector3 &p_v) const;
bool is_zero_approx() const; bool is_zero_approx() const;
bool is_finite() const;
/* Operators */ /* 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)); 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 { Vector3i max(const Vector3i &p_vector3i) const {
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z)); 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_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const; _FORCE_INLINE_ double length() const;
@ -89,7 +97,10 @@ struct _NO_DISCARD_ Vector3i {
_FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() 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 clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */ /* 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)); 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 { 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)); 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; _FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const; bool is_equal_approx(const Vector4 &p_vec4) const;
bool is_zero_approx() const; bool is_zero_approx() const;
bool is_finite() const;
real_t length() const; real_t length() const;
void normalize(); void normalize();
Vector4 normalized() const; Vector4 normalized() const;
@ -102,8 +111,11 @@ struct _NO_DISCARD_ Vector4 {
Vector4 posmod(const real_t p_mod) const; Vector4 posmod(const real_t p_mod) const;
Vector4 posmodv(const Vector4 &p_modv) const; Vector4 posmodv(const Vector4 &p_modv) const;
void snap(const Vector4 &p_step); void snap(const Vector4 &p_step);
void snapf(real_t p_step);
Vector4 snapped(const Vector4 &p_step) const; 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 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
Vector4 clampf(real_t p_min, real_t p_max) const;
Vector4 inverse() const; Vector4 inverse() const;
_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) 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)); 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 { 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)); 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_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const; _FORCE_INLINE_ double length() const;
@ -91,7 +99,10 @@ struct _NO_DISCARD_ Vector4i {
_FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() 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 clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */ /* Operators */

View File

@ -29,6 +29,7 @@
/**************************************************************************/ /**************************************************************************/
#include <godot_cpp/classes/file_access.hpp> #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/worker_thread_pool.hpp>
#include <godot_cpp/classes/xml_parser.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); 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 } // namespace godot

View File

@ -39,22 +39,17 @@
#include <godot_cpp/core/class_db.hpp> #include <godot_cpp/core/class_db.hpp>
namespace godot { 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; return nullptr;
} }
void Wrapped::_postinitialize() { void Wrapped::_postinitialize() {
const StringName *extension_class = _get_extension_class_name(); // Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (extension_class) { if (_is_extension_class()) {
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this); _notificationv(Object::NOTIFICATION_POSTINITIALIZE);
}
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);
}
} }
} }
@ -79,6 +74,19 @@ Wrapped::Wrapped(const StringName p_godot_class) {
} }
#endif #endif
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr())); _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) { 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, ClassDB::ClassInfo> ClassDB::classes;
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks; std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
std::vector<StringName> ClassDB::class_register_order; 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; GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
MethodDefinition D_METHOD(StringName p_name) { 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) { if (mi.argument_count > 0) {
mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count); mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count);
mi.arguments_metadata = (GDExtensionClassMethodArgumentMetadata *)memalloc(sizeof(GDExtensionClassMethodArgumentMetadata) * 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[i] = p_method.arguments[i]._to_gdextension();
mi.arguments_metadata[i] = p_method.arguments_metadata[i]; 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()); 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 } // 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)); 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 } // 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() : MethodInfo::MethodInfo() :
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {} 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; GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars = nullptr;
GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len = nullptr; GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_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; 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; GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len = nullptr; GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len = nullptr;
GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars = 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; GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index = nullptr; GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const = 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; GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr;
GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr; GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr; GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
@ -166,6 +170,7 @@ GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr; GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr; GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_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; GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr; GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr; GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
@ -196,6 +201,40 @@ GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classd
GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr; GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr;
GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr; GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr;
GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_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 } // 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_wide_chars, GDExtensionInterfaceStringNewWithWideChars);
LOAD_PROC_ADDRESS(string_new_with_latin1_chars_and_len, GDExtensionInterfaceStringNewWithLatin1CharsAndLen); 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_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_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_utf32_chars_and_len, GDExtensionInterfaceStringNewWithUtf32CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_wide_chars_and_len, GDExtensionInterfaceStringNewWithWideCharsAndLen); LOAD_PROC_ADDRESS(string_new_with_wide_chars_and_len, GDExtensionInterfaceStringNewWithWideCharsAndLen);
LOAD_PROC_ADDRESS(string_to_latin1_chars, GDExtensionInterfaceStringToLatin1Chars); 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_vector2_array_operator_index_const, GDExtensionInterfacePackedVector2ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index, GDExtensionInterfacePackedVector3ArrayOperatorIndex); LOAD_PROC_ADDRESS(packed_vector3_array_operator_index, GDExtensionInterfacePackedVector3ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index_const, GDExtensionInterfacePackedVector3ArrayOperatorIndexConst); 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, GDExtensionInterfaceArrayOperatorIndex);
LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst); LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef); 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(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding); LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding); 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_set_instance, GDExtensionInterfaceObjectSetInstance);
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName); LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo); 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(get_library_path, GDExtensionInterfaceGetLibraryPath);
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin); LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin); 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->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level; r_initialization->deinitialize = deinitialize_level;
@ -465,6 +513,13 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ
ClassDB::initialize(p_level); ClassDB::initialize(p_level);
} }
level_initialized[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) { 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); 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 } // 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); 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 { AABB AABB::intersection(const AABB &p_aabb) const {
#ifdef MATH_CHECKS #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)) { 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]); 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 { bool Basis::operator==(const Basis &p_matrix) const {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) { 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 { bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
if (length() == 0) { if (length() == 0) {
return p_right.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()); return is_str_less(get_data(), p_right.get_data());
} }
template <class T> template <typename T>
CharStringT<T> &CharStringT<T>::operator+=(T p_char) { CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
const int64_t lhs_len = length(); const int64_t lhs_len = length();
resize(lhs_len + 2); resize(lhs_len + 2);
@ -86,7 +86,7 @@ CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
return *this; return *this;
} }
template <class T> template <typename T>
void CharStringT<T>::operator=(const T *p_cstr) { void CharStringT<T>::operator=(const T *p_cstr) {
copy_from(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) { void CharStringT<T>::copy_from(const T *p_cstr) {
if (!p_cstr) { if (!p_cstr) {
resize(0); resize(0);
@ -178,8 +178,8 @@ String String::utf8(const char *from, int64_t len) {
return ret; return ret;
} }
void String::parse_utf8(const char *from, int64_t len) { Error String::parse_utf8(const char *from, int64_t len) {
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, 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) { 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; return ret;
} }
void String::parse_utf16(const char16_t *from, int64_t len) { Error String::parse_utf16(const char16_t *from, int64_t len, bool default_little_endian) {
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len); 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) { 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_string_array.hpp>
#include <godot_cpp/variant/packed_vector2_array.hpp> #include <godot_cpp/variant/packed_vector2_array.hpp>
#include <godot_cpp/variant/packed_vector3_array.hpp> #include <godot_cpp/variant/packed_vector3_array.hpp>
#include <godot_cpp/variant/packed_vector4_array.hpp>
namespace godot { namespace godot {
@ -198,6 +199,24 @@ Vector3 *PackedVector3Array::ptrw() {
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0); return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
} }
const 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 &Array::operator[](int64_t p_index) const {
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index); const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *var; return *var;

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); 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 { Plane::operator String() const {
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]"; 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 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; 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; 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); 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 { real_t Quaternion::length() const {
return Math::sqrt(length_squared()); 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); 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 { bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
#ifdef MATH_CHECKS #ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) { 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]); 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 Transform2D::looking_at(const Vector2 &p_target) const {
Transform2D return_trans = Transform2D(get_rotation(), get_origin()); Transform2D return_trans = Transform2D(get_rotation(), get_origin());
Vector2 target_position = affine_inverse().xform(p_target); 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); 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 { bool Transform3D::operator==(const Transform3D &p_transform) const {
return (basis == p_transform.basis && origin == p_transform.origin); 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)); 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 { Vector2 Vector2::snapped(const Vector2 &p_step) const {
return Vector2( return Vector2(
Math::snapped(x, p_step.x), Math::snapped(x, p_step.x),
Math::snapped(y, p_step.y)); 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 { Vector2 Vector2::limit_length(const real_t p_len) const {
const real_t l = length(); const real_t l = length();
Vector2 v = *this; Vector2 v = *this;
@ -188,6 +200,10 @@ bool Vector2::is_zero_approx() const {
return Math::is_zero_approx(x) && Math::is_zero_approx(y); 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 { Vector2::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")"; return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")";
} }

View File

@ -35,12 +35,30 @@
namespace godot { 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 { Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const {
return Vector2i( return Vector2i(
CLAMP(x, p_min.x, p_max.x), CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y)); 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 { int64_t Vector2i::length_squared() const {
return x * (int64_t)x + y * (int64_t)y; 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)); 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) { void Vector3::snap(const Vector3 p_step) {
x = Math::snapped(x, p_step.x); x = Math::snapped(x, p_step.x);
y = Math::snapped(y, p_step.y); y = Math::snapped(y, p_step.y);
z = Math::snapped(z, p_step.z); 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 Vector3::snapped(const Vector3 p_step) const {
Vector3 v = *this; Vector3 v = *this;
v.snap(p_step); v.snap(p_step);
return v; 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 { Vector3 Vector3::limit_length(const real_t p_len) const {
const real_t l = length(); const real_t l = length();
Vector3 v = *this; 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); 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 { Vector3::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")"; return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")";
} }

View File

@ -35,6 +35,20 @@
namespace godot { 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 { 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); 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)); 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 { Vector3i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; 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); 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 { real_t Vector4::length() const {
return Math::sqrt(length_squared()); return Math::sqrt(length_squared());
} }
@ -169,12 +173,25 @@ void Vector4::snap(const Vector4 &p_step) {
w = Math::snapped(w, p_step.w); 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 Vector4::snapped(const Vector4 &p_step) const {
Vector4 v = *this; Vector4 v = *this;
v.snap(p_step); v.snap(p_step);
return v; return v;
} }
Vector4 Vector4::snappedf(real_t p_step) const {
Vector4 v = *this;
v.snapf(p_step);
return v;
}
Vector4 Vector4::inverse() const { Vector4 Vector4::inverse() const {
return Vector4(1.0f / x, 1.0f / y, 1.0f / z, 1.0f / w); 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)); 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 { 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) + ")"; 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 { 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 { Vector4i::Axis Vector4i::min_axis_index() const {
uint32_t min_index = 0; uint32_t min_index = 0;
int32_t min_value = x; 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)); 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 { Vector4i::operator String() const {
return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; 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) project(godot-cpp-test)
cmake_minimum_required(VERSION 3.6)
set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory") set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory")
set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings") set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings")

View File

@ -16,6 +16,10 @@ env = SConscript("../SConstruct")
env.Append(CPPPATH=["src/"]) env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp") 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": if env["platform"] == "macos":
library = env.SharedLibrary( library = env.SharedLibrary(
"project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format( "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" android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework" ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
ios.release = "res://bin/libgdexample.ios.template_release.xcframework" ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm" web.debug.threads.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.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] [dependencies]
ios.debug = { ios.debug = {

View File

@ -9,12 +9,15 @@ class TestClass:
func _ready(): func _ready():
var example: Example = $Example var example: Example = $Example
# Timing of set instance binding.
assert_equal(example.is_object_binding_set_by_parent_constructor(), true)
# Signal. # Signal.
example.emit_custom_signal("Button", 42) example.emit_custom_signal("Button", 42)
assert_equal(custom_signal_emitted, ["Button", 42]) assert_equal(custom_signal_emitted, ["Button", 42])
# To string. # 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 :-( # It appears there's a bug with instance ids :-(
#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id()) #assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())
@ -191,6 +194,10 @@ func _ready():
control.queue_free() control.queue_free()
sprite.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. # 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(Vector2i(1, 1)), Vector2i(1, 1))
assert_equal(example.test_variant_vector2i_conversion(Vector2(1.0, 1.0)), 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(example.test_virtual_implemented_in_script("Virtual", 939), "Implemented")
assert_equal(custom_signal_emitted, ["Virtual", 939]) 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. # Test that notifications happen on both parent and child classes.
var example_child = $ExampleChild var example_child = $ExampleChild
assert_equal(example_child.get_value1(), 11) assert_equal(example_child.get_value1(), 11)

View File

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

View File

@ -11,6 +11,7 @@
#include <godot_cpp/classes/label.hpp> #include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/multiplayer_api.hpp> #include <godot_cpp/classes/multiplayer_api.hpp>
#include <godot_cpp/classes/multiplayer_peer.hpp> #include <godot_cpp/classes/multiplayer_peer.hpp>
#include <godot_cpp/classes/os.hpp>
#include <godot_cpp/variant/utility_functions.hpp> #include <godot_cpp/variant/utility_functions.hpp>
using namespace godot; 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("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("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_array"), &Example::test_array);
ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg); ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray); 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"); GDVIRTUAL_BIND(_do_something_virtual, "name", "value");
ClassDB::bind_method(D_METHOD("test_virtual_implemented_in_script"), &Example::test_virtual_implemented_in_script); ClassDB::bind_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_static", "a", "b"), &Example::test_static);
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2); ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
@ -287,7 +293,17 @@ void Example::_bind_methods() {
BIND_ENUM_CONSTANT(OUTSIDE_OF_CLASS); 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."); //UtilityFunctions::print("Constructor.");
} }
@ -367,6 +383,10 @@ void Example::emit_custom_signal(const String &name, int value) {
emit_signal("custom_signal", name, 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 Example::test_array() const {
Array arr; Array arr;
@ -671,6 +691,10 @@ String Example::test_virtual_implemented_in_script(const String &p_name, int p_v
return "Unimplemented"; return "Unimplemented";
} }
String Example::test_use_engine_singleton() const {
return OS::get_singleton()->get_name();
}
void ExampleRuntime::_bind_methods() { void ExampleRuntime::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_prop_value", "value"), &ExampleRuntime::set_prop_value); 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); ClassDB::bind_method(D_METHOD("get_prop_value"), &ExampleRuntime::get_prop_value);

View File

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

View File

@ -21,15 +21,15 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
return; return;
} }
ClassDB::register_class<ExampleRef>(); GDREGISTER_CLASS(ExampleRef);
ClassDB::register_class<ExampleMin>(); GDREGISTER_CLASS(ExampleMin);
ClassDB::register_class<Example>(); GDREGISTER_CLASS(Example);
ClassDB::register_class<ExampleVirtual>(true); GDREGISTER_VIRTUAL_CLASS(ExampleVirtual);
ClassDB::register_abstract_class<ExampleAbstractBase>(); GDREGISTER_ABSTRACT_CLASS(ExampleAbstractBase);
ClassDB::register_class<ExampleConcrete>(); GDREGISTER_CLASS(ExampleConcrete);
ClassDB::register_class<ExampleBase>(); GDREGISTER_CLASS(ExampleBase);
ClassDB::register_class<ExampleChild>(); GDREGISTER_CLASS(ExampleChild);
ClassDB::register_runtime_class<ExampleRuntime>(); GDREGISTER_RUNTIME_CLASS(ExampleRuntime);
} }
void uninitialize_example_module(ModuleInitializationLevel p_level) { 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 import EnumVariable, PathVariable, BoolVariable
from SCons.Variables.BoolVariable import _text2bool from SCons.Variables.BoolVariable import _text2bool
from SCons.Tool import Tool from SCons.Tool import Tool
from SCons.Action import Action
from SCons.Builder import Builder from SCons.Builder import Builder
from SCons.Errors import UserError from SCons.Errors import UserError
from SCons.Script import ARGUMENTS from SCons.Script import ARGUMENTS
@ -66,6 +67,67 @@ def get_custom_platforms(env):
return platforms 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"] platforms = ["linux", "macos", "windows", "android", "ios", "web"]
# CPU architecture options. # 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 # compiledb
opts.Add( opts.Add(
BoolVariable( BoolVariable(
@ -254,6 +318,7 @@ def options(opts, env):
) )
opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True)) 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("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) # Add platform options (custom tools can override platforms)
for pl in sorted(set(platforms + custom_platforms)): for pl in sorted(set(platforms + custom_platforms)):
@ -262,6 +327,51 @@ def options(opts, env):
tool.options(opts) 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): def generate(env):
# Default num_jobs to local cpu count if not user specified. # Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden # SCons has a peculiarity where user-specified options won't be overridden
@ -330,6 +440,9 @@ def generate(env):
tool.generate(env) tool.generate(env)
if env["threads"]:
env.Append(CPPDEFINES=["THREADS_ENABLED"])
if env.use_hot_reload: if env.use_hot_reload:
env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"]) env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"])
@ -373,6 +486,8 @@ def generate(env):
suffix += "." + env["arch"] suffix += "." + env["arch"]
if env["ios_simulator"]: if env["ios_simulator"]:
suffix += ".simulator" suffix += ".simulator"
if not env["threads"]:
suffix += ".nothreads"
env["suffix"] = suffix # Exposed when included from another project env["suffix"] = suffix # Exposed when included from another project
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"] env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
@ -381,8 +496,17 @@ def generate(env):
env.Tool("compilation_db") env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env))) env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env)))
# Formatting
if not env["verbose"]:
no_verbose(env)
# Builders # 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") env.AddMethod(_godot_cpp, "GodotCPP")

View File

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