From 92028ca8f58dc9e97ec47ee61c21817e11fa1c13 Mon Sep 17 00:00:00 2001 From: Jovan Gerodetti Date: Tue, 30 Jan 2024 00:26:00 +0100 Subject: [PATCH] Introduce Godot Rust Script (#7) * Introduce Godot Rust Script * upgrade godot-rust-script (builtin hotreload) * update godot-rust-script / gdext * remove scene object registry * Disable godot 4.2 errors * Fix godot-rust-script clippy lints * update rust-script * improve build env --- .github/build_godot_cache.sh | 2 +- .github/workflows/build.yml | 41 ++- native/Cargo.lock | 298 ++++++++++++++++-- native/Cargo.toml | 5 +- native/src/lib.rs | 23 +- native/src/scripts/mod.rs | 4 + .../src/scripts/particles/dust_particles.rs | 64 ++++ native/src/scripts/particles/mod.rs | 1 + native/src/scripts/spawner/car_spawner.rs | 108 +++++++ native/src/scripts/spawner/mod.rs | 1 + native/src/terrain_builder.rs | 45 ++- resources/Objects/Helis/Helicopter.tscn | 16 +- resources/Objects/Spawner/CarSpawner.tscn | 7 +- resources/Shaders/ocean_visualshader.tres | 1 - resources/TestScenes/test_track.tscn | 25 +- resources/Textures/tex39-39.png.import-2VCCBd | 0 resources/Textures/tex40-2.png.import-47AJay | 0 resources/main.tscn | 1 + src/Objects/Helicopters/Helicopter.gd | 2 +- src/Objects/Particles/DustParticles.gd | 29 -- src/Objects/Spawner/CarSpawner.gd | 35 -- src/Objects/World/Networks.gd | 3 +- src/native.gdextension | 13 +- 23 files changed, 583 insertions(+), 141 deletions(-) create mode 100644 native/src/scripts/mod.rs create mode 100644 native/src/scripts/particles/dust_particles.rs create mode 100644 native/src/scripts/particles/mod.rs create mode 100644 native/src/scripts/spawner/car_spawner.rs create mode 100644 native/src/scripts/spawner/mod.rs create mode 100644 resources/Textures/tex39-39.png.import-2VCCBd create mode 100644 resources/Textures/tex40-2.png.import-47AJay delete mode 100644 src/Objects/Particles/DustParticles.gd delete mode 100644 src/Objects/Spawner/CarSpawner.gd diff --git a/.github/build_godot_cache.sh b/.github/build_godot_cache.sh index 02777a3..c3b52d2 100755 --- a/.github/build_godot_cache.sh +++ b/.github/build_godot_cache.sh @@ -27,4 +27,4 @@ done godot_job=$(jobs -p) -kill $godot_job \ No newline at end of file +kill -s TERM $godot_job diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4db242c..57bfdd1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,6 +38,7 @@ jobs: env: TARGET_TRIPLET: ${{ matrix.arch }}-${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }} CARGO_BUILD: cargo build --target + RUST_BACKTRACE: full steps: - name: checkout @@ -62,7 +63,7 @@ jobs: if: inputs.release run: | cd native/ - ${{ env.CARGO_BUILD}} ${{ env.TARGET_TRIPLET}} --release + ${{ env.CARGO_BUILD }} ${{ env.TARGET_TRIPLET}} --release - name: Artifacts uses: actions/upload-artifact@v3 with: @@ -129,27 +130,53 @@ jobs: uses: actions/download-artifact@v3 with: name: libnative-linux-x86_64 - path: native/target/x86_64-unknown-linux-gnu/release/ + path: native/target/x86_64-unknown-linux-gnu/debug/ - name: download x86_64 libs if: matrix.x86_64 uses: actions/download-artifact@v3 with: name: libnative-${{ matrix.platform }}-x86_64 - path: native/target/x86_64-${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }}/release/ + path: native/target/x86_64-${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }}/debug/ - name: download aarch64 libs if: matrix.aarch64 uses: actions/download-artifact@v3 with: name: libnative-${{ matrix.platform }}-aarch64 - path: native/target/aarch64-${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }}/release/ + path: native/target/aarch64-${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }}/debug/ - name: create universal libnative if: matrix.platform == 'darwin' run: | platform_dir="${{ matrix.vendor }}-${{ matrix.platform }}" - mkdir -p native/target/universal-$platform_dir/release/ - lipo -create native/target/x86_64-$platform_dir/release/${{ matrix.lib }} native/target/aarch64-$platform_dir/release/${{ matrix.lib }} -output native/target/universal-$platform_dir/release/${{ matrix.lib }} + mkdir -p native/target/universal-$platform_dir/debug/ + lipo -create native/target/x86_64-$platform_dir/debug/${{ matrix.lib }} native/target/aarch64-$platform_dir/debug/${{ matrix.lib }} -output native/target/universal-$platform_dir/debug/${{ matrix.lib }} + - name: copy libs + run: | + set -x + platform_dir="${{ matrix.vendor }}-${{ matrix.platform }}${{ matrix.env }}" + x86_64="native/target/x86_64-$platform_dir" + aarch64="native/target/aarch64-$platform_dir" + universal="native/target/universal-$platform_dir" + + if [[ -d "$x86_64/debug/" ]]; then + mkdir -p "$x86_64/release/" + cp $x86_64/debug/* "$x86_64/release/" + fi + + if [[ -d "$aarch64/debug/" ]]; then + mkdir -p "$aarch64/release/" + cp $aarch64/debug/* "$aarch64/release/" + fi + + if [[ -d "$universal/debug/" ]]; then + mkdir -p "$universal/release/" + cp $universal/debug/* "$universal/release/" + fi - name: import godot project - run: .github/build_godot_cache.sh + run: | + # import assets + .github/build_godot_cache.sh + # restart to make sure all rust scripts are detected + .github/build_godot_cache.sh - name: export-debug if: ${{ !inputs.release }} run: | diff --git a/native/Cargo.lock b/native/Cargo.lock index 3b83ca7..ade7b83 100644 --- a/native/Cargo.lock +++ b/native/Cargo.lock @@ -50,6 +50,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "const-str" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aca749d3d3f5b87a0d6100509879f9cf486ab510803a4a4e1001da1ff61c2bd6" + [[package]] name = "crossbeam-channel" version = "0.5.4" @@ -95,12 +101,82 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "gensym" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "uuid", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.26.1" @@ -116,7 +192,7 @@ checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" [[package]] name = "godot" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ "godot-core", "godot-macros", @@ -125,15 +201,20 @@ dependencies = [ [[package]] name = "godot-bindings" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ "godot4-prebuilt", ] +[[package]] +name = "godot-cell" +version = "0.1.0" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" + [[package]] name = "godot-codegen" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ "godot-bindings", "godot-fmt", @@ -147,10 +228,11 @@ dependencies = [ [[package]] name = "godot-core" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ "glam", "godot-bindings", + "godot-cell", "godot-codegen", "godot-ffi", ] @@ -158,8 +240,9 @@ dependencies = [ [[package]] name = "godot-ffi" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ + "gensym", "godot-bindings", "godot-codegen", "paste", @@ -168,7 +251,7 @@ dependencies = [ [[package]] name = "godot-fmt" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ "proc-macro2", ] @@ -176,17 +259,48 @@ dependencies = [ [[package]] name = "godot-macros" version = "0.1.0" -source = "git+https://github.com/godot-rust/gdext?rev=b4e6fd6c9c23e0fd3a124c2893a9592c861ab780#b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" +source = "git+https://github.com/godot-rust/gdext?rev=7fd1be904efccd71a9eb980c2e6fffa2d8705ec4#7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" dependencies = [ + "godot-bindings", "proc-macro2", "quote", "venial", ] +[[package]] +name = "godot-rust-script" +version = "0.1.0" +source = "git+https://github.com/titannano/godot-rust-script?rev=e06373cb0d8efce3ec097bbedde3e98e08a9ebfa#e06373cb0d8efce3ec097bbedde3e98e08a9ebfa" +dependencies = [ + "const-str", + "godot", + "godot-rust-script-derive", + "itertools", + "once_cell", + "rand", +] + +[[package]] +name = "godot-rust-script-derive" +version = "0.1.0" +source = "git+https://github.com/titannano/godot-rust-script?rev=e06373cb0d8efce3ec097bbedde3e98e08a9ebfa#e06373cb0d8efce3ec097bbedde3e98e08a9ebfa" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "godot4-prebuilt" version = "0.0.0" -source = "git+https://github.com/godot-rust/godot4-prebuilt?branch=4.1#23477b8096a90c3798ab3558b776e9743e59ea2a" +source = "git+https://github.com/godot-rust/godot4-prebuilt?branch=4.2#9e60296be502e294dde3f245971f2868ce553677" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -203,6 +317,22 @@ dependencies = [ "libc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itertools" version = "0.10.3" @@ -229,15 +359,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.117" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "memchr" -version = "2.4.1" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -260,18 +390,18 @@ dependencies = [ [[package]] name = "nanoserde" -version = "0.1.32" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755e7965536bc54d7c9fba2df5ada5bf835b0443fd613f0a53fa199a301839d3" +checksum = "4a983d0b19ed0fcd803c4f04f9b20d5e6dd17e06d44d98742a0985ac45dab1bc" dependencies = [ "nanoserde-derive", ] [[package]] name = "nanoserde-derive" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7a94da6c6181c35d043fc61c43ac96d3a5d739e7b8027f77650ba41504d6ab" +checksum = "d4dc96541767a4279572fdcf9f95af9cc1c9b2a2254e7a079203c81e206a9059" [[package]] name = "native" @@ -279,9 +409,11 @@ version = "0.4.0" dependencies = [ "backtrace", "godot", + "godot-rust-script", "itertools", "lerp", "num", + "num_enum", "rayon", ] @@ -371,6 +503,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "object" version = "0.27.1" @@ -380,17 +533,38 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "paste" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -404,6 +578,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "rayon" version = "1.5.2" @@ -455,12 +659,55 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +dependencies = [ + "getrandom", +] + [[package]] name = "venial" version = "0.5.0" @@ -470,3 +717,18 @@ dependencies = [ "proc-macro2", "quote", ] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +dependencies = [ + "memchr", +] diff --git a/native/Cargo.toml b/native/Cargo.toml index ef27fe8..522d76d 100644 --- a/native/Cargo.toml +++ b/native/Cargo.toml @@ -7,9 +7,12 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -godot = { git = "https://github.com/godot-rust/gdext", rev = "b4e6fd6c9c23e0fd3a124c2893a9592c861ab780" } +godot = { git = "https://github.com/godot-rust/gdext", rev = "7fd1be904efccd71a9eb980c2e6fffa2d8705ec4" } lerp = "0.4.0" backtrace = "0.3.64" num = "0.4.0" rayon = "1.5.1" itertools = "0.10.3" +num_enum = "0.7.1" + +godot-rust-script = { git = "https://github.com/titannano/godot-rust-script", rev = "e06373cb0d8efce3ec097bbedde3e98e08a9ebfa" } diff --git a/native/src/lib.rs b/native/src/lib.rs index 98ef338..d6676a1 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -1,8 +1,27 @@ +mod scripts; mod terrain_builder; -use godot::prelude::{gdextension, ExtensionLibrary}; +use godot::prelude::{gdextension, ExtensionLibrary, InitLevel}; struct NativeLib; #[gdextension] -unsafe impl ExtensionLibrary for NativeLib {} +unsafe impl ExtensionLibrary for NativeLib { + fn on_level_init(level: InitLevel) { + match level { + InitLevel::Core => (), + InitLevel::Servers => (), + InitLevel::Scene => godot_rust_script::init!(scripts), + InitLevel::Editor => (), + } + } + + fn on_level_deinit(level: InitLevel) { + match level { + InitLevel::Editor => (), + InitLevel::Scene => godot_rust_script::deinit!(), + InitLevel::Servers => (), + InitLevel::Core => (), + } + } +} diff --git a/native/src/scripts/mod.rs b/native/src/scripts/mod.rs new file mode 100644 index 0000000..e73e999 --- /dev/null +++ b/native/src/scripts/mod.rs @@ -0,0 +1,4 @@ +mod particles; +mod spawner; + +godot_rust_script::setup_library!(); diff --git a/native/src/scripts/particles/dust_particles.rs b/native/src/scripts/particles/dust_particles.rs new file mode 100644 index 0000000..d28c22f --- /dev/null +++ b/native/src/scripts/particles/dust_particles.rs @@ -0,0 +1,64 @@ +use godot_rust_script::{ + godot::{ + engine::{GpuParticles3D, PrimitiveMesh, StandardMaterial3D}, + prelude::{godot_error, Gd}, + }, + godot_script_impl, GodotScript, +}; + +/// Dust Particle behavior for a particle system. +/// This is used for the rotor effects +#[derive(GodotScript, Debug)] +#[script(base = GpuParticles3D)] +struct DustParticles { + /// The strength of the emitted dust. + #[prop(get = Self::strength, set = Self::set_strength)] + #[export(range(min = 0.1, max = 1.5, step = 0.05))] + strength: f64, + + base: Gd, +} + +#[godot_script_impl] +impl DustParticles { + pub fn _ready(&mut self) { + self.set_strength(0.0); + } + + /// get effect strength + fn strength(&self) -> f64 { + self.strength + } + + pub fn set_strength(&mut self, value: f64) { + self.strength = value; + + let is_emitting = value > 0.0; + + if self.base.is_emitting() != is_emitting { + self.base.set_emitting(is_emitting); + } + + if !self.base.is_emitting() { + return; + } + + let Some(mesh) = self.base.get_draw_pass_mesh(0) else { + godot_error!("Draw pass 1 does not exist!"); + return; + }; + + let mesh: Gd = mesh.cast(); + + let Some(material) = mesh.get_material() else { + godot_error!("mesh has no material!"); + return; + }; + + let mut material: Gd = material.cast(); + + let distance = (100.0 * (1.0 - value)).max(2.0); + + material.set_proximity_fade_distance(distance as f32); + } +} diff --git a/native/src/scripts/particles/mod.rs b/native/src/scripts/particles/mod.rs new file mode 100644 index 0000000..6617696 --- /dev/null +++ b/native/src/scripts/particles/mod.rs @@ -0,0 +1 @@ +mod dust_particles; diff --git a/native/src/scripts/spawner/car_spawner.rs b/native/src/scripts/spawner/car_spawner.rs new file mode 100644 index 0000000..0a08cd4 --- /dev/null +++ b/native/src/scripts/spawner/car_spawner.rs @@ -0,0 +1,108 @@ +use godot::obj::NewAlloc; +use godot_rust_script::{ + godot::{ + engine::{ResourceLoader, Timer}, + prelude::{ + godot_error, Callable, GString, Gd, Node3D, NodePath, PackedScene, StringName, ToGodot, + }, + }, + godot_script_impl, GodotScript, +}; + +#[derive(Debug, GodotScript)] +#[script(base = Node3D)] +struct CarSpawner { + default_car: Option>, + + #[export] + pub road_network_path: NodePath, + timer: Option>, + + base: Gd, +} + +#[godot_script_impl] +impl CarSpawner { + pub fn _init(&mut self) { + let mut loader = ResourceLoader::singleton(); + + self.default_car = loader + .load(GString::from( + "res://resources/Objects/Vehicles/car_station_wagon.tscn", + )) + .map(|res| res.cast()); + } + + pub fn spawn_car(&mut self) { + let inst = self + .default_car + .as_ref() + .expect("failed to load default_car") + .instantiate(); + + let Some(mut inst) = inst else { + godot_error!("failed to instantiate car scene!"); + return; + }; + + inst.set( + StringName::from("road_network_path"), + self.road_network_path.to_variant(), + ); + + if let Some(mut parent) = self.base.get_parent() { + parent.add_child(inst.clone()); + } + + let Some(current_scene) = self + .base + .get_tree() + .and_then(|tree| tree.get_current_scene()) + else { + godot_error!("there is no active scene!"); + return; + }; + + inst.set_owner(current_scene); + + let mut inst: Gd = inst.cast(); + + inst.global_translate(self.base.get_global_transform().origin); + inst.call(StringName::from("activate"), &[]); + } + + pub fn start_auto_spawn(&mut self) { + let timer = match self.timer.as_mut() { + None => { + let mut timer = Timer::new_alloc(); + self.timer = Some(timer.clone()); + + self.base + .add_child_ex(timer.clone().upcast()) + .force_readable_name(true) + .done(); + + timer.connect( + StringName::from("timeout"), + Callable::from_object_method(&self.base, "start_auto_spawn"), + ); + + self.timer.as_mut().unwrap() + } + + Some(timer) => timer, + }; + + timer.start_ex().time_sec(2.0).done(); + + self.spawn_car(); + } + + pub fn stop_auto_spawn(&mut self) { + let Some(timer) = self.timer.as_mut() else { + return; + }; + + timer.stop(); + } +} diff --git a/native/src/scripts/spawner/mod.rs b/native/src/scripts/spawner/mod.rs new file mode 100644 index 0000000..1b0d2b8 --- /dev/null +++ b/native/src/scripts/spawner/mod.rs @@ -0,0 +1 @@ +mod car_spawner; \ No newline at end of file diff --git a/native/src/terrain_builder.rs b/native/src/terrain_builder.rs index 6ad08dd..34f9c73 100644 --- a/native/src/terrain_builder.rs +++ b/native/src/terrain_builder.rs @@ -6,7 +6,7 @@ mod ybuffer; use godot::engine::mesh::PrimitiveType; use godot::engine::{ArrayMesh, Material, SurfaceTool}; -use godot::prelude::meta::VariantMetadata; +use godot::prelude::meta::GodotType; use godot::prelude::*; use std::cmp::{max, min}; @@ -27,12 +27,12 @@ use ybuffer::{HashMapYBuffer, YBuffer}; pub use terrain_rotation::TerrainRotation; -struct Shared(T); +struct Shared(T); -unsafe impl Send for Shared {} -unsafe impl Sync for Shared {} +unsafe impl Send for Shared {} +unsafe impl Sync for Shared {} -impl Deref for Shared { +impl Deref for Shared { type Target = T; fn deref(&self) -> &Self::Target { @@ -40,7 +40,7 @@ impl Deref for Shared { } } -impl Shared { +impl Shared { fn inner(self) -> T { self.0 } @@ -173,7 +173,7 @@ struct ThreadContext<'a> { } #[derive(GodotClass)] -#[class(base=RefCounted)] +#[class(base=RefCounted, init)] pub struct TerrainBuilder { tile_size: u8, city_size: u16, @@ -186,6 +186,23 @@ pub struct TerrainBuilder { #[godot_api] impl TerrainBuilder { + #[func] + fn new( + tilelist: Dictionary, + rotation: Gd, + materials: Dictionary, + ) -> Gd { + Gd::from_object(TerrainBuilder { + tile_size: 16, + city_size: 0, + tile_height: 8, + sea_level: 0, + rotation, + tilelist, + materials, + }) + } + #[func] fn set_city_size(&mut self, value: u16) { self.city_size = value; @@ -207,11 +224,11 @@ impl TerrainBuilder { } fn tilelist(&self) -> Shared { - Shared(self.tilelist.share()) + Shared(self.tilelist.clone()) } fn materials(&self) -> Shared { - Shared(self.materials.share()) + Shared(self.materials.clone()) } fn rotation(&self) -> &Gd { @@ -379,13 +396,13 @@ impl TerrainBuilder { } fn build_terain_chunk(context: &ThreadContext, surfaces: SurfaceMap) -> Shared> { - let mut generator = SurfaceTool::new(); - let mut mesh = ArrayMesh::new(); + let mut generator = SurfaceTool::new_gd(); + let mut mesh = ArrayMesh::new_gd(); let mut vertex_count = 0; for (surface_type, surface) in surfaces { generator.clear(); - generator.begin(PrimitiveType::PRIMITIVE_TRIANGLES); + generator.begin(PrimitiveType::TRIANGLES); for vertex_cell in surface { let vertex = Arc::try_unwrap(vertex_cell) @@ -417,7 +434,7 @@ impl TerrainBuilder { let surface_arrays = generator.commit_to_arrays(); let new_index = mesh.get_surface_count(); - mesh.add_surface_from_arrays(PrimitiveType::PRIMITIVE_TRIANGLES, surface_arrays); + mesh.add_surface_from_arrays(PrimitiveType::TRIANGLES, surface_arrays); let surface_material_variant = context.materials.get(surface_type.to_string()); @@ -506,7 +523,7 @@ impl TerrainBuilderFactory { rotation: Gd, materials: Dictionary, ) -> Gd { - Gd::new(TerrainBuilder { + Gd::from_object(TerrainBuilder { tile_size: 16, city_size: 0, tile_height: 8, diff --git a/resources/Objects/Helis/Helicopter.tscn b/resources/Objects/Helis/Helicopter.tscn index aa74f3a..b736893 100644 --- a/resources/Objects/Helis/Helicopter.tscn +++ b/resources/Objects/Helis/Helicopter.tscn @@ -1,17 +1,17 @@ [gd_scene load_steps=8 format=3 uid="uid://dl34exjsm3sq4"] -[ext_resource type="Material" uid="uid://cjoloelf8ku4k" path="res://resources/Materials/dust_material.tres" id="1"] +[ext_resource type="Material" uid="uid://cjoloelf8ku4k" path="res://resources/Materials/dust_material.tres" id="2_8yiqd"] +[ext_resource type="Script" path="res://native/src/scripts/particles/dust_particles.rs" id="2_ocmjg"] [ext_resource type="Script" path="res://src/Objects/Helicopters/Helicopter.gd" id="3"] [ext_resource type="AnimationNodeStateMachine" uid="uid://xbcrg5mghpup" path="res://resources/Animations/HelicopterRotorSoundStates.tres" id="4_8iee2"] [ext_resource type="AnimationLibrary" uid="uid://uec74t4jqdxi" path="res://resources/Animations/Helicopter.tres" id="5_ayahk"] -[ext_resource type="Script" path="res://src/Objects/Particles/DustParticles.gd" id="12"] [sub_resource type="PhysicsMaterial" id="20"] friction = 0.5 bounce = 0.7 -[sub_resource type="QuadMesh" id="9"] -material = ExtResource("1") +[sub_resource type="QuadMesh" id="QuadMesh_e0n42"] +material = ExtResource("2_8yiqd") [node name="Helicopter" type="RigidBody3D" node_paths=PackedStringArray("child_engine_sound_tree", "child_dust_particles")] mass = 929.8 @@ -35,14 +35,12 @@ amount = 100 lifetime = 0.4 visibility_aabb = AABB(-8.76025, -1.34854, -8.13392, 17.451, 2.29104, 17.5903) draw_order = 2 -draw_pass_1 = SubResource("9") -script = ExtResource("12") +draw_pass_1 = SubResource("QuadMesh_e0n42") +script = ExtResource("2_ocmjg") +strength = null [node name="RotorAudioTree" type="AnimationTree" parent="."] root_node = NodePath(".") -libraries = { -"": ExtResource("5_ayahk") -} tree_root = ExtResource("4_8iee2") advance_expression_base_node = NodePath("") anim_player = NodePath("../RotorAudioPlayer") diff --git a/resources/Objects/Spawner/CarSpawner.tscn b/resources/Objects/Spawner/CarSpawner.tscn index cc1081d..54be663 100644 --- a/resources/Objects/Spawner/CarSpawner.tscn +++ b/resources/Objects/Spawner/CarSpawner.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=4 format=3 uid="uid://rup3fivpcq5r"] +[gd_scene load_steps=4 format=3 uid="uid://blyermwgncstx"] -[ext_resource type="Script" path="res://src/Objects/Spawner/CarSpawner.gd" id="1"] +[ext_resource type="Script" path="res://native/src/scripts/spawner/car_spawner.rs" id="1_c5pws"] [sub_resource type="StandardMaterial3D" id="1"] albedo_color = Color(1, 0, 0, 1) @@ -12,7 +12,8 @@ bottom_radius = 0.1 height = 200.0 [node name="CarSpawner" type="Marker3D"] -script = ExtResource("1") +script = ExtResource("1_c5pws") +road_network_path = null [node name="CSGMesh3D" type="CSGMesh3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 100, 0) diff --git a/resources/Shaders/ocean_visualshader.tres b/resources/Shaders/ocean_visualshader.tres index 9fb00b5..b729dfe 100644 --- a/resources/Shaders/ocean_visualshader.tres +++ b/resources/Shaders/ocean_visualshader.tres @@ -754,7 +754,6 @@ void fragment() { } " -graph_offset = Vector2(483.027, -307.492) nodes/vertex/0/position = Vector2(2720, -520) nodes/vertex/5/node = SubResource("42") nodes/vertex/5/position = Vector2(-560, -120) diff --git a/resources/TestScenes/test_track.tscn b/resources/TestScenes/test_track.tscn index 9fcb0ec..704a8cc 100644 --- a/resources/TestScenes/test_track.tscn +++ b/resources/TestScenes/test_track.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=13 format=3 uid="uid://uvhjdh84glq8"] -[ext_resource type="PackedScene" uid="uid://rup3fivpcq5r" path="res://resources/Objects/Spawner/CarSpawner.tscn" id="1"] +[ext_resource type="PackedScene" uid="uid://blyermwgncstx" path="res://resources/Objects/Spawner/CarSpawner.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://c6cmp45buruhr" path="res://resources/Objects/Networks/Road/left_right.tscn" id="2"] [ext_resource type="PackedScene" uid="uid://k8hd8bpyy0c3" path="res://resources/Objects/Networks/Road/bottom_right.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://ctiydbpunmky5" path="res://resources/Objects/Networks/Road/top_bottom.tscn" id="4"] @@ -17,6 +17,7 @@ resource_name = "Scene" script/source = "extends Node3D const Building := preload(\"res://src/Objects/Map/Building.gd\") +const RoadNavigation := preload(\"res://src/Objects/Networks/RoadNavigation.gd\") func _ready() -> void: var building_ids = { @@ -37,9 +38,10 @@ func _ready() -> void: } var idx = 0 - var road_naviagtion := $Road + var road_naviagtion := $Road as RoadNavigation - for child in road_naviagtion.get_children(): + for item in road_naviagtion.get_children(): + var child := item as Node3D var node: Building match idx: @@ -77,7 +79,7 @@ func _ready() -> void: idx += 1 road_naviagtion.update_debug() - $CarSpawner.spawn_car() + ($CarSpawner as CarSpawner).spawn_car() " [node name="Node3D" type="Node3D"] @@ -131,26 +133,19 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 80, 0, 32) [node name="CSGBox3D" type="CSGBox3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 41.7865, -1, 6) -width = 128.791 -depth = 78.4864 +size = Vector3(128.791, 1, 78.4864) [node name="CSGBox2" type="CSGBox3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 48.0043, 3, 0) -width = 16.0 -height = 10.0 -depth = 25.0 +size = Vector3(16, 10, 25) [node name="CSGBox3" type="CSGBox3D" parent="."] transform = Transform3D(0.894934, -0.446198, 0, 0.446198, 0.894934, 0, 0, 0, 1, 34.2, -0.5, 0) -width = 18.0 -height = 10.0 -depth = 25.0 +size = Vector3(18, 10, 25) [node name="CSGBox4" type="CSGBox3D" parent="."] transform = Transform3D(0.894934, 0.446198, 0, -0.446198, 0.894934, 0, 0, 0, 1, 61.8294, -0.5, 0) -width = 18.0 -height = 10.0 -depth = 25.0 +size = Vector3(18, 10, 25) [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(0.993568, -0.0886679, 0.0704306, 0, 0.621979, 0.783034, -0.113236, -0.777998, 0.617978, 46.1015, 40.9621, 52.5325) diff --git a/resources/Textures/tex39-39.png.import-2VCCBd b/resources/Textures/tex39-39.png.import-2VCCBd new file mode 100644 index 0000000..e69de29 diff --git a/resources/Textures/tex40-2.png.import-47AJay b/resources/Textures/tex40-2.png.import-47AJay new file mode 100644 index 0000000..e69de29 diff --git a/resources/main.tscn b/resources/main.tscn index bd3f0d6..bd74e52 100644 --- a/resources/main.tscn +++ b/resources/main.tscn @@ -87,6 +87,7 @@ transform = Transform3D(1, 0, 0, 0, 0.847724, 0.530437, 0, -0.530437, 0.847724, script = ExtResource("10") snap = true track_y_axis = true +active = true [node name="DebugCameraAnchor" type="Marker3D" parent="SubViewportContainer/SubViewport/Schweizer_300"] process_mode = 3 diff --git a/src/Objects/Helicopters/Helicopter.gd b/src/Objects/Helicopters/Helicopter.gd index 821c7dc..280e560 100644 --- a/src/Objects/Helicopters/Helicopter.gd +++ b/src/Objects/Helicopters/Helicopter.gd @@ -1,6 +1,5 @@ extends RigidBody3D -const DustParticles := preload("res://src/Objects/Particles/DustParticles.gd") const Rotor := preload("res://src/Objects/Helicopters/Rotor.gd") const Logger := preload("res://src/util/Logger.gd") @@ -94,6 +93,7 @@ func _physics_process(_delta: float) -> void: self.is_on_ground = dust_strength > 0.99 self.rotor.power = self.engine_speed + @warning_ignore("unsafe_property_access") self.dust_particles.strength = self.engine_speed * dust_strength if colliding else 0.0 if colliding: diff --git a/src/Objects/Particles/DustParticles.gd b/src/Objects/Particles/DustParticles.gd deleted file mode 100644 index 21eba55..0000000 --- a/src/Objects/Particles/DustParticles.gd +++ /dev/null @@ -1,29 +0,0 @@ -extends GPUParticles3D - -@export_range(0, 1) var strength: float : get = _get_strength, set = _set_strength - -func _ready() -> void: - self._set_strength(0) - -func _get_strength() -> float: - if not self.process_material is ParticleProcessMaterial: - return 0.0 - - var material: ParticleProcessMaterial = self.process_material - - return material.initial_velocity_min / 15.0 - -func _set_strength(value: float): - @warning_ignore("shadowed_variable_base_class") - var is_emitting := value > 0 - - if self.emitting != is_emitting: - self.emitting = is_emitting - - if not self.emitting: - return - - var mesh: PrimitiveMesh = self.draw_pass_1 - var material: StandardMaterial3D = mesh.material - - material.proximity_fade_distance = max(100 * (1 - value), 2) diff --git a/src/Objects/Spawner/CarSpawner.gd b/src/Objects/Spawner/CarSpawner.gd deleted file mode 100644 index efe6376..0000000 --- a/src/Objects/Spawner/CarSpawner.gd +++ /dev/null @@ -1,35 +0,0 @@ -extends Node3D - -const DefaultCar = preload("res://resources/Objects/Vehicles/car_station_wagon.tscn") -const Car := preload("res://src/Objects/Vehicles/Car.gd") - -@export var road_network_path: NodePath - -var timer: Timer - -func spawn_car() -> void: - var inst: Car = DefaultCar.instantiate() - - inst.road_network_path = self.road_network_path - - self.get_parent().add_child(inst) - inst.owner = get_tree().current_scene - inst.global_translate(self.global_transform.origin) - inst.activate() - - -func start_auto_spawn(): - if not self.timer: - self.timer = Timer.new() - self.add_child(self.timer, true) - self.timer.timeout.connect(self.spawn_car) - - self.spawn_car() - self.timer.start(2.0) - - -func stop_auto_spawn(): - if not self.timer: - return - - self.timer.stop() diff --git a/src/Objects/World/Networks.gd b/src/Objects/World/Networks.gd index 00e9cf2..8f83af8 100644 --- a/src/Objects/World/Networks.gd +++ b/src/Objects/World/Networks.gd @@ -3,7 +3,6 @@ extends Node const TimeBudget := preload("res://src/util/TimeBudget.gd") const CityCoordsFeature := preload("res://src/features/CityCoordsFeature.gd") const SceneObjectRegistry := preload("res://src/SceneObjectRegistry.gd") -const CarSpawner := preload("res://src/Objects/Spawner/CarSpawner.gd") const Building := preload("res://src/Objects/Map/Building.gd") const RoadNavigation := preload("res://src/Objects/Networks/RoadNavigation.gd") @@ -85,10 +84,12 @@ func build_async(city: Dictionary): var car_spawner: CarSpawner = (load("res://resources/Objects/Spawner/CarSpawner.tscn") as PackedScene).instantiate() var random_child: Node3D = road_network.get_child(randi() % road_network.get_child_count()) var transform := random_child.global_transform.origin + @warning_ignore("unsafe_property_access") car_spawner.road_network_path = road_network.get_path() car_spawner.translate(transform) car_spawner.translate(Vector3.UP * 2) self.get_parent().add_child(car_spawner) + @warning_ignore("unsafe_method_access") car_spawner.start_auto_spawn() diff --git a/src/native.gdextension b/src/native.gdextension index eea9264..89e451c 100644 --- a/src/native.gdextension +++ b/src/native.gdextension @@ -1,10 +1,15 @@ [configuration] entry_symbol = "gdext_rust_init" compatibility_minimum = 4.1 +reloadable = true [libraries] -macos.arm64="res://native/target/aarch64-apple-darwin/release/libnative.dylib" -macos.x86_64="res://native/target/x86_64-apple-darwin/release/libnative.dylib" macos.universal="res://native/target/universal-apple-darwin/release/libnative.dylib" -windows.x86_64="res://native/target/x86_64-pc-windows-msvc/release/native.dll" -linux.x86_64="res://native/target/x86_64-unknown-linux-gnu/release/libnative.so" \ No newline at end of file +macos.debug.arm64="res://native/target/aarch64-apple-darwin/debug/libnative.dylib" +macos.release.arm64="res://native/target/aarch64-apple-darwin/release/libnative.dylib" +macos.debug.x86_64="res://native/target/x86_64-apple-darwin/debug/libnative.dylib" +macos.release.x86_64="res://native/target/x86_64-apple-darwin/release/libnative.dylib" +windows.debug.x86_64="res://native/target/x86_64-pc-windows-msvc/release/native.dll" +windows.release.x86_64="res://native/target/x86_64-pc-windows-msvc/release/native.dll" +linux.debug.x86_64="res://native/target/x86_64-unknown-linux-gnu/debug/libnative.so" +linux.release.x86_64="res://native/target/x86_64-unknown-linux-gnu/release/libnative.so"