From e8b6887b3679a6e817834f7eb057aeca425dda55 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Sat, 4 Nov 2023 16:53:09 -0500 Subject: [PATCH 01/18] =?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 0a2b3d14..575c224e 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -154,10 +154,18 @@ public: Variant(int64_t v); Variant(int32_t v) : Variant(static_cast(v)) {} - Variant(uint32_t v) : + Variant(int16_t v) : + Variant(static_cast(v)) {} + Variant(int8_t v) : Variant(static_cast(v)) {} Variant(uint64_t v) : Variant(static_cast(v)) {} + Variant(uint32_t v) : + Variant(static_cast(v)) {} + Variant(uint16_t v) : + Variant(static_cast(v)) {} + Variant(uint8_t v) : + Variant(static_cast(v)) {} Variant(double v); Variant(float v) : Variant((double)v) {} @@ -209,8 +217,12 @@ public: 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 db15be11..945d6f40 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -268,6 +268,14 @@ Variant::operator int32_t() const { return static_cast(operator int64_t()); } +Variant::operator int16_t() const { + return static_cast(operator int64_t()); +} + +Variant::operator int8_t() const { + return static_cast(operator int64_t()); +} + Variant::operator uint64_t() const { return static_cast(operator int64_t()); } @@ -276,6 +284,14 @@ Variant::operator uint32_t() const { return static_cast(operator int64_t()); } +Variant::operator uint16_t() const { + return static_cast(operator int64_t()); +} + +Variant::operator uint8_t() const { + return static_cast(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?= Date: Mon, 20 Nov 2023 23:23:17 +0100 Subject: [PATCH 02/18] 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 0ee04d90..c9560e9c 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/18] [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 1478403b..0b7dd4a8 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 14214c0d..b40049f9 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(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (init_callback) { - init_callback(static_cast(p_level)); + InitData *init_data = static_cast(p_userdata); + if (init_data && init_data->init_callback) { + init_data->init_callback(static_cast(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(p_level) >= MODULE_INITIALIZATION_LEVEL_MAX); ClassDB::current_level = p_level; - if (terminate_callback) { - terminate_callback(static_cast(p_level)); + InitData *init_data = static_cast(p_userdata); + if (init_data && init_data->terminate_callback) { + init_data->terminate_callback(static_cast(p_level)); } - EditorPlugins::deinitialize(p_level); - ClassDB::deinitialize(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; +} + +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(p_level); + init_data->minimum_initialization_level = static_cast(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/18] 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] (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 c9560e9c..4bb1af34 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 Date: Thu, 23 Nov 2023 00:08:13 +0300 Subject: [PATCH 05/18] [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 0e688551..95efa679 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 Date: Wed, 25 Oct 2023 23:57:13 -0700 Subject: [PATCH 06/18] 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 c413cecc..bf09ba3b 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 Date: Sat, 11 Nov 2023 23:29:33 +1030 Subject: [PATCH 07/18] 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 bf09ba3b..1076e8f2 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 18db9fd0..d11d4bba 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 Date: Wed, 29 Nov 2023 11:50:48 -0600 Subject: [PATCH 08/18] 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 2c5e1b60..8a2092c1 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(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(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 eb8dbb9d..e0b186bb 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 475eed2b..848f5035 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 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