From e8b6887b3679a6e817834f7eb057aeca425dda55 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews <repiteo@outlook.com> Date: Sat, 4 Nov 2023 16:53:09 -0500 Subject: [PATCH 01/36] =?UTF-8?q?Add=20missing=20int=E2=86=92Variant=20con?= =?UTF-8?q?versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit bcac96c8c272d9d4c60fb781974e80db1cb19527) --- include/godot_cpp/variant/variant.hpp | 14 +++++++++++++- src/variant/variant.cpp | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 0a2b3d140..575c224ec 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -154,10 +154,18 @@ class Variant { Variant(int64_t v); Variant(int32_t v) : Variant(static_cast<int64_t>(v)) {} - Variant(uint32_t v) : + Variant(int16_t v) : + Variant(static_cast<int64_t>(v)) {} + Variant(int8_t v) : Variant(static_cast<int64_t>(v)) {} Variant(uint64_t v) : Variant(static_cast<int64_t>(v)) {} + Variant(uint32_t v) : + Variant(static_cast<int64_t>(v)) {} + Variant(uint16_t v) : + Variant(static_cast<int64_t>(v)) {} + Variant(uint8_t v) : + Variant(static_cast<int64_t>(v)) {} Variant(double v); Variant(float v) : Variant((double)v) {} @@ -209,8 +217,12 @@ class Variant { operator bool() const; operator int64_t() const; operator int32_t() const; + operator int16_t() const; + operator int8_t() const; operator uint64_t() const; operator uint32_t() const; + operator uint16_t() const; + operator uint8_t() const; operator double() const; operator float() const; operator String() const; diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index db15be119..945d6f406 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -268,6 +268,14 @@ Variant::operator int32_t() const { return static_cast<int32_t>(operator int64_t()); } +Variant::operator int16_t() const { + return static_cast<int16_t>(operator int64_t()); +} + +Variant::operator int8_t() const { + return static_cast<int8_t>(operator int64_t()); +} + Variant::operator uint64_t() const { return static_cast<uint64_t>(operator int64_t()); } @@ -276,6 +284,14 @@ Variant::operator uint32_t() const { return static_cast<uint32_t>(operator int64_t()); } +Variant::operator uint16_t() const { + return static_cast<uint16_t>(operator int64_t()); +} + +Variant::operator uint8_t() const { + return static_cast<uint8_t>(operator int64_t()); +} + Variant::operator double() const { double result; to_type_constructor[FLOAT](&result, _native_ptr()); From 92449b46e1a27e7dd197dc1854daaad560cc8b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= <rverschelde@gmail.com> Date: Mon, 20 Nov 2023 23:23:17 +0100 Subject: [PATCH 02/36] CI: Install Android NDK r23c explicitly It has just been removed from the Ubuntu 20.04 default install, breaking our CI setup. Also, sets Emscripten version to 3.1.39, as done upstream. Newer versions actually break dynamic library support. (cherry picked from commit eea33b413361ef023cddfaa03d9f5acb60538006) --- .github/workflows/ci.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ee04d908..c9560e9c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: platform: android artifact-name: godot-cpp-android-arm64-release artifact-path: bin/libgodot-cpp.android.template_release.arm64.a - flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64 + flags: arch=arm64 run-tests: false cache-name: android-arm64 @@ -88,7 +88,7 @@ jobs: env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ - EM_VERSION: 3.1.45 + EM_VERSION: 3.1.39 EM_CACHE_FOLDER: "emsdk-cache" steps: @@ -108,11 +108,12 @@ jobs: with: python-version: '3.x' - - name: Linux dependencies - if: ${{ matrix.platform == 'linux' }} - run: | - sudo apt-get update -qq - sudo apt-get install -qqq build-essential pkg-config + - name: Android dependencies + if: ${{ matrix.platform == 'android' }} + uses: nttld/setup-ndk@v1 + with: + ndk-version: r23c + link-to-sdk: true - name: Web dependencies if: ${{ matrix.platform == 'web' }} @@ -121,16 +122,16 @@ jobs: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} - - name: Install scons - run: | - python -m pip install scons==4.0.0 - - name: Setup MinGW for Windows/MinGW build if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }} uses: egor-tensin/setup-mingw@v2 with: version: 12.2.0 + - name: Install scons + run: | + python -m pip install scons==4.0.0 + - name: Generate godot-cpp sources only run: | scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }} From b622b11df3bc6ee96f9a99e74ae38f96889d91b3 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 22 Nov 2023 14:14:41 +0200 Subject: [PATCH 03/36] [iOS] Fix initialisation/termination of multiple statically linked extensions. (cherry picked from commit adc9def046b1f871d58163adc959e78db131324a) --- include/godot_cpp/godot.hpp | 32 ++++++++++--- src/godot.cpp | 90 ++++++++++++++++++++++++++++--------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 1478403b2..0b7dd4a83 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -187,26 +187,44 @@ enum ModuleInitializationLevel { MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE, MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS, MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE, - MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR + MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR, + MODULE_INITIALIZATION_LEVEL_MAX }; class GDExtensionBinding { public: using Callback = void (*)(ModuleInitializationLevel p_level); - static Callback init_callback; - static Callback terminate_callback; - static GDExtensionInitializationLevel minimum_initialization_level; - static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); + struct InitData { + GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; + Callback init_callback = nullptr; + Callback terminate_callback = nullptr; + }; + + class InitDataList { + int data_count = 0; + int data_capacity = 0; + InitData **data = nullptr; + + public: + void add(InitData *p_cb); + ~InitDataList(); + }; + + static bool api_initialized; + static int level_initialized[MODULE_INITIALIZATION_LEVEL_MAX]; + static InitDataList initdata; + static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization); public: - static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level); - static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level); + static void initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level); + static void deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level); class InitObject { GDExtensionInterfaceGetProcAddress get_proc_address; GDExtensionClassLibraryPtr library; GDExtensionInitialization *initialization; + mutable InitData *init_data = nullptr; public: InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); diff --git a/src/godot.cpp b/src/godot.cpp index 14214c0d2..b40049f9c 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -189,9 +189,9 @@ GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugi } // namespace internal -GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr; -GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr; -GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; +bool GDExtensionBinding::api_initialized = false; +int GDExtensionBinding::level_initialized[MODULE_INITIALIZATION_LEVEL_MAX] = { 0 }; +GDExtensionBinding::InitDataList GDExtensionBinding::initdata; #define ERR_PRINT_EARLY(m_msg) \ internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false) @@ -218,7 +218,20 @@ typedef struct { GDExtensionInterfacePrintErrorWithMessage print_error_with_message; } LegacyGDExtensionInterface; -GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { +GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, InitData *p_init_data, GDExtensionInitialization *r_initialization) { + if (!p_init_data || !p_init_data->init_callback) { + ERR_FAIL_V_MSG(false, "Initialization callback must be defined."); + } + + if (api_initialized) { + r_initialization->initialize = initialize_level; + r_initialization->deinitialize = deinitialize_level; + r_initialization->userdata = p_init_data; + r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level; + + return true; + } + // Make sure we weren't passed the legacy struct. uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address; if (raw_interface[0] == 4 && raw_interface[1] == 0) { @@ -401,59 +414,96 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge r_initialization->initialize = initialize_level; r_initialization->deinitialize = deinitialize_level; - r_initialization->minimum_initialization_level = minimum_initialization_level; - - ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); + r_initialization->userdata = p_init_data; + r_initialization->minimum_initialization_level = p_init_data->minimum_initialization_level; Variant::init_bindings(); godot::internal::register_engine_classes(); + api_initialized = true; return true; } #undef LOAD_PROC_ADDRESS #undef ERR_PRINT_EARLY -void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) { +void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) { + ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (init_callback) { - init_callback(static_cast<ModuleInitializationLevel>(p_level)); + InitData *init_data = static_cast<InitData *>(p_userdata); + if (init_data && init_data->init_callback) { + init_data->init_callback(static_cast<ModuleInitializationLevel>(p_level)); } - ClassDB::initialize(p_level); + if (level_initialized[p_level] == 0) { + ClassDB::initialize(p_level); + } + level_initialized[p_level]++; } -void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) { +void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) { + ERR_FAIL_COND(static_cast<ModuleInitializationLevel>(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (terminate_callback) { - terminate_callback(static_cast<ModuleInitializationLevel>(p_level)); + InitData *init_data = static_cast<InitData *>(p_userdata); + if (init_data && init_data->terminate_callback) { + init_data->terminate_callback(static_cast<ModuleInitializationLevel>(p_level)); + } + + level_initialized[p_level]--; + if (level_initialized[p_level] == 0) { + EditorPlugins::deinitialize(p_level); + ClassDB::deinitialize(p_level); + } +} + +void GDExtensionBinding::InitDataList::add(InitData *p_data) { + if (data_count == data_capacity) { + void *new_ptr = realloc(data, sizeof(InitData *) * (data_capacity + 32)); + if (new_ptr) { + data = (InitData **)(new_ptr); + data_capacity += 32; + } else { + ERR_FAIL_MSG("Unable to allocate memory for extension callbacks."); + } } + data[data_count++] = p_data; +} - EditorPlugins::deinitialize(p_level); - ClassDB::deinitialize(p_level); +GDExtensionBinding::InitDataList::~InitDataList() { + for (int i = 0; i < data_count; i++) { + if (data[i]) { + delete data[i]; + } + } + if (data) { + free(data); + } } + GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { get_proc_address = p_get_proc_address; library = p_library; initialization = r_initialization; + init_data = new InitData(); + GDExtensionBinding::initdata.add(init_data); } void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const { - GDExtensionBinding::init_callback = p_init; + init_data->init_callback = p_init; } void GDExtensionBinding::InitObject::register_terminator(Callback p_terminate) const { - GDExtensionBinding::terminate_callback = p_terminate; + init_data->terminate_callback = p_terminate; } void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const { - GDExtensionBinding::minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level); + init_data->minimum_initialization_level = static_cast<GDExtensionInitializationLevel>(p_level); } GDExtensionBool GDExtensionBinding::InitObject::init() const { - return GDExtensionBinding::init(get_proc_address, library, initialization); + return GDExtensionBinding::init(get_proc_address, library, init_data, initialization); } } // namespace godot From cd904155a86fc2a76286b88e3a6ee12149be0ebe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 19:10:15 +0000 Subject: [PATCH 04/36] Bump mymindstorm/setup-emsdk from 12 to 13 Bumps [mymindstorm/setup-emsdk](https://github.com/mymindstorm/setup-emsdk) from 12 to 13. - [Release notes](https://github.com/mymindstorm/setup-emsdk/releases) - [Commits](https://github.com/mymindstorm/setup-emsdk/compare/v12...v13) --- updated-dependencies: - dependency-name: mymindstorm/setup-emsdk dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> (cherry picked from commit 78bf5a42edae13abcce2c413a3000085c545a11f) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9560e9c3..4bb1af34d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,7 +117,7 @@ jobs: - name: Web dependencies if: ${{ matrix.platform == 'web' }} - uses: mymindstorm/setup-emsdk@v12 + uses: mymindstorm/setup-emsdk@v13 with: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} From 51aeda7437ee3dd991daca1413998aab1fa416e2 Mon Sep 17 00:00:00 2001 From: DmitriySalnikov <salnikov.mine@yandex.ru> Date: Thu, 23 Nov 2023 00:08:13 +0300 Subject: [PATCH 05/36] [Scons] Set the minimum Android API level to 21 (cherry picked from commit 79d2a9c4563cb768f508cc3f791c66c7cc57d379) --- tools/android.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/android.py b/tools/android.py index 0e6885515..95efa679d 100644 --- a/tools/android.py +++ b/tools/android.py @@ -8,7 +8,7 @@ def options(opts): opts.Add( "android_api_level", "Target Android API level", - "18" if "32" in ARGUMENTS.get("arch", "arm64") else "21", + "21", ) opts.Add( "ANDROID_NDK_ROOT", @@ -35,11 +35,9 @@ def generate(env): my_spawn.configure(env) # Validate API level - api_level = int(env["android_api_level"]) - if "64" in env["arch"] and api_level < 21: - print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21") + if int(env["android_api_level"]) < 21: + print("WARNING: minimum supported Android target api is 21. Forcing target api 21.") env["android_api_level"] = "21" - api_level = 21 # Setup toolchain toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/" From 6bb4b1d3218f141a77245b673434b32d84da76b9 Mon Sep 17 00:00:00 2001 From: Bytzo <bytzo@bytzo.net> Date: Wed, 25 Oct 2023 23:57:13 -0700 Subject: [PATCH 06/36] Prevent CMake from always including debug symbols (cherry picked from commit db884e9b1d91300da91d1e82be2effda270401ec) --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c413cecc9..bf09ba3bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,10 +99,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-DNOMINMAX) else() # GCC/Clang - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -g") - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g") else() set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") endif(CMAKE_BUILD_TYPE MATCHES Debug) From d5a2e8e7975bc738312c11c2ea2ead133473c1a1 Mon Sep 17 00:00:00 2001 From: LAK132 <lakridesagain@gmail.com> Date: Sat, 11 Nov 2023 23:29:33 +1030 Subject: [PATCH 07/36] Fix file list issues when trying to build with meson via cmake (cherry picked from commit 39c139c8143d3dfb1595ea812f1cf0c08ef9b4fe) --- CMakeLists.txt | 1 + binding_generator.py | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf09ba3bf..1076e8f20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ endif() execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GENERATED_FILES_LIST + OUTPUT_STRIP_TRAILING_WHITESPACE ) add_custom_command(OUTPUT ${GENERATED_FILES_LIST} diff --git a/binding_generator.py b/binding_generator.py index 18db9fd0d..d11d4bbad 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -135,9 +135,7 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False): def print_file_list(api_filepath, output_dir, headers=False, sources=False): - end = ";" - for f in get_file_list(api_filepath, output_dir, headers, sources): - print(f, end=end) + print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None) def scons_emit_files(target, source, env): From b1bd58d7da56166a4982c9bc4916966d00ed5d9b Mon Sep 17 00:00:00 2001 From: David Snopek <dsnopek@gmail.com> Date: Wed, 29 Nov 2023 11:50:48 -0600 Subject: [PATCH 08/36] Send NOTIFICATION_POSTINITIALIZE to extension classes (cherry picked from commit 20c4e843b09b7263078c23ec635198feae03c227) --- src/classes/wrapped.cpp | 6 ++++++ test/project/main.gd | 5 +++++ test/src/example.cpp | 15 +++++++++++++++ test/src/example.h | 7 +++++++ 4 files changed, 33 insertions(+) diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index 2c5e1b607..8a2092c1e 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -50,6 +50,12 @@ void Wrapped::_postinitialize() { godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this); } godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks()); + if (extension_class) { + Object *obj = dynamic_cast<Object *>(this); + if (obj) { + obj->notification(Object::NOTIFICATION_POSTINITIALIZE); + } + } } Wrapped::Wrapped(const StringName p_godot_class) { diff --git a/test/project/main.gd b/test/project/main.gd index eb8dbb9de..e0b186bb2 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -169,6 +169,11 @@ func _ready(): get_viewport().push_input(event) assert_equal(custom_signal_emitted, ["_input: H", 72]) + # Check NOTIFICATION_POST_INITIALIZED, both when created from GDScript and godot-cpp. + var new_example_ref = ExampleRef.new() + assert_equal(new_example_ref.was_post_initialized(), true) + assert_equal(example.test_post_initialize(), 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 475eed2bc..848f50352 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -23,10 +23,18 @@ int ExampleRef::get_id() const { return id; } +void ExampleRef::_notification(int p_what) { + if (p_what == NOTIFICATION_POSTINITIALIZE) { + post_initialized = true; + } +} + void ExampleRef::_bind_methods() { ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id); ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id); + ClassDB::bind_method(D_METHOD("was_post_initialized"), &ExampleRef::was_post_initialized); + ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id"); } @@ -161,6 +169,7 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("return_last_rpc_arg"), &Example::return_last_rpc_arg); ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200)); + ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize); 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); @@ -426,6 +435,12 @@ Vector4 Example::get_v4() const { return Vector4(1.2, 3.4, 5.6, 7.8); } +bool Example::test_post_initialize() const { + Ref<ExampleRef> new_example_ref; + new_example_ref.instantiate(); + return new_example_ref->was_post_initialized(); +} + // Virtual function override. bool Example::_has_point(const Vector2 &point) const { Label *label = get_node<Label>("Label"); diff --git a/test/src/example.h b/test/src/example.h index cab7d22f6..d0130765b 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -35,16 +35,21 @@ class ExampleRef : public RefCounted { static int last_id; int id; + bool post_initialized = false; protected: static void _bind_methods(); + void _notification(int p_what); + public: ExampleRef(); ~ExampleRef(); void set_id(int p_id); int get_id() const; + + bool was_post_initialized() const { return post_initialized; } }; class ExampleMin : public Control { @@ -148,6 +153,8 @@ class Example : public Control { Vector2 get_custom_position() const; Vector4 get_v4() const; + bool test_post_initialize() const; + // Static method. static int test_static(int p_a, int p_b); static void test_static2(); From e9273e85281d534e59359ee3ca40f080d74466af Mon Sep 17 00:00:00 2001 From: David Snopek <dsnopek@gmail.com> Date: Thu, 30 Nov 2023 15:20:08 -0600 Subject: [PATCH 09/36] Avoid error from -Werror=type-limits on GCC 11 (cherry picked from commit cad5be53b1dd81416d644ef5002c85951f07adcc) --- src/godot.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/godot.cpp b/src/godot.cpp index b40049f9c..1621b2052 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -264,7 +264,12 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge } else if (internal::godot_version.minor != GODOT_VERSION_MINOR) { compatible = internal::godot_version.minor > GODOT_VERSION_MINOR; } else { +#if GODOT_VERSION_PATCH > 0 compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH; +#else + // Prevent -Wtype-limits warning due to unsigned comparison. + compatible = true; +#endif } if (!compatible) { // We need to use snprintf() here because vformat() uses Variant, and we haven't loaded From 2e42c7020e6c67ea55edee384710332c0d442a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= <rverschelde@gmail.com> Date: Fri, 1 Dec 2023 10:45:02 +0100 Subject: [PATCH 10/36] CMake: Remove hardcoded warnings list and forcing -Werror on library builds The CMake buildsystem should be completely reviewed to properly match what is done by SCons, instead of making its own arbitrary decisions on how godot-cpp should be compiled. Currently the SCons setup doesn't include warning options, so CMake shouldn't either. Options similar to upstream Godot's SCons setup could be added, and then replicated for CMake. (cherry picked from commit 41517eacb1115e5020af8c305492f6c77ffa89bc) --- CMakeLists.txt | 11 ----------- test/CMakeLists.txt | 22 ---------------------- 2 files changed, 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1076e8f20..a9603ab6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,11 +47,6 @@ option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF) # Add path to modules list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) -# Check if we are building ourself or being included -if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) - set(GODOT_CPP_BUILDING_SELF ON) -endif() - # Set some helper variables for readability set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" ) set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" ) @@ -158,12 +153,6 @@ add_library(godot::cpp ALIAS ${PROJECT_NAME}) include(GodotCompilerWarnings) -# Treat warnings as errors if we are building ourself -if(GODOT_CPP_BUILDING_SELF) - unset( GODOT_CPP_WARNING_AS_ERROR CACHE ) - set_warning_as_error() -endif() - target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9d692e6a6..a17b9aacd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -59,31 +59,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") else() -#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - # using Clang -#elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # using GCC and maybe MinGW? - set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'") - # Hmm.. maybe to strikt? set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wchar-subscripts -Wcomment -Wdisabled-optimization") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wformat -Wformat=2 -Wformat-security -Wformat-y2k") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wimport -Winit-self -Winline -Winvalid-pch -Werror") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-braces -Wmissing-format-attribute") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wpointer-arith") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wredundant-decls -Wreturn-type -Wsequence-point") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wswitch -Wswitch-enum -Wtrigraphs") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused-label") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wunused-value -Wvariadic-macros -Wvolatile-register-var -Wno-error=attributes") - - # -Wshadow -Wextra -Wall -Weffc++ -Wfloat-equal -Wstack-protector -Wunused-parameter -Wsign-compare -Wunused-variable -Wcast-align - # -Wunused-function -Wstrict-aliasing -Wstrict-aliasing=2 -Wmissing-field-initializers - - if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -Wno-ignored-attributes") - endif() if(CMAKE_BUILD_TYPE MATCHES Debug) set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0") From 756190705e8a233149e513b207ef2381ab2132ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 19:33:16 +0000 Subject: [PATCH 11/36] Bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> (cherry picked from commit a7becb43e6e560e0679416d7c2abb7ae8194a539) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4bb1af34d..ada01e93b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: continue-on-error: true - name: Set up Python (for SCons) - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' From 49098fbdc71ffe8e3293ee57cdf401e2b06c6c03 Mon Sep 17 00:00:00 2001 From: Aaron Franke <arnfranke@yahoo.com> Date: Sun, 17 Dec 2023 11:45:31 -0600 Subject: [PATCH 12/36] Allow detecting when building as a GDExtension (cherry picked from commit e17c7bf53060c7f1d34246af68b1d103dd8c01f7) --- tools/godotcpp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 925b214d0..4ab18cd3c 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -267,6 +267,9 @@ def generate(env): if env["precision"] == "double": env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"]) + # Allow detecting when building as a GDExtension. + env.Append(CPPDEFINES=["GDEXTENSION"]) + # Suffix suffix = ".{}.{}".format(env["platform"], env["target"]) if env.dev_build: From 82475b215b40f0831a9a3be882a6bce7a6d9d73f Mon Sep 17 00:00:00 2001 From: ArchLinus <archlinus123@gmail.com> Date: Fri, 29 Dec 2023 09:32:14 -0500 Subject: [PATCH 13/36] Add an error message if android NDK is not installed (cherry picked from commit 718d0baea3e310391c6feb5b61b8e2dda6a08533) --- tools/android.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/android.py b/tools/android.py index 95efa679d..f9bfe2b41 100644 --- a/tools/android.py +++ b/tools/android.py @@ -52,6 +52,12 @@ def generate(env): elif sys.platform == "darwin": toolchain += "darwin-x86_64" env.Append(LINKFLAGS=["-shared"]) + + if not os.path.exists(toolchain): + print("ERROR: Could not find NDK toolchain at " + toolchain + ".") + print("Make sure NDK version " + get_ndk_version() + " is installed.") + env.Exit(1) + env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways # Get architecture info From 1c03aa774665d101ee708a6941225d67346ebea4 Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:54:57 +0100 Subject: [PATCH 14/36] Add missing `OP_POWER` operator to `Variant` (cherry picked from commit f037a697eb2ce45d63840dfe87c48212d7cbf09e) --- binding_generator.py | 1 + include/godot_cpp/variant/variant.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/binding_generator.py b/binding_generator.py index d11d4bbad..79b54136a 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -2334,6 +2334,7 @@ def get_operator_id_name(op): "unary-": "negate", "unary+": "positive", "%": "module", + "**": "power", "<<": "shift_left", ">>": "shift_right", "&": "bit_and", diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 575c224ec..7b82d5eb3 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -122,6 +122,7 @@ class Variant { OP_NEGATE, OP_POSITIVE, OP_MODULE, + OP_POWER, // bitwise OP_SHIFT_LEFT, OP_SHIFT_RIGHT, From dde0bbb93d33ebf7b8550da93ce5773d76b30053 Mon Sep 17 00:00:00 2001 From: Daylily-Zeleen <daylily-zeleen@foxmail.com> Date: Sun, 7 Jan 2024 15:24:02 +0800 Subject: [PATCH 15/36] Remove "godot" namespace when binding global constants. (cherry picked from commit bd40a94424ca91bc2d2bc76f2a02ac7f8bd5d3cf) --- binding_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 79b54136a..aa77a5cb0 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -1716,9 +1716,9 @@ def generate_global_constant_binds(api, output_dir): continue if enum_def["is_bitfield"]: - header.append(f'VARIANT_BITFIELD_CAST(godot::{enum_def["name"]});') + header.append(f'VARIANT_BITFIELD_CAST({enum_def["name"]});') else: - header.append(f'VARIANT_ENUM_CAST(godot::{enum_def["name"]});') + header.append(f'VARIANT_ENUM_CAST({enum_def["name"]});') # Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file. header.append(f"VARIANT_ENUM_CAST(godot::Variant::Type);") From 6884ca9be0ed9c50bc1b46e5c68d963aecb2a9eb Mon Sep 17 00:00:00 2001 From: nightblade9 <nightbladecodes@gmail.com> Date: Sun, 7 Jan 2024 18:53:34 -0500 Subject: [PATCH 16/36] Update README.md with basic pre-requisites (cherry picked from commit ee169b201bc4461accfe31668f7795bf317fbae2) --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c36e89252..e86c7c488 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,10 @@ so formatting is done before your changes are submitted. ## Getting started -It's a bit similar to what it was for 3.x but also a bit different. +You need the same C++ pre-requisites installed that are required for the `godot` repository. Follow the [official build instructions for your target platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/index.html#building-for-target-platforms). + +Getting started with GDExtensions is a bit similar to what it was for 3.x but also a bit different. + This new approach is much more akin to how core Godot modules are structured. Compiling this repository generates a static library to be linked with your shared lib, From 2cc967787a8e7ed2c6adc495d1f4cbdff902d958 Mon Sep 17 00:00:00 2001 From: MJacred <loesch.benny92@gmx.de> Date: Mon, 22 Jan 2024 10:50:27 +0100 Subject: [PATCH 17/36] Update README: fix godot-cpp issue tracker url (cherry picked from commit 8a535d0ecc473e9c8221342363bb295c11ba6bd5) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e86c7c488..b11628408 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ first-party `godot-cpp` extension. Some compatibility breakage is to be expected as GDExtension and `godot-cpp` get more used, documented, and critical issues get resolved. See the [Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension) -and the [godot-cpp issue tracker](https://github.com/godotengine/godot/issues) +and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues) for a list of known issues, and be sure to provide feedback on issues and PRs which affect your use of this extension. From 6202bf141e163eb82fba2e8932c65943ff93749c Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:30:24 +0200 Subject: [PATCH 18/36] Switch to 64-bit ints. (cherry picked from commit 59a5a8b104e3fcf63c13732ffbb12d8c577a26ce) --- binding_generator.py | 22 +- include/godot_cpp/templates/cowdata.hpp | 205 +++++++++++------- include/godot_cpp/templates/safe_refcount.hpp | 9 + include/godot_cpp/templates/vector.hpp | 91 ++++---- include/godot_cpp/variant/char_string.hpp | 18 +- src/variant/char_string.cpp | 34 +-- src/variant/packed_arrays.cpp | 40 ++-- 7 files changed, 251 insertions(+), 168 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index aa77a5cb0..98d117273 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -541,10 +541,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl # Special cases. if class_name == "String": - result.append("\tstatic String utf8(const char *from, int len = -1);") - result.append("\tvoid parse_utf8(const char *from, int len = -1);") - result.append("\tstatic String utf16(const char16_t *from, int len = -1);") - result.append("\tvoid parse_utf16(const char16_t *from, int 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("\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("\tCharString utf8() const;") result.append("\tCharString ascii() const;") result.append("\tChar16String utf16() const;") @@ -603,8 +603,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("\tString &operator+=(const wchar_t *p_str);") result.append("\tString &operator+=(const char32_t *p_str);") - result.append("\tconst char32_t &operator[](int p_index) const;") - result.append("\tchar32_t &operator[](int p_index);") + result.append("\tconst char32_t &operator[](int64_t p_index) const;") + result.append("\tchar32_t &operator[](int64_t p_index);") result.append("\tconst char32_t *ptr() const;") result.append("\tchar32_t *ptrw();") @@ -622,8 +622,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl return_type = "int32_t" elif class_name == "PackedFloat32Array": return_type = "float" - result.append(f"\tconst {return_type} &operator[](int p_index) const;") - result.append(f"\t{return_type} &operator[](int p_index);") + result.append(f"\tconst {return_type} &operator[](int64_t p_index) const;") + result.append(f"\t{return_type} &operator[](int64_t p_index);") result.append(f"\tconst {return_type} *ptr() const;") result.append(f"\t{return_type} *ptrw();") iterators = """ @@ -694,8 +694,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append(iterators.replace("$TYPE", return_type)) if class_name == "Array": - result.append("\tconst Variant &operator[](int p_index) const;") - result.append("\tVariant &operator[](int p_index);") + result.append("\tconst Variant &operator[](int64_t p_index) const;") + result.append("\tVariant &operator[](int64_t p_index);") result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);") result.append("\tvoid _ref(const Array &p_from) const;") @@ -1638,7 +1638,7 @@ def generate_global_constants(api, output_dir): header.append("") for constant in api["global_constants"]: - header.append(f'\tconst int {escape_identifier(constant["name"])} = {constant["value"]};') + header.append(f'\tconst int64_t {escape_identifier(constant["name"])} = {constant["value"]};') header.append("") diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index 9b36538d0..b6f66d7fa 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -52,6 +52,8 @@ class VMap; template <class T> class CharStringT; +SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint64_t) + // Silence a false positive warning (see GH-52119). #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -69,52 +71,71 @@ class CowData { template <class TS> friend class CharStringT; -private: - mutable T *_ptr = nullptr; +public: + typedef int64_t Size; + typedef uint64_t USize; + static constexpr USize MAX_INT = INT64_MAX; - // internal helpers +private: + // Function to find the next power of 2 to an integer. + static _FORCE_INLINE_ USize next_po2(USize x) { + if (x == 0) { + return 0; + } - _FORCE_INLINE_ SafeNumeric<uint32_t> *_get_refcount() const { - if (!_ptr) { - return nullptr; + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + if (sizeof(USize) == 8) { + x |= x >> 32; } - return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2; + return ++x; } - _FORCE_INLINE_ uint32_t *_get_size() const { + static constexpr USize ALLOC_PAD = sizeof(USize) * 2; // For size and atomic refcount. + + mutable T *_ptr = nullptr; + + // internal helpers + + _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const { if (!_ptr) { return nullptr; } - return reinterpret_cast<uint32_t *>(_ptr) - 1; + return reinterpret_cast<SafeNumeric<USize> *>(_ptr) - 2; } - _FORCE_INLINE_ T *_get_data() const { + _FORCE_INLINE_ USize *_get_size() const { if (!_ptr) { return nullptr; } - return reinterpret_cast<T *>(_ptr); + + return reinterpret_cast<USize *>(_ptr) - 1; } - _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { - return next_power_of_2(p_elements * sizeof(T)); + _FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const { + return next_po2(p_elements * sizeof(T)); } - _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { + _FORCE_INLINE_ bool _get_alloc_size_checked(USize p_elements, USize *out) const { if (unlikely(p_elements == 0)) { *out = 0; return true; } -#if defined(__GNUC__) - size_t o; - size_t p; +#if defined(__GNUC__) && defined(IS_32_BIT) + USize o; + USize p; if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) { *out = 0; return false; } - *out = next_power_of_2(o); - if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) { + *out = next_po2(o); + if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) { return false; // No longer allocated here. } #else @@ -128,22 +149,22 @@ class CowData { void _unref(void *p_data); void _ref(const CowData *p_from); void _ref(const CowData &p_from); - uint32_t _copy_on_write(); + USize _copy_on_write(); public: void operator=(const CowData<T> &p_from) { _ref(p_from); } _FORCE_INLINE_ T *ptrw() { _copy_on_write(); - return (T *)_get_data(); + return _ptr; } _FORCE_INLINE_ const T *ptr() const { - return _get_data(); + return _ptr; } - _FORCE_INLINE_ int size() const { - uint32_t *size = (uint32_t *)_get_size(); + _FORCE_INLINE_ Size size() const { + USize *size = (USize *)_get_size(); if (size) { return *size; } else { @@ -154,41 +175,42 @@ class CowData { _FORCE_INLINE_ void clear() { resize(0); } _FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; } - _FORCE_INLINE_ void set(int p_index, const T &p_elem) { + _FORCE_INLINE_ void set(Size p_index, const T &p_elem) { ERR_FAIL_INDEX(p_index, size()); _copy_on_write(); - _get_data()[p_index] = p_elem; + _ptr[p_index] = p_elem; } - _FORCE_INLINE_ T &get_m(int p_index) { + _FORCE_INLINE_ T &get_m(Size p_index) { CRASH_BAD_INDEX(p_index, size()); _copy_on_write(); - return _get_data()[p_index]; + return _ptr[p_index]; } - _FORCE_INLINE_ const T &get(int p_index) const { + _FORCE_INLINE_ const T &get(Size p_index) const { CRASH_BAD_INDEX(p_index, size()); - return _get_data()[p_index]; + return _ptr[p_index]; } - Error resize(int p_size); + template <bool p_ensure_zero = false> + Error resize(Size p_size); - _FORCE_INLINE_ void remove_at(int p_index) { + _FORCE_INLINE_ void remove_at(Size p_index) { ERR_FAIL_INDEX(p_index, size()); T *p = ptrw(); - int len = size(); - for (int i = p_index; i < len - 1; i++) { + Size len = size(); + for (Size i = p_index; i < len - 1; i++) { p[i] = p[i + 1]; } resize(len - 1); } - Error insert(int p_pos, const T &p_val) { + Error insert(Size p_pos, const T &p_val) { ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER); resize(size() + 1); - for (int i = (size() - 1); i > p_pos; i--) { + for (Size i = (size() - 1); i > p_pos; i--) { set(i, get(i - 1)); } set(p_pos, p_val); @@ -196,11 +218,13 @@ class CowData { return OK; } - int find(const T &p_val, int p_from = 0) const; + Size find(const T &p_val, Size p_from = 0) const; + Size rfind(const T &p_val, Size p_from = -1) const; + Size count(const T &p_val) const; _FORCE_INLINE_ CowData() {} _FORCE_INLINE_ ~CowData(); - _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); } + _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }; }; template <class T> @@ -209,44 +233,45 @@ void CowData<T>::_unref(void *p_data) { return; } - SafeNumeric<uint32_t> *refc = _get_refcount(); + SafeNumeric<USize> *refc = _get_refcount(); if (refc->decrement() > 0) { return; // still in use } - // clean up + if (!std::is_trivially_destructible<T>::value) { - uint32_t *count = _get_size(); + USize *count = _get_size(); T *data = (T *)(count + 1); - for (uint32_t i = 0; i < *count; ++i) { + for (USize i = 0; i < *count; ++i) { // call destructors data[i].~T(); } } // free mem - Memory::free_static((uint8_t *)p_data, true); + Memory::free_static(((uint8_t *)p_data) - ALLOC_PAD, false); } template <class T> -uint32_t CowData<T>::_copy_on_write() { +typename CowData<T>::USize CowData<T>::_copy_on_write() { if (!_ptr) { return 0; } - SafeNumeric<uint32_t> *refc = _get_refcount(); + SafeNumeric<USize> *refc = _get_refcount(); - uint32_t rc = refc->get(); + USize rc = refc->get(); if (unlikely(rc > 1)) { /* in use by more than me */ - uint32_t current_size = *_get_size(); + USize current_size = *_get_size(); - uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true); + USize *mem_new = (USize *)Memory::alloc_static(_get_alloc_size(current_size) + ALLOC_PAD, false); + mem_new += 2; - new (mem_new - 2) SafeNumeric<uint32_t>(1); // refcount - *(mem_new - 1) = current_size; // size + new (mem_new - 2) SafeNumeric<USize>(1); //refcount + *(mem_new - 1) = current_size; //size T *_data = (T *)(mem_new); @@ -255,8 +280,8 @@ uint32_t CowData<T>::_copy_on_write() { memcpy(mem_new, _ptr, current_size * sizeof(T)); } else { - for (uint32_t i = 0; i < current_size; i++) { - memnew_placement(&_data[i], T(_get_data()[i])); + for (USize i = 0; i < current_size; i++) { + memnew_placement(&_data[i], T(_ptr[i])); } } @@ -269,10 +294,11 @@ uint32_t CowData<T>::_copy_on_write() { } template <class T> -Error CowData<T>::resize(int p_size) { +template <bool p_ensure_zero> +Error CowData<T>::resize(Size p_size) { ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); - int current_size = size(); + Size current_size = size(); if (p_size == current_size) { return OK; @@ -286,27 +312,29 @@ Error CowData<T>::resize(int p_size) { } // possibly changing size, copy on write - uint32_t rc = _copy_on_write(); + USize rc = _copy_on_write(); - size_t current_alloc_size = _get_alloc_size(current_size); - size_t alloc_size; + USize current_alloc_size = _get_alloc_size(current_size); + USize alloc_size; ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); if (p_size > current_size) { if (alloc_size != current_alloc_size) { if (current_size == 0) { // alloc from scratch - uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true); + USize *ptr = (USize *)Memory::alloc_static(alloc_size + ALLOC_PAD, false); + ptr += 2; ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY); - *(ptr - 1) = 0; // size, currently none - new (ptr - 2) SafeNumeric<uint32_t>(1); // refcount + *(ptr - 1) = 0; //size, currently none + new (ptr - 2) SafeNumeric<USize>(1); //refcount _ptr = (T *)ptr; } else { - uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true); + USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); - new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount + _ptrnew += 2; + new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount _ptr = (T *)(_ptrnew); } @@ -315,11 +343,11 @@ Error CowData<T>::resize(int p_size) { // construct the newly created elements if (!std::is_trivially_constructible<T>::value) { - T *elems = _get_data(); - - for (int i = *_get_size(); i < p_size; i++) { - memnew_placement(&elems[i], T); + for (Size i = *_get_size(); i < p_size; i++) { + memnew_placement(&_ptr[i], T); } + } else if (p_ensure_zero) { + memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T)); } *_get_size() = p_size; @@ -327,16 +355,17 @@ Error CowData<T>::resize(int p_size) { } else if (p_size < current_size) { if (!std::is_trivially_destructible<T>::value) { // deinitialize no longer needed elements - for (uint32_t i = p_size; i < *_get_size(); i++) { - T *t = &_get_data()[i]; + for (USize i = p_size; i < *_get_size(); i++) { + T *t = &_ptr[i]; t->~T(); } } if (alloc_size != current_alloc_size) { - uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true); + USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); - new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount + _ptrnew += 2; + new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount _ptr = (T *)(_ptrnew); } @@ -348,14 +377,14 @@ Error CowData<T>::resize(int p_size) { } template <class T> -int CowData<T>::find(const T &p_val, int p_from) const { - int ret = -1; +typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const { + Size ret = -1; if (p_from < 0 || size() == 0) { return ret; } - for (int i = p_from; i < size(); i++) { + for (Size i = p_from; i < size(); i++) { if (get(i) == p_val) { ret = i; break; @@ -365,6 +394,36 @@ int CowData<T>::find(const T &p_val, int p_from) const { return ret; } +template <class T> +typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const { + const Size s = size(); + + if (p_from < 0) { + p_from = s + p_from; + } + if (p_from < 0 || p_from >= s) { + p_from = s - 1; + } + + for (Size i = p_from; i >= 0; i--) { + if (get(i) == p_val) { + return i; + } + } + return -1; +} + +template <class T> +typename CowData<T>::Size CowData<T>::count(const T &p_val) const { + Size amount = 0; + for (Size i = 0; i < size(); i++) { + if (get(i) == p_val) { + amount++; + } + } + return amount; +} + template <class T> void CowData<T>::_ref(const CowData *p_from) { _ref(*p_from); diff --git a/include/godot_cpp/templates/safe_refcount.hpp b/include/godot_cpp/templates/safe_refcount.hpp index f86504168..519bbf742 100644 --- a/include/godot_cpp/templates/safe_refcount.hpp +++ b/include/godot_cpp/templates/safe_refcount.hpp @@ -48,6 +48,15 @@ namespace godot { // value and, as an important benefit, you can be sure the value is properly synchronized // even with threads that are already running. +// These are used in very specific areas of the engine where it's critical that these guarantees are held +#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \ + static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \ + static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \ + static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value); +#define SAFE_FLAG_TYPE_PUN_GUARANTEES \ + static_assert(sizeof(SafeFlag) == sizeof(bool)); \ + static_assert(alignof(SafeFlag) == alignof(bool)); + template <class T> class SafeNumeric { std::atomic<T> value; diff --git a/include/godot_cpp/templates/vector.hpp b/include/godot_cpp/templates/vector.hpp index f5626af0d..05b7184c4 100644 --- a/include/godot_cpp/templates/vector.hpp +++ b/include/godot_cpp/templates/vector.hpp @@ -50,7 +50,7 @@ namespace godot { template <class T> class VectorWriteProxy { public: - _FORCE_INLINE_ T &operator[](int p_index) { + _FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) { CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size()); return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index]; @@ -63,22 +63,26 @@ class Vector { public: VectorWriteProxy<T> write; + typedef typename CowData<T>::Size Size; private: CowData<T> _cowdata; public: bool push_back(T p_elem); - _FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } // alias + _FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias void fill(T p_elem); - void remove_at(int p_index) { _cowdata.remove_at(p_index); } - void erase(const T &p_val) { - int idx = find(p_val); + void remove_at(Size p_index) { _cowdata.remove_at(p_index); } + _FORCE_INLINE_ bool erase(const T &p_val) { + Size idx = find(p_val); if (idx >= 0) { remove_at(idx); + return true; } + return false; } + void reverse(); _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } @@ -86,37 +90,45 @@ class Vector { _FORCE_INLINE_ void clear() { resize(0); } _FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); } - _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); } - _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); } - _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } - _FORCE_INLINE_ int size() const { return _cowdata.size(); } - Error resize(int p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); } - Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } - int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); } + _FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); } + _FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ Size size() const { return _cowdata.size(); } + Error resize(Size p_size) { return _cowdata.resize(p_size); } + Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); } + _FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); } + Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } + Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); } + Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); } + Size count(const T &p_val) const { return _cowdata.count(p_val); } void append_array(Vector<T> p_other); _FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; } - template <class C> - void sort_custom() { - int len = _cowdata.size(); + void sort() { + sort_custom<_DefaultComparator<T>>(); + } + + template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args> + void sort_custom(Args &&...args) { + Size len = _cowdata.size(); if (len == 0) { return; } T *data = ptrw(); - SortArray<T, C> sorter; + SortArray<T, Comparator, Validate> sorter{ args... }; sorter.sort(data, len); } - void sort() { - sort_custom<_DefaultComparator<T>>(); + Size bsearch(const T &p_value, bool p_before) { + return bsearch_custom<_DefaultComparator<T>>(p_value, p_before); } - int bsearch(const T &p_value, bool p_before) { - SearchArray<T> search; + template <class Comparator, class Value, class... Args> + Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) { + SearchArray<T, Comparator> search{ args... }; return search.bisect(ptrw(), size(), p_value, p_before); } @@ -125,7 +137,7 @@ class Vector { } void ordered_insert(const T &p_val) { - int i; + Size i; for (i = 0; i < _cowdata.size(); i++) { if (p_val < operator[](i)) { break; @@ -140,33 +152,36 @@ class Vector { Vector<uint8_t> to_byte_array() const { Vector<uint8_t> ret; + if (is_empty()) { + return ret; + } ret.resize(size() * sizeof(T)); memcpy(ret.ptrw(), ptr(), sizeof(T) * size()); return ret; } - Vector<T> slice(int p_begin, int p_end = INT_MAX) const { + Vector<T> slice(Size p_begin, Size p_end = CowData<T>::MAX_INT) const { Vector<T> result; - const int s = size(); + const Size s = size(); - int begin = Math::clamp(p_begin, -s, s); + Size begin = CLAMP(p_begin, -s, s); if (begin < 0) { begin += s; } - int end = Math::clamp(p_end, -s, s); + Size end = CLAMP(p_end, -s, s); if (end < 0) { end += s; } ERR_FAIL_COND_V(begin > end, result); - int result_size = end - begin; + Size result_size = end - begin; result.resize(result_size); const T *const r = ptr(); T *const w = result.ptrw(); - for (int i = 0; i < result_size; ++i) { + for (Size i = 0; i < result_size; ++i) { w[i] = r[begin + i]; } @@ -174,11 +189,11 @@ class Vector { } bool operator==(const Vector<T> &p_arr) const { - int s = size(); + Size s = size(); if (s != p_arr.size()) { return false; } - for (int i = 0; i < s; i++) { + for (Size i = 0; i < s; i++) { if (operator[](i) != p_arr[i]) { return false; } @@ -187,11 +202,11 @@ class Vector { } bool operator!=(const Vector<T> &p_arr) const { - int s = size(); + Size s = size(); if (s != p_arr.size()) { return true; } - for (int i = 0; i < s; i++) { + for (Size i = 0; i < s; i++) { if (operator[](i) != p_arr[i]) { return true; } @@ -268,7 +283,7 @@ class Vector { Error err = _cowdata.resize(p_init.size()); ERR_FAIL_COND(err); - int i = 0; + Size i = 0; for (const T &element : p_init) { _cowdata.set(i++, element); } @@ -280,7 +295,7 @@ class Vector { template <class T> void Vector<T>::reverse() { - for (int i = 0; i < size() / 2; i++) { + for (Size i = 0; i < size() / 2; i++) { T *p = ptrw(); SWAP(p[i], p[size() - i - 1]); } @@ -288,13 +303,13 @@ void Vector<T>::reverse() { template <class T> void Vector<T>::append_array(Vector<T> p_other) { - const int ds = p_other.size(); + const Size ds = p_other.size(); if (ds == 0) { return; } - const int bs = size(); + const Size bs = size(); resize(bs + ds); - for (int i = 0; i < ds; ++i) { + for (Size i = 0; i < ds; ++i) { ptrw()[bs + i] = p_other[i]; } } @@ -311,7 +326,7 @@ bool Vector<T>::push_back(T p_elem) { template <class T> void Vector<T>::fill(T p_elem) { T *p = ptrw(); - for (int i = 0; i < size(); i++) { + for (Size i = 0; i < size(); i++) { p[i] = p_elem; } } diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index fef6a7187..993d0467d 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -46,11 +46,11 @@ class CharProxy { template <class TS> friend class CharStringT; - const int _index; + const int64_t _index; CowData<T> &_cowdata; static inline const T _null = 0; - _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) : + _FORCE_INLINE_ CharProxy(const int64_t &p_index, CowData<T> &p_cowdata) : _index(p_index), _cowdata(p_cowdata) {} @@ -90,19 +90,19 @@ class CharStringT { public: _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } - _FORCE_INLINE_ int size() const { return _cowdata.size(); } - Error resize(int p_size) { return _cowdata.resize(p_size); } + _FORCE_INLINE_ int64_t size() const { return _cowdata.size(); } + Error resize(int64_t p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); } - _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } - _FORCE_INLINE_ const T &operator[](int p_index) const { + _FORCE_INLINE_ T get(int64_t p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(int64_t p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ const T &operator[](int64_t p_index) const { if (unlikely(p_index == _cowdata.size())) { return _null; } return _cowdata.get(p_index); } - _FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); } + _FORCE_INLINE_ CharProxy<T> operator[](int64_t p_index) { return CharProxy<T>(p_index, _cowdata); } _FORCE_INLINE_ CharStringT() {} _FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); } @@ -112,7 +112,7 @@ class CharStringT { void operator=(const T *p_cstr); bool operator<(const CharStringT<T> &p_right) const; CharStringT<T> &operator+=(T p_char); - int length() const { return size() ? size() - 1 : 0; } + int64_t length() const { return size() ? size() - 1 : 0; } const T *get_data() const; operator const T *() const { return get_data(); }; diff --git a/src/variant/char_string.cpp b/src/variant/char_string.cpp index 856037c43..153339899 100644 --- a/src/variant/char_string.cpp +++ b/src/variant/char_string.cpp @@ -76,7 +76,7 @@ bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const { template <class T> CharStringT<T> &CharStringT<T>::operator+=(T p_char) { - const int lhs_len = length(); + const int64_t lhs_len = length(); resize(lhs_len + 2); T *dst = ptrw(); @@ -172,23 +172,23 @@ String::String(const char32_t *from) { internal::gdextension_interface_string_new_with_utf32_chars(_native_ptr(), from); } -String String::utf8(const char *from, int len) { +String String::utf8(const char *from, int64_t len) { String ret; ret.parse_utf8(from, len); return ret; } -void String::parse_utf8(const char *from, int len) { +void String::parse_utf8(const char *from, int64_t len) { internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len); } -String String::utf16(const char16_t *from, int len) { +String String::utf16(const char16_t *from, int64_t len) { String ret; ret.parse_utf16(from, len); return ret; } -void String::parse_utf16(const char16_t *from, int len) { +void String::parse_utf16(const char16_t *from, int64_t len) { internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len); } @@ -230,8 +230,8 @@ String rtoss(double p_val) { } CharString String::utf8() const { - int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0); - int size = length + 1; + int64_t length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0); + int64_t size = length + 1; CharString str; str.resize(size); internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length); @@ -242,8 +242,8 @@ CharString String::utf8() const { } CharString String::ascii() const { - int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0); - int size = length + 1; + int64_t length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0); + int64_t size = length + 1; CharString str; str.resize(size); internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length); @@ -254,8 +254,8 @@ CharString String::ascii() const { } Char16String String::utf16() const { - int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0); - int size = length + 1; + int64_t length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0); + int64_t size = length + 1; Char16String str; str.resize(size); internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length); @@ -266,8 +266,8 @@ Char16String String::utf16() const { } Char32String String::utf32() const { - int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0); - int size = length + 1; + int64_t length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0); + int64_t size = length + 1; Char32String str; str.resize(size); internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length); @@ -278,8 +278,8 @@ Char32String String::utf32() const { } CharWideString String::wide_string() const { - int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0); - int size = length + 1; + int64_t length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0); + int64_t size = length + 1; CharWideString str; str.resize(size); internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length); @@ -386,11 +386,11 @@ String &String::operator+=(const char32_t *p_str) { return *this; } -const char32_t &String::operator[](int p_index) const { +const char32_t &String::operator[](int64_t p_index) const { return *internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, p_index); } -char32_t &String::operator[](int p_index) { +char32_t &String::operator[](int64_t p_index) { return *internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, p_index); } diff --git a/src/variant/packed_arrays.cpp b/src/variant/packed_arrays.cpp index 65b00025c..fe8b3597f 100644 --- a/src/variant/packed_arrays.cpp +++ b/src/variant/packed_arrays.cpp @@ -46,11 +46,11 @@ namespace godot { -const uint8_t &PackedByteArray::operator[](int p_index) const { +const uint8_t &PackedByteArray::operator[](int64_t p_index) const { return *internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index); } -uint8_t &PackedByteArray::operator[](int p_index) { +uint8_t &PackedByteArray::operator[](int64_t p_index) { return *internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index); } @@ -62,12 +62,12 @@ uint8_t *PackedByteArray::ptrw() { return internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0); } -const Color &PackedColorArray::operator[](int p_index) const { +const Color &PackedColorArray::operator[](int64_t p_index) const { const Color *color = (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *color; } -Color &PackedColorArray::operator[](int p_index) { +Color &PackedColorArray::operator[](int64_t p_index) { Color *color = (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index); return *color; } @@ -80,11 +80,11 @@ Color *PackedColorArray::ptrw() { return (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, 0); } -const float &PackedFloat32Array::operator[](int p_index) const { +const float &PackedFloat32Array::operator[](int64_t p_index) const { return *internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index); } -float &PackedFloat32Array::operator[](int p_index) { +float &PackedFloat32Array::operator[](int64_t p_index) { return *internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index); } @@ -96,11 +96,11 @@ float *PackedFloat32Array::ptrw() { return internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0); } -const double &PackedFloat64Array::operator[](int p_index) const { +const double &PackedFloat64Array::operator[](int64_t p_index) const { return *internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index); } -double &PackedFloat64Array::operator[](int p_index) { +double &PackedFloat64Array::operator[](int64_t p_index) { return *internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index); } @@ -112,11 +112,11 @@ double *PackedFloat64Array::ptrw() { return internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0); } -const int32_t &PackedInt32Array::operator[](int p_index) const { +const int32_t &PackedInt32Array::operator[](int64_t p_index) const { return *internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index); } -int32_t &PackedInt32Array::operator[](int p_index) { +int32_t &PackedInt32Array::operator[](int64_t p_index) { return *internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index); } @@ -128,11 +128,11 @@ int32_t *PackedInt32Array::ptrw() { return internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0); } -const int64_t &PackedInt64Array::operator[](int p_index) const { +const int64_t &PackedInt64Array::operator[](int64_t p_index) const { return *internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index); } -int64_t &PackedInt64Array::operator[](int p_index) { +int64_t &PackedInt64Array::operator[](int64_t p_index) { return *internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index); } @@ -144,12 +144,12 @@ int64_t *PackedInt64Array::ptrw() { return internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0); } -const String &PackedStringArray::operator[](int p_index) const { +const String &PackedStringArray::operator[](int64_t p_index) const { const String *string = (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *string; } -String &PackedStringArray::operator[](int p_index) { +String &PackedStringArray::operator[](int64_t p_index) { String *string = (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index); return *string; } @@ -162,12 +162,12 @@ String *PackedStringArray::ptrw() { return (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, 0); } -const Vector2 &PackedVector2Array::operator[](int p_index) const { +const Vector2 &PackedVector2Array::operator[](int64_t p_index) const { const Vector2 *vec = (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *vec; } -Vector2 &PackedVector2Array::operator[](int p_index) { +Vector2 &PackedVector2Array::operator[](int64_t p_index) { Vector2 *vec = (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index); return *vec; } @@ -180,12 +180,12 @@ Vector2 *PackedVector2Array::ptrw() { return (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0); } -const Vector3 &PackedVector3Array::operator[](int p_index) const { +const Vector3 &PackedVector3Array::operator[](int64_t p_index) const { const Vector3 *vec = (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index); return *vec; } -Vector3 &PackedVector3Array::operator[](int p_index) { +Vector3 &PackedVector3Array::operator[](int64_t p_index) { Vector3 *vec = (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index); return *vec; } @@ -198,12 +198,12 @@ Vector3 *PackedVector3Array::ptrw() { return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0); } -const Variant &Array::operator[](int 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); return *var; } -Variant &Array::operator[](int p_index) { +Variant &Array::operator[](int64_t p_index) { Variant *var = (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, p_index); return *var; } From 1ac8627b2e741cc73aa0ffc73637b8e2a34f9536 Mon Sep 17 00:00:00 2001 From: DaylilyZeleen <735170336@qq.com> Date: Thu, 18 Jan 2024 17:23:21 +0800 Subject: [PATCH 19/36] Fix object return value of builtin types' methods. (cherry picked from commit 6a3753c076fd6b709066a07bdc864f270090d8a9) --- binding_generator.py | 16 +++++++++++++++- include/godot_cpp/core/builtin_ptrcall.hpp | 12 ++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/binding_generator.py b/binding_generator.py index 98d117273..c5a2a2a55 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -916,8 +916,19 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append(method_signature + "{") method_call = "\t" + is_ref = False + if "return_type" in method: - method_call += f'return internal::_call_builtin_method_ptr_ret<{correct_type(method["return_type"])}>(' + return_type = method["return_type"] + if is_enum(return_type): + method_call += f"return ({get_gdextension_type(correct_type(return_type))})internal::_call_builtin_method_ptr_ret<int64_t>(" + elif is_pod_type(return_type) or is_variant(return_type): + method_call += f"return internal::_call_builtin_method_ptr_ret<{get_gdextension_type(correct_type(return_type))}>(" + elif is_refcounted(return_type): + method_call += f"return Ref<{return_type}>::_gde_internal_constructor(internal::_call_builtin_method_ptr_ret_obj<{return_type}>(" + is_ref = True + else: + method_call += f"return internal::_call_builtin_method_ptr_ret_obj<{return_type}>(" else: method_call += "internal::_call_builtin_method_ptr_no_ret(" method_call += f'_method_bindings.method_{method["name"]}, ' @@ -938,6 +949,9 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result += encode arguments.append(arg_name) method_call += ", ".join(arguments) + + if is_ref: + method_call += ")" # Close Ref<> constructor. method_call += ");" result.append(method_call) diff --git a/include/godot_cpp/core/builtin_ptrcall.hpp b/include/godot_cpp/core/builtin_ptrcall.hpp index 87311b8a9..19250d845 100644 --- a/include/godot_cpp/core/builtin_ptrcall.hpp +++ b/include/godot_cpp/core/builtin_ptrcall.hpp @@ -32,6 +32,7 @@ #define GODOT_BUILTIN_PTRCALL_HPP #include <gdextension_interface.h> +#include <godot_cpp/core/object.hpp> #include <array> @@ -39,6 +40,17 @@ namespace godot { namespace internal { +template <class O, class... Args> +O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) { + GodotObject *ret = nullptr; + std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; + method(base, call_args.data(), &ret, sizeof...(Args)); + if (ret == nullptr) { + return nullptr; + } + return reinterpret_cast<O *>(internal::get_object_instance_binding(ret)); +} + template <class... Args> void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) { std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; From bab62a4d72de5a433d224e6fbab8326004271128 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli <fabio.alessandrelli@gmail.com> Date: Tue, 30 Jan 2024 09:32:27 +0100 Subject: [PATCH 20/36] [SCons] Add support for custom build tools and platforms Use with: `scons platform=os2 custom_tools=/path/to/tools` (assuming you have an `os2.py` inside `/path/to/tools/`) (cherry picked from commit baaad7ada247bae37b68b5e42de7f7815a457535) --- tools/godotcpp.py | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 5e0f06559..98530e630 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -33,7 +33,26 @@ def validate_parent_dir(key, val, env): raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val))) -platforms = ("linux", "macos", "windows", "android", "ios", "web") +def get_platform_tools_paths(env): + path = env.get("custom_tools", None) + if path is None: + return ["tools"] + return [normalize_path(path, env), "tools"] + + +def get_custom_platforms(env): + path = env.get("custom_tools", None) + if path is None: + return [] + platforms = [] + for x in os.listdir(normalize_path(path, env)): + if not x.endswith(".py"): + continue + platforms.append(x.removesuffix(".py")) + return platforms + + +platforms = ["linux", "macos", "windows", "android", "ios", "web"] # CPU architecture options. architecture_array = [ @@ -82,12 +101,25 @@ def options(opts, env): else: raise ValueError("Could not detect platform automatically, please specify with platform=<platform>") + opts.Add( + PathVariable( + key="custom_tools", + help="Path to directory containing custom tools", + default=env.get("custom_tools", None), + validator=validate_dir, + ) + ) + + opts.Update(env) + + custom_platforms = get_custom_platforms(env) + opts.Add( EnumVariable( key="platform", help="Target platform", default=env.get("platform", default_platform), - allowed_values=platforms, + allowed_values=platforms + custom_platforms, ignorecase=2, ) ) @@ -183,9 +215,9 @@ def options(opts, env): ) ) - # Add platform options - for pl in platforms: - tool = Tool(pl, toolpath=["tools"]) + # Add platform options (custom tools can override platforms) + for pl in sorted(set(platforms + custom_platforms)): + tool = Tool(pl, toolpath=get_platform_tools_paths(env)) if hasattr(tool, "options"): tool.options(opts) @@ -239,7 +271,7 @@ def generate(env): print("Building for architecture " + env["arch"] + " on platform " + env["platform"]) - tool = Tool(env["platform"], toolpath=["tools"]) + tool = Tool(env["platform"], toolpath=get_platform_tools_paths(env)) if tool is None or not tool.exists(env): raise ValueError("Required toolchain not found for platform " + env["platform"]) From 670c4d0eac5f9f06dedd89fed28c33b86d93635a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli <fabio.alessandrelli@gmail.com> Date: Wed, 14 Feb 2024 15:32:27 +0100 Subject: [PATCH 21/36] [SCons] Split `targets.py`, apply flags from tools Split `targets` tool logic, moving all the compiler-specific flags to a new `common_compiler_flags.py` file, and everything else (CPPDEFINES, optimize option logic, dev build logic, etc) to the `godotcpp` tool. The default tools now apply the common compiler flags by importing the file and explicitly calling `configure`. (cherry picked from commit 16df4bff300b1e3ec6256936802ece4a158a28be) --- tools/android.py | 3 + tools/common_compiler_flags.py | 86 ++++++++++++++++++++ tools/godotcpp.py | 83 ++++++++++++++----- tools/ios.py | 3 + tools/linux.py | 3 + tools/macos.py | 3 + tools/targets.py | 144 --------------------------------- tools/web.py | 3 + tools/windows.py | 5 +- 9 files changed, 167 insertions(+), 166 deletions(-) create mode 100644 tools/common_compiler_flags.py delete mode 100644 tools/targets.py diff --git a/tools/android.py b/tools/android.py index 0c2535410..8454d479a 100644 --- a/tools/android.py +++ b/tools/android.py @@ -1,6 +1,7 @@ import os import sys import my_spawn +import common_compiler_flags from SCons.Script import ARGUMENTS @@ -118,3 +119,5 @@ def generate(env): env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]]) env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"]) + + common_compiler_flags.generate(env) diff --git a/tools/common_compiler_flags.py b/tools/common_compiler_flags.py new file mode 100644 index 000000000..437f256b3 --- /dev/null +++ b/tools/common_compiler_flags.py @@ -0,0 +1,86 @@ +import os +import subprocess +import sys + + +def using_clang(env): + return "clang" in os.path.basename(env["CC"]) + + +def is_vanilla_clang(env): + if not using_clang(env): + return False + try: + version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8") + except (subprocess.CalledProcessError, OSError): + print("Couldn't parse CXX environment variable to infer compiler version.") + return False + return not version.startswith("Apple") + + +def exists(env): + return True + + +def generate(env): + # Require C++17 + if env.get("is_msvc", False): + env.Append(CXXFLAGS=["/std:c++17"]) + else: + env.Append(CXXFLAGS=["-std=c++17"]) + + # Disable exception handling. Godot doesn't use exceptions anywhere, and this + # saves around 20% of binary size and very significant build time. + if env["disable_exceptions"]: + if env.get("is_msvc", False): + env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)]) + else: + env.Append(CXXFLAGS=["-fno-exceptions"]) + elif env.get("is_msvc", False): + env.Append(CXXFLAGS=["/EHsc"]) + + # Set optimize and debug_symbols flags. + # "custom" means do nothing and let users set their own optimization flags. + if env.get("is_msvc", False): + if env["debug_symbols"]: + env.Append(CCFLAGS=["/Zi", "/FS"]) + env.Append(LINKFLAGS=["/DEBUG:FULL"]) + + if env["optimize"] == "speed": + env.Append(CCFLAGS=["/O2"]) + env.Append(LINKFLAGS=["/OPT:REF"]) + elif env["optimize"] == "speed_trace": + env.Append(CCFLAGS=["/O2"]) + env.Append(LINKFLAGS=["/OPT:REF", "/OPT:NOICF"]) + elif env["optimize"] == "size": + env.Append(CCFLAGS=["/O1"]) + env.Append(LINKFLAGS=["/OPT:REF"]) + elif env["optimize"] == "debug" or env["optimize"] == "none": + env.Append(CCFLAGS=["/Od"]) + else: + if env["debug_symbols"]: + # Adding dwarf-4 explicitly makes stacktraces work with clang builds, + # otherwise addr2line doesn't understand them. + env.Append(CCFLAGS=["-gdwarf-4"]) + if env.dev_build: + env.Append(CCFLAGS=["-g3"]) + else: + env.Append(CCFLAGS=["-g2"]) + else: + if using_clang(env) and not is_vanilla_clang(env): + # Apple Clang, its linker doesn't like -s. + env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"]) + else: + env.Append(LINKFLAGS=["-s"]) + + if env["optimize"] == "speed": + env.Append(CCFLAGS=["-O3"]) + # `-O2` is friendlier to debuggers than `-O3`, leading to better crash backtraces. + elif env["optimize"] == "speed_trace": + env.Append(CCFLAGS=["-O2"]) + elif env["optimize"] == "size": + env.Append(CCFLAGS=["-Os"]) + elif env["optimize"] == "debug": + env.Append(CCFLAGS=["-Og"]) + elif env["optimize"] == "none": + env.Append(CCFLAGS=["-O0"]) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 98530e630..71199c18d 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -1,9 +1,12 @@ import os, sys, platform from SCons.Variables import EnumVariable, PathVariable, BoolVariable +from SCons.Variables.BoolVariable import _text2bool from SCons.Tool import Tool from SCons.Builder import Builder from SCons.Errors import UserError +from SCons.Script import ARGUMENTS + from binding_generator import scons_generate_bindings, scons_emit_files @@ -14,6 +17,17 @@ def add_sources(sources, dir, extension): sources.append(dir + "/" + f) +def get_cmdline_bool(option, default): + """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line, + and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings. + """ + cmdline_val = ARGUMENTS.get(option) + if cmdline_val is not None: + return _text2bool(cmdline_val) + else: + return default + + def normalize_path(val, env): return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val) @@ -215,16 +229,23 @@ def options(opts, env): ) ) + opts.Add( + EnumVariable( + "optimize", + "The desired optimization flags", + "speed_trace", + ("none", "custom", "debug", "speed", "speed_trace", "size"), + ) + ) + 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)) + # Add platform options (custom tools can override platforms) for pl in sorted(set(platforms + custom_platforms)): tool = Tool(pl, toolpath=get_platform_tools_paths(env)) if hasattr(tool, "options"): tool.options(opts) - # Targets flags tool (optimizations, debug symbols) - target_tool = Tool("targets", toolpath=["tools"]) - target_tool.options(opts) - def generate(env): # Default num_jobs to local cpu count if not user specified. @@ -271,30 +292,52 @@ def generate(env): print("Building for architecture " + env["arch"] + " on platform " + env["platform"]) + # These defaults may be needed by platform tools + env.editor_build = env["target"] == "editor" + env.dev_build = env["dev_build"] + env.debug_features = env["target"] in ["editor", "template_debug"] + + if env.dev_build: + opt_level = "none" + elif env.debug_features: + opt_level = "speed_trace" + else: # Release + opt_level = "speed" + + env["optimize"] = ARGUMENTS.get("optimize", opt_level) + env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build) + tool = Tool(env["platform"], toolpath=get_platform_tools_paths(env)) if tool is None or not tool.exists(env): raise ValueError("Required toolchain not found for platform " + env["platform"]) tool.generate(env) - target_tool = Tool("targets", toolpath=["tools"]) - target_tool.generate(env) - - # Disable exception handling. Godot doesn't use exceptions anywhere, and this - # saves around 20% of binary size and very significant build time. - if env["disable_exceptions"]: - if env.get("is_msvc", False): - env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)]) - else: - env.Append(CXXFLAGS=["-fno-exceptions"]) - elif env.get("is_msvc", False): - env.Append(CXXFLAGS=["/EHsc"]) - # Require C++17 - if env.get("is_msvc", False): - env.Append(CXXFLAGS=["/std:c++17"]) + if env.editor_build: + env.Append(CPPDEFINES=["TOOLS_ENABLED"]) + + # Configuration of build targets: + # - Editor or template + # - Debug features (DEBUG_ENABLED code) + # - Dev only code (DEV_ENABLED code) + # - Optimization level + # - Debug symbols for crash traces / debuggers + # Keep this configuration in sync with SConstruct in upstream Godot. + if env.debug_features: + # DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended + # to give *users* extra debugging information for their game development. + env.Append(CPPDEFINES=["DEBUG_ENABLED"]) + # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set. + env.Append(CPPDEFINES=["DEBUG_METHODS_ENABLED"]) + + if env.dev_build: + # DEV_ENABLED enables *engine developer* code which should only be compiled for those + # working on the engine itself. + env.Append(CPPDEFINES=["DEV_ENABLED"]) else: - env.Append(CXXFLAGS=["-std=c++17"]) + # Disable assert() for production targets (only used in thirdparty code). + env.Append(CPPDEFINES=["NDEBUG"]) if env["precision"] == "double": env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"]) diff --git a/tools/ios.py b/tools/ios.py index e387f4264..28415ce40 100644 --- a/tools/ios.py +++ b/tools/ios.py @@ -1,6 +1,7 @@ import os import sys import subprocess +import common_compiler_flags from SCons.Variables import * if sys.version_info < (3,): @@ -104,3 +105,5 @@ def generate(env): env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]]) env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"]) + + common_compiler_flags.generate(env) diff --git a/tools/linux.py b/tools/linux.py index cb48ae586..ee6cdc636 100644 --- a/tools/linux.py +++ b/tools/linux.py @@ -1,3 +1,4 @@ +import common_compiler_flags from SCons.Variables import * from SCons.Tool import clang, clangxx @@ -34,3 +35,5 @@ def generate(env): env.Append(LINKFLAGS=["-march=rv64gc"]) env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"]) + + common_compiler_flags.generate(env) diff --git a/tools/macos.py b/tools/macos.py index 0c75e4a76..883d21ec3 100644 --- a/tools/macos.py +++ b/tools/macos.py @@ -1,5 +1,6 @@ import os import sys +import common_compiler_flags def has_osxcross(): @@ -70,3 +71,5 @@ def generate(env): ) env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"]) + + common_compiler_flags.generate(env) diff --git a/tools/targets.py b/tools/targets.py deleted file mode 100644 index 216113494..000000000 --- a/tools/targets.py +++ /dev/null @@ -1,144 +0,0 @@ -import os -import subprocess -import sys -from SCons.Script import ARGUMENTS -from SCons.Variables import * -from SCons.Variables.BoolVariable import _text2bool - - -# Helper methods - - -def get_cmdline_bool(option, default): - """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line, - and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings. - """ - cmdline_val = ARGUMENTS.get(option) - if cmdline_val is not None: - return _text2bool(cmdline_val) - else: - return default - - -def using_clang(env): - return "clang" in os.path.basename(env["CC"]) - - -def is_vanilla_clang(env): - if not using_clang(env): - return False - try: - version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8") - except (subprocess.CalledProcessError, OSError): - print("Couldn't parse CXX environment variable to infer compiler version.") - return False - return not version.startswith("Apple") - - -# Main tool definition - - -def options(opts): - opts.Add( - EnumVariable( - "optimize", - "The desired optimization flags", - "speed_trace", - ("none", "custom", "debug", "speed", "speed_trace", "size"), - ) - ) - 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)) - - -def exists(env): - return True - - -def generate(env): - # Configuration of build targets: - # - Editor or template - # - Debug features (DEBUG_ENABLED code) - # - Dev only code (DEV_ENABLED code) - # - Optimization level - # - Debug symbols for crash traces / debuggers - - # Keep this configuration in sync with SConstruct in upstream Godot. - - env.editor_build = env["target"] == "editor" - env.dev_build = env["dev_build"] - env.debug_features = env["target"] in ["editor", "template_debug"] - - if env.dev_build: - opt_level = "none" - elif env.debug_features: - opt_level = "speed_trace" - else: # Release - opt_level = "speed" - - env["optimize"] = ARGUMENTS.get("optimize", opt_level) - env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build) - - if env.editor_build: - env.Append(CPPDEFINES=["TOOLS_ENABLED"]) - - if env.debug_features: - # DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended - # to give *users* extra debugging information for their game development. - env.Append(CPPDEFINES=["DEBUG_ENABLED"]) - # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set. - env.Append(CPPDEFINES=["DEBUG_METHODS_ENABLED"]) - - if env.dev_build: - # DEV_ENABLED enables *engine developer* code which should only be compiled for those - # working on the engine itself. - env.Append(CPPDEFINES=["DEV_ENABLED"]) - else: - # Disable assert() for production targets (only used in thirdparty code). - env.Append(CPPDEFINES=["NDEBUG"]) - - # Set optimize and debug_symbols flags. - # "custom" means do nothing and let users set their own optimization flags. - if env.get("is_msvc", False): - if env["debug_symbols"]: - env.Append(CCFLAGS=["/Zi", "/FS"]) - env.Append(LINKFLAGS=["/DEBUG:FULL"]) - - if env["optimize"] == "speed": - env.Append(CCFLAGS=["/O2"]) - env.Append(LINKFLAGS=["/OPT:REF"]) - elif env["optimize"] == "speed_trace": - env.Append(CCFLAGS=["/O2"]) - env.Append(LINKFLAGS=["/OPT:REF", "/OPT:NOICF"]) - elif env["optimize"] == "size": - env.Append(CCFLAGS=["/O1"]) - env.Append(LINKFLAGS=["/OPT:REF"]) - elif env["optimize"] == "debug" or env["optimize"] == "none": - env.Append(CCFLAGS=["/Od"]) - else: - if env["debug_symbols"]: - # Adding dwarf-4 explicitly makes stacktraces work with clang builds, - # otherwise addr2line doesn't understand them. - env.Append(CCFLAGS=["-gdwarf-4"]) - if env.dev_build: - env.Append(CCFLAGS=["-g3"]) - else: - env.Append(CCFLAGS=["-g2"]) - else: - if using_clang(env) and not is_vanilla_clang(env): - # Apple Clang, its linker doesn't like -s. - env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"]) - else: - env.Append(LINKFLAGS=["-s"]) - - if env["optimize"] == "speed": - env.Append(CCFLAGS=["-O3"]) - # `-O2` is friendlier to debuggers than `-O3`, leading to better crash backtraces. - elif env["optimize"] == "speed_trace": - env.Append(CCFLAGS=["-O2"]) - elif env["optimize"] == "size": - env.Append(CCFLAGS=["-Os"]) - elif env["optimize"] == "debug": - env.Append(CCFLAGS=["-Og"]) - elif env["optimize"] == "none": - env.Append(CCFLAGS=["-O0"]) diff --git a/tools/web.py b/tools/web.py index a4620c37a..c7440bcd4 100644 --- a/tools/web.py +++ b/tools/web.py @@ -1,4 +1,5 @@ import os +import common_compiler_flags from SCons.Util import WhereIs @@ -42,3 +43,5 @@ def generate(env): env.Append(LINKFLAGS=["-s", "SIDE_MODULE=1"]) env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) + + common_compiler_flags.generate(env) diff --git a/tools/windows.py b/tools/windows.py index d5a729c58..a263241aa 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -1,7 +1,6 @@ import sys - import my_spawn - +import common_compiler_flags from SCons.Tool import msvc, mingw from SCons.Variables import * @@ -90,3 +89,5 @@ def generate(env): ) env.Append(CPPDEFINES=["WINDOWS_ENABLED"]) + + common_compiler_flags.generate(env) From 08da55cd0b75fc99692fffafdb7370306345c432 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:26:45 +0200 Subject: [PATCH 22/36] [Core] Improve `CowData` and `Memory` metadata alignment. (cherry picked from commit b173a4d93551bbaabd3c4c26104f3c098055efae) --- include/godot_cpp/core/memory.hpp | 46 +++++++++--- include/godot_cpp/templates/cowdata.hpp | 99 ++++++++++++++++--------- src/core/memory.cpp | 12 +-- 3 files changed, 105 insertions(+), 52 deletions(-) diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index 548f33015..1c44d63fa 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -40,10 +40,6 @@ #include <type_traits> -#ifndef PAD_ALIGN -#define PAD_ALIGN 16 //must always be greater than this at much -#endif - void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory @@ -68,6 +64,18 @@ class Memory { Memory(); public: + // Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t + // ┌─────────────────┬──┬────────────────┬──┬───────────... + // │ uint64_t │░░│ uint64_t │░░│ T[] + // │ alloc size │░░│ element count │░░│ data + // └─────────────────┴──┴────────────────┴──┴───────────... + // Offset: ↑ SIZE_OFFSET ↑ ELEMENT_OFFSET ↑ DATA_OFFSET + // Note: "alloc size" is used and set by the engine and is never accessed or changed for the extension. + + static constexpr size_t SIZE_OFFSET = 0; + static constexpr size_t ELEMENT_OFFSET = ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t) == 0) ? (SIZE_OFFSET + sizeof(uint64_t)) : ((SIZE_OFFSET + sizeof(uint64_t)) + alignof(uint64_t) - ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t))); + static constexpr size_t DATA_OFFSET = ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t) == 0) ? (ELEMENT_OFFSET + sizeof(uint64_t)) : ((ELEMENT_OFFSET + sizeof(uint64_t)) + alignof(max_align_t) - ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t))); + static void *alloc_static(size_t p_bytes, bool p_pad_align = false); static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false); static void free_static(void *p_ptr, bool p_pad_align = false); @@ -98,7 +106,7 @@ struct Comparator { template <class T> void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) { - if (!std::is_trivially_destructible<T>::value) { + if constexpr (!std::is_trivially_destructible_v<T>) { p_class->~T(); } @@ -112,7 +120,7 @@ void memdelete(T *p_class) { template <class T, class A> void memdelete_allocator(T *p_class) { - if (!std::is_trivially_destructible<T>::value) { + if constexpr (!std::is_trivially_destructible_v<T>) { p_class->~T(); } @@ -135,6 +143,10 @@ class DefaultTypedAllocator { #define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count) +_FORCE_INLINE_ uint64_t *_get_element_count_ptr(uint8_t *p_ptr) { + return (uint64_t *)(p_ptr - Memory::DATA_OFFSET + Memory::ELEMENT_OFFSET); +} + template <typename T> T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { if (p_elements == 0) { @@ -144,12 +156,14 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { same strategy used by std::vector, and the Vector class, so it should be safe.*/ size_t len = sizeof(T) * p_elements; - uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true); + uint8_t *mem = (uint8_t *)Memory::alloc_static(len, true); T *failptr = nullptr; // Get rid of a warning. ERR_FAIL_NULL_V(mem, failptr); - *(mem - 1) = p_elements; - if (!std::is_trivially_destructible<T>::value) { + uint64_t *_elem_count_ptr = _get_element_count_ptr(mem); + *(_elem_count_ptr) = p_elements; + + if constexpr (!std::is_trivially_destructible_v<T>) { T *elems = (T *)mem; /* call operator new */ @@ -161,12 +175,20 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { return (T *)mem; } +template <typename T> +size_t memarr_len(const T *p_class) { + uint8_t *ptr = (uint8_t *)p_class; + uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr); + return *(_elem_count_ptr); +} + template <typename T> void memdelete_arr(T *p_class) { - uint64_t *ptr = (uint64_t *)p_class; + uint8_t *ptr = (uint8_t *)p_class; - if (!std::is_trivially_destructible<T>::value) { - uint64_t elem_count = *(ptr - 1); + if constexpr (!std::is_trivially_destructible_v<T>) { + uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr); + uint64_t elem_count = *(_elem_count_ptr); for (uint64_t i = 0; i < elem_count; i++) { p_class[i].~T(); diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index b6f66d7fa..f2959d197 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -52,7 +52,7 @@ class VMap; template <class T> class CharStringT; -SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint64_t) +static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>); // Silence a false positive warning (see GH-52119). #if defined(__GNUC__) && !defined(__clang__) @@ -96,18 +96,39 @@ class CowData { return ++x; } - static constexpr USize ALLOC_PAD = sizeof(USize) * 2; // For size and atomic refcount. + // Alignment: ↓ max_align_t ↓ USize ↓ max_align_t + // ┌────────────────────┬──┬─────────────┬──┬───────────... + // │ SafeNumeric<USize> │░░│ USize │░░│ T[] + // │ ref. count │░░│ data size │░░│ data + // └────────────────────┴──┴─────────────┴──┴───────────... + // Offset: ↑ REF_COUNT_OFFSET ↑ SIZE_OFFSET ↑ DATA_OFFSET + + static constexpr size_t REF_COUNT_OFFSET = 0; + static constexpr size_t SIZE_OFFSET = ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize) == 0) ? (REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) : ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) + alignof(USize) - ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize))); + static constexpr size_t DATA_OFFSET = ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t) == 0) ? (SIZE_OFFSET + sizeof(USize)) : ((SIZE_OFFSET + sizeof(USize)) + alignof(max_align_t) - ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t))); mutable T *_ptr = nullptr; // internal helpers + static _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount_ptr(uint8_t *p_ptr) { + return (SafeNumeric<USize> *)(p_ptr + REF_COUNT_OFFSET); + } + + static _FORCE_INLINE_ USize *_get_size_ptr(uint8_t *p_ptr) { + return (USize *)(p_ptr + SIZE_OFFSET); + } + + static _FORCE_INLINE_ T *_get_data_ptr(uint8_t *p_ptr) { + return (T *)(p_ptr + DATA_OFFSET); + } + _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const { if (!_ptr) { return nullptr; } - return reinterpret_cast<SafeNumeric<USize> *>(_ptr) - 2; + return (SafeNumeric<USize> *)((uint8_t *)_ptr - DATA_OFFSET + REF_COUNT_OFFSET); } _FORCE_INLINE_ USize *_get_size() const { @@ -115,7 +136,7 @@ class CowData { return nullptr; } - return reinterpret_cast<USize *>(_ptr) - 1; + return (USize *)((uint8_t *)_ptr - DATA_OFFSET + SIZE_OFFSET); } _FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const { @@ -240,7 +261,7 @@ void CowData<T>::_unref(void *p_data) { } // clean up - if (!std::is_trivially_destructible<T>::value) { + if constexpr (!std::is_trivially_destructible_v<T>) { USize *count = _get_size(); T *data = (T *)(count + 1); @@ -251,7 +272,7 @@ void CowData<T>::_unref(void *p_data) { } // free mem - Memory::free_static(((uint8_t *)p_data) - ALLOC_PAD, false); + Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false); } template <class T> @@ -267,26 +288,27 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() { /* in use by more than me */ USize current_size = *_get_size(); - USize *mem_new = (USize *)Memory::alloc_static(_get_alloc_size(current_size) + ALLOC_PAD, false); - mem_new += 2; + uint8_t *mem_new = (uint8_t *)Memory::alloc_static(_get_alloc_size(current_size) + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, 0); - new (mem_new - 2) SafeNumeric<USize>(1); //refcount - *(mem_new - 1) = current_size; //size + SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); + USize *_size_ptr = _get_size_ptr(mem_new); + T *_data_ptr = _get_data_ptr(mem_new); - T *_data = (T *)(mem_new); + new (_refc_ptr) SafeNumeric<USize>(1); //refcount + *(_size_ptr) = current_size; //size // initialize new elements - if (std::is_trivially_copyable<T>::value) { - memcpy(mem_new, _ptr, current_size * sizeof(T)); - + if constexpr (std::is_trivially_copyable_v<T>) { + memcpy((uint8_t *)_data_ptr, _ptr, current_size * sizeof(T)); } else { for (USize i = 0; i < current_size; i++) { - memnew_placement(&_data[i], T(_ptr[i])); + memnew_placement(&_data_ptr[i], T(_ptr[i])); } } _unref(_ptr); - _ptr = _data; + _ptr = _data_ptr; rc = 1; } @@ -322,27 +344,33 @@ Error CowData<T>::resize(Size p_size) { if (alloc_size != current_alloc_size) { if (current_size == 0) { // alloc from scratch - USize *ptr = (USize *)Memory::alloc_static(alloc_size + ALLOC_PAD, false); - ptr += 2; - ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY); - *(ptr - 1) = 0; //size, currently none - new (ptr - 2) SafeNumeric<USize>(1); //refcount + uint8_t *mem_new = (uint8_t *)Memory::alloc_static(alloc_size + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); + + SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); + USize *_size_ptr = _get_size_ptr(mem_new); + T *_data_ptr = _get_data_ptr(mem_new); - _ptr = (T *)ptr; + new (_refc_ptr) SafeNumeric<USize>(1); //refcount + *(_size_ptr) = 0; //size, currently none + _ptr = _data_ptr; } else { - USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); - ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); - _ptrnew += 2; - new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount + uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); + + SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); + T *_data_ptr = _get_data_ptr(mem_new); - _ptr = (T *)(_ptrnew); + new (_refc_ptr) SafeNumeric<USize>(rc); //refcount + + _ptr = _data_ptr; } } // construct the newly created elements - if (!std::is_trivially_constructible<T>::value) { + if constexpr (!std::is_trivially_constructible_v<T>) { for (Size i = *_get_size(); i < p_size; i++) { memnew_placement(&_ptr[i], T); } @@ -353,7 +381,7 @@ Error CowData<T>::resize(Size p_size) { *_get_size() = p_size; } else if (p_size < current_size) { - if (!std::is_trivially_destructible<T>::value) { + if constexpr (!std::is_trivially_destructible_v<T>) { // deinitialize no longer needed elements for (USize i = p_size; i < *_get_size(); i++) { T *t = &_ptr[i]; @@ -362,12 +390,15 @@ Error CowData<T>::resize(Size p_size) { } if (alloc_size != current_alloc_size) { - USize *_ptrnew = (USize *)Memory::realloc_static(((uint8_t *)_ptr) - ALLOC_PAD, alloc_size + ALLOC_PAD, false); - ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); - _ptrnew += 2; - new (_ptrnew - 2) SafeNumeric<USize>(rc); //refcount + uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); + + SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new); + T *_data_ptr = _get_data_ptr(mem_new); + + new (_refc_ptr) SafeNumeric<USize>(rc); //refcount - _ptr = (T *)(_ptrnew); + _ptr = _data_ptr; } *_get_size() = p_size; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 80e71ec52..3a85f1fbf 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -41,12 +41,12 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { bool prepad = p_pad_align; #endif - void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0)); + void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? DATA_OFFSET : 0)); ERR_FAIL_NULL_V(mem, nullptr); if (prepad) { uint8_t *s8 = (uint8_t *)mem; - return s8 + PAD_ALIGN; + return s8 + DATA_OFFSET; } else { return mem; } @@ -69,10 +69,10 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { #endif if (prepad) { - mem -= PAD_ALIGN; - mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN); + mem -= DATA_OFFSET; + mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + DATA_OFFSET); ERR_FAIL_NULL_V(mem, nullptr); - return mem + PAD_ALIGN; + return mem + DATA_OFFSET; } else { return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes); } @@ -88,7 +88,7 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { #endif if (prepad) { - mem -= PAD_ALIGN; + mem -= DATA_OFFSET; } internal::gdextension_interface_mem_free(mem); } From f7a9d32f32226377a299746ef364fcccac8f9eb0 Mon Sep 17 00:00:00 2001 From: David Snopek <dsnopek@gmail.com> Date: Fri, 2 Feb 2024 10:07:45 -0600 Subject: [PATCH 23/36] Fix _notification with parent and child classes (cherry picked from commit 23c010900c9a09c5c99bfbb0d465cd468aa74b6c) --- include/godot_cpp/classes/wrapped.hpp | 4 ++-- test/project/main.gd | 5 +++++ test/project/main.tscn | 2 ++ test/src/example.cpp | 18 ++++++++++++++++++ test/src/example.h | 25 +++++++++++++++++++++++++ test/src/register_types.cpp | 2 ++ 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 4683070e0..332ea5ff4 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -201,11 +201,11 @@ public: \ static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) { \ if (p_instance && m_class::_get_notification()) { \ + m_inherits::notification_bind(p_instance, p_what); \ if (m_class::_get_notification() != m_inherits::_get_notification()) { \ m_class *cls = reinterpret_cast<m_class *>(p_instance); \ - return cls->_notification(p_what); \ + cls->_notification(p_what); \ } \ - m_inherits::notification_bind(p_instance, p_what); \ } \ } \ \ diff --git a/test/project/main.gd b/test/project/main.gd index e0b186bb2..329c62220 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -174,6 +174,11 @@ func _ready(): assert_equal(new_example_ref.was_post_initialized(), true) assert_equal(example.test_post_initialize(), true) + # Test that notifications happen on both parent and child classes. + var example_child = $ExampleChild + assert_equal(example_child.get_value1(), 11) + assert_equal(example_child.get_value2(), 33) + exit_with_status() func _on_Example_custom_signal(signal_name, value): diff --git a/test/project/main.tscn b/test/project/main.tscn index 2b98e0f0d..14e0aed5b 100644 --- a/test/project/main.tscn +++ b/test/project/main.tscn @@ -22,4 +22,6 @@ offset_right = 79.0 offset_bottom = 29.0 text = "Click me!" +[node name="ExampleChild" type="ExampleChild" parent="."] + [connection signal="custom_signal" from="Example" to="." method="_on_Example_custom_signal"] diff --git a/test/src/example.cpp b/test/src/example.cpp index 848f50352..c8eba28a7 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -455,3 +455,21 @@ void Example::_input(const Ref<InputEvent> &event) { emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode()); } } + +void ExampleBase::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_value1"), &ExampleBase::get_value1); + ClassDB::bind_method(D_METHOD("get_value2"), &ExampleBase::get_value2); +} + +void ExampleBase::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE) { + value1 = 11; + value2 = 22; + } +} + +void ExampleChild::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE) { + value2 = 33; + } +} diff --git a/test/src/example.h b/test/src/example.h index d0130765b..5735b96a4 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -186,4 +186,29 @@ class ExampleAbstract : public Object { static void _bind_methods() {} }; +class ExampleBase : public Node { + GDCLASS(ExampleBase, Node); + +protected: + int value1 = 0; + int value2 = 0; + + static void _bind_methods(); + + void _notification(int p_what); + +public: + int get_value1() { return value1; } + int get_value2() { return value2; } +}; + +class ExampleChild : public ExampleBase { + GDCLASS(ExampleChild, ExampleBase); + +protected: + static void _bind_methods() {} + + void _notification(int p_what); +}; + #endif // EXAMPLE_CLASS_H diff --git a/test/src/register_types.cpp b/test/src/register_types.cpp index dbb37d90b..560dd907c 100644 --- a/test/src/register_types.cpp +++ b/test/src/register_types.cpp @@ -26,6 +26,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) { ClassDB::register_class<Example>(); ClassDB::register_class<ExampleVirtual>(true); ClassDB::register_abstract_class<ExampleAbstract>(); + ClassDB::register_class<ExampleBase>(); + ClassDB::register_class<ExampleChild>(); } void uninitialize_example_module(ModuleInitializationLevel p_level) { From ed576f8318b7bfed488f2f1fee2bc9126f671a60 Mon Sep 17 00:00:00 2001 From: Marc Gilleron <marc.gilleron@gmail.com> Date: Fri, 8 Mar 2024 19:42:07 +0000 Subject: [PATCH 24/36] Fix explicit namespaces in macros (cherry picked from commit e6077906474ba3c3d31b59ea079b3381ae5b0095) --- include/godot_cpp/core/class_db.hpp | 8 ++++---- include/godot_cpp/core/object.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index bafd2ce1b..5b0a6ddf3 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -155,20 +155,20 @@ class ClassDB { }; #define BIND_CONSTANT(m_constant) \ - godot::ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant); + ::godot::ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant); #define BIND_ENUM_CONSTANT(m_constant) \ - godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant); + ::godot::ClassDB::bind_integer_constant(get_class_static(), ::godot::_gde_constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant); #define BIND_BITFIELD_FLAG(m_constant) \ - godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true); + ::godot::ClassDB::bind_integer_constant(get_class_static(), ::godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true); #define BIND_VIRTUAL_METHOD(m_class, m_method) \ { \ auto _call##m_method = [](GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) -> void { \ call_with_ptr_args(reinterpret_cast<m_class *>(p_instance), &m_class::m_method, p_args, p_ret); \ }; \ - 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> diff --git a/include/godot_cpp/core/object.hpp b/include/godot_cpp/core/object.hpp index d66e38894..eb0c4d16d 100644 --- a/include/godot_cpp/core/object.hpp +++ b/include/godot_cpp/core/object.hpp @@ -45,10 +45,10 @@ #include <vector> -#define ADD_SIGNAL(m_signal) godot::ClassDB::add_signal(get_class_static(), m_signal) -#define ADD_GROUP(m_name, m_prefix) godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix) -#define ADD_SUBGROUP(m_name, m_prefix) godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix) -#define ADD_PROPERTY(m_property, m_setter, m_getter) godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter) +#define ADD_SIGNAL(m_signal) ::godot::ClassDB::add_signal(get_class_static(), m_signal) +#define ADD_GROUP(m_name, m_prefix) ::godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix) +#define ADD_SUBGROUP(m_name, m_prefix) ::godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix) +#define ADD_PROPERTY(m_property, m_setter, m_getter) ::godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter) namespace godot { From 07e245e3e4481ce25291fd41b09cc4ff6b992057 Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Fri, 8 Mar 2024 13:32:19 +0100 Subject: [PATCH 25/36] Fix invalid `void` return in `BitField` (cherry picked from commit 7ed8ef7221082a045ecb6a3cea52102b68b70c37) --- include/godot_cpp/core/type_info.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index f0edda5c6..6873e1f59 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -255,7 +255,7 @@ class BitField { public: _FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; } _FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; } - _FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; } + _FORCE_INLINE_ void clear_flag(T p_flag) { value &= ~p_flag; } _FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; } _FORCE_INLINE_ operator int64_t() const { return value; } _FORCE_INLINE_ operator Variant() const { return value; } From e99d7b3b7e8712240822cd6694569606eda951be Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:47:57 +0200 Subject: [PATCH 26/36] [Packed*Array] Add support for initializer lists. (cherry picked from commit 8c98a90f321cebdb70cabb46a84557355918848f) --- binding_generator.py | 15 +++++++++++++++ test/project/main.gd | 1 + test/src/example.cpp | 10 ++++++++++ test/src/example.h | 1 + 4 files changed, 27 insertions(+) diff --git a/binding_generator.py b/binding_generator.py index c5a2a2a55..caad05c36 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -375,6 +375,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if class_name == "PackedVector3Array": result.append("#include <godot_cpp/variant/vector3.hpp>") + if is_packed_array(class_name): + result.append("#include <godot_cpp/core/error_macros.hpp>") + result.append("#include <initializer_list>") + if class_name == "Array": result.append("#include <godot_cpp/variant/array_helpers.hpp>") @@ -692,6 +696,17 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl } """ result.append(iterators.replace("$TYPE", return_type)) + init_list = """ + _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": result.append("\tconst Variant &operator[](int64_t p_index) const;") diff --git a/test/project/main.gd b/test/project/main.gd index 329c62220..9717eca22 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -91,6 +91,7 @@ func _ready(): # PackedArray iterators assert_equal(example.test_vector_ops(), 105) + assert_equal(example.test_vector_init_list(), 105) # Properties. assert_equal(example.group_subgroup_custom_position, Vector2(0, 0)) diff --git a/test/src/example.cpp b/test/src/example.cpp index c8eba28a7..8094f7d5e 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -148,6 +148,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_fourty_two"), &Example::test_string_is_fourty_two); 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); ClassDB::bind_method(D_METHOD("test_object_cast_to_node", "object"), &Example::test_object_cast_to_node); ClassDB::bind_method(D_METHOD("test_object_cast_to_control", "object"), &Example::test_object_cast_to_control); @@ -339,6 +340,15 @@ int Example::test_vector_ops() const { return ret; } +int Example::test_vector_init_list() const { + PackedInt32Array arr = { 10, 20, 30, 45 }; + int ret = 0; + for (const int32_t &E : arr) { + ret += E; + } + return ret; +} + int Example::test_tarray_arg(const TypedArray<int64_t> &p_array) { int sum = 0; for (int i = 0; i < p_array.size(); i++) { diff --git a/test/src/example.h b/test/src/example.h index 5735b96a4..79c1e4d62 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -127,6 +127,7 @@ class Example : public Control { String test_str_utility() const; bool test_string_is_fourty_two(const String &p_str) const; int test_vector_ops() const; + int test_vector_init_list() const; bool test_object_cast_to_node(Object *p_object) const; bool test_object_cast_to_control(Object *p_object) const; From 76d6ce7136a99da530f615e7a18a766dfbc5d001 Mon Sep 17 00:00:00 2001 From: David Snopek <dsnopek@gmail.com> Date: Thu, 1 Feb 2024 14:22:26 -0600 Subject: [PATCH 27/36] Avoid creating most objects that Godot is going to use placement new to initialize (cherry picked from commit c4fde852e69e3f28975a60630ae2232f71321a56) --- binding_generator.py | 14 +++++ include/godot_cpp/variant/variant.hpp | 3 +- src/variant/variant.cpp | 84 +++++++++++---------------- 3 files changed, 48 insertions(+), 53 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index caad05c36..7ed3ed9c3 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -417,6 +417,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("\tstatic struct _MethodBindings {") + result.append("\t\tGDExtensionTypeFromVariantConstructorFunc from_variant_constructor;") + if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: result.append(f'\t\tGDExtensionPtrConstructor constructor_{constructor["index"]};') @@ -457,6 +459,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("\tstatic void init_bindings();") result.append("\tstatic void _init_bindings_constructors_destructor();") + result.append("") + result.append(f"\t{class_name}(const Variant *p_variant);") + result.append("") result.append("public:") @@ -785,6 +790,10 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append(f"void {class_name}::_init_bindings_constructors_destructor() {{") + result.append( + f"\t_method_bindings.from_variant_constructor = internal::gdextension_interface_get_variant_to_type_constructor({enum_type_name});" + ) + if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: result.append( @@ -866,6 +875,11 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl copy_constructor_index = -1 + result.append(f"{class_name}::{class_name}(const Variant *p_variant) {{") + result.append("\t_method_bindings.from_variant_constructor(&opaque, p_variant->_native_ptr());") + result.append("}") + result.append("") + if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: method_signature = f"{class_name}::{class_name}(" diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 7b82d5eb3..5c3d6fea0 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -47,8 +47,6 @@ class ObjectID; class Variant { uint8_t opaque[GODOT_CPP_VARIANT_SIZE]{ 0 }; - _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); } - friend class GDExtensionBinding; friend class MethodBind; @@ -145,6 +143,7 @@ class Variant { static GDExtensionTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX]; public: + _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); } Variant(); Variant(std::nullptr_t n) : Variant() {} diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index 945d6f406..161362b29 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -303,123 +303,131 @@ Variant::operator float() const { } Variant::operator String() const { - String result; - to_type_constructor[STRING](result._native_ptr(), _native_ptr()); - return result; + return String(this); } Variant::operator Vector2() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector2 result; to_type_constructor[VECTOR2]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Vector2i() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector2i result; to_type_constructor[VECTOR2I]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Rect2() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Rect2 result; to_type_constructor[RECT2]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Rect2i() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Rect2i result; to_type_constructor[RECT2I]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Vector3() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector3 result; to_type_constructor[VECTOR3]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Vector3i() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector3i result; to_type_constructor[VECTOR3I]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Transform2D() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Transform2D result; to_type_constructor[TRANSFORM2D]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Vector4() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector4 result; to_type_constructor[VECTOR4]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Vector4i() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Vector4i result; to_type_constructor[VECTOR4I]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Plane() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Plane result; to_type_constructor[PLANE]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Quaternion() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Quaternion result; to_type_constructor[QUATERNION]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator godot::AABB() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) godot::AABB result; to_type_constructor[AABB]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Basis() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Basis result; to_type_constructor[BASIS]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Transform3D() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Transform3D result; to_type_constructor[TRANSFORM3D]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Projection() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Projection result; to_type_constructor[PROJECTION]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator Color() const { + // @todo Avoid initializing result before calling constructor (which will initialize it again) Color result; to_type_constructor[COLOR]((GDExtensionTypePtr)&result, _native_ptr()); return result; } Variant::operator StringName() const { - StringName result; - to_type_constructor[STRING_NAME](result._native_ptr(), _native_ptr()); - return result; + return StringName(this); } Variant::operator NodePath() const { - NodePath result; - to_type_constructor[NODE_PATH](result._native_ptr(), _native_ptr()); - return result; + return NodePath(this); } Variant::operator godot::RID() const { - godot::RID result; - to_type_constructor[RID](result._native_ptr(), _native_ptr()); - return result; + return godot::RID(this); } Variant::operator Object *() const { @@ -447,81 +455,55 @@ Variant::operator ObjectID() const { } Variant::operator Callable() const { - Callable result; - to_type_constructor[CALLABLE](result._native_ptr(), _native_ptr()); - return result; + return Callable(this); } Variant::operator Signal() const { - Signal result; - to_type_constructor[SIGNAL](result._native_ptr(), _native_ptr()); - return result; + return Signal(this); } Variant::operator Dictionary() const { - Dictionary result; - to_type_constructor[DICTIONARY](result._native_ptr(), _native_ptr()); - return result; + return Dictionary(this); } Variant::operator Array() const { - Array result; - to_type_constructor[ARRAY](result._native_ptr(), _native_ptr()); - return result; + return Array(this); } Variant::operator PackedByteArray() const { - PackedByteArray result; - to_type_constructor[PACKED_BYTE_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedByteArray(this); } Variant::operator PackedInt32Array() const { - PackedInt32Array result; - to_type_constructor[PACKED_INT32_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedInt32Array(this); } Variant::operator PackedInt64Array() const { - PackedInt64Array result; - to_type_constructor[PACKED_INT64_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedInt64Array(this); } Variant::operator PackedFloat32Array() const { - PackedFloat32Array result; - to_type_constructor[PACKED_FLOAT32_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedFloat32Array(this); } Variant::operator PackedFloat64Array() const { - PackedFloat64Array result; - to_type_constructor[PACKED_FLOAT64_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedFloat64Array(this); } Variant::operator PackedStringArray() const { - PackedStringArray result; - to_type_constructor[PACKED_STRING_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedStringArray(this); } Variant::operator PackedVector2Array() const { - PackedVector2Array result; - to_type_constructor[PACKED_VECTOR2_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedVector2Array(this); } Variant::operator PackedVector3Array() const { - PackedVector3Array result; - to_type_constructor[PACKED_VECTOR3_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedVector3Array(this); } Variant::operator PackedColorArray() const { - PackedColorArray result; - to_type_constructor[PACKED_COLOR_ARRAY](result._native_ptr(), _native_ptr()); - return result; + return PackedColorArray(this); } Variant &Variant::operator=(const Variant &other) { From 9e48c45bfc896c8ef5071a80079b5c831bb7ddd0 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews <repiteo@outlook.com> Date: Sun, 10 Mar 2024 16:02:43 -0500 Subject: [PATCH 28/36] Enforce template syntax `typename` over `class` (cherry picked from commit 87f5fb06912d19b3ff3ba80b747fcea3023a1ed5) --- binding_generator.py | 14 ++-- .../classes/editor_plugin_registration.hpp | 4 +- include/godot_cpp/classes/ref.hpp | 16 ++--- include/godot_cpp/classes/wrapped.hpp | 4 +- include/godot_cpp/core/binder_common.hpp | 72 +++++++++---------- include/godot_cpp/core/builtin_ptrcall.hpp | 12 ++-- include/godot_cpp/core/class_db.hpp | 24 +++---- include/godot_cpp/core/defs.hpp | 2 +- include/godot_cpp/core/engine_ptrcall.hpp | 12 ++-- include/godot_cpp/core/math.hpp | 4 +- include/godot_cpp/core/memory.hpp | 14 ++-- include/godot_cpp/core/method_bind.hpp | 42 +++++------ include/godot_cpp/core/method_ptrcall.hpp | 6 +- include/godot_cpp/core/object.hpp | 16 ++--- include/godot_cpp/core/type_info.hpp | 8 +-- include/godot_cpp/templates/cowdata.hpp | 32 ++++----- include/godot_cpp/templates/hash_map.hpp | 10 +-- include/godot_cpp/templates/hash_set.hpp | 6 +- include/godot_cpp/templates/hashfuncs.hpp | 10 +-- include/godot_cpp/templates/list.hpp | 10 +-- include/godot_cpp/templates/local_vector.hpp | 6 +- include/godot_cpp/templates/pair.hpp | 16 ++--- include/godot_cpp/templates/rb_map.hpp | 2 +- include/godot_cpp/templates/rb_set.hpp | 2 +- include/godot_cpp/templates/rid_owner.hpp | 6 +- include/godot_cpp/templates/safe_refcount.hpp | 4 +- include/godot_cpp/templates/search_array.hpp | 2 +- include/godot_cpp/templates/self_list.hpp | 2 +- include/godot_cpp/templates/sort_array.hpp | 4 +- .../godot_cpp/templates/thread_work_pool.hpp | 6 +- include/godot_cpp/templates/vector.hpp | 16 ++--- include/godot_cpp/templates/vmap.hpp | 2 +- include/godot_cpp/templates/vset.hpp | 2 +- include/godot_cpp/variant/char_string.hpp | 8 +-- include/godot_cpp/variant/typed_array.hpp | 2 +- include/godot_cpp/variant/variant.hpp | 4 +- src/variant/char_string.cpp | 8 +-- 37 files changed, 205 insertions(+), 205 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 7ed3ed9c3..86d511a7e 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -520,7 +520,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl vararg = method["is_vararg"] if vararg: - result.append("\ttemplate<class... Args>") + result.append("\ttemplate<typename... Args>") method_signature = "\t" if "is_static" in method and method["is_static"]: @@ -618,7 +618,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("\tchar32_t *ptrw();") if class_name == "Array": - result.append("\ttemplate <class... Args>") + result.append("\ttemplate <typename... Args>") result.append("\tstatic Array make(Args... args) {") result.append("\t\treturn helpers::append_all(Array(), args...);") result.append("\t}") @@ -1371,7 +1371,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("protected:") # T is the custom class we want to register (from which the call initiates, going up the inheritance chain), # B is its base class (can be a custom class too, that's why we pass it). - result.append("\ttemplate <class T, class B>") + result.append("\ttemplate <typename T, typename B>") result.append("\tstatic void register_virtuals() {") if class_name != "Object": result.append(f"\t\t{inherits}::register_virtuals<T, B>();") @@ -1417,16 +1417,16 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if class_name == "Object": result.append("") - result.append("\ttemplate<class T>") + result.append("\ttemplate<typename T>") result.append("\tstatic T *cast_to(Object *p_object);") - result.append("\ttemplate<class T>") + result.append("\ttemplate<typename T>") result.append("\tstatic const T *cast_to(const Object *p_object);") result.append("\tvirtual ~Object() = default;") elif use_template_get_node and class_name == "Node": - result.append("\ttemplate<class T>") + result.append("\ttemplate<typename T>") result.append( "\tT *get_node(const NodePath &p_path) const { return Object::cast_to<T>(get_node_internal(p_path)); }" ) @@ -2042,7 +2042,7 @@ def make_signature( def make_varargs_template(function_data, static=False): result = [] - function_signature = "\tpublic: template<class... Args> " + function_signature = "\tpublic: template<typename... Args> " if static: function_signature += "static " diff --git a/include/godot_cpp/classes/editor_plugin_registration.hpp b/include/godot_cpp/classes/editor_plugin_registration.hpp index 1ccde314e..7870bfc70 100644 --- a/include/godot_cpp/classes/editor_plugin_registration.hpp +++ b/include/godot_cpp/classes/editor_plugin_registration.hpp @@ -47,11 +47,11 @@ class EditorPlugins { static void remove_plugin_class(const StringName &p_class_name); static void deinitialize(GDExtensionInitializationLevel p_level); - template <class T> + template <typename T> static void add_by_type() { add_plugin_class(T::get_class_static()); } - template <class T> + template <typename T> static void remove_by_type() { remove_plugin_class(T::get_class_static()); } diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index f3fc3e942..c4682bcf3 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -45,7 +45,7 @@ namespace godot { class RefCounted; -template <class T> +template <typename T> class Ref { T *reference = nullptr; @@ -108,7 +108,7 @@ class Ref { ref(p_from); } - template <class T_Other> + template <typename T_Other> void operator=(const Ref<T_Other> &p_from) { RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr())); if (!refb) { @@ -144,7 +144,7 @@ class Ref { } } - template <class T_Other> + template <typename T_Other> void reference_ptr(T_Other *p_ptr) { if (reference == p_ptr) { return; @@ -161,7 +161,7 @@ class Ref { ref(p_from); } - template <class T_Other> + template <typename T_Other> Ref(const Ref<T_Other> &p_from) { RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr())); if (!refb) { @@ -226,7 +226,7 @@ class Ref { } }; -template <class T> +template <typename T> struct PtrToArg<Ref<T>> { _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr; @@ -248,7 +248,7 @@ struct PtrToArg<Ref<T>> { } }; -template <class T> +template <typename T> struct PtrToArg<const Ref<T> &> { typedef Ref<T> EncodeT; @@ -259,7 +259,7 @@ struct PtrToArg<const Ref<T> &> { } }; -template <class T> +template <typename T> struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> { static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; @@ -269,7 +269,7 @@ struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value> } }; -template <class T> +template <typename T> struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> { static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT; static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 332ea5ff4..65c62eb53 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -102,7 +102,7 @@ void add_engine_class_registration_callback(EngineClassRegistrationCallback p_ca void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks); void register_engine_classes(); -template <class T> +template <typename T> struct EngineClassRegistration { EngineClassRegistration() { add_engine_class_registration_callback(&EngineClassRegistration<T>::callback); @@ -164,7 +164,7 @@ protected: return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \ } \ \ - template <class T, class B> \ + template <typename T, typename B> \ static void register_virtuals() { \ m_inherits::register_virtuals<T, B>(); \ } \ diff --git a/include/godot_cpp/core/binder_common.hpp b/include/godot_cpp/core/binder_common.hpp index 09da62b1b..059350170 100644 --- a/include/godot_cpp/core/binder_common.hpp +++ b/include/godot_cpp/core/binder_common.hpp @@ -83,7 +83,7 @@ namespace godot { }; \ } -template <class T> +template <typename T> struct VariantCaster { static _FORCE_INLINE_ T cast(const Variant &p_variant) { using TStripped = std::remove_pointer_t<T>; @@ -95,7 +95,7 @@ struct VariantCaster { } }; -template <class T> +template <typename T> struct VariantCaster<T &> { static _FORCE_INLINE_ T cast(const Variant &p_variant) { using TStripped = std::remove_pointer_t<T>; @@ -107,7 +107,7 @@ struct VariantCaster<T &> { } }; -template <class T> +template <typename T> struct VariantCaster<const T &> { static _FORCE_INLINE_ T cast(const Variant &p_variant) { using TStripped = std::remove_pointer_t<T>; @@ -144,7 +144,7 @@ struct VariantObjectClassChecker<const Ref<T> &> { } }; -template <class T> +template <typename T> struct VariantCasterAndValidate { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); @@ -159,7 +159,7 @@ struct VariantCasterAndValidate { } }; -template <class T> +template <typename T> struct VariantCasterAndValidate<T &> { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); @@ -174,7 +174,7 @@ struct VariantCasterAndValidate<T &> { } }; -template <class T> +template <typename T> struct VariantCasterAndValidate<const T &> { static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) { GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE); @@ -189,47 +189,47 @@ struct VariantCasterAndValidate<const T &> { } }; -template <class T, class... P, size_t... Is> +template <typename T, typename... P, size_t... Is> void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) { (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); } -template <class T, class... P, size_t... Is> +template <typename T, typename... P, size_t... Is> void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) { (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); } -template <class T, class R, class... P, size_t... Is> +template <typename T, typename R, typename... P, size_t... Is> void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) { PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); } -template <class T, class R, class... P, size_t... Is> +template <typename T, typename R, typename... P, size_t... Is> void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) { PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); } -template <class T, class... P> +template <typename T, typename... P> void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void * /*ret*/) { call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class... P> +template <typename T, typename... P> void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void * /*ret*/) { call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class R, class... P> +template <typename T, typename R, typename... P> void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) { call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class R, class... P> +template <typename T, typename R, typename... P> void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret) { call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class... P, size_t... Is> +template <typename T, typename... P, size_t... Is> void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -241,7 +241,7 @@ void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), con (void)(p_args); // Avoid warning. } -template <class T, class... P, size_t... Is> +template <typename T, typename... P, size_t... Is> void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -253,7 +253,7 @@ void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) con (void)(p_args); // Avoid warning. } -template <class T, class R, class... P, size_t... Is> +template <typename T, typename R, typename... P, size_t... Is> void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -264,7 +264,7 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co #endif } -template <class T, class R, class... P, size_t... Is> +template <typename T, typename R, typename... P, size_t... Is> void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -276,7 +276,7 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co (void)p_args; } -template <class T, class... P> +template <typename T, typename... P> void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -311,7 +311,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class... P> +template <typename T, typename... P> void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -346,7 +346,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class R, class... P> +template <typename T, typename R, typename... P> void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -381,7 +381,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); } -template <class T, class R, class... P> +template <typename T, typename R, typename... P> void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -423,7 +423,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #endif -template <class Q> +template <typename Q> void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) { if (p_arg == index) { type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE); @@ -431,7 +431,7 @@ void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType index++; } -template <class... P> +template <typename... P> GDExtensionVariantType call_get_argument_type(int p_arg) { GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL; int index = 0; @@ -443,7 +443,7 @@ GDExtensionVariantType call_get_argument_type(int p_arg) { return type; } -template <class Q> +template <typename Q> void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { if (p_arg == index) { info = GetTypeInfo<Q>::get_class_info(); @@ -451,7 +451,7 @@ void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &inf index++; } -template <class... P> +template <typename... P> void call_get_argument_type_info(int p_arg, PropertyInfo &info) { int index = 0; // I think rocket science is simpler than modern C++. @@ -461,7 +461,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) { (void)index; // Suppress GCC warning. } -template <class Q> +template <typename Q> void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) { if (p_arg == index) { md = GetTypeInfo<Q>::METADATA; @@ -469,7 +469,7 @@ void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMe index++; } -template <class... P> +template <typename... P> GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) { GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; @@ -482,7 +482,7 @@ GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) { return md; } -template <class... P, size_t... Is> +template <typename... P, size_t... Is> void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -493,7 +493,7 @@ void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_arg #endif } -template <class... P> +template <typename... P> void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -528,17 +528,17 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{}); } -template <class... P, size_t... Is> +template <typename... P, size_t... Is> void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) { p_method(PtrToArg<P>::convert(p_args[Is])...); } -template <class... P> +template <typename... P> void call_with_ptr_args_static_method(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args) { call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); } -template <class R, class... P, size_t... Is> +template <typename R, typename... P, size_t... Is> void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) { r_error.error = GDEXTENSION_CALL_OK; @@ -549,7 +549,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar #endif } -template <class R, class... P> +template <typename R, typename... P> void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) { #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { @@ -584,12 +584,12 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); } -template <class R, class... P, size_t... Is> +template <typename R, typename... P, size_t... Is> void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) { PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret); } -template <class R, class... P> +template <typename R, typename... P> void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) { call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); } diff --git a/include/godot_cpp/core/builtin_ptrcall.hpp b/include/godot_cpp/core/builtin_ptrcall.hpp index 19250d845..286051fa8 100644 --- a/include/godot_cpp/core/builtin_ptrcall.hpp +++ b/include/godot_cpp/core/builtin_ptrcall.hpp @@ -40,7 +40,7 @@ namespace godot { namespace internal { -template <class O, class... Args> +template <typename O, typename... Args> O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) { GodotObject *ret = nullptr; std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; @@ -51,13 +51,13 @@ O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GD return reinterpret_cast<O *>(internal::get_object_instance_binding(ret)); } -template <class... Args> +template <typename... Args> void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) { std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; constructor(base, call_args.data()); } -template <class T, class... Args> +template <typename T, typename... Args> T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) { T ret; std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; @@ -65,20 +65,20 @@ T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExten return ret; } -template <class... Args> +template <typename... Args> void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) { std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } }; method(base, call_args.data(), nullptr, sizeof...(Args)); } -template <class T> +template <typename T> T _call_builtin_operator_ptr(const GDExtensionPtrOperatorEvaluator op, GDExtensionConstTypePtr left, GDExtensionConstTypePtr right) { T ret; op(left, right, &ret); return ret; } -template <class T> +template <typename T> T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) { T ret; getter(base, &ret); diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 5b0a6ddf3..26f58e4af 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -114,26 +114,26 @@ class ClassDB { static void initialize_class(const ClassInfo &cl); static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method); - template <class T, bool is_abstract> + template <typename T, bool is_abstract> static void _register_class(bool p_virtual = false); public: - template <class T> + template <typename T> static void register_class(bool p_virtual = false); - template <class T> + template <typename T> static void register_abstract_class(); _FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { instance_binding_callbacks[p_name] = p_callbacks; } - template <class N, class M, typename... VarArgs> + template <typename N, typename M, typename... VarArgs> static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args); - template <class N, class M, typename... VarArgs> + template <typename N, typename M, typename... VarArgs> static MethodBind *bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args); - template <class M> + template <typename M> static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true); static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix); @@ -171,7 +171,7 @@ class ClassDB { ::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) { static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS."); instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks; @@ -219,17 +219,17 @@ void ClassDB::_register_class(bool p_virtual) { initialize_class(classes[cl.name]); } -template <class T> +template <typename T> void ClassDB::register_class(bool p_virtual) { ClassDB::_register_class<T, false>(p_virtual); } -template <class T> +template <typename T> void ClassDB::register_abstract_class() { ClassDB::_register_class<T, true>(); } -template <class N, class M, typename... VarArgs> +template <typename N, typename M, typename... VarArgs> MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; @@ -240,7 +240,7 @@ MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args)); } -template <class N, class M, typename... VarArgs> +template <typename N, typename M, typename... VarArgs> MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. const Variant *argptrs[sizeof...(p_args) + 1]; @@ -252,7 +252,7 @@ MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p return bind_methodfi(0, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args)); } -template <class M> +template <typename M> MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) { MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant); ERR_FAIL_NULL_V(bind, nullptr); diff --git a/include/godot_cpp/core/defs.hpp b/include/godot_cpp/core/defs.hpp index c03db5035..16812c2b4 100644 --- a/include/godot_cpp/core/defs.hpp +++ b/include/godot_cpp/core/defs.hpp @@ -108,7 +108,7 @@ typedef float real_t; // Generic swap template. #ifndef SWAP #define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y)) -template <class T> +template <typename T> inline void __swap_tmpl(T &x, T &y) { T aux = x; x = y; diff --git a/include/godot_cpp/core/engine_ptrcall.hpp b/include/godot_cpp/core/engine_ptrcall.hpp index 69ab196bf..482dfab71 100644 --- a/include/godot_cpp/core/engine_ptrcall.hpp +++ b/include/godot_cpp/core/engine_ptrcall.hpp @@ -43,7 +43,7 @@ namespace godot { namespace internal { -template <class O, class... Args> +template <typename O, typename... Args> O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { GodotObject *ret = nullptr; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; @@ -54,7 +54,7 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co return reinterpret_cast<O *>(internal::get_object_instance_binding(ret)); } -template <class R, class... Args> +template <typename R, typename... Args> R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { R ret; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; @@ -62,13 +62,13 @@ R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const A return ret; } -template <class... Args> +template <typename... Args> void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr); } -template <class R, class... Args> +template <typename R, typename... Args> R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) { R ret; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; @@ -76,7 +76,7 @@ R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) { return ret; } -template <class... Args> +template <typename... Args> Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *instance, const Args &...args) { GodotObject *ret = nullptr; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; @@ -84,7 +84,7 @@ Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *in return (Object *)internal::get_object_instance_binding(ret); } -template <class... Args> +template <typename... Args> void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &...args) { std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; func(nullptr, mb_args.data(), mb_args.size()); diff --git a/include/godot_cpp/core/math.hpp b/include/godot_cpp/core/math.hpp index db97ba5db..2cbbe2726 100644 --- a/include/godot_cpp/core/math.hpp +++ b/include/godot_cpp/core/math.hpp @@ -84,7 +84,7 @@ constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) { // Generic swap template. #ifndef SWAP #define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y)) -template <class T> +template <typename T> inline void __swap_tmpl(T &x, T &y) { T aux = x; x = y; @@ -138,7 +138,7 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) { return -1; } -template <class T> +template <typename T> static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { --x; diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index 1c44d63fa..750509455 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -83,7 +83,7 @@ class Memory { _ALWAYS_INLINE_ void postinitialize_handler(void *) {} -template <class T> +template <typename T> _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { postinitialize_handler(p_obj); return p_obj; @@ -99,12 +99,12 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { #define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new (m_placement, sizeof(m_class), "") m_class) // Generic comparator used in Map, List, etc. -template <class T> +template <typename T> struct Comparator { _ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); } }; -template <class T> +template <typename T> void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) { if constexpr (!std::is_trivially_destructible_v<T>) { p_class->~T(); @@ -113,12 +113,12 @@ void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wra Memory::free_static(p_class); } -template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true> +template <typename T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true> void memdelete(T *p_class) { godot::internal::gdextension_interface_object_destroy(p_class->_owner); } -template <class T, class A> +template <typename T, typename A> void memdelete_allocator(T *p_class) { if constexpr (!std::is_trivially_destructible_v<T>) { p_class->~T(); @@ -133,10 +133,10 @@ class DefaultAllocator { _ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); } }; -template <class T> +template <typename T> class DefaultTypedAllocator { public: - template <class... Args> + template <typename... Args> _ALWAYS_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); } _ALWAYS_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); } }; diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index 37ae73176..4afd7b8a1 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -147,7 +147,7 @@ class 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 { protected: R(T::*method) @@ -208,7 +208,7 @@ class MethodBindVarArgBase : public MethodBind { } }; -template <class T> +template <typename T> class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> { friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>; @@ -231,14 +231,14 @@ class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, v } }; -template <class T> +template <typename T> MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant)); a->set_instance_class(T::get_class_static()); return a; } -template <class T, class R> +template <typename T, typename R> class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> { friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>; @@ -260,7 +260,7 @@ class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, } }; -template <class T, class R> +template <typename T, typename R> MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant)); a->set_instance_class(T::get_class_static()); @@ -277,9 +277,9 @@ class _gde_UnexistingClass; // No return, not const. #ifdef TYPED_METHOD_BIND -template <class T, class... P> +template <typename T, typename... P> #else -template <class... P> +template <typename... P> #endif // TYPED_METHOD_BIND class MethodBindT : public MethodBind { void (MB_T::*method)(P...); @@ -339,7 +339,7 @@ class MethodBindT : public MethodBind { } }; -template <class T, class... P> +template <typename T, typename... P> MethodBind *create_method_bind(void (T::*p_method)(P...)) { #ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindT<T, P...>)(p_method)); @@ -353,9 +353,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) { // No return, const. #ifdef TYPED_METHOD_BIND -template <class T, class... P> +template <typename T, typename... P> #else -template <class... P> +template <typename... P> #endif // TYPED_METHOD_BIND class MethodBindTC : public MethodBind { void (MB_T::*method)(P...) const; @@ -415,7 +415,7 @@ class MethodBindTC : public MethodBind { } }; -template <class T, class... P> +template <typename T, typename... P> MethodBind *create_method_bind(void (T::*p_method)(P...) const) { #ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method)); @@ -429,9 +429,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...) const) { // Return, not const. #ifdef TYPED_METHOD_BIND -template <class T, class R, class... P> +template <typename T, typename R, typename... P> #else -template <class R, class... P> +template <typename R, typename... P> #endif // TYPED_METHOD_BIND class MethodBindTR : public MethodBind { R(MB_T::*method) @@ -498,7 +498,7 @@ class MethodBindTR : public MethodBind { } }; -template <class T, class R, class... P> +template <typename T, typename R, typename... P> MethodBind *create_method_bind(R (T::*p_method)(P...)) { #ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method)); @@ -512,9 +512,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) { // Return, const. #ifdef TYPED_METHOD_BIND -template <class T, class R, class... P> +template <typename T, typename R, typename... P> #else -template <class R, class... P> +template <typename R, typename... P> #endif // TYPED_METHOD_BIND class MethodBindTRC : public MethodBind { R(MB_T::*method) @@ -581,7 +581,7 @@ class MethodBindTRC : public MethodBind { } }; -template <class T, class R, class... P> +template <typename T, typename R, typename... P> MethodBind *create_method_bind(R (T::*p_method)(P...) const) { #ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method)); @@ -596,7 +596,7 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) { // no return -template <class... P> +template <typename... P> class MethodBindTS : public MethodBind { void (*function)(P...); @@ -652,7 +652,7 @@ class MethodBindTS : public MethodBind { } }; -template <class... P> +template <typename... P> MethodBind *create_static_method_bind(void (*p_method)(P...)) { MethodBind *a = memnew((MethodBindTS<P...>)(p_method)); return a; @@ -660,7 +660,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) { // return -template <class R, class... P> +template <typename R, typename... P> class MethodBindTRS : public MethodBind { R(*function) (P...); @@ -722,7 +722,7 @@ class MethodBindTRS : public MethodBind { } }; -template <class R, class... P> +template <typename R, typename... P> MethodBind *create_static_method_bind(R (*p_method)(P...)) { MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method)); return a; diff --git a/include/godot_cpp/core/method_ptrcall.hpp b/include/godot_cpp/core/method_ptrcall.hpp index 32f3f459d..ca3327ed9 100644 --- a/include/godot_cpp/core/method_ptrcall.hpp +++ b/include/godot_cpp/core/method_ptrcall.hpp @@ -39,7 +39,7 @@ namespace godot { -template <class T> +template <typename T> struct PtrToArg {}; #define MAKE_PTRARG(m_type) \ @@ -166,7 +166,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant); // This is for Object. -template <class T> +template <typename T> struct PtrToArg<T *> { static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object"); _FORCE_INLINE_ static T *convert(const void *p_ptr) { @@ -178,7 +178,7 @@ struct PtrToArg<T *> { } }; -template <class T> +template <typename T> struct PtrToArg<const T *> { static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object"); _FORCE_INLINE_ static const T *convert(const void *p_ptr) { diff --git a/include/godot_cpp/core/object.hpp b/include/godot_cpp/core/object.hpp index eb0c4d16d..a10cde0ef 100644 --- a/include/godot_cpp/core/object.hpp +++ b/include/godot_cpp/core/object.hpp @@ -75,31 +75,31 @@ struct MethodInfo { MethodInfo(); MethodInfo(StringName p_name); - template <class... Args> + template <typename... Args> MethodInfo(StringName p_name, const Args &...args); MethodInfo(Variant::Type ret); MethodInfo(Variant::Type ret, StringName p_name); - template <class... Args> + template <typename... Args> MethodInfo(Variant::Type ret, StringName p_name, const Args &...args); MethodInfo(const PropertyInfo &p_ret, StringName p_name); - template <class... Args> + template <typename... Args> MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...); }; -template <class... Args> +template <typename... Args> MethodInfo::MethodInfo(StringName p_name, const Args &...args) : name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { arguments = { args... }; } -template <class... Args> +template <typename... Args> MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) : name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { return_val.type = ret; arguments = { args... }; } -template <class... Args> +template <typename... Args> MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...args) : name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { arguments = { args... }; @@ -138,7 +138,7 @@ class ObjectDB { } }; -template <class T> +template <typename T> T *Object::cast_to(Object *p_object) { if (p_object == nullptr) { return nullptr; @@ -151,7 +151,7 @@ T *Object::cast_to(Object *p_object) { return dynamic_cast<T *>(internal::get_object_instance_binding(casted)); } -template <class T> +template <typename T> const T *Object::cast_to(const Object *p_object) { if (p_object == nullptr) { return nullptr; diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index 6873e1f59..2c4f8e404 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -90,7 +90,7 @@ static PropertyInfo make_property_info(Variant::Type p_type, const StringName &p // instead of a forward declaration. You can always forward declare 'T' in a header file, and then // include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated. -template <class T, typename = void> +template <typename T, typename = void> struct GetTypeInfo; #define MAKE_TYPE_INFO(m_type, m_var_type) \ @@ -248,7 +248,7 @@ inline StringName _gde_constant_get_enum_name(T param, StringName p_constant) { return GetTypeInfo<T>::get_class_info().class_name; } -template <class T> +template <typename T> class BitField { int64_t value = 0; @@ -295,7 +295,7 @@ inline StringName _gde_constant_get_bitfield_name(T param, StringName p_constant return GetTypeInfo<BitField<T>>::get_class_info().class_name; } -template <class T> +template <typename T> struct PtrToArg<TypedArray<T>> { _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr)); @@ -306,7 +306,7 @@ struct PtrToArg<TypedArray<T>> { } }; -template <class T> +template <typename T> struct PtrToArg<const TypedArray<T> &> { typedef Array EncodeT; _FORCE_INLINE_ static TypedArray<T> diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index f2959d197..dcb74eccc 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -43,13 +43,13 @@ namespace godot { -template <class T> +template <typename T> class Vector; -template <class T, class V> +template <typename T, typename V> class VMap; -template <class T> +template <typename T> class CharStringT; static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>); @@ -60,15 +60,15 @@ static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>); #pragma GCC diagnostic ignored "-Wplacement-new" #endif -template <class T> +template <typename T> class CowData { - template <class TV> + template <typename TV> friend class Vector; - template <class TV, class VV> + template <typename TV, typename VV> friend class VMap; - template <class TS> + template <typename TS> friend class CharStringT; public: @@ -248,7 +248,7 @@ class CowData { _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }; }; -template <class T> +template <typename T> void CowData<T>::_unref(void *p_data) { if (!p_data) { return; @@ -275,7 +275,7 @@ void CowData<T>::_unref(void *p_data) { Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false); } -template <class T> +template <typename T> typename CowData<T>::USize CowData<T>::_copy_on_write() { if (!_ptr) { return 0; @@ -315,7 +315,7 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() { return rc; } -template <class T> +template <typename T> template <bool p_ensure_zero> Error CowData<T>::resize(Size p_size) { ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); @@ -407,7 +407,7 @@ Error CowData<T>::resize(Size p_size) { return OK; } -template <class T> +template <typename T> typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const { Size ret = -1; @@ -425,7 +425,7 @@ typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const { return ret; } -template <class T> +template <typename T> typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const { const Size s = size(); @@ -444,7 +444,7 @@ typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const { return -1; } -template <class T> +template <typename T> typename CowData<T>::Size CowData<T>::count(const T &p_val) const { Size amount = 0; for (Size i = 0; i < size(); i++) { @@ -455,12 +455,12 @@ typename CowData<T>::Size CowData<T>::count(const T &p_val) const { return amount; } -template <class T> +template <typename T> void CowData<T>::_ref(const CowData *p_from) { _ref(*p_from); } -template <class T> +template <typename T> void CowData<T>::_ref(const CowData &p_from) { if (_ptr == p_from._ptr) { return; // self assign, do nothing. @@ -478,7 +478,7 @@ void CowData<T>::_ref(const CowData &p_from) { } } -template <class T> +template <typename T> CowData<T>::~CowData() { _unref(_ptr); } diff --git a/include/godot_cpp/templates/hash_map.hpp b/include/godot_cpp/templates/hash_map.hpp index 77c7b7a91..59cd8e0b0 100644 --- a/include/godot_cpp/templates/hash_map.hpp +++ b/include/godot_cpp/templates/hash_map.hpp @@ -52,7 +52,7 @@ namespace godot { * The assignment operator copy the pairs from one map to the other. */ -template <class TKey, class TValue> +template <typename TKey, typename TValue> struct HashMapElement { HashMapElement *next = nullptr; HashMapElement *prev = nullptr; @@ -62,10 +62,10 @@ struct HashMapElement { data(p_key, p_value) {} }; -template <class TKey, class TValue, - class Hasher = HashMapHasherDefault, - class Comparator = HashMapComparatorDefault<TKey>, - class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>> +template <typename TKey, typename TValue, + typename Hasher = HashMapHasherDefault, + typename Comparator = HashMapComparatorDefault<TKey>, + typename Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>> class HashMap { public: const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. diff --git a/include/godot_cpp/templates/hash_set.hpp b/include/godot_cpp/templates/hash_set.hpp index 884ae4db7..1845a1bb4 100644 --- a/include/godot_cpp/templates/hash_set.hpp +++ b/include/godot_cpp/templates/hash_set.hpp @@ -48,9 +48,9 @@ namespace godot { * */ -template <class TKey, - class Hasher = HashMapHasherDefault, - class Comparator = HashMapComparatorDefault<TKey>> +template <typename TKey, + typename Hasher = HashMapHasherDefault, + typename Comparator = HashMapComparatorDefault<TKey>> class HashSet { public: static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. diff --git a/include/godot_cpp/templates/hashfuncs.hpp b/include/godot_cpp/templates/hashfuncs.hpp index d6f340029..40b10a9e2 100644 --- a/include/godot_cpp/templates/hashfuncs.hpp +++ b/include/godot_cpp/templates/hashfuncs.hpp @@ -253,7 +253,7 @@ static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i); } -template <class T> +template <typename T> static _FORCE_INLINE_ uint32_t hash_make_uint32_t(T p_in) { union { T t; @@ -286,7 +286,7 @@ static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = return ((p_prev << 5) + p_prev) ^ p_in; } -template <class T> +template <typename T> static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) { union { T t; @@ -298,15 +298,15 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) { return _u._u64; } -template <class T> +template <typename T> class Ref; struct HashMapHasherDefault { // Generic hash function for any type. - template <class T> + template <typename T> static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } - template <class T> + template <typename T> static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); } static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } diff --git a/include/godot_cpp/templates/list.hpp b/include/godot_cpp/templates/list.hpp index 2c8a7c874..376e3ea87 100644 --- a/include/godot_cpp/templates/list.hpp +++ b/include/godot_cpp/templates/list.hpp @@ -45,7 +45,7 @@ namespace godot { -template <class T, class A = DefaultAllocator> +template <typename T, typename A = DefaultAllocator> class List { struct _Data; @@ -410,7 +410,7 @@ class List { /** * find an element in the list, */ - template <class T_v> + template <typename T_v> Element *find(const T_v &p_val) { Element *it = front(); while (it) { @@ -646,7 +646,7 @@ class List { sort_custom<Comparator<T>>(); } - template <class C> + template <typename C> void sort_custom_inplace() { if (size() < 2) { return; @@ -693,7 +693,7 @@ class List { _data->last = to; } - template <class C> + template <typename C> struct AuxiliaryComparator { C compare; _FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const { @@ -701,7 +701,7 @@ class List { } }; - template <class C> + template <typename C> void sort_custom() { // this version uses auxiliary memory for speed. // if you don't want to use auxiliary memory, use the in_place version diff --git a/include/godot_cpp/templates/local_vector.hpp b/include/godot_cpp/templates/local_vector.hpp index 8ce4e6552..5dad32e0e 100644 --- a/include/godot_cpp/templates/local_vector.hpp +++ b/include/godot_cpp/templates/local_vector.hpp @@ -43,7 +43,7 @@ namespace godot { // If tight, it grows strictly as much as needed. // Otherwise, it grows exponentially (the default and what you want in most cases). -template <class T, class U = uint32_t, bool force_trivial = false, bool tight = false> +template <typename T, typename U = uint32_t, bool force_trivial = false, bool tight = false> class LocalVector { private: U count = 0; @@ -257,7 +257,7 @@ class LocalVector { return -1; } - template <class C> + template <typename C> void sort_custom() { U len = count; if (len == 0) { @@ -331,7 +331,7 @@ class LocalVector { } }; -template <class T, class U = uint32_t, bool force_trivial = false> +template <typename T, typename U = uint32_t, bool force_trivial = false> using TightLocalVector = LocalVector<T, U, force_trivial, true>; } // namespace godot diff --git a/include/godot_cpp/templates/pair.hpp b/include/godot_cpp/templates/pair.hpp index ed35302b1..f87541305 100644 --- a/include/godot_cpp/templates/pair.hpp +++ b/include/godot_cpp/templates/pair.hpp @@ -33,7 +33,7 @@ namespace godot { -template <class F, class S> +template <typename F, typename S> struct Pair { F first; S second; @@ -49,17 +49,17 @@ struct Pair { } }; -template <class F, class S> +template <typename F, typename S> bool operator==(const Pair<F, S> &pair, const Pair<F, S> &other) { return (pair.first == other.first) && (pair.second == other.second); } -template <class F, class S> +template <typename F, typename S> bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) { return (pair.first != other.first) || (pair.second != other.second); } -template <class F, class S> +template <typename F, typename S> struct PairSort { bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const { if (A.first != B.first) { @@ -69,7 +69,7 @@ struct PairSort { } }; -template <class K, class V> +template <typename K, typename V> struct KeyValue { const K key; V value; @@ -85,17 +85,17 @@ struct KeyValue { } }; -template <class K, class V> +template <typename K, typename V> bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) { return (pair.key == other.key) && (pair.value == other.value); } -template <class K, class V> +template <typename K, typename V> bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) { return (pair.key != other.key) || (pair.value != other.value); } -template <class K, class V> +template <typename K, typename V> struct KeyValueSort { bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const { return A.key < B.key; diff --git a/include/godot_cpp/templates/rb_map.hpp b/include/godot_cpp/templates/rb_map.hpp index cce1e91b9..6ab71fd7e 100644 --- a/include/godot_cpp/templates/rb_map.hpp +++ b/include/godot_cpp/templates/rb_map.hpp @@ -40,7 +40,7 @@ namespace godot { // based on the very nice implementation of rb-trees by: // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html -template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator> +template <typename K, typename V, typename C = Comparator<K>, typename A = DefaultAllocator> class RBMap { enum Color { RED, diff --git a/include/godot_cpp/templates/rb_set.hpp b/include/godot_cpp/templates/rb_set.hpp index c803f8183..69aa8d7f9 100644 --- a/include/godot_cpp/templates/rb_set.hpp +++ b/include/godot_cpp/templates/rb_set.hpp @@ -38,7 +38,7 @@ namespace godot { -template <class T, class C = Comparator<T>, class A = DefaultAllocator> +template <typename T, typename C = Comparator<T>, typename A = DefaultAllocator> class RBSet { enum Color { RED, diff --git a/include/godot_cpp/templates/rid_owner.hpp b/include/godot_cpp/templates/rid_owner.hpp index 005fc876f..1dd4a3933 100644 --- a/include/godot_cpp/templates/rid_owner.hpp +++ b/include/godot_cpp/templates/rid_owner.hpp @@ -42,7 +42,7 @@ namespace godot { -template <class T, bool THREAD_SAFE = false> +template <typename T, bool THREAD_SAFE = false> class RID_Alloc { T **chunks = nullptr; uint32_t **free_list_chunks = nullptr; @@ -347,7 +347,7 @@ class RID_Alloc { } }; -template <class T, bool THREAD_SAFE = false> +template <typename T, bool THREAD_SAFE = false> class RID_PtrOwner { RID_Alloc<T *, THREAD_SAFE> alloc; @@ -406,7 +406,7 @@ class RID_PtrOwner { alloc(p_target_chunk_byte_size) {} }; -template <class T, bool THREAD_SAFE = false> +template <typename T, bool THREAD_SAFE = false> class RID_Owner { RID_Alloc<T, THREAD_SAFE> alloc; diff --git a/include/godot_cpp/templates/safe_refcount.hpp b/include/godot_cpp/templates/safe_refcount.hpp index 519bbf742..12e6840ae 100644 --- a/include/godot_cpp/templates/safe_refcount.hpp +++ b/include/godot_cpp/templates/safe_refcount.hpp @@ -57,7 +57,7 @@ namespace godot { static_assert(sizeof(SafeFlag) == sizeof(bool)); \ static_assert(alignof(SafeFlag) == alignof(bool)); -template <class T> +template <typename T> class SafeNumeric { std::atomic<T> value; @@ -195,7 +195,7 @@ class SafeRefCount { #else -template <class T> +template <typename T> class SafeNumeric { protected: T value; diff --git a/include/godot_cpp/templates/search_array.hpp b/include/godot_cpp/templates/search_array.hpp index ce2713bdc..11a9db525 100644 --- a/include/godot_cpp/templates/search_array.hpp +++ b/include/godot_cpp/templates/search_array.hpp @@ -35,7 +35,7 @@ namespace godot { -template <class T, class Comparator = _DefaultComparator<T>> +template <typename T, typename Comparator = _DefaultComparator<T>> class SearchArray { public: Comparator compare; diff --git a/include/godot_cpp/templates/self_list.hpp b/include/godot_cpp/templates/self_list.hpp index 3bb13a354..f7a65f689 100644 --- a/include/godot_cpp/templates/self_list.hpp +++ b/include/godot_cpp/templates/self_list.hpp @@ -36,7 +36,7 @@ namespace godot { -template <class T> +template <typename T> class SelfList { public: class List { diff --git a/include/godot_cpp/templates/sort_array.hpp b/include/godot_cpp/templates/sort_array.hpp index 5dda5782c..7ce5c7842 100644 --- a/include/godot_cpp/templates/sort_array.hpp +++ b/include/godot_cpp/templates/sort_array.hpp @@ -41,7 +41,7 @@ namespace godot { break; \ } -template <class T> +template <typename T> struct _DefaultComparator { _FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); } }; @@ -52,7 +52,7 @@ struct _DefaultComparator { #define SORT_ARRAY_VALIDATE_ENABLED false #endif -template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED> +template <typename T, typename Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED> class SortArray { enum { INTROSORT_THRESHOLD = 16 diff --git a/include/godot_cpp/templates/thread_work_pool.hpp b/include/godot_cpp/templates/thread_work_pool.hpp index a3efd42e0..cb20c6e97 100644 --- a/include/godot_cpp/templates/thread_work_pool.hpp +++ b/include/godot_cpp/templates/thread_work_pool.hpp @@ -52,7 +52,7 @@ class ThreadWorkPool { virtual ~BaseWork() = default; }; - template <class C, class M, class U> + template <typename C, typename M, typename U> struct Work : public BaseWork { C *instance; M method; @@ -94,7 +94,7 @@ class ThreadWorkPool { } public: - template <class C, class M, class U> + template <typename C, typename M, typename U> void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { ERR_FAIL_NULL(threads); // Never initialized. ERR_FAIL_COND(current_work != nullptr); @@ -145,7 +145,7 @@ class ThreadWorkPool { current_work = nullptr; } - template <class C, class M, class U> + template <typename C, typename M, typename U> void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { switch (p_elements) { case 0: diff --git a/include/godot_cpp/templates/vector.hpp b/include/godot_cpp/templates/vector.hpp index 05b7184c4..aaa84f338 100644 --- a/include/godot_cpp/templates/vector.hpp +++ b/include/godot_cpp/templates/vector.hpp @@ -47,7 +47,7 @@ namespace godot { -template <class T> +template <typename T> class VectorWriteProxy { public: _FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) { @@ -57,7 +57,7 @@ class VectorWriteProxy { } }; -template <class T> +template <typename T> class Vector { friend class VectorWriteProxy<T>; @@ -110,7 +110,7 @@ class Vector { sort_custom<_DefaultComparator<T>>(); } - template <class Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, class... Args> + template <typename Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, typename... Args> void sort_custom(Args &&...args) { Size len = _cowdata.size(); if (len == 0) { @@ -126,7 +126,7 @@ class Vector { return bsearch_custom<_DefaultComparator<T>>(p_value, p_before); } - template <class Comparator, class Value, class... Args> + template <typename Comparator, typename Value, typename... Args> Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) { SearchArray<T, Comparator> search{ args... }; return search.bisect(ptrw(), size(), p_value, p_before); @@ -293,7 +293,7 @@ class Vector { _FORCE_INLINE_ ~Vector() {} }; -template <class T> +template <typename T> void Vector<T>::reverse() { for (Size i = 0; i < size() / 2; i++) { T *p = ptrw(); @@ -301,7 +301,7 @@ void Vector<T>::reverse() { } } -template <class T> +template <typename T> void Vector<T>::append_array(Vector<T> p_other) { const Size ds = p_other.size(); if (ds == 0) { @@ -314,7 +314,7 @@ void Vector<T>::append_array(Vector<T> p_other) { } } -template <class T> +template <typename T> bool Vector<T>::push_back(T p_elem) { Error err = resize(size() + 1); ERR_FAIL_COND_V(err, true); @@ -323,7 +323,7 @@ bool Vector<T>::push_back(T p_elem) { return false; } -template <class T> +template <typename T> void Vector<T>::fill(T p_elem) { T *p = ptrw(); for (Size i = 0; i < size(); i++) { diff --git a/include/godot_cpp/templates/vmap.hpp b/include/godot_cpp/templates/vmap.hpp index 881ac25e6..926ccd390 100644 --- a/include/godot_cpp/templates/vmap.hpp +++ b/include/godot_cpp/templates/vmap.hpp @@ -35,7 +35,7 @@ namespace godot { -template <class T, class V> +template <typename T, typename V> class VMap { public: struct Pair { diff --git a/include/godot_cpp/templates/vset.hpp b/include/godot_cpp/templates/vset.hpp index 29f0cefe9..ce21ba83f 100644 --- a/include/godot_cpp/templates/vset.hpp +++ b/include/godot_cpp/templates/vset.hpp @@ -35,7 +35,7 @@ namespace godot { -template <class T> +template <typename T> class VSet { Vector<T> _data; diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index 993d0467d..991c0392a 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -38,12 +38,12 @@ namespace godot { -template <class T> +template <typename T> class CharStringT; -template <class T> +template <typename T> class CharProxy { - template <class TS> + template <typename TS> friend class CharStringT; const int64_t _index; @@ -80,7 +80,7 @@ class CharProxy { } }; -template <class T> +template <typename T> class CharStringT { friend class String; diff --git a/include/godot_cpp/variant/typed_array.hpp b/include/godot_cpp/variant/typed_array.hpp index 5e7084e4a..54738a640 100644 --- a/include/godot_cpp/variant/typed_array.hpp +++ b/include/godot_cpp/variant/typed_array.hpp @@ -36,7 +36,7 @@ namespace godot { -template <class T> +template <typename T> class TypedArray : public Array { public: _FORCE_INLINE_ void operator=(const Array &p_array) { diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 5c3d6fea0..76fb8d111 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -269,7 +269,7 @@ class Variant { void callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); - template <class... Args> + template <typename... Args> Variant call(const StringName &method, Args... args) { std::array<Variant, sizeof...(args)> vargs = { args... }; std::array<const Variant *, sizeof...(args)> argptrs; @@ -284,7 +284,7 @@ class Variant { static void callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); - template <class... Args> + template <typename... Args> static Variant call_static(Variant::Type type, const StringName &method, Args... args) { std::array<Variant, sizeof...(args)> vargs = { args... }; std::array<const Variant *, sizeof...(args)> argptrs; diff --git a/src/variant/char_string.cpp b/src/variant/char_string.cpp index 153339899..37b41f6ac 100644 --- a/src/variant/char_string.cpp +++ b/src/variant/char_string.cpp @@ -65,7 +65,7 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { } } -template <class T> +template <typename T> bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const { if (length() == 0) { return p_right.length() != 0; @@ -74,7 +74,7 @@ bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const { return is_str_less(get_data(), p_right.get_data()); } -template <class T> +template <typename T> CharStringT<T> &CharStringT<T>::operator+=(T p_char) { const int64_t lhs_len = length(); resize(lhs_len + 2); @@ -86,7 +86,7 @@ CharStringT<T> &CharStringT<T>::operator+=(T p_char) { return *this; } -template <class T> +template <typename T> void CharStringT<T>::operator=(const T *p_cstr) { copy_from(p_cstr); } @@ -127,7 +127,7 @@ const wchar_t *CharStringT<wchar_t>::get_data() const { } } -template <class T> +template <typename T> void CharStringT<T>::copy_from(const T *p_cstr) { if (!p_cstr) { resize(0); From 594a93f8ac9e524775ffc9609daa366fd849eea1 Mon Sep 17 00:00:00 2001 From: ytnuf <161308826+ytnuf@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:25:56 +0000 Subject: [PATCH 29/36] Change cmake_minimum_required to match actual requirements This is because target_link_options was added in v3.13 So this wouldn't build with cmake v3.12 Likewise in CMAKE_CXX_STANDARD only supports value of 17 starting with cmake v3.9 So the test wouldn't build properly with cmake v3.6 (cherry picked from commit 5c12bd22872742f274079fb11e6d884d4dd2723e) --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9603ab6d..dd43a04db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ # Todo # Test build for Windows, Mac and mingw. -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.13) project(godot-cpp LANGUAGES CXX) option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a17b9aacd..c0457bfbd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ +cmake_minimum_required(VERSION 3.13) project(godot-cpp-test) -cmake_minimum_required(VERSION 3.6) set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory") set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings") From c8fa4c0fd0a1a74a65e8ed294b7803a1de0b6d56 Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:19:54 +0100 Subject: [PATCH 30/36] Fix incorrect utility call signature (cherry picked from commit d055b575fb325b8ce72345dc924a52b22d9e2255) --- include/godot_cpp/core/engine_ptrcall.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/godot_cpp/core/engine_ptrcall.hpp b/include/godot_cpp/core/engine_ptrcall.hpp index 482dfab71..555806b8e 100644 --- a/include/godot_cpp/core/engine_ptrcall.hpp +++ b/include/godot_cpp/core/engine_ptrcall.hpp @@ -77,7 +77,7 @@ R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...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; std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } }; func(&ret, mb_args.data(), mb_args.size()); From 8e5d7c926873e071fac23557c5d4081203af8926 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews <repiteo@outlook.com> Date: Wed, 10 Apr 2024 13:51:53 -0500 Subject: [PATCH 31/36] Use `GDREGISTER` defines in example (cherry picked from commit a537b4af4ded29ee715a950f47887cb5367b9825) --- README.md | 2 +- test/src/register_types.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b11628408..16f7b2d1a 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } - ClassDB::register_class<Example>(); + GDREGISTER_CLASS(Example); } ``` diff --git a/test/src/register_types.cpp b/test/src/register_types.cpp index 560dd907c..5f082329b 100644 --- a/test/src/register_types.cpp +++ b/test/src/register_types.cpp @@ -21,13 +21,13 @@ void initialize_example_module(ModuleInitializationLevel p_level) { return; } - ClassDB::register_class<ExampleRef>(); - ClassDB::register_class<ExampleMin>(); - ClassDB::register_class<Example>(); - ClassDB::register_class<ExampleVirtual>(true); - ClassDB::register_abstract_class<ExampleAbstract>(); - ClassDB::register_class<ExampleBase>(); - ClassDB::register_class<ExampleChild>(); + GDREGISTER_CLASS(ExampleRef); + GDREGISTER_CLASS(ExampleMin); + GDREGISTER_CLASS(Example); + GDREGISTER_VIRTUAL_CLASS(ExampleVirtual); + GDREGISTER_ABSTRACT_CLASS(ExampleAbstract); + GDREGISTER_CLASS(ExampleBase); + GDREGISTER_CLASS(ExampleChild); } void uninitialize_example_module(ModuleInitializationLevel p_level) { From 7f3e725a8a104356a71eb6fe1a3f868bad69c0c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:23:26 +0000 Subject: [PATCH 32/36] Bump mymindstorm/setup-emsdk from 13 to 14 Bumps [mymindstorm/setup-emsdk](https://github.com/mymindstorm/setup-emsdk) from 13 to 14. - [Release notes](https://github.com/mymindstorm/setup-emsdk/releases) - [Commits](https://github.com/mymindstorm/setup-emsdk/compare/v13...v14) --- updated-dependencies: - dependency-name: mymindstorm/setup-emsdk dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> (cherry picked from commit 32ca574f494b3e45b1ce2224f4f4e271cbd7c822) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ada01e93b..764a06f68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,7 +117,7 @@ jobs: - name: Web dependencies if: ${{ matrix.platform == 'web' }} - uses: mymindstorm/setup-emsdk@v13 + uses: mymindstorm/setup-emsdk@v14 with: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} From 28a6609c0b91ee23ee7c172bf3c43747acc5fe7c Mon Sep 17 00:00:00 2001 From: Thaddeus Crews <repiteo@outlook.com> Date: Thu, 18 Jan 2024 14:22:16 -0600 Subject: [PATCH 33/36] Implement `verbose` toggle from godot repo (cherry picked from commit b05c21bb1d41cfc1f94140884059da93a80ce43e) --- .github/workflows/ci.yml | 8 ++--- tools/godotcpp.py | 73 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 764a06f68..89258520d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,22 +134,22 @@ jobs: - name: Generate godot-cpp sources only run: | - scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }} + scons platform=${{ matrix.platform }} verbose=yes build_library=no ${{ matrix.flags }} scons -c - name: Build godot-cpp (debug) run: | - scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }} + scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} - name: Build test without rebuilding godot-cpp (debug) run: | cd test - scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }} build_library=no + scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} build_library=no - name: Build test and godot-cpp (release) run: | cd test - scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }} + scons platform=${{ matrix.platform }} verbose=yes target=template_release ${{ matrix.flags }} - name: Download latest Godot artifacts uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9 diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 71199c18d..92ad7aeb1 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -3,6 +3,7 @@ from SCons.Variables import EnumVariable, PathVariable, BoolVariable from SCons.Variables.BoolVariable import _text2bool from SCons.Tool import Tool +from SCons.Action import Action from SCons.Builder import Builder from SCons.Errors import UserError from SCons.Script import ARGUMENTS @@ -66,6 +67,67 @@ def get_custom_platforms(env): return platforms +def no_verbose(env): + colors = {} + + # Colors are disabled in non-TTY environments such as pipes. This means + # that if output is redirected to a file, it will not contain color codes + if sys.stdout.isatty(): + colors["blue"] = "\033[0;94m" + colors["bold_blue"] = "\033[1;94m" + colors["reset"] = "\033[0m" + else: + colors["blue"] = "" + colors["bold_blue"] = "" + colors["reset"] = "" + + # There is a space before "..." to ensure that source file names can be + # Ctrl + clicked in the VS Code terminal. + compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + java_compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + compile_shared_source_message = "{}Compiling shared {}$SOURCE{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + link_program_message = "{}Linking Program {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + link_library_message = "{}Linking Static Library {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + ranlib_library_message = "{}Ranlib Library {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + link_shared_library_message = "{}Linking Shared Library {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + generated_file_message = "{}Generating {}$TARGET{} ...{}".format( + colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] + ) + + env.Append(CXXCOMSTR=[compile_source_message]) + env.Append(CCCOMSTR=[compile_source_message]) + env.Append(SHCCCOMSTR=[compile_shared_source_message]) + env.Append(SHCXXCOMSTR=[compile_shared_source_message]) + env.Append(ARCOMSTR=[link_library_message]) + env.Append(RANLIBCOMSTR=[ranlib_library_message]) + env.Append(SHLINKCOMSTR=[link_shared_library_message]) + env.Append(LINKCOMSTR=[link_program_message]) + env.Append(JARCOMSTR=[java_library_message]) + env.Append(JAVACCOMSTR=[java_compile_source_message]) + env.Append(RCCOMSTR=[compiled_resource_message]) + env.Append(GENCOMSTR=[generated_file_message]) + + platforms = ["linux", "macos", "windows", "android", "ios", "web"] # CPU architecture options. @@ -239,6 +301,7 @@ def options(opts, env): ) opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True)) opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False)) + opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) # Add platform options (custom tools can override platforms) for pl in sorted(set(platforms + custom_platforms)): @@ -362,8 +425,16 @@ def generate(env): env.Tool("compilation_db") env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env))) + # Formatting + if not env["verbose"]: + no_verbose(env) + # Builders - env.Append(BUILDERS={"GodotCPPBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)}) + env.Append( + BUILDERS={ + "GodotCPPBindings": Builder(action=Action(scons_generate_bindings, "$GENCOMSTR"), emitter=scons_emit_files) + } + ) env.AddMethod(_godot_cpp, "GodotCPP") From e897dbe58a96f3180c86ca0defe05d2c014ef0f7 Mon Sep 17 00:00:00 2001 From: thimenesup <thimenesup@gmail.com> Date: Sun, 14 Apr 2024 20:27:53 +0200 Subject: [PATCH 34/36] Fix Projection create_orthogonal being incorrect Title (cherry picked from commit e4ae69f607fca68ca8521b384095acad2788390e) --- src/variant/projection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variant/projection.cpp b/src/variant/projection.cpp index c28e6513e..ddedc93f9 100644 --- a/src/variant/projection.cpp +++ b/src/variant/projection.cpp @@ -136,7 +136,7 @@ Projection Projection::create_for_hmd(int p_eye, real_t p_aspect, real_t p_intra Projection Projection::create_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { Projection proj; - proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_zfar, p_zfar); + proj.set_orthogonal(p_left, p_right, p_bottom, p_top, p_znear, p_zfar); return proj; } From 30ebe5fdf94e71ffcf6e9fbaf9b88faf84059963 Mon Sep 17 00:00:00 2001 From: Chris Cranford <chris@hibernate.org> Date: Tue, 16 Apr 2024 00:01:55 -0400 Subject: [PATCH 35/36] Fix PropertyInfo to use hint/usage default constants (cherry picked from commit e160966163a4ccf04b531903adc88d9531af309a) --- include/godot_cpp/core/property_info.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/godot_cpp/core/property_info.hpp b/include/godot_cpp/core/property_info.hpp index 8146859f3..72ee27187 100644 --- a/include/godot_cpp/core/property_info.hpp +++ b/include/godot_cpp/core/property_info.hpp @@ -47,9 +47,9 @@ struct PropertyInfo { Variant::Type type = Variant::NIL; StringName name; StringName class_name; - uint32_t hint = 0; + uint32_t hint = PROPERTY_HINT_NONE; String hint_string; - uint32_t usage = 7; + uint32_t usage = PROPERTY_USAGE_DEFAULT; PropertyInfo() = default; From 4b0ee133274d67687b6003b8d5fdaf7b79cf4921 Mon Sep 17 00:00:00 2001 From: David Snopek <dsnopek@gmail.com> Date: Wed, 17 Apr 2024 13:02:32 -0500 Subject: [PATCH 36/36] gdextension: Sync with upstream commit fe0e8e55752b0c2e64997025717b491703e0f8ad (4.1.4-stable) --- gdextension/extension_api.json | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json index 883b51970..09ff79bad 100644 --- a/gdextension/extension_api.json +++ b/gdextension/extension_api.json @@ -2,10 +2,10 @@ "header": { "version_major": 4, "version_minor": 1, - "version_patch": 3, + "version_patch": 4, "version_status": "stable", "version_build": "official", - "version_full_name": "Godot Engine v4.1.3.stable.official" + "version_full_name": "Godot Engine v4.1.4.stable.official" }, "builtin_class_sizes": [ { @@ -95246,13 +95246,6 @@ } ] }, - { - "name": "FramebufferCacheRD", - "is_refcounted": false, - "is_instantiable": false, - "inherits": "Object", - "api_type": "core" - }, { "name": "GDExtension", "is_refcounted": true, @@ -198993,6 +198986,23 @@ } ] }, + { + "name": "debug_canvas_item_get_rect", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 624227424, + "return_value": { + "type": "Rect2" + }, + "arguments": [ + { + "name": "item", + "type": "RID" + } + ] + }, { "name": "canvas_light_create", "is_const": false, @@ -255227,13 +255237,6 @@ } ] }, - { - "name": "UniformSetCacheRD", - "is_refcounted": false, - "is_instantiable": false, - "inherits": "Object", - "api_type": "core" - }, { "name": "VBoxContainer", "is_refcounted": false,