diff options
-rw-r--r-- | .github/actions/godot-cache-restore/action.yml | 25 | ||||
-rw-r--r-- | .github/actions/godot-cache-save/action.yml | 11 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 42 | ||||
-rw-r--r-- | .github/workflows/runner.yml | 21 | ||||
-rw-r--r-- | .github/workflows/static_checks.yml | 5 | ||||
-rw-r--r-- | gdextension/gdextension_interface.h | 12 | ||||
-rw-r--r-- | include/godot_cpp/classes/wrapped.hpp | 34 | ||||
-rw-r--r-- | include/godot_cpp/core/class_db.hpp | 6 | ||||
-rw-r--r-- | include/godot_cpp/godot.hpp | 1 | ||||
-rw-r--r-- | include/godot_cpp/variant/basis.hpp | 2 | ||||
-rw-r--r-- | include/godot_cpp/variant/quaternion.hpp | 86 | ||||
-rw-r--r-- | include/godot_cpp/variant/variant.hpp | 2 | ||||
-rw-r--r-- | src/classes/wrapped.cpp | 42 | ||||
-rw-r--r-- | src/godot.cpp | 2 | ||||
-rw-r--r-- | src/variant/basis.cpp | 7 | ||||
-rw-r--r-- | src/variant/quaternion.cpp | 68 | ||||
-rw-r--r-- | src/variant/variant.cpp | 11 | ||||
-rw-r--r-- | test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/SConstruct | 1 | ||||
-rw-r--r-- | test/project/main.gd | 10 | ||||
-rw-r--r-- | test/src/example.cpp | 13 | ||||
-rw-r--r-- | test/src/example.h | 11 | ||||
-rw-r--r-- | test/src/register_types.cpp | 1 | ||||
-rw-r--r-- | tools/godotcpp.py | 1 |
24 files changed, 251 insertions, 164 deletions
diff --git a/.github/actions/godot-cache-restore/action.yml b/.github/actions/godot-cache-restore/action.yml index 5df5776..f10222b 100644 --- a/.github/actions/godot-cache-restore/action.yml +++ b/.github/actions/godot-cache-restore/action.yml @@ -3,19 +3,22 @@ description: Restore Godot build cache. inputs: cache-name: description: The cache base name (job name by default). - default: "${{github.job}}" + default: ${{ github.job }} scons-cache: - description: The scons cache path. - default: "${{github.workspace}}/.scons-cache/" + description: The SCons cache path. + default: ${{ github.workspace }}/.scons-cache/ + runs: - using: "composite" + using: composite steps: - - name: Restore .scons_cache directory - uses: actions/cache/restore@v3 + - name: Restore SCons cache directory + uses: actions/cache/restore@v4 with: - path: ${{inputs.scons-cache}} - key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} + path: ${{ inputs.scons-cache }} + key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} + restore-keys: | - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}} + ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} + ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }} + ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }} + ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }} diff --git a/.github/actions/godot-cache-save/action.yml b/.github/actions/godot-cache-save/action.yml index b7cbf91..df877ce 100644 --- a/.github/actions/godot-cache-save/action.yml +++ b/.github/actions/godot-cache-save/action.yml @@ -3,15 +3,16 @@ description: Save Godot build cache. inputs: cache-name: description: The cache base name (job name by default). - default: "${{github.job}}" + default: ${{ github.job }} scons-cache: description: The SCons cache path. - default: "${{github.workspace}}/.scons-cache/" + default: ${{ github.workspace }}/.scons-cache/ + runs: - using: "composite" + using: composite steps: - name: Save SCons cache directory uses: actions/cache/save@v4 with: - path: ${{inputs.scons-cache}} - key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} + path: ${{ inputs.scons-cache }} + key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13b7243..c9f5db7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,14 +1,18 @@ name: Continuous integration -on: [push, pull_request] +on: + workflow_call: env: # Only used for the cache key. Increment version to force clean build. GODOT_BASE_BRANCH: master # Used to select the version of Godot to run the tests with. GODOT_TEST_VERSION: master + # Use UTF-8 on Linux. + LANG: en_US.UTF-8 + LC_ALL: en_US.UTF-8 concurrency: - group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}} + group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -20,7 +24,7 @@ jobs: matrix: include: - name: 🐧 Linux (GCC) - os: ubuntu-20.04 + os: ubuntu-22.04 platform: linux artifact-name: godot-cpp-linux-glibc2.27-x86_64-release artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a @@ -28,7 +32,7 @@ jobs: cache-name: linux-x86_64 - name: 🐧 Linux (GCC, Double Precision) - os: ubuntu-20.04 + os: ubuntu-22.04 platform: linux artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a @@ -63,7 +67,7 @@ jobs: cache-name: macos-universal - name: 🤖 Android (arm64) - os: ubuntu-20.04 + os: ubuntu-22.04 platform: android artifact-name: godot-cpp-android-arm64-release artifact-path: bin/libgodot-cpp.android.template_release.arm64.a @@ -81,7 +85,7 @@ jobs: cache-name: ios-arm64 - name: 🌐 Web (wasm32) - os: ubuntu-20.04 + os: ubuntu-22.04 platform: web artifact-name: godot-cpp-web-wasm32-release artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a @@ -91,7 +95,7 @@ jobs: env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ EM_VERSION: 3.1.39 - EM_CACHE_FOLDER: "emsdk-cache" + EM_CACHE_FOLDER: emsdk-cache steps: - name: Checkout @@ -108,24 +112,24 @@ jobs: - name: Set up Python (for SCons) uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: 3.x - name: Android dependencies - if: ${{ matrix.platform == 'android' }} + if: matrix.platform == 'android' uses: nttld/setup-ndk@v1 with: ndk-version: r23c link-to-sdk: true - name: Web dependencies - if: ${{ matrix.platform == 'web' }} + if: matrix.platform == 'web' uses: mymindstorm/setup-emsdk@v14 with: - version: ${{env.EM_VERSION}} - actions-cache-folder: ${{env.EM_CACHE_FOLDER}} + version: ${{ env.EM_VERSION }} + actions-cache-folder: ${{ env.EM_CACHE_FOLDER }} - name: Setup MinGW for Windows/MinGW build - if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }} + if: matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' uses: egor-tensin/setup-mingw@v2 with: version: 12.2.0 @@ -161,7 +165,7 @@ jobs: - name: Download latest Godot artifacts uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9 - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master' with: repo: godotengine/godot branch: master @@ -175,13 +179,13 @@ jobs: path: godot-artifacts - name: Prepare Godot artifacts for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master' run: | chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV - name: Download requested Godot version for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION != 'master' }} + if: matrix.run-tests && env.GODOT_TEST_VERSION != 'master' run: | wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip unzip -a Godot.zip @@ -189,7 +193,7 @@ jobs: echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV - name: Run tests - if: ${{ matrix.run-tests }} + if: matrix.run-tests run: | $GODOT --headless --version cd test @@ -206,7 +210,7 @@ jobs: linux-cmake: name: 🐧 Build (Linux, GCC, CMake) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 @@ -230,7 +234,7 @@ jobs: linux-cmake-ninja: name: 🐧 Build (Linux, GCC, CMake Ninja) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml new file mode 100644 index 0000000..a2e4f91 --- /dev/null +++ b/.github/workflows/runner.yml @@ -0,0 +1,21 @@ +name: 🔗 GHA +on: [push, pull_request, merge_group] + +concurrency: + group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner + cancel-in-progress: true + +jobs: + # First stage: Only static checks, fast and prevent expensive builds from running. + + static-checks: + if: '!vars.DISABLE_GODOT_CI' + name: 📊 Static Checks + uses: ./.github/workflows/static_checks.yml + + # Second stage: Run all the builds and some of the tests. + + ci: + name: 🛠️ Continuous Integration + needs: static-checks + uses: ./.github/workflows/ci.yml diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index 6899248..c8d2713 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -1,8 +1,9 @@ name: 📊 Static Checks -on: [push, pull_request] +on: + workflow_call: concurrency: - group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static + group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static cancel-in-progress: true jobs: diff --git a/gdextension/gdextension_interface.h b/gdextension/gdextension_interface.h index 0ffe110..ff89700 100644 --- a/gdextension/gdextension_interface.h +++ b/gdextension/gdextension_interface.h @@ -1272,6 +1272,18 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMember)(GDExtensionVaria typedef GDExtensionBool (*GDExtensionInterfaceVariantHasKey)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid); /** + * @name variant_get_object_instance_id + * @since 4.4 + * + * Gets the object instance ID from a variant of type GDEXTENSION_VARIANT_TYPE_OBJECT. + * + * @param p_self A pointer to the Variant. + * + * @return The instance ID for the contained object. + */ +typedef GDObjectInstanceID (*GDExtensionInterfaceVariantGetObjectInstanceId)(GDExtensionConstVariantPtr p_self); + +/** * @name variant_get_type_name * @since 4.1 * diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 0ffd783..06b1b67 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -40,6 +40,14 @@ #include <godot_cpp/godot.hpp> +#if defined(MACOS_ENABLED) && defined(HOT_RELOAD_ENABLED) +#include <mutex> +#define _GODOT_CPP_AVOID_THREAD_LOCAL +#define _GODOT_CPP_THREAD_LOCAL +#else +#define _GODOT_CPP_THREAD_LOCAL thread_local +#endif + namespace godot { class ClassDB; @@ -58,8 +66,16 @@ class Wrapped { template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>> friend _ALWAYS_INLINE_ void _pre_initialize(); - thread_local static const StringName *_constructing_extension_class_name; - thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks; +#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL + static std::recursive_mutex _constructing_mutex; +#endif + + _GODOT_CPP_THREAD_LOCAL static const StringName *_constructing_extension_class_name; + _GODOT_CPP_THREAD_LOCAL static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks; + +#ifdef HOT_RELOAD_ENABLED + _GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner; +#endif template <typename T> _ALWAYS_INLINE_ static void _set_construct_info() { @@ -71,15 +87,6 @@ protected: virtual bool _is_extension_class() const { return false; } static const StringName *_get_extension_class_name(); // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. -#ifdef HOT_RELOAD_ENABLED - struct RecreateInstance { - GDExtensionClassInstancePtr wrapper; - GDExtensionObjectPtr owner; - RecreateInstance *next; - }; - inline static RecreateInstance *recreate_instance = nullptr; -#endif - void _notification(int p_what) {} bool _set(const StringName &p_name, const Variant &p_property) { return false; } bool _get(const StringName &p_name, Variant &r_property) const { return false; } @@ -126,6 +133,9 @@ public: template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>> _ALWAYS_INLINE_ void _pre_initialize() { +#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL + Wrapped::_constructing_mutex.lock(); +#endif Wrapped::_set_construct_info<T>(); } @@ -250,7 +260,7 @@ public: } \ \ static const ::godot::StringName &get_class_static() { \ - static const ::godot::StringName string_name = ::godot::StringName(#m_class); \ + static const ::godot::StringName string_name = ::godot::StringName(U## #m_class); \ return string_name; \ } \ \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 988277b..d9dce79 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -129,9 +129,11 @@ private: static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) { if constexpr (!std::is_abstract_v<T>) { #ifdef HOT_RELOAD_ENABLED +#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL + std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex); +#endif + Wrapped::_constructing_recreate_owner = obj; T *new_instance = (T *)memalloc(sizeof(T)); - Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance }; - Wrapped::recreate_instance = &recreate_data; memnew_placement(new_instance, T); return new_instance; #else diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index f410439..1d36acc 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -82,6 +82,7 @@ extern "C" GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_ extern "C" GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method; extern "C" GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member; extern "C" GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key; +extern "C" GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id; extern "C" GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name; extern "C" GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert; extern "C" GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict; diff --git a/include/godot_cpp/variant/basis.hpp b/include/godot_cpp/variant/basis.hpp index e740a64..f3ebe15 100644 --- a/include/godot_cpp/variant/basis.hpp +++ b/include/godot_cpp/variant/basis.hpp @@ -224,7 +224,7 @@ struct _NO_DISCARD_ Basis { operator Quaternion() const { return get_quaternion(); } - static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false); Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); } Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); } diff --git a/include/godot_cpp/variant/quaternion.hpp b/include/godot_cpp/variant/quaternion.hpp index 5de91b2..8d0afd7 100644 --- a/include/godot_cpp/variant/quaternion.hpp +++ b/include/godot_cpp/variant/quaternion.hpp @@ -31,6 +31,7 @@ #ifndef GODOT_QUATERNION_HPP #define GODOT_QUATERNION_HPP +#include <godot_cpp/classes/global_constants.hpp> #include <godot_cpp/core/math.hpp> #include <godot_cpp/variant/vector3.hpp> @@ -47,11 +48,11 @@ struct _NO_DISCARD_ Quaternion { real_t components[4] = { 0, 0, 0, 1.0 }; }; - _FORCE_INLINE_ real_t &operator[](int idx) { - return components[idx]; + _FORCE_INLINE_ real_t &operator[](int p_idx) { + return components[p_idx]; } - _FORCE_INLINE_ const real_t &operator[](int idx) const { - return components[idx]; + _FORCE_INLINE_ const real_t &operator[](int p_idx) const { + return components[p_idx]; } _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quaternion &p_quaternion) const; @@ -66,14 +67,13 @@ struct _NO_DISCARD_ Quaternion { _FORCE_INLINE_ real_t dot(const Quaternion &p_q) const; real_t angle_to(const Quaternion &p_to) const; - Vector3 get_euler_xyz() const; - Vector3 get_euler_yxz() const; - Vector3 get_euler() const { return get_euler_yxz(); } + Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const; + static Quaternion from_euler(const Vector3 &p_euler); - Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const; - Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const; - Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const; - Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; + Quaternion slerp(const Quaternion &p_to, real_t p_weight) const; + Quaternion slerpni(const Quaternion &p_to, real_t p_weight) const; + Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const; + Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const; Vector3 get_axis() const; real_t get_angle() const; @@ -89,28 +89,28 @@ struct _NO_DISCARD_ Quaternion { void operator*=(const Quaternion &p_q); Quaternion operator*(const Quaternion &p_q) const; - _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const { + _FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), p_v, "The quaternion " + operator String() + " must be normalized."); #endif Vector3 u(x, y, z); - Vector3 uv = u.cross(v); - return v + ((uv * w) + u.cross(uv)) * ((real_t)2); + Vector3 uv = u.cross(p_v); + return p_v + ((uv * w) + u.cross(uv)) * ((real_t)2); } - _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const { - return inverse().xform(v); + _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_v) const { + return inverse().xform(p_v); } _FORCE_INLINE_ void operator+=(const Quaternion &p_q); _FORCE_INLINE_ void operator-=(const Quaternion &p_q); - _FORCE_INLINE_ void operator*=(const real_t &s); - _FORCE_INLINE_ void operator/=(const real_t &s); - _FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const; - _FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const; + _FORCE_INLINE_ void operator*=(real_t p_s); + _FORCE_INLINE_ void operator/=(real_t p_s); + _FORCE_INLINE_ Quaternion operator+(const Quaternion &p_q2) const; + _FORCE_INLINE_ Quaternion operator-(const Quaternion &p_q2) const; _FORCE_INLINE_ Quaternion operator-() const; - _FORCE_INLINE_ Quaternion operator*(const real_t &s) const; - _FORCE_INLINE_ Quaternion operator/(const real_t &s) const; + _FORCE_INLINE_ Quaternion operator*(real_t p_s) const; + _FORCE_INLINE_ Quaternion operator/(real_t p_s) const; _FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const; _FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const; @@ -128,8 +128,6 @@ struct _NO_DISCARD_ Quaternion { Quaternion(const Vector3 &p_axis, real_t p_angle); - Quaternion(const Vector3 &p_euler); - Quaternion(const Quaternion &p_q) : x(p_q.x), y(p_q.y), @@ -144,9 +142,9 @@ struct _NO_DISCARD_ Quaternion { w = p_q.w; } - Quaternion(const Vector3 &v0, const Vector3 &v1) { // Shortest arc. - Vector3 c = v0.cross(v1); - real_t d = v0.dot(v1); + Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc. + Vector3 c = p_v0.cross(p_v1); + real_t d = p_v0.dot(p_v1); if (d < -1.0f + (real_t)CMP_EPSILON) { x = 0; @@ -187,25 +185,25 @@ void Quaternion::operator-=(const Quaternion &p_q) { w -= p_q.w; } -void Quaternion::operator*=(const real_t &s) { - x *= s; - y *= s; - z *= s; - w *= s; +void Quaternion::operator*=(real_t p_s) { + x *= p_s; + y *= p_s; + z *= p_s; + w *= p_s; } -void Quaternion::operator/=(const real_t &s) { - *this *= 1.0f / s; +void Quaternion::operator/=(real_t p_s) { + *this *= 1.0f / p_s; } -Quaternion Quaternion::operator+(const Quaternion &q2) const { +Quaternion Quaternion::operator+(const Quaternion &p_q2) const { const Quaternion &q1 = *this; - return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w); + return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w); } -Quaternion Quaternion::operator-(const Quaternion &q2) const { +Quaternion Quaternion::operator-(const Quaternion &p_q2) const { const Quaternion &q1 = *this; - return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w); + return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w); } Quaternion Quaternion::operator-() const { @@ -213,12 +211,12 @@ Quaternion Quaternion::operator-() const { return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w); } -Quaternion Quaternion::operator*(const real_t &s) const { - return Quaternion(x * s, y * s, z * s, w * s); +Quaternion Quaternion::operator*(real_t p_s) const { + return Quaternion(x * p_s, y * p_s, z * p_s, w * p_s); } -Quaternion Quaternion::operator/(const real_t &s) const { - return *this * (1.0f / s); +Quaternion Quaternion::operator/(real_t p_s) const { + return *this * (1.0f / p_s); } bool Quaternion::operator==(const Quaternion &p_quaternion) const { @@ -229,7 +227,7 @@ bool Quaternion::operator!=(const Quaternion &p_quaternion) const { return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w; } -_FORCE_INLINE_ Quaternion operator*(const real_t &p_real, const Quaternion &p_quaternion) { +_FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) { return p_quaternion * p_real; } diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index a868a7c..4c5f206 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -264,6 +264,8 @@ public: operator PackedColorArray() const; operator PackedVector4Array() const; + Object *get_validated_object() const; + Variant &operator=(const Variant &other); Variant &operator=(Variant &&other); bool operator==(const Variant &other) const; diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index ffca4f9..3eb17ca 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -39,14 +39,27 @@ #include <godot_cpp/core/class_db.hpp> namespace godot { -thread_local const StringName *Wrapped::_constructing_extension_class_name = nullptr; -thread_local const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr; + +#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL +std::recursive_mutex Wrapped::_constructing_mutex; +#endif + +_GODOT_CPP_THREAD_LOCAL const StringName *Wrapped::_constructing_extension_class_name = nullptr; +_GODOT_CPP_THREAD_LOCAL const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr; + +#ifdef HOT_RELOAD_ENABLED +_GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr; +#endif const StringName *Wrapped::_get_extension_class_name() { return nullptr; } void Wrapped::_postinitialize() { +#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL + Wrapped::_constructing_mutex.unlock(); +#endif + // Only send NOTIFICATION_POSTINITIALIZE for extension classes. if (_is_extension_class()) { _notificationv(Object::NOTIFICATION_POSTINITIALIZE); @@ -55,25 +68,14 @@ void Wrapped::_postinitialize() { Wrapped::Wrapped(const StringName p_godot_class) { #ifdef HOT_RELOAD_ENABLED - if (unlikely(Wrapped::recreate_instance)) { - RecreateInstance *recreate_data = Wrapped::recreate_instance; - RecreateInstance *previous = nullptr; - while (recreate_data) { - if (recreate_data->wrapper == this) { - _owner = recreate_data->owner; - if (previous) { - previous->next = recreate_data->next; - } else { - Wrapped::recreate_instance = recreate_data->next; - } - return; - } - previous = recreate_data; - recreate_data = recreate_data->next; - } - } + if (unlikely(Wrapped::_constructing_recreate_owner)) { + _owner = Wrapped::_constructing_recreate_owner; + Wrapped::_constructing_recreate_owner = nullptr; + } else #endif - _owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr())); + { + _owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr())); + } if (_constructing_extension_class_name) { godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this); diff --git a/src/godot.cpp b/src/godot.cpp index 68da08f..2a2c889 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -88,6 +88,7 @@ GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_type = null GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method = nullptr; GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member = nullptr; GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key = nullptr; +GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id = nullptr; GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name = nullptr; GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert = nullptr; GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict = nullptr; @@ -368,6 +369,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(variant_has_method, GDExtensionInterfaceVariantHasMethod); LOAD_PROC_ADDRESS(variant_has_member, GDExtensionInterfaceVariantHasMember); LOAD_PROC_ADDRESS(variant_has_key, GDExtensionInterfaceVariantHasKey); + LOAD_PROC_ADDRESS(variant_get_object_instance_id, GDExtensionInterfaceVariantGetObjectInstanceId); LOAD_PROC_ADDRESS(variant_get_type_name, GDExtensionInterfaceVariantGetTypeName); LOAD_PROC_ADDRESS(variant_can_convert, GDExtensionInterfaceVariantCanConvert); LOAD_PROC_ADDRESS(variant_can_convert_strict, GDExtensionInterfaceVariantCanConvertStrict); diff --git a/src/variant/basis.cpp b/src/variant/basis.cpp index 200cd06..d8a9919 100644 --- a/src/variant/basis.cpp +++ b/src/variant/basis.cpp @@ -1037,12 +1037,15 @@ void Basis::rotate_sh(real_t *p_values) { p_values[8] = d4 * s_scale_dst4; } -Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) { +Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero."); ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero."); #endif - Vector3 v_z = -p_target.normalized(); + Vector3 v_z = p_target.normalized(); + if (!p_use_model_front) { + v_z = -v_z; + } Vector3 v_x = p_up.cross(v_z); #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other."); diff --git a/src/variant/quaternion.cpp b/src/variant/quaternion.cpp index c010850..3dd7af5 100644 --- a/src/variant/quaternion.cpp +++ b/src/variant/quaternion.cpp @@ -37,28 +37,15 @@ namespace godot { real_t Quaternion::angle_to(const Quaternion &p_to) const { real_t d = dot(p_to); - return Math::acos(CLAMP(d * d * 2 - 1, -1, 1)); + // acos does clamping. + return Math::acos(d * d * 2 - 1); } -// get_euler_xyz returns a vector containing the Euler angles in the format -// (ax,ay,az), where ax is the angle of rotation around x axis, -// and similar for other axes. -// This implementation uses XYZ convention (Z is the first rotation). -Vector3 Quaternion::get_euler_xyz() const { - Basis m(*this); - return m.get_euler(EULER_ORDER_XYZ); -} - -// get_euler_yxz returns a vector containing the Euler angles in the format -// (ax,ay,az), where ax is the angle of rotation around x axis, -// and similar for other axes. -// This implementation uses YXZ convention (Z is the first rotation). -Vector3 Quaternion::get_euler_yxz() const { +Vector3 Quaternion::get_euler(EulerOrder p_order) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized."); #endif - Basis m(*this); - return m.get_euler(EULER_ORDER_YXZ); + return Basis(*this).get_euler(p_order); } void Quaternion::operator*=(const Quaternion &p_q) { @@ -103,7 +90,7 @@ bool Quaternion::is_normalized() const { Quaternion Quaternion::inverse() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized."); #endif return Quaternion(-x, -y, -z, w); } @@ -125,10 +112,10 @@ Quaternion Quaternion::exp() const { return Quaternion(src_v, theta); } -Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const { +Quaternion Quaternion::slerp(const Quaternion &p_to, real_t p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized."); #endif Quaternion to1; real_t omega, cosom, sinom, scale0, scale1; @@ -166,10 +153,10 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con scale0 * w + scale1 * to1.w); } -Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const { +Quaternion Quaternion::slerpni(const Quaternion &p_to, real_t p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized."); #endif const Quaternion &from = *this; @@ -190,10 +177,10 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c invFactor * from.w + newFactor * p_to.w); } -Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const { +Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized."); #endif Quaternion from_q = *this; Quaternion pre_q = p_pre_a; @@ -236,15 +223,15 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight); Quaternion q2 = to_q * ln.exp(); - // To cancel error made by Expmap ambiguity, do blends. + // To cancel error made by Expmap ambiguity, do blending. return q1.slerp(q2, p_weight); } -Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight, - const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { +Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight, + real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized."); #endif Quaternion from_q = *this; Quaternion pre_q = p_pre_a; @@ -287,7 +274,7 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t); Quaternion q2 = to_q * ln.exp(); - // To cancel error made by Expmap ambiguity, do blends. + // To cancel error made by Expmap ambiguity, do blending. return q1.slerp(q2, p_weight); } @@ -309,7 +296,7 @@ real_t Quaternion::get_angle() const { Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) { #ifdef MATH_CHECKS - ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized."); + ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized."); #endif real_t d = p_axis.length(); if (d == 0) { @@ -332,7 +319,7 @@ Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) { // (ax, ay, az), where ax is the angle of rotation around x axis, // and similar for other axes. // This implementation uses YXZ convention (Z is the first rotation). -Quaternion::Quaternion(const Vector3 &p_euler) { +Quaternion Quaternion::from_euler(const Vector3 &p_euler) { real_t half_a1 = p_euler.y * 0.5f; real_t half_a2 = p_euler.x * 0.5f; real_t half_a3 = p_euler.z * 0.5f; @@ -348,10 +335,11 @@ Quaternion::Quaternion(const Vector3 &p_euler) { real_t cos_a3 = Math::cos(half_a3); real_t sin_a3 = Math::sin(half_a3); - x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3; - y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3; - z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3; - w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3; + return Quaternion( + sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3, + sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3, + -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3, + sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3); } } // namespace godot diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index 9dcf705..1f57d48 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -448,12 +448,7 @@ Variant::operator ObjectID() const { if (get_type() == Type::INT) { return ObjectID(operator uint64_t()); } else if (get_type() == Type::OBJECT) { - Object *obj = operator Object *(); - if (obj != nullptr) { - return ObjectID(obj->get_instance_id()); - } else { - return ObjectID(); - } + return ObjectID(internal::gdextension_interface_variant_get_object_instance_id(_native_ptr())); } else { return ObjectID(); } @@ -515,6 +510,10 @@ Variant::operator PackedVector4Array() const { return PackedVector4Array(this); } +Object *Variant::get_validated_object() const { + return ObjectDB::get_instance(operator ObjectID()); +} + Variant &Variant::operator=(const Variant &other) { clear(); internal::gdextension_interface_variant_new_copy(_native_ptr(), other._native_ptr()); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 42ea6e0..f1c4c0d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,6 +38,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # using Visual Studio C++ set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /WX") # /GF /MP set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /DTYPED_METHOD_BIND") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /utf-8") if(CMAKE_BUILD_TYPE MATCHES Debug) set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi diff --git a/test/SConstruct b/test/SConstruct index 1f1db0f..b949bca 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -42,4 +42,5 @@ else: source=sources, ) +env.NoCache(library) Default(library) diff --git a/test/project/main.gd b/test/project/main.gd index 386d188..e5a3b95 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -209,6 +209,12 @@ func _ready(): assert_equal(example.test_variant_float_conversion(10.0), 10.0) assert_equal(example.test_variant_float_conversion(10), 10.0) + # Test checking if objects are valid. + var object_of_questionable_validity = Object.new() + assert_equal(example.test_object_is_valid(object_of_questionable_validity), true) + object_of_questionable_validity.free() + assert_equal(example.test_object_is_valid(object_of_questionable_validity), false) + # Test that ptrcalls from GDExtension to the engine are correctly encoding Object and RefCounted. var new_node = Node.new() example.test_add_child(new_node) @@ -279,6 +285,10 @@ func _ready(): assert_equal(library_path, ProjectSettings.globalize_path(library_path)) assert_equal(FileAccess.file_exists(library_path), true) + # Test a class with a unicode name. + var przykład = ExamplePrzykład.new() + assert_equal(przykład.get_the_word(), "słowo to przykład") + exit_with_status() func _on_Example_custom_signal(signal_name, value): diff --git a/test/src/example.cpp b/test/src/example.cpp index 692d004..22739b2 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -217,6 +217,7 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_variant_vector2i_conversion", "variant"), &Example::test_variant_vector2i_conversion); ClassDB::bind_method(D_METHOD("test_variant_int_conversion", "variant"), &Example::test_variant_int_conversion); ClassDB::bind_method(D_METHOD("test_variant_float_conversion", "variant"), &Example::test_variant_float_conversion); + ClassDB::bind_method(D_METHOD("test_object_is_valid", "variant"), &Example::test_object_is_valid); ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child); ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset); @@ -598,6 +599,10 @@ float Example::test_variant_float_conversion(const Variant &p_variant) const { return p_variant; } +bool Example::test_object_is_valid(const Variant &p_variant) const { + return static_cast<bool>(p_variant.get_validated_object()); +} + void Example::test_add_child(Node *p_node) { add_child(p_node); } @@ -755,3 +760,11 @@ ExampleRuntime::ExampleRuntime() { ExampleRuntime::~ExampleRuntime() { } + +void ExamplePrzykład::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_the_word"), &ExamplePrzykład::get_the_word); +} + +String ExamplePrzykład::get_the_word() const { + return U"słowo to przykład"; +} diff --git a/test/src/example.h b/test/src/example.h index a28deff..a7ae54c 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -147,6 +147,7 @@ public: Vector2i test_variant_vector2i_conversion(const Variant &p_variant) const; int test_variant_int_conversion(const Variant &p_variant) const; float test_variant_float_conversion(const Variant &p_variant) const; + bool test_object_is_valid(const Variant &p_variant) const; void test_add_child(Node *p_node); void test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset) const; @@ -275,4 +276,14 @@ public: ~ExampleRuntime(); }; +class ExamplePrzykład : public RefCounted { + GDCLASS(ExamplePrzykład, RefCounted); + +protected: + static void _bind_methods(); + +public: + String get_the_word() const; +}; + #endif // EXAMPLE_CLASS_H diff --git a/test/src/register_types.cpp b/test/src/register_types.cpp index 7cfe689..d9290c8 100644 --- a/test/src/register_types.cpp +++ b/test/src/register_types.cpp @@ -30,6 +30,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(ExampleBase); GDREGISTER_CLASS(ExampleChild); GDREGISTER_RUNTIME_CLASS(ExampleRuntime); + GDREGISTER_CLASS(ExamplePrzykład); } void uninitialize_example_module(ModuleInitializationLevel p_level) { diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 9ceac02..b2a63dc 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -552,6 +552,7 @@ def _godot_cpp(env): if env["build_library"]: library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources) + env.NoCache(library) default_args = [library] # Add compiledb if the option is set |