diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 0c612da..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --quiet --package xtask --" \ No newline at end of file diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..65326bb --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use nix \ No newline at end of file diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml new file mode 100644 index 0000000..48352bb --- /dev/null +++ b/.forgejo/workflows/build-release.yml @@ -0,0 +1,167 @@ +name: Build Zenyx โšก + +on: + push: + pull_request: + +jobs: + setup: + name: ๐Ÿ”ง Setup Environment + runs-on: ubuntu-latest + outputs: + cache-hit: ${{ steps.cache-tools.outputs.cache-hit }} + steps: + - name: ๐Ÿ“ฅ Checkout source + uses: https://github.com/actions/checkout@v4 + + - name: ๐Ÿ—„๏ธ Cache tools + uses: https://github.com/actions/cache@v4 + id: cache-tools + with: + path: | + ~/.cargo/bin + /tmp/zig + key: cargo-tools-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + cargo-tools- + + - name: ๐Ÿฆ€ Install Rust toolchain + if: steps.cache-tools.outputs.cache-hit != 'true' + uses: https://github.com/actions-rs/toolchain@v1 + with: + toolchain: stable + components: rust-src + override: true + + - name: ๐Ÿ“ฆ Install Build Tools + if: steps.cache-tools.outputs.cache-hit != 'true' + run: | + mkdir -p /tmp/zig + cd /tmp/zig + curl -Lo zig-linux-x86_64.tar.xz https://ziglang.org/builds/zig-linux-x86_64-0.15.0-dev.377+f01833e03.tar.xz + tar -Jxf zig-linux-x86_64.tar.xz -C /tmp/zig --strip-components=1 + cargo install cargo-zigbuild cargo-xwin --force + + cargo-test: + name: ๐Ÿงช Run Cargo Tests + needs: [setup] + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“ฅ Checkout source + uses: https://github.com/actions/checkout@v4 + + - name: ๐Ÿ—„๏ธ Restore Cargo cache + uses: https://github.com/actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + cargo- + + - name: ๐Ÿฆ€ Install Rust toolchain + if: steps.restore-cargo-cache.outputs.cache-hit != 'true' + uses: https://github.com/actions-rs/toolchain@v1 + with: + toolchain: stable + components: rust-src + override: true + + - name: ๐ŸŒ‹ Install Vulkan tools + run: | + apt update + apt install -y vulkan-tools glslc + + + - name: ๐Ÿš€ Run tests + uses: https://github.com/actions-rs/cargo@v1 + with: + command: test + args: --release --all + + build: + name: ๐Ÿ—๏ธ Build ${{ matrix.target }} + needs: [setup, cargo-test] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + - x86_64-unknown-linux-gnu + - aarch64-unknown-linux-gnu + - x86_64-pc-windows-msvc + include: + - target: x86_64-unknown-linux-gnu + binary_name: zenyx-x86_64-linux + ext: "" + command: zigbuild + args: --target x86_64-unknown-linux-gnu --release + - target: aarch64-unknown-linux-gnu + binary_name: zenyx-aarch64-linux + ext: "" + command: zigbuild + args: --target aarch64-unknown-linux-gnu --release + - target: x86_64-pc-windows-msvc + binary_name: zenyx-x86_64-windows-msvc.exe + ext: ".exe" + command: xwin + args: build --target x86_64-pc-windows-msvc --release + + steps: + - name: ๐Ÿ“ฅ Checkout source + uses: https://github.com/actions/checkout@v4 + + - name: ๐Ÿ—„๏ธ Restore tool cache + uses: https://github.com/actions/cache@v4 + with: + path: | + ~/.cargo/bin + /tmp/zig + key: cargo-tools-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + cargo-tools- + + + - name: ๐Ÿ“ Add Zig to PATH + run: echo "/tmp/zig" >> $GITHUB_PATH + + - name: ๐ŸŽฏ Install Rust target + uses: https://github.com/actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + override: true + + - name: ๐Ÿ—„๏ธ Restore Cargo cache + uses: https://github.com/actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + cargo- + - name: ๐ŸŒ‹ Install Vulkan tools + run: | + apt update + apt install -y vulkan-tools glslc + + - name: ๐Ÿš€ Build release binary + uses: https://github.com/actions-rs/cargo@v1 + with: + command: ${{ matrix.command }} + args: ${{ matrix.args }} + + - name: ๐Ÿ“ฆ Package artifact + run: | + mkdir -p artifacts + cp target/${{ matrix.target }}/release/zenyx${{ matrix.ext }} artifacts/${{ matrix.binary_name }} + + - name: โฌ†๏ธ Upload artifact + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: ${{ matrix.binary_name }}.zip + path: artifacts \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6b07e23 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.obj filter=lfs diff=lfs merge=lfs -text +*.mtl filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index 3db2488..0000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Rust - -on: - push: - branches: [ "main", "master" ] - pull_request: - branches: [ "main", "master" ] - -env: - CARGO_TERM_COLOR: always - -jobs: - build: - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - arch: [x86_64, aarch64] - include: - - arch: x86_64 - target: x86_64-unknown-linux-gnu - - arch: aarch64 - target: aarch64-unknown-linux-gnu - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v3 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - target: ${{ matrix.target }} - - - name: Build - run: cargo build --release --target ${{ matrix.target }} - - - name: Run tests - run: cargo test --verbose --target ${{ matrix.target }} - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: Zenyx-${{ runner.os }}-${{ matrix.arch }}-binary - path: | - target/${{ matrix.target }}/release/*.exe - target/${{ matrix.target }}/release/*[^.]* \ No newline at end of file diff --git a/.gitignore b/.gitignore index 583276e..e4833a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ -/target -.idea -Cargo.lock -*.log \ No newline at end of file +/target +.idea +# Cargo.lock +*.log +.direnv +**/result +.vscode/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e69de29 diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fb809d9 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3778 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy 0.7.35", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.9.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "approx" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +dependencies = [ + "serde", +] + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytemuck" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.9.0", + "log", + "polling", + "rustix", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgmath" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" +dependencies = [ + "approx", + "num-traits", +] + +[[package]] +name = "chrono" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.9.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca" +dependencies = [ + "bitflags 2.9.0", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "bytemuck", + "cfg-if", + "crunchy", + "num-traits", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.2", + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.9.0", + "libc", + "redox_syscall 0.5.11", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "metal" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" +dependencies = [ + "bitflags 2.9.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "naga" +version = "25.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b977c445f26e49757f9aca3631c3b8b836942cb278d69a92e7b80d3b24da632" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.9.0", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "once_cell", + "petgraph", + "rustc-hash", + "spirv", + "strum", + "thiserror 2.0.12", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.0", + "jni-sys", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.0", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.0", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.0", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.0", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c41bc8b0e50ea7a5304a56f25e0066f526e99641b46fd7b9ad4421dd35bff6" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.0", + "objc2-foundation 0.3.0", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.0", + "objc2-core-foundation", + "objc2-foundation 0.3.0", + "objc2-metal 0.3.0", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.9.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owned_ttf_parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.11", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06" +dependencies = [ + "fixedbitset", + "hashbrown", + "indexmap", + "serde", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy 0.8.24", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.37.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[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 0.2.15", +] + +[[package]] +name = "range-alloc" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror 1.0.69", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2 0.6.0", + "objc2-core-foundation", + "objc2-foundation 0.3.0", + "objc2-quartz-core 0.3.0", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "renderer" +version = "0.1.0" + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slabbin" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db491c0d4152a069911a0fbdaca959691bf0b9d7110d98a7ed1c8e59b79ab30" + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.9.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminator" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949066bef99a7825532a6db2c32b4fc7fe9f2a44c88ec6838cf5d61c16c27486" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tobj" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025" +dependencies = [ + "ahash", +] + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vk-parse" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3859da4d7b98bec73e68fb65815d47a263819c415c90eed42b80440a02cbce8c" +dependencies = [ + "xml-rs", +] + +[[package]] +name = "vulkano" +version = "0.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08840c2b51759a6f88f26f5ea378bc8b5c199a5b4760ddda292304be087249c4" +dependencies = [ + "ash", + "bytemuck", + "crossbeam-queue", + "foldhash", + "half", + "heck 0.4.1", + "indexmap", + "libloading", + "nom", + "once_cell", + "parking_lot", + "proc-macro2", + "quote", + "raw-window-handle", + "raw-window-metal", + "serde", + "serde_json", + "slabbin", + "smallvec", + "thread_local", + "vk-parse", + "vulkano-macros", + "x11-dl", + "x11rb", +] + +[[package]] +name = "vulkano-macros" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dc929c42c9336fd082079ac3ea30126e4a0dfe36fd2e2b3581303f7d140d20f" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" +dependencies = [ + "bitflags 2.9.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.9.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" +dependencies = [ + "rustix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" +dependencies = [ + "bitflags 2.9.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccaacc76703fefd6763022ac565b590fcade92202492381c95b2edfdf7d46b3" +dependencies = [ + "bitflags 2.9.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2" +dependencies = [ + "bitflags 2.9.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "wgpu" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6049eb2014a0e0d8689f9b787605dd71d5bbfdc74095ead499f3cff705c229" +dependencies = [ + "arrayvec", + "bitflags 2.9.0", + "cfg_aliases", + "document-features", + "hashbrown", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "25.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19813e647da7aa3cdaa84f5846e2c64114970ea7c86b1e6aae8be08091f4bdc" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.9.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror 2.0.12", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd488b3239b6b7b185c3b045c39ca6bf8af34467a4c5de4e0b1a564135d093d" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09ad7aceb3818e52539acc679f049d3475775586f3f4e311c30165cf2c00445" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cba5fb5f7f9c98baa7c889d444f63ace25574833df56f5b817985f641af58e46" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "25.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7c4a1dc42ff14c23c9b11ebf1ee85cde661a9b1cf0392f79c1faca5bc559fb" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.9.0", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hashbrown", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "ordered-float", + "parking_lot", + "portable-atomic", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.12", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-types" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa49460c2a8ee8edba3fca54325540d904dd85b2e086ada762767e17d06e8bc" +dependencies = [ + "bitflags 2.9.0", + "bytemuck", + "js-sys", + "log", + "thiserror 2.0.12", + "web-sys", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.9.0", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.9.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zenyx" +version = "0.1.0" +dependencies = [ + "allocator-api2", + "bytemuck", + "cgmath", + "image", + "smol", + "terminator", + "thiserror 2.0.12", + "tobj", + "tracing", + "tracing-subscriber", + "vulkano", + "wgpu", + "winit", + "zlog", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive 0.8.24", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zlog" +version = "0.1.0" +dependencies = [ + "chrono", + "pretty_assertions", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..732a166 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,60 @@ +[package] +name = "zenyx" +version = "0.1.0" +edition = "2024" +authors = ["Caznix (Chance) "] +description = "A memory safe, opinionated Game Engine/Framework, written in Rust." +keywords = ["engine", "graphics", "game"] +categories = ["game-development", "graphics"] +license = "MIT" +homepage = "https://zenyx-engine.github.io/" +repository = "https://codeberg.org/Caznix/Zenyx" + +[lib] +crate-type = ["cdylib"] + +[workspace] +resolver = "2" +members = ["subcrates/renderer", "subcrates/zlog"] + +[workspace.dependencies] +zlog = { path = "subcrates/zlog" } + +[profile.release] +lto = true +codegen-units = 1 +panic = "abort" +split-debuginfo = "off" + +[profile.dev] +debug = 0 + +[profile.mini] +inherits = "release" +opt-level = "z" +debug = false +strip = true +lto = true +codegen-units = 1 +incremental = false +panic = "abort" + +[dependencies] +bytemuck = "1.22.0" +cgmath = "0.18.0" +image = "0.25.6" +smol = "2.0.2" + +winit = { version = "0.30.9" } +terminator = "0.3.2" +thiserror = "2.0.12" +tobj = "4.0.3" +tracing = "0.1.41" +tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } +vulkano = "0.35.1" +wgpu = { version = "25.0.0", features = ["spirv"] } +zlog.workspace = true +allocator-api2 = "0.2.21" + +[target.aarch64-linux-android.dependencies] +winit = { version = "0.30.9", features = ["android-native-activity"] } diff --git a/LICENSE.md b/LICENSE.md index c918216..e3d1dd3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,21 @@ -# MIT License - -## Copyright (c) 2024 Caznix - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.** +# MIT License + +## Copyright (c) 2025 Nonsensical Dev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.** diff --git a/README.md b/README.md index e69de29..a3e525d 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,148 @@ +
+ +Zenyx engine + +![Version](https://img.shields.io/badge/version-0.1.0-blue) +![License](https://img.shields.io/gitlab/license/Caznix/Zenyx) +![Build](https://img.shields.io/github/actions/workflow/status/Caznix/Zenyx/rust.yml?branch=main) + +![platform](https://img.shields.io/badge/platform-windows%20%7C%20linux%20%7C%20macos-informational) + +
+ +--- + +# What is Zenyx? + +Zenyx is an in-development game engine leveraging the power of [wgpu](https://github.com/gfx-rs/wgpu) for graphics rendering and [winit](https://github.com/rust-windowing/winit) for window management. Built with Rust, Zenyx aims to be an intuitive and innovative game engine, designed to adapt to various workflows while introducing new possibilities for game development. + +## Planned Features + +> ๐Ÿš€ Note: The following features represent the intended direction of Zenyx and are not fully implemented at this stage. + +### **Zenyx is being designed with the following capabilities in mind:** + +- โœจ **Cross-Platform Compatibility:** Targeting Windows, Linux, and macOS. +- โšก **Performance and Safety:** Built with Rust to provide both speed and memory safety. +- ๐ŸŽฏ **Intuitive and Extensible Design:** Focusing on user-friendly workflows and highly customizable tools. +- ๐Ÿ”ง **Modular Architecture:** Designed with a modular structure for straightforward customization. +- ๐Ÿ› ๏ธ **Integrated Toolset:** Envisioning built-in tools for spatial audio and level editing. +- ๐Ÿ“ฆ **Efficient Asset Management:** Developing a robust resource handling system. +- ๐ŸŽฒ **Performant Physics Engine:** Zenyx Makes use of [Rapier2D](https://docs.rs/rapier2d/latest/rapier2d/) & [Rapier3D](https://docs.rs/rapier3d/latest/rapier3d/) +- ๐Ÿ—‚๏ธ **Advanced Scene Management:** Designing flexible tools for organizing game scenes. + +### **Current Limitations:** + +Currently, Zenyx faces certain limitations due to its early stage of development and the capabilities of its underlying rendering backend, wgpu: + +- **No Hardware Ray Tracing:** As wgpu currently only supports standard rasterization pipelines, Zenyx inherits this limitation. Hardware ray tracing is not yet available. You can follow the progress of ray tracing support in wgpu [here](https://github.com/gfx-rs/wgpu/issues/6762). +- **Alpha software:** Zenyx is in the initial phases of development. It is not yet suitable for any practical use cases. Many of the features listed above are still goals and have not been implemented. +- **Limited macOS Support:** While macOS (and or IOS) is a target platform, it currently requires MoltenVK due to wgpu's lack of native Metal support. This might introduce additional dependencies, potential compatibility issues, or generally unintended behavior on such platforms +- **Incomplete Documentation and Tooling:** As the engine is under active development, comprehensive documentation and a full suite of built-in tools are not yet available, however they are still planned for the near future. + +## FAQ + +
+What platforms does Zenyx support? + +Zenyx primarily supports Windows and Linux, with secondary support for macOS. See the +[Platform support table](#what-platforms-will-be-supported-in-the-future) for more +information. + +
+ +
+Is Zenyx ready for production use? + +Zenyx is currently in early development and is not yet ready for any simple use +cases, but we're working hard to make it the best it can be before we release +1.0. If this interests you, and you're interested in helping, please check out +the [contribution section](CONTRIBUTING.md) for the ways you can help. + +
+ +
+How can I contribute to Zenyx? + +We welcome contributions! Please check our contribution guidelines and open a +pull request on GitHub, if you aren't a developer, you can also report bugs or +feature requests on our [issue tracker](https://codeberg.org/Zenyx/zenyx/issues). +For more information, please see the [Contributing section](#contributing). + +
+ +
+What are the system requirements? + +Detailed system requirements will be provided as the engine matures. Currently, +the only requirement is a modern OS and a system with atleast a semi-recent GPU. + +
+ +
+Is Zenyx free to use? + +Yes, Zenyx is open-source software licensed under MIT. You can Modify, +Distribute, and use Zenyx for any purpose you wish. + +
+ +## What platforms will be supported in the future? + +| Platform | Support Priority | Status | Notes | +|:----------:|:----------------:|:------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Windows | Primary | โœ… | | +| Linux/*BSD | Primary | โœ… | | +| macOS | Secondary | โš ๏ธ | The current main set of maintainers do not own any native MacOS devices to perform tests with. | +| Android | Help wanted | โ“ | | +| iOS | Not planned | โ“ | | +| Web | TBD | โ“ | | +| Consoles | Not planned | โ›” | Consoles require specific dev kits,proprietary licenses, and substantial fees that we (Nonsensical-dev,the Zenyx maintainers,and the open source contributors) currently do not have the capacity for. This may change in the future but most likely will not be soon. | + +# Documentation + +## Getting Started + +Zenyx is currently in a pre-release state and is not yet ready for general use. +Keep an eye on this section for updates on when you can start using Zenyx. + +# Contributing + +We encourage community involvement in the development of Zenyx! If you're interested in contributing, +please review our [Contribution Guide](CONTRIBUTING.md) for our coding standards and community guidelines. + +You can contribute in various ways, even if you're not a developer. Spreading the word about Zenyx, +reporting any bugs you encounter, suggesting new features, +and helping us improve our documentation are all valuable contributions. + +If you are interested in contributing code to Zenyx, please follow the platform-specific instructions below: + +## Prerequisites (all platforms) + +1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your system. + +2. Make sure you have [git](https://git-scm.com/downloads) installed for version control. + +## Building + +**1**. Clone the Zenyx repository from your favorite mirror: + + git clone https://codeberg.org/Zenyx/zenyx + +**2**. Navigate to the project directory: + + cd ./Zenyx + +**3**. Build the project using Cargo: + + cargo run + +# Press kit + +### Text + +Zenyx Typeface + +### Colored badges + +Zenyx Logo diff --git a/assets/Badge.png b/assets/Badge.png new file mode 100644 index 0000000..a9b7e38 Binary files /dev/null and b/assets/Badge.png differ diff --git a/assets/Badge.svg b/assets/Badge.svg new file mode 100644 index 0000000..714305d --- /dev/null +++ b/assets/Badge.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/Logo.png b/assets/Logo.png new file mode 100644 index 0000000..bc92691 Binary files /dev/null and b/assets/Logo.png differ diff --git a/assets/Logo.svg b/assets/Logo.svg new file mode 100644 index 0000000..7730d19 --- /dev/null +++ b/assets/Logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/Pumpkin.mtl b/assets/Pumpkin.mtl new file mode 100644 index 0000000..3234b01 --- /dev/null +++ b/assets/Pumpkin.mtl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db34f4a5f9afedfdd9961833c8fab52675c80eec253998d4950fbd6e8e146f5a +size 423 diff --git a/assets/Pumpkin.obj b/assets/Pumpkin.obj new file mode 100644 index 0000000..3213ff6 --- /dev/null +++ b/assets/Pumpkin.obj @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea2ba2cb7b88b20e6b1d52c0726e7a707b20a6ed22f23d640031e87d1942f5a3 +size 681889 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..5235544 --- /dev/null +++ b/build.rs @@ -0,0 +1,26 @@ +use std::{env, process::Command}; + +fn main() { + println!("cargo::rerun-if-changed=shaders"); + let outdir = env::var("OUT_DIR").unwrap(); + let vert = Command::new("glslc") + .args(["shaders/shader.vert", "-o", &format!("{outdir}/vert.spv")]) + .output() + .expect("Failed to execute 'glslc'"); + let frag = Command::new("glslc") + .args(["shaders/shader.frag", "-o", &format!("{outdir}/frag.spv")]) + .output() + .expect("Failed to execute 'glslc'"); + if !vert.status.success() { + panic!( + "Failed to compile vertex shader: {}", + String::from_utf8(vert.stderr).unwrap() + ) + } + if !frag.status.success() { + panic!( + "Failed to compile fragment shader: {}", + String::from_utf8(frag.stderr).unwrap() + ) + } +} diff --git a/cargo.toml b/cargo.toml deleted file mode 100644 index f2fa59a..0000000 --- a/cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[workspace] -resolver = "2" -members = [ - "engine", - "editor", - "xtask", -] \ No newline at end of file diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..1aa9adf --- /dev/null +++ b/default.nix @@ -0,0 +1,75 @@ +{ lib, + rustPlatform, + nix-gitignore, + bash, + makeWrapper, + dav1d, + vulkan-loader, + libGL, + wayland, + pkg-config, + libxkbcommon, + pkgs, + stdenv, + targetPackages ? pkgs, +}: let + version = (builtins.fromTOML (builtins.readFile ./engine/Cargo.toml)).package.version; + src = nix-gitignore.gitignoreSource [] ./.; +in +rustPlatform.buildRustPackage rec { + pname = "zenyx"; + inherit src version; + cargoLock.lockFile = ./Cargo.lock; + + nativeBuildInputs = [ + pkg-config + ] ++ lib.optionals stdenv.targetPlatform.isDarwin [ + targetPackages.darwin.apple_sdk.frameworks.CoreServices + ]; + + buildInputs = with targetPackages; [ + dav1d + ] ++ lib.optionals (stdenv.targetPlatform.isLinux || stdenv.targetPlatform.isWindows) [ + vulkan-loader + ] ++ lib.optionals stdenv.targetPlatform.isLinux [ + makeWrapper + wayland + libxkbcommon + libGL + xorg.libXcursor + xorg.libXrandr + xorg.libXi + xorg.libX11 + xorg.libxcb + bash + ] ++ lib.optionals stdenv.targetPlatform.isDarwin [ + makeWrapper + darwin.apple_sdk.frameworks.Cocoa + darwin.apple_sdk.frameworks.Metal + darwin.apple_sdk.frameworks.CoreVideo + darwin.apple_sdk.frameworks.QuartzCore + ]; + + CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = + lib.optionalString stdenv.targetPlatform.isWindows "${stdenv.cc.targetPrefix}gcc"; + + NIX_LDFLAGS = lib.optionalString stdenv.targetPlatform.isDarwin "-framework CoreFoundation"; + + postInstall = lib.optionalString stdenv.targetPlatform.isLinux '' + wrapProgram $out/bin/${pname} \ + --prefix PATH : ${lib.makeBinPath [ bash ]} \ + --set LD_LIBRARY_PATH ${lib.makeLibraryPath buildInputs} + '' + lib.optionalString stdenv.targetPlatform.isWindows '' + mkdir -p $out/bin + cp ${targetPackages.vulkan-loader}/bin/vulkan-1.dll $out/bin/ + ''; + + doCheck = false; + + meta = { + description = "Cross-platform WSYWIG Game Engine"; + license = lib.licenses.mit; + platforms = lib.platforms.all; + mainProgram = "zenyx"; + }; +} \ No newline at end of file diff --git a/editor/src/main.rs b/editor/src/main.rs deleted file mode 100644 index 6bd4269..0000000 --- a/editor/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("editor") -} \ No newline at end of file diff --git a/engine/.gitignore b/engine/.gitignore deleted file mode 100644 index ea8c4bf..0000000 --- a/engine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/engine/Cargo.toml b/engine/Cargo.toml deleted file mode 100644 index b5bc16e..0000000 --- a/engine/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "zenyx" -version = "0.1.0" -edition = "2021" - -[dependencies] -chrono = "0.4.38" -colored = "2.1.0" -lazy_static = "1.5.0" -#log = "0.4.22" -log2 = "0.1.14" -parking_lot = "0.12.3" -reedline = "0.37.0" -regex = "1.11.1" -thiserror = "2.0.3" -tokio = { version = "1.41.1", features = ["macros", "rt", "rt-multi-thread"] } diff --git a/engine/src/core/commands.rs b/engine/src/core/commands.rs deleted file mode 100644 index 45884ac..0000000 --- a/engine/src/core/commands.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::process::Command; - -use log2::{debug, info}; - -use crate::core::repl::COMMAND_LIST; - -pub fn say_hello() { - println!("Hello from your new command!"); -} - -pub fn echo(args: Vec) { - debug!("{}", args.join(" ")); - println!("{}", args.join(" ")) -} - -pub fn exit() { - debug!("Exiting..."); - std::process::exit(0) -} -pub fn clear() { - info!("Clearing screen..., running command"); - let _result = if cfg!(target_os = "windows") { - debug!("target_os is windows"); - Command::new("cmd").args(["/c", "cls"]).spawn() - } else { - debug!("target_os was unix"); - // "clear" or "tput reset" - Command::new("tput").arg("reset").spawn() - }; -} -pub fn cmds() { - println!("Commands:"); - for cmd in COMMAND_LIST.commands.read().iter() { - println!("{:#}", cmd); - } -} diff --git a/engine/src/core/mod.rs b/engine/src/core/mod.rs deleted file mode 100644 index 7c5620e..0000000 --- a/engine/src/core/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod commands; -pub mod repl; -pub mod splash; diff --git a/engine/src/core/repl.rs b/engine/src/core/repl.rs deleted file mode 100644 index 899c606..0000000 --- a/engine/src/core/repl.rs +++ /dev/null @@ -1,248 +0,0 @@ -use super::commands; -use chrono::Local; -use lazy_static::lazy_static; -use log2::{debug, error, info}; -use parking_lot::RwLock; -use reedline::{Prompt, Reedline, Signal}; -use regex::Regex; -use std::{borrow::Borrow, collections::HashMap, sync::Arc}; - -struct ZPrompt { - left_text: String, - right_text: String, -} - -#[derive(Clone, Debug)] -enum Callable { - Simple(fn()), - WithArgs(fn(Vec)), -} -#[derive(Debug)] -pub struct Command { - pub name: &'static str, - pub description: Option<&'static str>, - function: Callable, - pub arg_count: u8, -} - -impl Command { - pub fn execute(&self, args: Option>) { - //debug!("Executing command: {}", self.name); - match &self.function { - Callable::Simple(f) => { - if let Some(args) = args { - error!( - "Command expected 0 arguments but {} args were given. Ignoring..", - args.len() - ); - } - f() - } - Callable::WithArgs(f) => match args { - Some(args) => f(args), - None => error!("Command expected arguments but received 0"), - }, - } - } -} - -impl std::fmt::Display for Command { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Name: {}\n\t{}", - self.name, - self.description.unwrap_or("No description") - ) - } -} - -lazy_static! { - pub static ref COMMAND_LIST: Arc = Arc::new(CommandList::new()); -} - -pub struct CommandList { - pub commands: RwLock>, - pub aliases: RwLock>, -} - -impl CommandList { - fn new() -> Self { - CommandList { - commands: RwLock::new(Vec::new()), - aliases: RwLock::new(HashMap::new()), - } - } - - fn add_command( - &self, - name: &'static str, - description: Option<&'static str>, - func: Callable, - arg_count: Option, - ) { - debug!("Adding command: {}", name); - let mut commands = self.commands.write(); - - commands.push(Command { - name, - description, - function: func, - arg_count: arg_count.unwrap_or(0), - }); - } - fn add_alias(&self, name: String, alias: String) { - //println!("Input alias: {}", alias); - if self.aliases.read().contains_key(&alias) { - error!("Alias: '{}' already exists", alias); - return; - } - let mut commands = self.commands.write(); - if let Some(command) = commands.iter_mut().find(|cmd| cmd.name == name) { - info!("Adding alias: {} for cmd: {}", alias, command.name); - self.aliases - .write() - .insert(alias.to_string(), name.to_string()); - } else { - error!("Command: '{}' was not found", name); - } - } - - fn execute_command(&self, mut name: String, args: Option>) { - //info!("received input command: {}", name); - let commands = self.commands.borrow(); - if self.aliases.read().contains_key(&name) { - name = self - .aliases - .read() - .get_key_value(&name) - .unwrap() - .1 - .to_string(); - debug!("changed to {}", name); - } - if let Some(command) = commands.read().iter().find(|cmd| cmd.name == name) { match (command.arg_count, args.as_ref()) { - (expected, Some(args_vec)) if args_vec.len() != expected as usize => { - eprintln!( - "Command: '{}' expected {} arguments but received {}", - name, - expected, - args_vec.len() - ); - } - (_, _) => command.execute(args), - } } - } -} - -impl Prompt for ZPrompt { - fn render_prompt_left(&self) -> std::borrow::Cow { - std::borrow::Cow::Borrowed(&self.left_text) - } - - fn render_prompt_right(&self) -> std::borrow::Cow { - std::borrow::Cow::Borrowed(&self.right_text) - } - - fn render_prompt_history_search_indicator( - &self, - _history_search: reedline::PromptHistorySearch, - ) -> std::borrow::Cow { - std::borrow::Cow::Borrowed("") - } - - fn render_prompt_indicator( - &self, - prompt_mode: reedline::PromptEditMode, - ) -> std::borrow::Cow { - match prompt_mode { - reedline::PromptEditMode::Default => std::borrow::Cow::Borrowed(">>"), - reedline::PromptEditMode::Emacs => { - let timestamp = Local::now().format("[%H:%M:%S.%3f/SHELL] >>\t").to_string(); - std::borrow::Cow::Owned(timestamp) - } - reedline::PromptEditMode::Vi(_) => std::borrow::Cow::Borrowed("vi>>"), - reedline::PromptEditMode::Custom(_) => std::borrow::Cow::Borrowed("custom>>"), - } - } - - fn render_prompt_multiline_indicator(&self) -> std::borrow::Cow { - std::borrow::Cow::Borrowed("><") - } -} - -fn setup() { - COMMAND_LIST.add_command( - "hello", - Some("test"), - Callable::Simple(commands::say_hello), - None, - ); - COMMAND_LIST.add_command("exit", None, Callable::Simple(commands::exit), None); - COMMAND_LIST.add_command("clear", None, Callable::Simple(commands::clear), None); - COMMAND_LIST.add_command("echo", None, Callable::WithArgs(commands::echo), Some(1)); - COMMAND_LIST.add_command("cmds", None, Callable::Simple(commands::cmds), None); - COMMAND_LIST.add_alias("cmds".to_string(), "help".to_string()); - COMMAND_LIST.add_alias("cmds".to_string(), "cmd_list".to_string()); - COMMAND_LIST.add_alias("hello".to_string(), "exit".to_string()); - COMMAND_LIST.add_alias("clear".to_string(), "exit".to_string()); -} - -pub async fn handle_repl() { - let mut line_editor = Reedline::create(); - setup(); - - loop { - let sig = line_editor.read_line(&ZPrompt { - left_text: String::new(), - right_text: "<<".to_string(), - }); - - match sig { - Ok(Signal::Success(buffer)) => { - if buffer == "exit" { - std::process::exit(0); - } else { - evaluate_command(&buffer); - } - } - Ok(Signal::CtrlC) => { - println!("\nCONTROL+C RECEIVED, TERMINATING"); - std::process::exit(0); - } - err => { - eprintln!("Error: {:?}", err); - } - } - } -} - -fn evaluate_command(input: &str) { - if input.trim().is_empty() { - return; - } - - let pattern = Regex::new(r"[;|\n]").unwrap(); - let commands: Vec<&str> = pattern.split(input).collect(); - - for command in commands { - let command = command.trim(); - if command.is_empty() { - println!("Empty command, skipping."); - continue; - } - - let tokens: Vec<&str> = command.split_whitespace().collect(); - if tokens.is_empty() { - return; - } - - let cmd_name = tokens[0]; - let args: Vec = tokens[1..].iter().map(|&s| s.to_string()).collect(); - - COMMAND_LIST.execute_command( - cmd_name.to_string(), - if args.is_empty() { None } else { Some(args) }, - ); - } -} diff --git a/engine/src/core/splash.rs b/engine/src/core/splash.rs deleted file mode 100644 index f35c870..0000000 --- a/engine/src/core/splash.rs +++ /dev/null @@ -1,26 +0,0 @@ -use colored::Colorize; - -pub fn print_splash() { - println!( - r#" - &&&&&&&&&&& - &&&&&&&&&&&&&&&&& - &&&&&&&&&&&&&&&&&&&&& - && &&&&&&&&& - && &&&&&&&&& -&&&&&&&&&&&& &&&&&&&&&&& -&&&&&&&&&&&&& &&&&&&&&&&&& -&&&&&&&&&&&&& &&&&&&&&&&&&& -&&&&&&&&&&&& &&&&&&&&&&&&& -&&&&&&&&&&& &&&&&&&&&&&& - &&&&&&&&& && - &&&&&&&&& && - &&&&&&&&&&&&&&&&&&&&& - &&&&&&&&&&&&&&&&& - &&&&&&&&&&& - - Version: {} - "#, - env!("CARGO_PKG_VERSION").yellow().italic().underline() - ); -} diff --git a/engine/src/main.rs b/engine/src/main.rs deleted file mode 100644 index b94b1eb..0000000 --- a/engine/src/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::io; - -use log2::info; - -pub mod core; - -#[tokio::main] -async fn main() -> Result<(), io::Error> { - let _log2 = log2::open("z.log").tee(true).level("trace").start(); - info!("Initalizing Engine"); - let shell_thread = tokio::task::spawn(async { - info!("Shell thread started"); - core::repl::handle_repl().await; - } -); - - core::splash::print_splash(); - info!("Engine Initalized"); - shell_thread.await?; - Ok(()) -} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..4eb8d37 --- /dev/null +++ b/flake.lock @@ -0,0 +1,190 @@ +{ + "nodes": { + "alejandra": { + "inputs": { + "fenix": "fenix", + "flakeCompat": "flakeCompat", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730688725, + "narHash": "sha256-g0SSfTWZ5mtMOpQic+eqq9sXMy1E/7yKxxfupZd9V4A=", + "owner": "kamadorueda", + "repo": "alejandra", + "rev": "2bb91e309ca99656addff5c74545acbf5813636d", + "type": "github" + }, + "original": { + "owner": "kamadorueda", + "ref": "3.1.0", + "repo": "alejandra", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "alejandra", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1730615655, + "narHash": "sha256-2HBR3zLn57LXKNRtxBb+O+uDqHM4n0pz51rPayMl4cg=", + "owner": "nix-community", + "repo": "fenix", + "rev": "efeb50e2535b17ffd4a135e6e3e5fd60a525180c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-compat": { + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "revCount": 69, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flakeCompat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1744932701, + "narHash": "sha256-fusHbZCyv126cyArUwwKrLdCkgVAIaa/fQJYFlCEqiU=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b024ced1aac25639f8ca8fdfc2f8c4fbd66c48ef", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "alejandra": "alejandra", + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay", + "utils": "utils" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1730555913, + "narHash": "sha256-KNHZUlqsEibg3YtfUyOFQSofP8hp1HKoY+laoesBxRM=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "f17a5bbfd0969ba2e63a74505a80e55ecb174ed9", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1744943606, + "narHash": "sha256-VL4swGy4uBcHvX+UR5pMeNE9uQzXfA7B37lkwet1EmA=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "ec22cd63500f4832d1f3432d2425e0b31b0361b1", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..21466a2 --- /dev/null +++ b/flake.nix @@ -0,0 +1,87 @@ +{ + description = "Zenyx - A WSYWIG game engine written in rust "; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + utils.url = "github:numtide/flake-utils"; + rust-overlay.url = "github:oxalica/rust-overlay"; + flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + alejandra.url = "github:kamadorueda/alejandra/3.1.0"; + alejandra.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + utils, + rust-overlay, + alejandra, + ... + }: + { + overlays.default = final: prev: { + zenyx = final.callPackage ./default.nix {}; + }; + } + // utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs { + inherit system; + overlays = [ + self.overlays.default + (import rust-overlay) + ]; + }; + + nativeBuildInputs = with pkgs; [ + vulkan-tools + vulkan-tools-lunarg + shaderc + cargo-xbuild + cargo-pgo + cargo-cross + cargo-xwin + cargo-wizard + wine64 + pkg-config + ]; + + buildInputs = with pkgs; [ + vulkan-loader + libGL + wayland + libxkbcommon + xorg.libXcursor + xorg.libXrandr + xorg.libXi + xorg.libX11 + xorg.libxcb + ]; + in { + packages = { + inherit (pkgs) zenyx; + default = pkgs.zenyx; + windows = let + pkgsCross = import nixpkgs { + system = "x86_64-linux"; + crossSystem = nixpkgs.lib.systems.examples.mingwW64; + }; + in pkgsCross.callPackage ./default.nix {}; + }; + + devShells.default = pkgs.mkShell { + name = "zenyx"; + nativeBuildInputs = with pkgs; [ + (rust-bin.stable.latest.default.override { + extensions = ["rust-src" "cargo" "rustfmt" "clippy"]; + targets = [ "x86_64-pc-windows-msvc" "x86_64-unknown-linux-gnu" ]; + + }) + pkg-config + ] ++ nativeBuildInputs; + buildInputs = buildInputs; + LD_LIBRARY_PATH= pkgs.lib.makeLibraryPath buildInputs; + }; + formatter = alejandra.packages.${system}.default; + } + ); +} diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..a99bc20 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,7 @@ +indent_style = "Block" +wrap_comments = true +format_code_in_doc_comments = true +trailing_comma = "Vertical" +group_imports = "StdExternalCrate" +reorder_impl_items = true +unstable_features = true diff --git a/shaders/shader.frag b/shaders/shader.frag new file mode 100644 index 0000000..c9ffc77 --- /dev/null +++ b/shaders/shader.frag @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(set = 1, binding = 0) uniform texture2D t_diffuse; +layout(set = 1, binding = 1) uniform sampler s_diffuse; +layout(location = 0) out vec4 out_color; +// layout(group = 0, binding = 0) out texture2D; +void main() { + out_color = texture(sampler2D(t_diffuse, s_diffuse), tex_coords); +} diff --git a/shaders/shader.vert b/shaders/shader.vert new file mode 100644 index 0000000..79c95f0 --- /dev/null +++ b/shaders/shader.vert @@ -0,0 +1,15 @@ +#version 450 + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 color; +layout(location = 3) in vec2 tex_coords; +layout(location = 0) out vec2 tex_coord; +layout(set = 0, binding = 0) uniform UniformBufferObject { + mat4x4 projection; +} view; +void main() { + gl_Position = view.projection * vec4(position, 1.0); + tex_coord = tex_coords; + // gl_Position + // out_color = color; +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..64217fe --- /dev/null +++ b/shell.nix @@ -0,0 +1,15 @@ +( + import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + nodeName = lock.nodes.root.inputs.flake-compat; + in + fetchTarball { + url = lock.nodes.${nodeName}.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz"; + sha256 = lock.nodes.${nodeName}.locked.narHash; + } + ) + {src = ./.;} +) +.shellNix diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..588bfe9 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,49 @@ +pub struct Camera { + pub eye: cgmath::Point3, + pub target: cgmath::Point3, + pub up: cgmath::Vector3, + pub aspect: f32, + pub fovy: f32, + pub znear: f32, + pub zfar: f32, +} + +impl Camera { + fn build_view_projection_matrix(&self) -> cgmath::Matrix4 { + let view = cgmath::Matrix4::look_at_rh(self.eye, self.target, self.up); + + let proj = cgmath::perspective(cgmath::Deg(self.fovy), self.aspect, self.znear, self.zfar); + + OPENGL_TO_WGPU_MATRIX * proj * view + } + + pub fn update_aspect(&mut self, aspect: f32) { + self.aspect = aspect; + } +} + +pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( + 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0, +); + +unsafe impl bytemuck::Pod for CameraUniform {} +unsafe impl bytemuck::Zeroable for CameraUniform {} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CameraUniform { + view_proj: cgmath::Matrix4, +} +impl Default for CameraUniform { + fn default() -> CameraUniform { + use cgmath::SquareMatrix; + Self { + view_proj: cgmath::Matrix4::identity(), + } + } +} +impl CameraUniform { + pub fn update_view_proj(&mut self, camera: &Camera) { + self.view_proj = camera.build_view_projection_matrix(); + } +} diff --git a/src/collections/mod.rs b/src/collections/mod.rs new file mode 100644 index 0000000..fa842ed --- /dev/null +++ b/src/collections/mod.rs @@ -0,0 +1,3 @@ +mod sparse_set; + +pub use sparse_set::SparseSet; diff --git a/src/collections/sparse_set.rs b/src/collections/sparse_set.rs new file mode 100644 index 0000000..5e0ec84 --- /dev/null +++ b/src/collections/sparse_set.rs @@ -0,0 +1,273 @@ +use core::{num::NonZeroUsize, usize}; + +use allocator_api2::{ + alloc::{Allocator, Global}, + boxed::Box, + vec::Vec, +}; +use bytemuck::Contiguous; + +const SPARSE_PAGESIZE: usize = (1 << 10) * 4; +type SparsePage = Option<(Box<[Option; SPARSE_PAGESIZE], A>, usize)>; + +pub struct SparseSet +where + PackedAlloc: Allocator, + SparseAlloc: Allocator, +{ + sparse: Vec, SparseAlloc>, + dense: Vec, + dense_to_id: Vec, +} + +impl SparseSet { + pub const fn new() -> Self { + Self { + sparse: Vec::new(), + dense: Vec::new(), + dense_to_id: Vec::new(), + } + } +} + +impl SparseSet +where + PackedAlloc: Allocator, + SparseAlloc: Allocator + Clone, +{ + pub fn insert(&mut self, id: usize, value: T) -> Option { + match self.get_dense_idx(id) { + Some(idx) => { + let previous = core::mem::replace(&mut self.dense[idx], value); + self.dense_to_id[idx] = id; + Some(previous) + } + None => { + self.increase_page_usage_count(id); + self.set_dense_idx(id, Some(self.dense.len())); + self.dense.push(value); + self.dense_to_id.push(id); + None + } + } + } + + pub fn get(&self, id: usize) -> Option<&T> { + self.dense.get(self.get_dense_idx(id)?) + } + + pub fn get_mut(&mut self, id: usize) -> Option<&mut T> { + let idx = self.get_dense_idx(id)?; + self.dense.get_mut(idx) + } + + fn set_dense_idx(&mut self, id: usize, idx: Option) { + let page = id / SPARSE_PAGESIZE; + let sparse_index = id % SPARSE_PAGESIZE; + + if page >= self.sparse.len() { + self.sparse.resize(page + 1, None); + } + + if self.sparse[page].is_none() { + self.sparse[page] = Some(( + Box::new_in([None; 4096], self.sparse.allocator().clone()), + 1, + )) + } + + match &mut self.sparse[page] { + Some(page) => { + page.0[sparse_index] = idx.map(|i| NonZeroUsize::new(i + 1).unwrap()); + } + None => unreachable!("wtf, failed to init sparse page 5 lines above??"), + } + } + + pub fn get_dense_idx(&self, id: usize) -> Option { + let page = id / SPARSE_PAGESIZE; + let sparse_index = id % SPARSE_PAGESIZE; + let page = self.sparse.get(page)?.as_ref()?; + page.0[sparse_index].map(|idx| idx.into_integer() - 1) + } + + fn reduce_page_usage_count(&mut self, id: usize) { + let page = id / SPARSE_PAGESIZE; + let Some(usage) = &mut self.sparse[page] else { + return; + }; + usage.1 -= 1; + let usage = usage.1; + if usage == 0 { + self.sparse[page] = None; + } + } + + fn increase_page_usage_count(&mut self, id: usize) { + let page = id / SPARSE_PAGESIZE; + if page >= self.sparse.len() { + return; + } + let Some(usage) = &mut self.sparse[page] else { + return; + }; + usage.1 += 1; + } + + pub fn remove(&mut self, id: usize) -> Option { + let index = self.get_dense_idx(id)?; + if self.dense.is_empty() { + return None; + } + + self.set_dense_idx(*self.dense_to_id.last().unwrap(), Some(index)); + self.set_dense_idx(id, None); + self.reduce_page_usage_count(id); + + let previous = self.dense.swap_remove(index); + self.dense_to_id.swap_remove(index); + Some(previous) + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn len(&self) -> usize { + self.dense.len() + } + + pub fn contains(&self, id: usize) -> bool { + self.get_dense_idx(id).is_some() + } + + pub fn keys(&self) -> &[usize] { + &self.dense_to_id + } + + pub fn values(&self) -> &[T] { + &self.dense + } + + pub fn new_in(packed_alloc: PackedAlloc, sparse_alloc: SparseAlloc) -> Self { + Self { + dense: Vec::new_in(packed_alloc), + sparse: Vec::new_in(sparse_alloc.clone()), + dense_to_id: Vec::new_in(sparse_alloc), + } + } +} + +impl SparseSet +where + PackedAlloc: Allocator, +{ + pub const fn new_in_packed(packed_alloc: PackedAlloc) -> Self { + Self { + sparse: Vec::new(), + dense: Vec::new_in(packed_alloc), + dense_to_id: Vec::new(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn insert() { + let mut sparse_set = SparseSet::::new(); + sparse_set.insert(10, 1); + assert_eq!(sparse_set.keys(), &[10]); + assert_eq!(sparse_set.values(), &[1]); + + assert_eq!( + sparse_set.sparse[0].as_ref().unwrap().0[10].unwrap(), + NonZeroUsize::new(1).unwrap() + ); + assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1); + assert_eq!(sparse_set.insert(10, 2).unwrap(), 1); + assert_eq!(sparse_set.values(), &[2]); + assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1); + + sparse_set.insert(11, 4); + assert_eq!(sparse_set.keys(), &[10, 11]); + assert_eq!(sparse_set.values(), &[2, 4]); + assert_eq!( + sparse_set.sparse[0].as_ref().unwrap().0[11].unwrap(), + NonZeroUsize::new(2).unwrap() + ); + assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 2); + + sparse_set.insert(5000, 3); + assert_eq!(sparse_set.keys(), &[10, 11, 5000]); + assert_eq!(sparse_set.values(), &[2, 4, 3]); + assert_eq!( + sparse_set.sparse[5000 / SPARSE_PAGESIZE] + .as_ref() + .unwrap() + .0[5000 % SPARSE_PAGESIZE] + .unwrap(), + NonZeroUsize::new(3).unwrap() + ); + assert_eq!( + sparse_set.sparse[5000 / SPARSE_PAGESIZE] + .as_ref() + .unwrap() + .1, + 1 + ); + + assert_eq!(*sparse_set.get(10).unwrap(), 2); + assert_eq!(*sparse_set.get(11).unwrap(), 4); + assert_eq!(*sparse_set.get(5000).unwrap(), 3); + } + + #[test] + fn remove() { + let mut sparse_set = SparseSet::::new(); + sparse_set.insert(10, 1); + sparse_set.insert(11, 2); + sparse_set.insert(12, 2); + sparse_set.insert(SPARSE_PAGESIZE, 1); + sparse_set.insert(SPARSE_PAGESIZE + 1, 2); + sparse_set.insert(SPARSE_PAGESIZE + 2, 3); + + assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 2).unwrap(), 3); + assert_eq!(sparse_set.sparse[1].as_ref().unwrap().1, 2); + assert_eq!(sparse_set.keys(), [10, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1]); + assert_eq!(sparse_set.values(), [1, 2, 2, 1, 2]); + + assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 1).unwrap(), 2); + assert_eq!(sparse_set.sparse[1].as_ref().unwrap().1, 1); + assert_eq!(sparse_set.keys(), [10, 11, 12, SPARSE_PAGESIZE]); + assert_eq!(sparse_set.values(), [1, 2, 2, 1]); + + assert_eq!(sparse_set.remove(SPARSE_PAGESIZE).unwrap(), 1); + assert!(sparse_set.sparse[1].is_none()); + assert_eq!(sparse_set.keys(), [10, 11, 12]); + assert_eq!(sparse_set.values(), [1, 2, 2]); + + + sparse_set.insert(SPARSE_PAGESIZE, 1); + sparse_set.insert(SPARSE_PAGESIZE + 1, 2); + sparse_set.insert(SPARSE_PAGESIZE + 2, 3); + + assert_eq!(sparse_set.remove(10).unwrap(), 1); + assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 2); + // swap-remove + assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1]); + assert_eq!(sparse_set.values(), [3, 2, 2, 1, 2]); + + assert_eq!(sparse_set.remove(11).unwrap(), 2); + assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1); + assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, 12, SPARSE_PAGESIZE]); + assert_eq!(sparse_set.values(), [3, 2, 2, 1]); + + assert_eq!(sparse_set.remove(12).unwrap(), 2); + assert!(sparse_set.sparse[0].is_none()); + assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, SPARSE_PAGESIZE]); + assert_eq!(sparse_set.values(), [3, 2, 1]); + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d5be06a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +include!("main.rs"); diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2764eed --- /dev/null +++ b/src/main.rs @@ -0,0 +1,547 @@ +use bytemuck::bytes_of; +use std::collections::BTreeMap; +use std::io::BufReader; +use std::sync::Arc; +use std::time::Instant; +use tracing::info; +use wgpu::util::DeviceExt; +use wgpu::{ + Backends, FragmentState, IndexFormat, Instance, InstanceDescriptor, PipelineCompilationOptions, +}; +use winit::application::ApplicationHandler; +use winit::event::{ElementState, MouseButton}; +use winit::event_loop::{ActiveEventLoop, EventLoop}; +#[cfg(target_os = "android")] +use winit::platform::android::activity::AndroidApp; +use winit::window::{Window, WindowAttributes, WindowId}; +use zlog::LogLevel; +use zlog::config::LoggerConfig; + +pub mod camera; +pub mod collections; +pub mod model; +pub mod texture; + +struct WindowContext<'window> { + window: Arc, + renderer: WgpuRenderer<'window>, +} +impl std::ops::Deref for WindowContext<'_> { + type Target = winit::window::Window; + + fn deref(&self) -> &Self::Target { + self.window.as_ref() + } +} + +struct WgpuRenderer<'surface> { + device: wgpu::Device, + queue: wgpu::Queue, + surface: wgpu::Surface<'surface>, + surface_config: wgpu::SurfaceConfiguration, + render_pipeline: wgpu::RenderPipeline, + depth_texture: wgpu::Texture, + depth_texture_view: wgpu::TextureView, + camera: camera::Camera, + camera_uniform: camera::CameraUniform, + camera_buffer: wgpu::Buffer, + camera_bind_group: wgpu::BindGroup, + pumpkin: model::Model, + delta: f32, + last_frame_time: Instant, + default_texture: wgpu::BindGroup, +} + +impl WgpuRenderer<'_> { + pub fn draw(&mut self) { + let surface_texture = self.surface.get_current_texture().unwrap(); + let view = surface_texture.texture.create_view(&Default::default()); + let mut encoder = + self.device + .create_command_encoder(&wgpu::wgt::CommandEncoderDescriptor { + label: Some("Render encoder"), + }); + { + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Render"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::WHITE), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &self.depth_texture_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: wgpu::StoreOp::Store, + }), + stencil_ops: None, + }), + occlusion_query_set: None, + timestamp_writes: None, + }); + rpass.set_pipeline(&self.render_pipeline); + rpass.set_bind_group(0, &self.camera_bind_group, &[]); + + for mesh in &self.pumpkin.meshes { + let bind_group = mesh + .material + .and_then(|i| self.pumpkin.materials.get(i)) + .map(|m| &m.bind_group) + .unwrap_or(&self.default_texture); + rpass.set_bind_group(1, bind_group, &[]); + rpass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); + rpass.set_index_buffer(mesh.index_buffer.slice(..), IndexFormat::Uint32); + rpass.draw_indexed(0..mesh.num_elements, 0, 0..1); + } + } + self.queue.submit(Some(encoder.finish())); + let delta_time = std::time::Instant::now() - self.last_frame_time; + self.delta = delta_time.as_secs_f32(); + info!("{}", self.delta); + surface_texture.present(); + self.last_frame_time = std::time::Instant::now(); + } +} + +struct App<'window> { + state: WgpuState, + windows: BTreeMap>, +} + +impl App<'_> { + fn new() -> Self { + Self { + state: WgpuState::new(), + windows: BTreeMap::new(), + } + } + + pub fn spawn_window(&mut self, event_loop: &ActiveEventLoop) { + let attr = WindowAttributes::default() + .with_title("Zenyx - SubWindow") + .with_min_inner_size(winit::dpi::LogicalSize::new(1, 1)); + + let window = event_loop.create_window(attr).unwrap(); + let window = Arc::new(window); + let renderer = self.state.create_renderer(window.clone()); + let window_ctx = WindowContext { + renderer: smol::block_on(renderer), + window: window.clone(), + }; + let window_id = window.id(); + self.windows.insert(window_id, window_ctx); + } +} + +struct WgpuState { + instance: wgpu::Instance, +} + +static _ICON: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/Badge.png")); +static _PUMPKIN: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/Pumpkin.obj")); + +impl WgpuState { + fn new() -> Self { + let backends = Backends::PRIMARY; + let instance_descriptor = InstanceDescriptor { + backends, + ..Default::default() + }; + let instance = Instance::new(&instance_descriptor); + Self { instance } + } + + async fn create_renderer<'surface>(&self, window: Arc) -> WgpuRenderer<'surface> { + let surface = self.instance.create_surface(window.clone()).unwrap(); + let adapter = self + .instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + ..Default::default() + }) + .await + .unwrap(); + let device_descriptor = wgpu::DeviceDescriptor::default(); + let (device, queue) = adapter.request_device(&device_descriptor).await.unwrap(); + + let size = window.inner_size(); + let width = size.width.max(1); + let height = size.height.max(1); + let texture_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + // This should match the filterable field of the + // corresponding Texture entry above. + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + label: Some("texture_bind_group_layout"), + }); + let camera_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("Camera Bind group layout"), + }); + #[repr(align(4))] + struct ShaderCode([u8; N]); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Pipeline Layout"), + bind_group_layouts: &[&camera_bind_group_layout, &texture_bind_group_layout], + push_constant_ranges: &[], + }); + + let vert_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("Vertex Shader"), + source: unsafe { + static SHADER_CODE: &[u8] = + &ShaderCode(*include_bytes!(concat!(env!("OUT_DIR"), "/vert.spv"))).0; + // assert!(bytes.len() % 4 == 0); + let shader = SHADER_CODE.align_to::().1; + wgpu::ShaderSource::SpirV(std::borrow::Cow::Borrowed(shader)) + }, + }); + let frag_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("Fragment Shader"), + source: unsafe { + static SHADER_CODE: &[u8] = + &ShaderCode(*include_bytes!(concat!(env!("OUT_DIR"), "/frag.spv"))).0; + debug_assert!(SHADER_CODE.len() % 4 == 0); + let shader = SHADER_CODE.align_to::().1; + wgpu::ShaderSource::SpirV(std::borrow::Cow::Borrowed(shader)) + }, + }); + let var_name = [Some(wgpu::ColorTargetState { + format: surface.get_capabilities(&adapter).formats[0], + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrites::ALL, + })]; + let pipeline_descriptor = wgpu::RenderPipelineDescriptor { + label: Some("Main pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &vert_shader, + entry_point: Some("main"), + buffers: &[model::Vertex::desc()], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false, + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(FragmentState { + module: &frag_shader, + entry_point: Some("main"), + compilation_options: PipelineCompilationOptions::default(), + targets: &var_name, + }), + multiview: None, + cache: None, + }; + // todo!(); + let surface_caps = surface.get_capabilities(&adapter); + let present_mode = if surface_caps + .present_modes + .contains(&wgpu::PresentMode::Mailbox) + { + wgpu::PresentMode::Mailbox + } else { + wgpu::PresentMode::Fifo + }; + let surface_config = wgpu::SurfaceConfiguration { + width, + height, + format: surface_caps.formats[0], + present_mode, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![], + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + desired_maximum_frame_latency: 3, + }; + + surface.configure(&device, &surface_config); + let pumpkin = model::Model::load_obj( + &mut BufReader::new(std::fs::File::open("Pumpkin.obj").unwrap()), + &device, + &queue, + &texture_bind_group_layout, + ); + let checkerboard_img = crate::texture::create_checkerboard(); + let checkerboard_texture = + texture::Texture::from_image(&device, &queue, &checkerboard_img, Some("checkerboard")) + .unwrap(); + + let checkerboard_sampler = device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::Repeat, + address_mode_v: wgpu::AddressMode::Repeat, + address_mode_w: wgpu::AddressMode::Repeat, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + + let default_texture = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("checkerboard-bind-group"), + layout: &texture_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&checkerboard_texture.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&checkerboard_sampler), + }, + ], + }); + let (depth_texture, depth_texture_view) = + create_depth_texture(&device, surface_config.width, surface_config.height); + let camera = camera::Camera { + // position the camera 1 unit up and 2 units back + // +z is out of the screen + eye: (0.0, 0.0, 2.0).into(), + // have it look at the origin + target: (0.0, 0.0, 0.0).into(), + // which way is "up" + up: cgmath::Vector3::unit_y(), + aspect: surface_config.width as f32 / surface_config.height as f32, + fovy: 45.0, + znear: 0.1, + zfar: 1000.0, + }; + + let mut camera_uniform = camera::CameraUniform::default(); + camera_uniform.update_view_proj(&camera); + + let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Camera Buffer"), + contents: bytemuck::cast_slice(&[camera_uniform]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + + let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &camera_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: camera_buffer.as_entire_binding(), + }], + label: Some("Camera Bind Group"), + }); + + let render_pipeline = device.create_render_pipeline(&pipeline_descriptor); + + WgpuRenderer { + surface, + surface_config, + depth_texture, + render_pipeline, + device, + camera, + queue, + camera_uniform, + camera_buffer, + camera_bind_group, + depth_texture_view, + pumpkin, + default_texture, + delta: 0f32, + last_frame_time: Instant::now(), + } + } +} + +fn create_depth_texture( + device: &wgpu::Device, + width: u32, + height: u32, +) -> (wgpu::Texture, wgpu::TextureView) { + let size = wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }; + + let desc = wgpu::TextureDescriptor { + label: Some("Depth Texture"), + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth32Float, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }; + + let texture = device.create_texture(&desc); + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + (texture, view) +} + +impl ApplicationHandler for App<'_> { + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + window_id: WindowId, + event: winit::event::WindowEvent, + ) { + match event { + winit::event::WindowEvent::RedrawRequested => { + let window_ctx = self.windows.get_mut(&window_id).unwrap(); + window_ctx.renderer.draw() + } + winit::event::WindowEvent::CloseRequested => { + let _ = self.windows.remove(&window_id); + if self.windows.is_empty() { + event_loop.exit(); + } + } + winit::event::WindowEvent::MouseInput { state, button, .. } => { + if button == MouseButton::Left && state == ElementState::Pressed { + self.spawn_window(event_loop); + } + } + winit::event::WindowEvent::Resized(size) => { + if let Some(window_ctx) = self.windows.get_mut(&window_id) { + if size.width == 0 || size.height == 0 { + return; + } + window_ctx + .renderer + .camera + .update_aspect(size.width as f32 / size.height as f32); + window_ctx + .renderer + .camera_uniform + .update_view_proj(&window_ctx.renderer.camera); + window_ctx.renderer.queue.write_buffer( + &window_ctx.renderer.camera_buffer, + 0, + bytes_of(&window_ctx.renderer.camera_uniform), + ); + let mut new_config = window_ctx.renderer.surface_config.clone(); + new_config.width = size.width; + new_config.height = size.height; + let (depth_texture, depth_view) = + create_depth_texture(&window_ctx.renderer.device, size.width, size.height); + window_ctx.renderer.depth_texture = depth_texture; + window_ctx.renderer.depth_texture_view = depth_view; + + window_ctx + .renderer + .surface + .configure(&window_ctx.renderer.device, &new_config) + } + } + _ => (), + } + } + + fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + let attr = WindowAttributes::default() + .with_title("Zenyx") + .with_min_inner_size(winit::dpi::LogicalSize::new(1, 1)); + + if self.windows.is_empty() { + let window = event_loop.create_window(attr).unwrap(); + let window = Arc::new(window); + let renderer = self.state.create_renderer(window.clone()); + let window_ctx = WindowContext { + renderer: smol::block_on(renderer), + window: window.clone(), + }; + let window_id = window.id(); + self.windows.insert(window_id, window_ctx); + } + } + fn suspended(&mut self, _event_loop: &ActiveEventLoop) { + self.windows.clear(); + } +} +pub fn main() -> Result<(), terminator::Terminator> { + let config = LoggerConfig::default() + .colored_stdout(true) + .log_to_stdout(true) + .file_include_time(true) + .log_to_file(true) + .level(LogLevel::Info) + .log_path("zenyx.log"); + let _logger = zlog::Logger::new(config); + #[cfg(not(target_os = "android"))] + { + _main() + } + #[cfg(target_os = "android")] + { + Ok(()) + } +} +pub fn run_app(event_loop: winit::event_loop::EventLoop<()>) -> Result<(), terminator::Terminator> { + let mut app = App::new(); + event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll); + event_loop.run_app(&mut app)?; + Ok(()) +} + +#[unsafe(no_mangle)] +#[cfg(target_os = "android")] +extern "C" fn android_main(app: AndroidApp) { + use winit::event_loop::EventLoopBuilder; + use winit::platform::android::EventLoopBuilderExtAndroid; + let event_loop = EventLoopBuilder::default() + .with_android_app(app) + .build() + .unwrap(); + run_app(event_loop).unwrap() +} + +fn _main() -> Result<(), terminator::Terminator> { + let event_loop = EventLoop::new()?; + run_app(event_loop)?; + info!("Exiting..."); + Ok(()) +} diff --git a/src/model/mod.rs b/src/model/mod.rs new file mode 100644 index 0000000..23bb69b --- /dev/null +++ b/src/model/mod.rs @@ -0,0 +1,226 @@ +use std::io::{BufRead, BufReader}; + +use crate::texture::Texture; +use cgmath::{Vector2, Vector3, Zero}; +use tobj::Model as tModel; +use wgpu::util::DeviceExt; + +pub struct Model { + pub meshes: Vec, + pub materials: Vec, +} + +pub struct Material { + pub name: String, + pub diffuse_texture: Texture, + pub bind_group: wgpu::BindGroup, +} + +pub struct Mesh { + pub name: String, + pub vertex_buffer: wgpu::Buffer, + pub index_buffer: wgpu::Buffer, + pub num_elements: u32, + pub material: Option, +} + +impl Model { + pub fn load_obj( + read: &mut R, + device: &wgpu::Device, + queue: &wgpu::Queue, + layout: &wgpu::BindGroupLayout, + ) -> Self { + let (models, obj_materials) = tobj::load_obj_buf( + read, + &tobj::LoadOptions { + triangulate: true, + single_index: true, + ..Default::default() + }, + |p| tobj::load_mtl_buf(&mut BufReader::new(std::fs::File::open(p).unwrap())), + ) + .unwrap(); + + let mut materials = Vec::new(); + + for m in obj_materials.unwrap() { + let Some(texture) = &m.diffuse_texture else { + continue; + }; + let diffuse_texture = load_texture(&m.name, texture, device, queue); + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("model-texture-bind"), + layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), + }, + ], + }); + + materials.push(Material { + name: m.name, + diffuse_texture, + bind_group, + }); + } + + let meshes = models + .into_iter() + .map(|m| { + let vertices = (0..m.mesh.positions.len() / 3) + .map(|i| { + let position = cgmath::vec3( + m.mesh.positions[i * 3], + m.mesh.positions[i * 3 + 1], + m.mesh.positions[i * 3 + 2], + ); + let tex_coords = cgmath::vec2( + m.mesh.texcoords[i * 2], + 1.0 - m.mesh.texcoords[i * 2 + 1], + ); + if m.mesh.normals.is_empty() { + Vertex { + position, + tex_coords, + normal: cgmath::Vector3::zero(), + color: cgmath::Vector3::zero(), + } + } else { + Vertex { + position, + tex_coords, + normal: cgmath::vec3( + m.mesh.normals[i * 3], + m.mesh.normals[i * 3 + 1], + m.mesh.normals[i * 3 + 2], + ), + color: cgmath::Vector3::zero(), + } + } + }) + .collect::>(); + + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: None, + contents: bytemuck::cast_slice(&vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: None, + contents: bytemuck::cast_slice(&m.mesh.indices), + usage: wgpu::BufferUsages::INDEX, + }); + + Mesh { + name: "TOBJ_MESH".to_string(), + vertex_buffer, + index_buffer, + num_elements: m.mesh.indices.len() as u32, + material: m.mesh.material_id, + } + }) + .collect::>(); + + Self { meshes, materials } + } +} + +pub fn load_texture>( + label: &str, + path: S, + device: &wgpu::Device, + queue: &wgpu::Queue, +) -> Texture { + let file = std::fs::read(path).unwrap(); + Texture::from_bytes(device, queue, &file, label).unwrap() +} + +pub fn load(obj: &[tModel]) -> (Vec, Vec) { + let mut combined_vertices = Vec::new(); + let mut combined_indices = Vec::new(); + let mut vertex_offset = 0; + + for object in obj { + let mesh: &_ = &object.mesh; + let vertices: Vec = (0..mesh.positions.len() / 3) + .map(|i| Vertex { + position: Vector3::from([ + mesh.positions[i * 3], + mesh.positions[i * 3 + 1], + mesh.positions[i * 3 + 2], + ]), + color: cgmath::Vector3::from([1.0, 1.0, 1.0]), + normal: if !mesh.normals.is_empty() { + Vector3::from([ + mesh.normals[i * 3], + mesh.normals[i * 3 + 1], + mesh.normals[i * 3 + 2], + ]) + } else { + Vector3::zero() + }, + tex_coords: if !mesh.texcoords.is_empty() { + Vector2::from([mesh.texcoords[i * 2], mesh.texcoords[i * 2 + 1]]) + } else { + Vector2::zero() + }, + }) + .collect(); + combined_vertices.extend(vertices); + combined_indices.extend(mesh.indices.iter().map(|&index| index + vertex_offset)); + vertex_offset += (mesh.positions.len() as u32) / 3; + } + + (combined_vertices, combined_indices) +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct Vertex { + pub position: cgmath::Vector3, + pub color: cgmath::Vector3, + pub normal: cgmath::Vector3, + pub tex_coords: cgmath::Vector2, +} + +unsafe impl bytemuck::Pod for Vertex {} +unsafe impl bytemuck::Zeroable for Vertex {} +impl Vertex { + pub const ATTRIBS: [wgpu::VertexAttribute; 4] = [ + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: std::mem::offset_of!(Vertex, color) as u64, + shader_location: 1, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: std::mem::offset_of!(Vertex, normal) as u64, + shader_location: 2, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: std::mem::offset_of!(Vertex, tex_coords) as u64, + shader_location: 3, + format: wgpu::VertexFormat::Float32x2, + }, + ]; + + pub const fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &Self::ATTRIBS, + } + } +} diff --git a/src/texture.rs b/src/texture.rs new file mode 100644 index 0000000..f5aaab1 --- /dev/null +++ b/src/texture.rs @@ -0,0 +1,108 @@ +use image::GenericImageView; +use thiserror::Error; +#[derive(Debug, Error)] +pub enum TextureError { + #[error("Failed to load image")] + ImageError( + #[from] + #[source] + image::ImageError, + ), +} +pub struct Texture { + #[allow(unused)] + pub texture: wgpu::Texture, + pub view: wgpu::TextureView, + pub sampler: wgpu::Sampler, +} +impl Texture { + pub fn from_bytes( + device: &wgpu::Device, + queue: &wgpu::Queue, + bytes: &[u8], + label: &str, + ) -> Result { + let img = image::load_from_memory(bytes)?; + Self::from_image(device, queue, &img, Some(label)) + } + + pub fn from_image( + device: &wgpu::Device, + queue: &wgpu::Queue, + img: &image::DynamicImage, + label: Option<&str>, + ) -> Result { + let rgba = img.to_rgba8(); + let dimensions = img.dimensions(); + + let size = wgpu::Extent3d { + width: dimensions.0, + height: dimensions.1, + depth_or_array_layers: 1, + }; + let texture = device.create_texture(&wgpu::TextureDescriptor { + label, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + view_formats: &[], + }); + + queue.write_texture( + wgpu::TexelCopyTextureInfo { + aspect: wgpu::TextureAspect::All, + texture: &texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + &rgba, + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(4 * dimensions.0), + rows_per_image: Some(dimensions.1), + }, + size, + ); + + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + + Ok(Self { + texture, + view, + sampler, + }) + } +} + +pub fn create_checkerboard() -> image::DynamicImage { + let size = 512; + let tile_size = 24; + let mut img = image::RgbaImage::new(size, size); + + for y in 0..size { + for x in 0..size { + let tile_x = x / tile_size; + let tile_y = y / tile_size; + let color = if (tile_x + tile_y) % 2 == 0 { + [0, 0, 0, 255] + } else { + [255, 5, 255, 255] + }; + img.put_pixel(x, y, image::Rgba(color)); + } + } + + image::DynamicImage::ImageRgba8(img) +} diff --git a/editor/Cargo.toml b/subcrates/renderer/Cargo.toml similarity index 55% rename from editor/Cargo.toml rename to subcrates/renderer/Cargo.toml index f584ecb..c29f61c 100644 --- a/editor/Cargo.toml +++ b/subcrates/renderer/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "editor" +name = "renderer" version = "0.1.0" -edition = "2021" +edition = "2024" [dependencies] - diff --git a/subcrates/renderer/src/lib.rs b/subcrates/renderer/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/subcrates/renderer/src/lib.rs @@ -0,0 +1 @@ + diff --git a/subcrates/zlog/Cargo.toml b/subcrates/zlog/Cargo.toml new file mode 100644 index 0000000..b8e90fc --- /dev/null +++ b/subcrates/zlog/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "zlog" +version = "0.1.0" +edition = "2024" + +[dependencies] +tracing = "0.1.41" +tracing-subscriber = "0.3.19" +serde = { version = "1.0.219", optional = true } +serde_json = { version = "1.0.140", optional = true } +chrono = { version = "0.4.40", optional = true } + +[dev-dependencies] +pretty_assertions = "1.4.1" + +[features] +default = ["json"] +json = ["dep:serde_json", "dep:chrono", "serde"] +serde = ["dep:serde"] \ No newline at end of file diff --git a/subcrates/zlog/src/config.rs b/subcrates/zlog/src/config.rs new file mode 100644 index 0000000..dc50fbe --- /dev/null +++ b/subcrates/zlog/src/config.rs @@ -0,0 +1,102 @@ +use std::path::{Path, PathBuf}; + +use crate::LogLevel; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LoggerConfig { + pub(crate) log_level: Option, + pub(crate) log_to_file: bool, + pub(crate) log_file_path: PathBuf, + pub(crate) log_to_stdout: bool, + pub(crate) stdout_color: bool, + pub(crate) stdout_include_time: bool, + pub(crate) file_include_time: bool, + pub(crate) crate_max_level: Option, + pub(crate) log_use_json: bool, + pub(crate) log_json_show_timestamp: bool, + pub(crate) log_json_show_level: bool, + pub(crate) log_json_show_message: bool, + pub(crate) log_json_show_additional_fields: bool, +} + +impl LoggerConfig { + pub fn level(mut self, level: LogLevel) -> Self { + self.log_level = Some(level); + self + } + + pub fn log_to_file(mut self, f: bool) -> Self { + self.log_to_file = f; + self + } + + pub fn colored_stdout(mut self, c: bool) -> Self { + self.stdout_color = c; + self + } + + pub fn log_to_stdout(mut self, s: bool) -> Self { + self.log_to_stdout = s; + self + } + + pub fn log_path>(mut self, p: P) -> Self { + self.log_file_path = p.as_ref().to_path_buf(); + self + } + + pub fn stdout_include_time(mut self, i: bool) -> Self { + self.stdout_include_time = i; + self + } + + pub fn file_include_time(mut self, i: bool) -> Self { + self.file_include_time = i; + self + } + + pub fn log_use_json(mut self, i: bool) -> Self { + self.log_use_json = i; + self + } + + pub fn log_json_show_timestamp(mut self, i: bool) -> Self { + self.log_json_show_timestamp = i; + self + } + + pub fn log_json_show_level(mut self, i: bool) -> Self { + self.log_json_show_level = i; + self + } + + pub fn log_json_show_message(mut self, i: bool) -> Self { + self.log_json_show_message = i; + self + } + + pub fn log_json_show_additional_fields(mut self, i: bool) -> Self { + self.log_json_show_additional_fields = i; + self + } +} + +impl Default for LoggerConfig { + fn default() -> Self { + Self { + log_level: None, + crate_max_level: None, + log_to_file: true, + log_file_path: "app.log".into(), + log_to_stdout: true, + stdout_color: true, + stdout_include_time: false, + file_include_time: false, + log_use_json: false, + log_json_show_timestamp: false, + log_json_show_level: false, + log_json_show_message: false, + log_json_show_additional_fields: false + } + } +} diff --git a/subcrates/zlog/src/lib.rs b/subcrates/zlog/src/lib.rs new file mode 100644 index 0000000..e6b64a4 --- /dev/null +++ b/subcrates/zlog/src/lib.rs @@ -0,0 +1,346 @@ +pub mod config; +pub mod query; +#[cfg(test)] +mod tests; + +use std::{ + fmt, + fs::OpenOptions, + io::{BufWriter, Write}, + str::FromStr, + sync::{ + Arc, RwLock, + mpsc::{self, Sender}, + }, + thread, + time::SystemTime, +}; + +use config::LoggerConfig; +use query::LogQuery; +use tracing::{Event, Level, Subscriber, level_filters::LevelFilter, subscriber::DefaultGuard}; +use tracing_subscriber::{ + layer::{Context, Layer, SubscriberExt}, + registry::LookupSpan, + util::SubscriberInitExt, +}; + +#[cfg(feature = "json")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "json")] +use serde_json::Value; + +#[cfg(feature = "json")] +use chrono::{DateTime, Utc}; + +#[derive(Debug, Clone, PartialEq, Eq)] +enum LogEvent { + Log(LogEntry), + Shutdown, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LogEntry { + timestamp: SystemTime, + level: Level, + message: String, + #[cfg(feature = "json")] + additional_fields: serde_json::Map, +} + +impl PartialOrd for LogEntry { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for LogEntry { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.timestamp + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .cmp( + &other + .timestamp + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(), + ) + } +} + +struct BufferLayer { + log_entries: Arc>>, + senders: Vec>, +} + +impl BufferLayer { + pub fn new(log_entries: Arc>>, senders: Vec>) -> Self { + Self { + log_entries, + senders, + } + } +} + +impl Drop for BufferLayer { + fn drop(&mut self) { + for tx in &self.senders { + if let Err(e) = tx.send(LogEvent::Shutdown) { + panic!("{e}") + } + } + self.senders.clear(); + } +} + +impl Layer for BufferLayer +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) { + let metadata = event.metadata(); + let level = *metadata.level(); + let timestamp = SystemTime::now(); + #[cfg(feature = "json")] + let additional_fields = serde_json::Map::new(); + let mut message = String::new(); + let mut visitor = LogVisitor::new(&mut message); + event.record(&mut visitor); + + let log_entry = LogEvent::Log(LogEntry { + timestamp, + level, + message, + #[cfg(feature = "json")] + additional_fields + }); + + if let LogEvent::Log(ref entry) = log_entry { + if let Ok(mut buf) = self.log_entries.write() { + buf.push(entry.clone()); + } + } + + for tx in &self.senders { + let _ = tx.send(log_entry.clone()); + } + } +} + +struct LogVisitor<'msg> { + message: &'msg mut String, +} + +impl<'msg> LogVisitor<'msg> { + fn new(message: &'msg mut String) -> Self { + Self { message } + } +} + +impl tracing::field::Visit for LogVisitor<'_> { + fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn fmt::Debug) { + use std::fmt::Write; + if field.name() == "message" { + write!(self.message, "{:?}", value).unwrap(); + } else { + write!(self.message, "{}={:?} ", field.name(), value).unwrap(); + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] +pub enum LogLevel { + Error, + #[default] + Info, + Warn, + Debug, + Trace, +} + +impl From for LevelFilter { + fn from(level: LogLevel) -> Self { + match level { + LogLevel::Error => LevelFilter::ERROR, + LogLevel::Info => LevelFilter::INFO, + LogLevel::Debug => LevelFilter::DEBUG, + LogLevel::Trace => LevelFilter::TRACE, + LogLevel::Warn => LevelFilter::WARN, + } + } +} + +impl fmt::Display for LogLevel { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl FromStr for LogLevel { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "trace" => Ok(Self::Trace), + "debug" => Ok(Self::Debug), + "info" => Ok(Self::Info), + "error" => Ok(Self::Error), + "warn" => Ok(Self::Warn), + _ => Err(()), + } + } +} + +pub struct Logger { + subscriber_guard: Option, + log_entries: Arc>>, + _handles: Vec>, +} + +impl Logger { + pub fn new(config: LoggerConfig) -> Self { + let log_entries = Arc::new(RwLock::new(Vec::new())); + let mut senders = Vec::new(); + let mut handles = Vec::new(); + + if config.log_to_stdout || config.log_use_json { + let (tx, rx) = mpsc::channel(); + senders.push(tx); + let config_clone = config.clone(); + let handle = thread::spawn(move || { + for msg in rx { + match msg { + LogEvent::Log(mut entry) => { + println!( + "{}", + format_entry( + &mut entry, + &config_clone + ) + ); + } + LogEvent::Shutdown => break, + } + } + }); + handles.push(handle); + } + + if config.log_to_file { + let (tx, rx) = mpsc::channel(); + senders.push(tx); + let config_clone = config.clone(); + let path = config.log_file_path.clone(); + let handle = thread::spawn(move || { + let file = OpenOptions::new() + .append(true) + .create(true) + .open(&path) + .expect("Failed to open log file"); + let mut writer = BufWriter::new(file); + for msg in rx { + match msg { + LogEvent::Log(mut entry) => { + let line = format_entry(&mut entry, &config_clone); + writeln!(writer, "{}", line).expect("Failed to write to log file"); + writer.flush().expect("Failed to flush log file"); + } + LogEvent::Shutdown => break, + } + } + }); + handles.push(handle); + } + + let buffer_layer = BufferLayer::new(log_entries.clone(), senders); + + let mk_logger = |guard: DefaultGuard| Logger { + subscriber_guard: Some(guard), + log_entries, + _handles: handles, + }; + if let Some(level) = config.log_level { + let subscriber = tracing_subscriber::registry() + .with(buffer_layer) + .with(LevelFilter::from(level)); + let guard = subscriber.set_default(); + mk_logger(guard) + } else { + let subscriber = tracing_subscriber::registry().with(buffer_layer); + let guard = subscriber.set_default(); + mk_logger(guard) + } + } + + pub fn get_logs(&self, query: LogQuery) -> Vec { + let guard = self.log_entries.read().unwrap(); + match query { + LogQuery::All => guard.clone(), + LogQuery::From(t) => guard.iter().filter(|e| e.timestamp >= t).cloned().collect(), + } + } +} + +impl Drop for Logger { + fn drop(&mut self) { + let _ = self.subscriber_guard.take(); + let handles = std::mem::take(&mut self._handles); + for handle in handles { + handle.join().unwrap_or_else(|e| { + eprintln!("Logger thread panicked: {:?}", e); + }); + } + } +} + +fn format_entry(entry: &mut LogEntry, log_config: &LoggerConfig) -> String { + if log_config.log_use_json { + return format_entry_json(entry, log_config); + } + + if log_config.log_to_stdout || log_config.log_to_file { + return format_entry_string(entry, log_config); + } else { + return String::new(); + } +} + +fn format_entry_string(entry: &LogEntry, log_config: &LoggerConfig) -> String { + let lvl = if log_config.stdout_color { + match entry.level { + Level::ERROR => "\x1b[31mERROR\x1b[0m", + Level::WARN => "\x1b[33mWARN\x1b[0m", + Level::INFO => "\x1b[32mINFO\x1b[0m", + Level::DEBUG => "\x1b[36mDEBUG\x1b[0m", + Level::TRACE => "\x1b[34mTRACE\x1b[0m", + } + } else { + entry.level.as_str() + }; + + format!("{} {}", lvl, entry.message) +} + +/// Formats the log entry as a json object ([`serde_json`]) and returns it as a [`String`] +fn format_entry_json(entry: &mut LogEntry, log_config: &LoggerConfig) -> String { + let mut json_object = serde_json::Map::new(); + + if log_config.log_json_show_timestamp { + json_object.insert("timestamp".to_string(), Value::String(DateTime::::from(entry.timestamp).to_rfc3339())); + } + + if log_config.log_json_show_level { + json_object.insert("level".to_string(), Value::String(entry.level.to_string())); + } + + if log_config.log_json_show_message { + json_object.insert("message".to_string(), Value::String(entry.message.to_string())); + } + + if log_config.log_json_show_additional_fields { + json_object.append(&mut entry.additional_fields); + } + + serde_json::to_string(&json_object).unwrap() +} \ No newline at end of file diff --git a/subcrates/zlog/src/query.rs b/subcrates/zlog/src/query.rs new file mode 100644 index 0000000..5002fac --- /dev/null +++ b/subcrates/zlog/src/query.rs @@ -0,0 +1,14 @@ +use std::time::SystemTime; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Default)] +pub enum LogQuery { + #[default] + All, + From(SystemTime), +} + +impl LogQuery { + pub fn since(time: SystemTime) -> Self { + LogQuery::From(time) + } +} diff --git a/subcrates/zlog/src/tests.rs b/subcrates/zlog/src/tests.rs new file mode 100644 index 0000000..13c90ab --- /dev/null +++ b/subcrates/zlog/src/tests.rs @@ -0,0 +1,139 @@ +use pretty_assertions::assert_eq; +use tracing::Level; +use serde_json::Map; +use serde::{Serialize, Deserialize}; + +use super::*; + +#[test] +fn test_logger_sequential_consistency() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + use tracing::{debug, error, info, trace, warn}; + + let config = LoggerConfig::default() + .log_to_stdout(true) + .log_to_file(true); + let logger = Logger::new(config); + + static COUNTER: AtomicUsize = AtomicUsize::new(0); + + for i in 0..4096 * 128 { + let count = COUNTER.fetch_add(1, Ordering::SeqCst); + match i % 5 { + 0 => error!("Error message {}", count), + 1 => warn!("Warning message {}", count), + 2 => info!("Info message {}", count), + 3 => debug!("Debug message {}", count), + _ => trace!("Trace message {}", count), + } + } + + let logs = logger.get_logs(LogQuery::All); + assert_eq!( + logs.len(), + 4096 * 128, + "Should have exactly 5000 log entries" + ); + + for (i, log) in logs.iter().enumerate() { + let expected_count = i; + let expected_level = match i % 5 { + 0 => Level::ERROR, + 1 => Level::WARN, + 2 => Level::INFO, + 3 => Level::DEBUG, + _ => Level::TRACE, + }; + + assert_eq!( + log.level, expected_level, + "Log {} has incorrect level: {:?}", + i, log.level + ); + + let expected_msg = match expected_level { + Level::ERROR => format!("Error message {}", expected_count), + Level::WARN => format!("Warning message {}", expected_count), + Level::INFO => format!("Info message {}", expected_count), + Level::DEBUG => format!("Debug message {}", expected_count), + Level::TRACE => format!("Trace message {}", expected_count), + }; + + assert_eq!( + log.message, expected_msg, + "Log {} has incorrect message. Expected: '{}', Got: '{}'", + i, expected_msg, log.message + ); + + if i > 0 { + assert!( + log.timestamp >= logs[i - 1].timestamp, + "Log {} has timestamp out of order. Current: {:?}, Previous: {:?}", + i, + log.timestamp, + logs[i - 1].timestamp + ); + } + } + + let mut counts: Vec = logs + .iter() + .map(|log| { + log.message + .split_whitespace() + .last() + .unwrap() + .parse::() + .unwrap() + }) + .collect(); + counts.sort(); + counts.dedup(); + assert_eq!(counts.len(), 4096 * 128, "Found duplicate log entries"); +} + +#[test] +fn test_logger_sequential_consistency_json() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + use tracing::{debug, error, info, trace, warn}; + + let config = LoggerConfig::default() + .log_to_stdout(false) + .log_to_file(false) + .log_use_json(true) + .log_json_show_timestamp(true) + .log_json_show_level(true) + .log_json_show_message(true) + .log_json_show_additional_fields(false); // Not implemented yet + let logger = Logger::new(config); + + static COUNTER: AtomicUsize = AtomicUsize::new(0); + + for i in 0..4096 * 128 { + let count = COUNTER.fetch_add(1, Ordering::SeqCst); + match i % 5 { + 0 => error!("Error message {}", count), + 1 => warn!("Warning message {}", count), + 2 => info!("Info message {}", count), + 3 => debug!("Debug message {}", count), + _ => trace!("Trace message {}", count), + } + } + + let mut log_json: Vec> = vec![]; + + for log in logger.get_logs(LogQuery::All) { + let mut json_object = serde_json::Map::new(); + json_object.insert("timestamp".to_string(), Value::String(DateTime::::from(log.timestamp).to_rfc3339())); + json_object.insert("level".to_string(), Value::String(log.level.to_string())); + json_object.insert("message".to_string(), Value::String(log.message.to_string())); + + log_json.push(json_object); + } + + for log in log_json { + serde_json::to_string(&log).unwrap(); + } +} \ No newline at end of file diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml deleted file mode 100644 index 7e4ef1a..0000000 --- a/xtask/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - - -[dependencies] -clap = { version = "4.5.20", features = ["derive"] } - -[profile.dev] -rpath = false -panic = "abort" -lto = "off" -opt-level = 0 -debug = false -overflow-checks = false -incremental = true -codegen-units = 256 - -strip = "symbols" -debug-assertions = false - -[profile.dev.package."*"] -opt-level = 0 -debug = false -overflow-checks = false -incremental = true -codegen-units = 256 - -strip = "symbols" -debug-assertions = false - diff --git a/xtask/src/editor.rs b/xtask/src/editor.rs deleted file mode 100644 index 8cfa650..0000000 --- a/xtask/src/editor.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn build_editor() {} \ No newline at end of file diff --git a/xtask/src/engine.rs b/xtask/src/engine.rs deleted file mode 100644 index ecdf677..0000000 --- a/xtask/src/engine.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::process::Stdio; - - -pub fn build_engine() { - -} - -pub fn build_core() { - let threads = format!("-j{}",std::thread::available_parallelism().unwrap().get()); - let mut run = std::process::Command::new("cargo") - .arg("run") - - .arg(threads) - .arg("--bin") - .arg("zenyx") - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .spawn() - .unwrap(); - run.wait().unwrap(); -} \ No newline at end of file diff --git a/xtask/src/main.rs b/xtask/src/main.rs deleted file mode 100644 index b146421..0000000 --- a/xtask/src/main.rs +++ /dev/null @@ -1,70 +0,0 @@ - -use clap::{CommandFactory, Parser, Subcommand, ValueEnum}; -pub mod engine; -pub mod editor; - -#[derive(Parser)] -#[command(version, about, long_about = None,disable_version_flag = true,disable_help_flag = true)] -struct Cli { - #[arg(short,long)] - release: bool, - #[command(subcommand)] - command: Option, -} - -#[derive(Subcommand)] -enum Commands { - Run { - #[arg()] - task: Task - }, - Config, - -} -#[derive(Clone,ValueEnum)] -enum Task { - Engine, // Builds both editor and core - Editor, // Builds editor only - Core, // Builds engine core only - Help, -} - - - -fn main() { - let cli = Cli::parse(); - - - - - if cli.release { - println!("Running in release mode") - } - - match &cli.command { - - None => { - Cli::command().print_help().map_err(|e| { - println!("Could not run Xtask: {e}"); - - }).unwrap(); - } - Some(Commands::Run { task }) => { - match task { - Task::Engine => engine::build_engine(), - Task::Editor => todo!("Editor is not being actively worked on"), - Task::Core => { - engine::build_core(); - }, - Task::Help => { - println!("The following options are avalible to run"); - todo!() - }, - } - } - Some(Commands::Config) => { - todo!() - } - } - -} \ No newline at end of file