diff options
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | binding_generator.py | 223 | ||||
-rw-r--r-- | gdextension/extension_api.json | 5 | ||||
-rw-r--r-- | include/godot_cpp/core/type_info.hpp | 19 | ||||
-rw-r--r-- | include/godot_cpp/templates/safe_refcount.hpp | 2 | ||||
-rw-r--r-- | test/project/main.gd | 6 | ||||
-rw-r--r-- | test/src/example.cpp | 22 | ||||
-rw-r--r-- | test/src/example.h | 3 | ||||
-rw-r--r-- | tools/web.py | 2 |
9 files changed, 203 insertions, 88 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9609061..af62675 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,10 +124,6 @@ else() endif() endif() -if (GODOT_ENABLE_HOT_RELOAD) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D HOT_RELOAD_ENABLED") -endif() - # Generate source from the bindings file find_package(Python3 3.4 REQUIRED) # pathlib should be present if(GENERATE_TEMPLATE_GET_NODE) @@ -170,6 +166,11 @@ target_compile_features(${PROJECT_NAME} cxx_std_17 ) +if(GODOT_ENABLE_HOT_RELOAD) + target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) + target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) +endif() + target_compile_definitions(${PROJECT_NAME} PUBLIC $<$<CONFIG:Debug>: DEBUG_ENABLED diff --git a/binding_generator.py b/binding_generator.py index e7609b2..71afe04 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -542,8 +542,14 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_header.append("") + includes = [] for builtin in builtin_classes: - builtin_header.append(f"#include <godot_cpp/variant/{camel_to_snake(builtin)}.hpp>") + includes.append(f"godot_cpp/variant/{camel_to_snake(builtin)}.hpp") + + includes.sort() + + for include in includes: + builtin_header.append(f"#include <{include}>") builtin_header.append("") @@ -599,11 +605,10 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes): continue result += make_varargs_template( - method, "is_static" in method and method["is_static"], class_name, False, False, True + method, "is_static" in method and method["is_static"], class_name, False, True ) result.append("") - result.append("") result.append(f"#endif // ! {header_guard}") return "\n".join(result) @@ -628,38 +633,53 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl # Special cases. if class_name == "String": + result.append("#include <godot_cpp/classes/global_constants.hpp>") result.append("#include <godot_cpp/variant/char_string.hpp>") result.append("#include <godot_cpp/variant/char_utils.hpp>") - result.append("#include <godot_cpp/classes/global_constants.hpp>") + result.append("") if class_name == "PackedStringArray": result.append("#include <godot_cpp/variant/string.hpp>") + result.append("") if class_name == "PackedColorArray": result.append("#include <godot_cpp/variant/color.hpp>") + result.append("") if class_name == "PackedVector2Array": result.append("#include <godot_cpp/variant/vector2.hpp>") + result.append("") if class_name == "PackedVector3Array": result.append("#include <godot_cpp/variant/vector3.hpp>") + result.append("") if class_name == "PackedVector4Array": result.append("#include <godot_cpp/variant/vector4.hpp>") + result.append("") if is_packed_array(class_name): result.append("#include <godot_cpp/core/error_macros.hpp>") result.append("#include <initializer_list>") + result.append("") if class_name == "Array": result.append("#include <godot_cpp/variant/array_helpers.hpp>") + result.append("") if class_name == "Callable": result.append("#include <godot_cpp/variant/callable_custom.hpp>") - - for include in fully_used_classes: - if include == "TypedArray": - result.append("#include <godot_cpp/variant/typed_array.hpp>") - else: - result.append(f"#include <godot_cpp/{get_include_path(include)}>") + result.append("") if len(fully_used_classes) > 0: + includes = [] + for include in fully_used_classes: + if include == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(include)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + result.append("") result.append("#include <gdextension_interface.h>") @@ -737,7 +757,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("public:") result.append( - f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast<uint8_t (*)[{snake_class_name}_SIZE]>(&opaque); }}" + f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast<uint8_t(*)[{snake_class_name}_SIZE]>(&opaque); }}" ) copy_constructor_index = -1 @@ -852,14 +872,14 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if "operators" in builtin_api: for operator in builtin_api["operators"]: - if operator["name"] not in ["in", "xor"]: + if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'\t{correct_type(operator["return_type"])} operator{operator["name"]}({type_for_parameter(operator["right_type"])}p_other) const;' + f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const;' ) else: result.append( - f'\t{correct_type(operator["return_type"])} operator{operator["name"].replace("unary", "")}() const;' + f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}() const;' ) # Copy assignment. @@ -918,7 +938,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append(f"\tconst {return_type} *ptr() const;") result.append(f"\t{return_type} *ptrw();") iterators = """ - struct Iterator { + struct Iterator { _FORCE_INLINE_ $TYPE &operator*() const { return *elem_ptr; } @@ -980,19 +1000,17 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl } _FORCE_INLINE_ ConstIterator end() const { return ConstIterator(ptr() + size()); - } -""" + }""" result.append(iterators.replace("$TYPE", return_type)) init_list = """ - _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { + _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { ERR_FAIL_COND(resize(p_init.size()) != 0); size_t i = 0; for (const $TYPE &element : p_init) { set(i++, element); } - } -""" + }""" result.append(init_list.replace("$TYPE", return_type).replace("$CLASS", class_name)) if class_name == "Array": @@ -1031,7 +1049,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} // namespace godot") + result.append("") result.append(f"#endif // ! {header_guard}") + result.append("") return "\n".join(result) @@ -1045,7 +1065,6 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl add_header(f"{snake_class_name}.cpp", result) - result.append("") result.append(f"#include <godot_cpp/variant/{snake_class_name}.hpp>") result.append("") result.append("#include <godot_cpp/core/binder_common.hpp>") @@ -1054,10 +1073,16 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") # Only used since the "fully used" is included in header already. - for include in used_classes: - result.append(f"#include <godot_cpp/{get_include_path(include)}>") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("#include <godot_cpp/core/builtin_ptrcall.hpp>") @@ -1291,10 +1316,10 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if "operators" in builtin_api: for operator in builtin_api["operators"]: - if operator["name"] not in ["in", "xor"]: + if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"]}({type_for_parameter(operator["right_type"])}p_other) const {{' + f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const {{' ) (encode, arg_name) = get_encoded_arg("other", operator["right_type"], None) result += encode @@ -1304,10 +1329,10 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("}") else: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"].replace("unary", "")}() const {{' + f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}() const {{' ) result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr)nullptr);' + f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);' ) result.append("}") result.append("") @@ -1343,6 +1368,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} //namespace godot") + result.append("") return "\n".join(result) @@ -1518,11 +1544,18 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): result.append("") - for included in used_classes: - result.append(f"#include <godot_cpp/{get_include_path(included)}>") + if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() - if len(used_classes) == 0: + for include in includes: + result.append(f"#include <{include}>") + else: result.append("#include <godot_cpp/core/method_ptrcall.hpp>") + result.append("") result.append("namespace godot {") @@ -1562,16 +1595,23 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") - for included in fully_used_classes: - if included == "TypedArray": - result.append("#include <godot_cpp/variant/typed_array.hpp>") - else: - result.append(f"#include <godot_cpp/{get_include_path(included)}>") + if len(fully_used_classes) > 0: + includes = [] + for included in fully_used_classes: + if included == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + + result.append("") if class_name == "EditorPlugin": result.append("#include <godot_cpp/classes/editor_plugin_registration.hpp>") - - if len(fully_used_classes) > 0: result.append("") if class_name != "Object" and class_name != "ClassDBSingleton": @@ -1610,7 +1650,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") result.append("public:") - result.append("") if "enums" in class_api: for enum_api in class_api["enums"]: @@ -1643,6 +1682,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us vararg = "is_vararg" in method and method["is_vararg"] + if vararg: + result.append("") + result.append("private:") + method_signature = "\t" method_signature += make_signature( class_name, method, for_header=True, use_template_get_node=use_template_get_node @@ -1650,6 +1693,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_signature + ";") if vararg: + result.append("") + result.append("public:") # Add templated version. result += make_varargs_template(method) @@ -1664,6 +1709,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) result.append(method_signature + ";") + result.append("") + result.append("protected:") # T is the custom class we want to register (from which the call initiates, going up the inheritance chain), # B is its base class (can be a custom class too, that's why we pass it). @@ -1680,7 +1727,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us # If the method is different from the base class, it means T overrides it, so it needs to be bound. # Note that with an `if constexpr`, the code inside the `if` will not even be compiled if the # condition returns false (in such cases it can't compile due to ambiguity). - f"\t\tif constexpr (!std::is_same_v<decltype(&B::{method_name}),decltype(&T::{method_name})>) {{" + f"\t\tif constexpr (!std::is_same_v<decltype(&B::{method_name}), decltype(&T::{method_name})>) {{" ) result.append(f"\t\t\tBIND_VIRTUAL_METHOD(T, {method_name});") result.append("\t\t}") @@ -1708,7 +1755,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if class_name == "WorkerThreadPool": result.append("\tenum {") - result.append("\tINVALID_TASK_ID = -1") + result.append("\t\tINVALID_TASK_ID = -1") result.append("\t};") result.append("\ttypedef int64_t TaskID;") result.append("\ttypedef int64_t GroupID;") @@ -1720,8 +1767,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) if class_name == "Object": - result.append("") - result.append("\ttemplate <typename T>") result.append("\tstatic T *cast_to(Object *p_object);") @@ -1736,7 +1781,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us "\tT *get_node(const NodePath &p_path) const { return Object::cast_to<T>(get_node_internal(p_path)); }" ) - result.append("") result.append("};") result.append("") @@ -1820,7 +1864,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_body) result.append("\t} \\") - result.append("\t;") + result.append("\t") result.append("") result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\") @@ -1832,10 +1876,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us else: result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') - result.append("\t;") + result.append("\t") result.append("") result.append(f"#endif // ! {header_guard}") + result.append("") return "\n".join(result) @@ -1857,10 +1902,16 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("#include <godot_cpp/core/error_macros.hpp>") result.append("") - for included in used_classes: - result.append(f"#include <godot_cpp/{get_include_path(included)}>") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("namespace godot {") @@ -2010,8 +2061,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature) result.append("") + result.append("} // namespace godot") result.append("") - result.append("} // namespace godot ") return "\n".join(result) @@ -2039,23 +2090,24 @@ def generate_global_constants(api, output_dir): header.append("namespace godot {") header.append("") - for constant in api["global_constants"]: - header.append(f'\tconst int64_t {escape_identifier(constant["name"])} = {constant["value"]};') + if len(api["global_constants"]) > 0: + for constant in api["global_constants"]: + header.append(f'const int64_t {escape_identifier(constant["name"])} = {constant["value"]};') - header.append("") + header.append("") for enum_def in api["global_enums"]: if enum_def["name"].startswith("Variant."): continue if enum_def["is_bitfield"]: - header.append(f'\tenum {enum_def["name"]} : uint64_t {{') + header.append(f'enum {enum_def["name"]} : uint64_t {{') else: - header.append(f'\tenum {enum_def["name"]} {{') + header.append(f'enum {enum_def["name"]} {{') for value in enum_def["values"]: - header.append(f'\t\t{value["name"]} = {value["value"]},') - header.append("\t};") + header.append(f'\t{value["name"]} = {value["value"]},') + header.append("};") header.append("") header.append("} // namespace godot") @@ -2174,11 +2226,17 @@ def generate_utility_functions(api, output_dir): vararg = "is_vararg" in function and function["is_vararg"] + if vararg: + header.append("") + header.append("private:") + function_signature = "\t" function_signature += make_signature("UtilityFunctions", function, for_header=True, static=True) header.append(function_signature + ";") if vararg: + header.append("") + header.append("public:") # Add templated version. header += make_varargs_template(function, static=True) @@ -2199,8 +2257,8 @@ def generate_utility_functions(api, output_dir): source.append("#include <godot_cpp/variant/utility_functions.hpp>") source.append("") - source.append("#include <godot_cpp/core/error_macros.hpp>") source.append("#include <godot_cpp/core/engine_ptrcall.hpp>") + source.append("#include <godot_cpp/core/error_macros.hpp>") source.append("") source.append("namespace godot {") source.append("") @@ -2302,7 +2360,7 @@ def make_function_parameters(parameters, include_default=False, for_builtin=Fals signature.append(parameter) if is_vararg: - signature.append("const Args&... p_args") + signature.append("const Args &...p_args") return ", ".join(signature) @@ -2360,9 +2418,6 @@ def make_signature( if "is_virtual" in function_data and function_data["is_virtual"]: function_signature += "virtual " - if is_vararg: - function_signature += "private: " - if static: function_signature += "static " @@ -2415,7 +2470,6 @@ def make_varargs_template( function_data, static=False, class_befor_signature="", - with_public_declare=True, with_indent=True, for_builtin_classes=False, ): @@ -2423,10 +2477,7 @@ def make_varargs_template( function_signature = "" - if with_public_declare: - function_signature = "public: " - - function_signature += "template <typename... Args> " + result.append("template <typename... Args>") if static: function_signature += "static " @@ -2469,7 +2520,7 @@ def make_varargs_template( function_signature += " {" result.append(function_signature) - 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: if argument["type"] == "Variant": args_array += escape_argument(argument["name"]) @@ -2719,8 +2770,8 @@ def correct_type(type_name, meta=None, use_alias=True): if meta is not None: if "int" in meta: return f"{meta}_t" - elif meta in type_conversion: - return type_conversion[type_name] + elif "char" in meta: + return f"{meta}_t" else: return meta if type_name in type_conversion: @@ -2832,6 +2883,38 @@ def get_operator_id_name(op): return op_id_map[op] +def get_operator_cpp_name(op): + op_cpp_map = { + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "+": "+", + "-": "-", + "*": "*", + "/": "/", + "unary-": "-", + "unary+": "+", + "%": "%", + "<<": "<<", + ">>": ">>", + "&": "&", + "|": "|", + "^": "^", + "~": "~", + "and": "&&", + "or": "||", + "not": "!", + } + return op_cpp_map[op] + + +def is_valid_cpp_operator(op): + return op not in ["**", "xor", "in"] + + def get_default_value_for_type(type_name): if type_name == "int": return "0" diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json index c9c7e92..10c2f34 100644 --- a/gdextension/extension_api.json +++ b/gdextension/extension_api.json @@ -3,9 +3,9 @@ "version_major": 4, "version_minor": 3, "version_patch": 0, - "version_status": "rc3", + "version_status": "stable", "version_build": "official", - "version_full_name": "Godot Engine v4.3.rc3.official" + "version_full_name": "Godot Engine v4.3.stable.official" }, "builtin_class_sizes": [ { @@ -29907,7 +29907,6 @@ { "type": "bool", "name": "capture_included", - "setter": "_set_capture_included", "getter": "is_capture_included" } ] diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index f368988..b78f7e7 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -397,16 +397,17 @@ MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE) MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL) MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY) MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) +MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY) /* -MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) -MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY) MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING) */ diff --git a/include/godot_cpp/templates/safe_refcount.hpp b/include/godot_cpp/templates/safe_refcount.hpp index 12e6840..98cb04b 100644 --- a/include/godot_cpp/templates/safe_refcount.hpp +++ b/include/godot_cpp/templates/safe_refcount.hpp @@ -132,7 +132,7 @@ public: } } - _ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) { + _ALWAYS_INLINE_ explicit SafeNumeric(T p_value = static_cast<T>(0)) { set(p_value); } }; diff --git a/test/project/main.gd b/test/project/main.gd index dadd4de..b2625b9 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -270,6 +270,12 @@ func _ready(): assert_equal(example_child.get_value1(), 11) assert_equal(example_child.get_value2(), 22) + # Test that the extension's library path is absolute and valid. + var library_path = Example.test_library_path() + assert_equal(library_path.begins_with("res://"), false) + assert_equal(library_path, ProjectSettings.globalize_path(library_path)) + assert_equal(FileAccess.file_exists(library_path), true) + exit_with_status() func _on_Example_custom_signal(signal_name, value): diff --git a/test/src/example.cpp b/test/src/example.cpp index a941889..8075f55 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -204,6 +204,7 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility); ClassDB::bind_method(D_METHOD("test_string_is_forty_two"), &Example::test_string_is_forty_two); ClassDB::bind_method(D_METHOD("test_string_resize"), &Example::test_string_resize); + ClassDB::bind_method(D_METHOD("test_typed_array_of_packed"), &Example::test_typed_array_of_packed); ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops); ClassDB::bind_method(D_METHOD("test_vector_init_list"), &Example::test_vector_init_list); @@ -248,6 +249,8 @@ void Example::_bind_methods() { 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_library_path"), &Example::test_library_path); + { MethodInfo mi; mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument")); @@ -424,6 +427,19 @@ String Example::test_string_resize(String p_string) const { return p_string; } +TypedArray<PackedInt32Array> Example::test_typed_array_of_packed() const { + TypedArray<PackedInt32Array> arr; + PackedInt32Array packed_arr1; + packed_arr1.push_back(1); + packed_arr1.push_back(2); + arr.push_back(packed_arr1); + PackedInt32Array packed_arr2; + packed_arr2.push_back(3); + packed_arr2.push_back(4); + arr.push_back(packed_arr2); + return arr; +} + int Example::test_vector_ops() const { PackedInt32Array arr; arr.push_back(10); @@ -695,6 +711,12 @@ String Example::test_use_engine_singleton() const { return OS::get_singleton()->get_name(); } +String Example::test_library_path() { + String library_path; + internal::gdextension_interface_get_library_path(internal::library, library_path._native_ptr()); + return library_path; +} + void ExampleRuntime::_bind_methods() { ClassDB::bind_method(D_METHOD("set_prop_value", "value"), &ExampleRuntime::set_prop_value); ClassDB::bind_method(D_METHOD("get_prop_value"), &ExampleRuntime::get_prop_value); diff --git a/test/src/example.h b/test/src/example.h index 7f3dfaa..6d88cf1 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -134,6 +134,7 @@ public: String test_str_utility() const; bool test_string_is_forty_two(const String &p_str) const; String test_string_resize(String p_original) const; + TypedArray<PackedInt32Array> test_typed_array_of_packed() const; int test_vector_ops() const; int test_vector_init_list() const; @@ -194,6 +195,8 @@ public: GDVIRTUAL1(_do_something_virtual_with_control, Control *); String test_use_engine_singleton() const; + + static String test_library_path(); }; VARIANT_ENUM_CAST(Example::Constants); diff --git a/tools/web.py b/tools/web.py index dea42b2..c8f07c5 100644 --- a/tools/web.py +++ b/tools/web.py @@ -39,7 +39,7 @@ def generate(env): env.Append(LINKFLAGS=["-sUSE_PTHREADS=1"]) # Build as side module (shared library). - env.Append(CPPFLAGS=["-sSIDE_MODULE=1"]) + env.Append(CCFLAGS=["-sSIDE_MODULE=1"]) env.Append(LINKFLAGS=["-sSIDE_MODULE=1"]) # Force wasm longjmp mode. |