commit 625348981daef88c319bf990b094d36d4a640b75 Author: copygirl Date: Sat Mar 22 12:49:27 2025 +0100 Initial commit (for lizzie <3) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66cc710 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target/ + diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..0434bcc --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,48 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "cargo": { + "args": [ + "build", + "--bin=bevy-bloxel-test", + "--package=bevy-bloxel-test" + ], + "filter": { + "name": "bevy-bloxel-test", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}", + "env": { + // When Bevy looks for assets, it checks BEVY_ASSET_ROOT, CARGO_MANIFEST_DIR, and + // then falls back to the executable directory. When debugging, the cargo manifest + // directory is not set, so we need to specify this environment variable. + "BEVY_ASSET_ROOT": "${workspaceFolder}", + }, + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=bevy-bloxel-test", + "--package=bevy-bloxel-test" + ], + "filter": { + "name": "bevy-bloxel-test", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}", + } + ] +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0938636 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5125 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "accesskit" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" + +[[package]] +name = "accesskit_consumer" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f47983a1084940ba9a39c077a8c63e55c619388be5476ac04c804cfbd1e63459" +dependencies = [ + "accesskit", + "hashbrown 0.15.2", + "immutable-chunkmap", +] + +[[package]] +name = "accesskit_macos" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7329821f3bd1101e03a7d2e03bd339e3ac0dc64c70b4c9f9ae1949e3ba8dece1" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "accesskit_windows" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24fcd5d23d70670992b823e735e859374d694a3d12bfd8dd32bd3bd8bedb5d81" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.2", + "paste", + "static_assertions", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "accesskit_winit" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6a48dad5530b6deb9fc7a52cc6c3bf72cdd9eb8157ac9d32d69f2427a5e879" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_windows", + "raw-window-handle", + "winit", +] + +[[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", + "const-random", + "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 = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.8.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + +[[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.8.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" + +[[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 = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[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 = "assert_type_match" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", +] + +[[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-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.4.0", + "event-listener-strategy", + "pin-project-lite", +] + +[[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 = "atomicow" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467163b50876d3a4a44da5f4dbd417537e522fc059ede8d518d57941cfb3d745" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bevy" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eaad7fe854258047680c51c3cacb804468553c04241912f6254c841c67c0198" +dependencies = [ + "bevy_internal", +] + +[[package]] +name = "bevy-bloxel-test" +version = "0.1.0" +dependencies = [ + "bevy", + "bitvec", + "overload", + "rand 0.9.0", + "zorder", +] + +[[package]] +name = "bevy_a11y" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245a938f754f70a380687b89f1c4dac75b62d58fae90ae969fcfb8ecd91ed879" +dependencies = [ + "accesskit", + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_reflect", +] + +[[package]] +name = "bevy_animation" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e2b3e4e6cb4df085b941b105f2c790901e34c8571e02342f8e96acdf7cf7d1" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_log", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_time", + "bevy_transform", + "bevy_utils", + "blake3", + "derive_more", + "downcast-rs", + "either", + "petgraph", + "ron", + "serde", + "smallvec", + "thread_local", + "uuid", +] + +[[package]] +name = "bevy_app" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ac033a388b8699d241499a43783a09e6a3bab2430f1297c6bd4974095efb3f" +dependencies = [ + "bevy_derive", + "bevy_ecs", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "console_error_panic_hook", + "ctrlc", + "derive_more", + "downcast-rs", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "bevy_asset" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fd901b3be016088c4dda2f628bda96b7cb578b9bc8ae684bbf30bec0a9483e" +dependencies = [ + "async-broadcast", + "async-fs", + "async-lock", + "atomicow", + "bevy_app", + "bevy_asset_macros", + "bevy_ecs", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bevy_window", + "bitflags 2.8.0", + "blake3", + "crossbeam-channel", + "derive_more", + "disqualified", + "downcast-rs", + "either", + "futures-io", + "futures-lite", + "js-sys", + "notify-debouncer-full", + "parking_lot", + "ron", + "serde", + "stackfuture", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "bevy_asset_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6725a785789ece8d8c73bba25fdac5e50494d959530e89565bbcea9f808b7181" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_audio" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30af4b6a91c8e08f623b0cdc53ce5b8f731c78af6ef728cdfc06dc61eda164c4" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_math", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "cpal", + "rodio", +] + +[[package]] +name = "bevy_color" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a87b7137ffa9844ae542043769fb98c35efbf2f8a8429ff2a73d8ef30e58baaa" +dependencies = [ + "bevy_math", + "bevy_reflect", + "bytemuck", + "derive_more", + "encase", + "serde", + "wgpu-types", +] + +[[package]] +name = "bevy_core" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9ce8da8e4016f63c1d361b52e61aaf4348c569829c74f1a5bbedfd8d3d57a3" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "uuid", +] + +[[package]] +name = "bevy_core_pipeline" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee0ff0f4723f30a5a6578915dbfe0129f2befaec8438dde70ac1fb363aee01f5" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.8.0", + "derive_more", + "nonmax", + "radsort", + "serde", + "smallvec", +] + +[[package]] +name = "bevy_derive" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d94761ce947b0a2402fd949fe1e7a5b1535293130ba4cd9893be6295d4680a" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn", +] + +[[package]] +name = "bevy_diagnostic" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e83c65979f063b593917ab9b1d7328c5854dba4b6ddf1ab78156c0105831fdf" +dependencies = [ + "bevy_app", + "bevy_core", + "bevy_ecs", + "bevy_tasks", + "bevy_time", + "bevy_utils", + "const-fnv1a-hash", + "sysinfo", +] + +[[package]] +name = "bevy_ecs" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1597106cc01e62e6217ccb662e0748b2ce330893f27c7dc17bac33e0bb99bca9" +dependencies = [ + "arrayvec", + "bevy_ecs_macros", + "bevy_ptr", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bitflags 2.8.0", + "concurrent-queue", + "derive_more", + "disqualified", + "fixedbitset 0.5.7", + "nonmax", + "petgraph", + "serde", + "smallvec", +] + +[[package]] +name = "bevy_ecs_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f453adf07712b39826bc5845e5b0887ce03204ee8359bbe6b40a9afda60564a1" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_encase_derive" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37ad69d36bb9e8479a88d481ef9748f5d7ab676040531d751d3a44441dcede7" +dependencies = [ + "bevy_macro_utils", + "encase_derive_impl", +] + +[[package]] +name = "bevy_gilrs" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a737451ccd6be5da68fbba5d984328b8a82eebd16c1fda0bec840090a3d454fd" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_input", + "bevy_time", + "bevy_utils", + "derive_more", + "gilrs", +] + +[[package]] +name = "bevy_gizmos" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1614516d0922ad60e87cc39658422286ed684aaf4b3162d25051bc105eed814" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_gizmos_macros", + "bevy_image", + "bevy_math", + "bevy_pbr", + "bevy_reflect", + "bevy_render", + "bevy_sprite", + "bevy_time", + "bevy_transform", + "bevy_utils", + "bytemuck", +] + +[[package]] +name = "bevy_gizmos_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edb9e0dca64e0fc9d6b1d9e6e2178396e339e3e2b9f751e2504e3ea4ddf4508" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_gltf" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8364f34bc08fe067ce32418e22ee96e177101dbf1bc00803aaeb2b262615be" +dependencies = [ + "base64 0.22.1", + "bevy_animation", + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_hierarchy", + "bevy_image", + "bevy_math", + "bevy_pbr", + "bevy_reflect", + "bevy_render", + "bevy_scene", + "bevy_tasks", + "bevy_transform", + "bevy_utils", + "derive_more", + "gltf", + "percent-encoding", + "serde", + "serde_json", + "smallvec", +] + +[[package]] +name = "bevy_hierarchy" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ced04e04437d0a439fe4722544c2a4678c1fe3412b57ee489d817c11884045" +dependencies = [ + "bevy_app", + "bevy_core", + "bevy_ecs", + "bevy_reflect", + "bevy_utils", + "disqualified", + "smallvec", +] + +[[package]] +name = "bevy_image" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b384d1ce9c87f6151292a76233897a628c2a50b3560487c4d74472225d49826" +dependencies = [ + "bevy_asset", + "bevy_color", + "bevy_math", + "bevy_reflect", + "bevy_utils", + "bitflags 2.8.0", + "bytemuck", + "derive_more", + "futures-lite", + "image", + "ktx2", + "ruzstd", + "serde", + "wgpu", +] + +[[package]] +name = "bevy_input" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52589939ca09695c69d629d166c5edf1759feaaf8f2078904aae9c33d08f5c3" +dependencies = [ + "bevy_app", + "bevy_core", + "bevy_ecs", + "bevy_math", + "bevy_reflect", + "bevy_utils", + "derive_more", + "smol_str", +] + +[[package]] +name = "bevy_internal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e0c1d980d276e11558184d0627c8967ad8b70dab3e54a0f377bb53b98515b6" +dependencies = [ + "bevy_a11y", + "bevy_animation", + "bevy_app", + "bevy_asset", + "bevy_audio", + "bevy_color", + "bevy_core", + "bevy_core_pipeline", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_gilrs", + "bevy_gizmos", + "bevy_gltf", + "bevy_hierarchy", + "bevy_image", + "bevy_input", + "bevy_log", + "bevy_math", + "bevy_pbr", + "bevy_picking", + "bevy_ptr", + "bevy_reflect", + "bevy_render", + "bevy_scene", + "bevy_sprite", + "bevy_state", + "bevy_tasks", + "bevy_text", + "bevy_time", + "bevy_transform", + "bevy_ui", + "bevy_utils", + "bevy_window", + "bevy_winit", +] + +[[package]] +name = "bevy_log" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b381a22e01f24af51536ef1eace94298dd555d06ffcf368125d16317f5f179cb" +dependencies = [ + "android_log-sys", + "bevy_app", + "bevy_ecs", + "bevy_utils", + "tracing-log", + "tracing-oslog", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "bevy_macro_utils" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb6ded1ddc124ea214f6a2140e47a78d1fe79b0638dad39419cdeef2e1133f1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "toml_edit", +] + +[[package]] +name = "bevy_math" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c2650169161b64f9a93e41f13253701fdf971dc95265ed667d17bea6d2a334f" +dependencies = [ + "bevy_reflect", + "derive_more", + "glam", + "itertools", + "rand 0.8.5", + "rand_distr", + "serde", + "smallvec", +] + +[[package]] +name = "bevy_mesh" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760f3c41b4c61a5f0d956537f454c49f79b8ed0fd0781b1a879ead8e69d95283" +dependencies = [ + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_mikktspace", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "bitflags 2.8.0", + "bytemuck", + "derive_more", + "hexasphere", + "serde", + "wgpu", +] + +[[package]] +name = "bevy_mikktspace" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226f663401069ded4352ed1472a85bb1f43e2b7305d6a50e53a4f6508168e380" +dependencies = [ + "glam", +] + +[[package]] +name = "bevy_pbr" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d54c840d4352dac51f2a27cf915ac99b2f93db008d8fb1be8d23b09d522acf" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.8.0", + "bytemuck", + "derive_more", + "fixedbitset 0.5.7", + "nonmax", + "radsort", + "smallvec", + "static_assertions", +] + +[[package]] +name = "bevy_picking" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2091a495c0f9c8962abb1e30f9d99696296c332b407e1f6fe1fe28aab96a8629" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_input", + "bevy_math", + "bevy_mesh", + "bevy_reflect", + "bevy_render", + "bevy_time", + "bevy_transform", + "bevy_utils", + "bevy_window", + "crossbeam-channel", + "uuid", +] + +[[package]] +name = "bevy_ptr" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89fe0b0b919146939481a3a7c38864face2c6d0fd2c73ab3d430dc693ecd9b11" + +[[package]] +name = "bevy_reflect" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ddbca0a39e88eff2c301dc794ee9d73a53f4b08d47b2c9b5a6aac182fae6217" +dependencies = [ + "assert_type_match", + "bevy_ptr", + "bevy_reflect_derive", + "bevy_utils", + "derive_more", + "disqualified", + "downcast-rs", + "erased-serde", + "glam", + "petgraph", + "serde", + "smallvec", + "smol_str", + "uuid", +] + +[[package]] +name = "bevy_reflect_derive" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d62affb769db17d34ad0b75ff27eca94867e2acc8ea350c5eca97d102bd98709" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", + "uuid", +] + +[[package]] +name = "bevy_render" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4aa9d7df5c2b65540093b8402aceec0a55d67b54606e57ce2969abe280b4c48" +dependencies = [ + "async-channel", + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_encase_derive", + "bevy_hierarchy", + "bevy_image", + "bevy_math", + "bevy_mesh", + "bevy_reflect", + "bevy_render_macros", + "bevy_tasks", + "bevy_time", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bytemuck", + "codespan-reporting", + "derive_more", + "downcast-rs", + "encase", + "futures-lite", + "image", + "js-sys", + "ktx2", + "naga", + "naga_oil", + "nonmax", + "offset-allocator", + "send_wrapper", + "serde", + "smallvec", + "wasm-bindgen", + "web-sys", + "wgpu", +] + +[[package]] +name = "bevy_render_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3469307d1b5ca5c37b7f9269be033845357412ebad33eace46826e59da592f66" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_scene" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfe819202aa97bbb206d79fef83504b34d45529810563aafc2fe02cc10e3ee4" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_reflect", + "bevy_render", + "bevy_transform", + "bevy_utils", + "derive_more", + "serde", + "uuid", +] + +[[package]] +name = "bevy_sprite" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27411a31704117002787c9e8cc1f2f89babf5e67572508aa029366d4643f8d01" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_math", + "bevy_picking", + "bevy_reflect", + "bevy_render", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bitflags 2.8.0", + "bytemuck", + "derive_more", + "fixedbitset 0.5.7", + "guillotiere", + "nonmax", + "radsort", + "rectangle-pack", +] + +[[package]] +name = "bevy_state" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243a72266f81452412f7a3859e5d11473952a25767dc29c8d285660330f007ba" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_hierarchy", + "bevy_reflect", + "bevy_state_macros", + "bevy_utils", +] + +[[package]] +name = "bevy_state_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022eb069dfd64090fd92ba4a7f235383e49aa1c0f4320dab4999b23f67843b36" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_tasks" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028630ddc355563bd567df1076db3515858aa26715ddf7467d2086f9b40e5ab1" +dependencies = [ + "async-channel", + "async-executor", + "concurrent-queue", + "futures-channel", + "futures-lite", + "pin-project", + "wasm-bindgen-futures", +] + +[[package]] +name = "bevy_text" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872b0b627cedf6d1bd97b75bc4d59c16f67afdd4f2fed8f7d808a258d6cb982e" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_image", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_sprite", + "bevy_transform", + "bevy_utils", + "bevy_window", + "cosmic-text", + "derive_more", + "serde", + "smallvec", + "sys-locale", + "unicode-bidi", +] + +[[package]] +name = "bevy_time" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b2051ec56301b994f7c182a2a6eb1490038149ad46d95eee715e1a922acdfd9" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_utils", + "crossbeam-channel", +] + +[[package]] +name = "bevy_transform" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8109b1234b0e58931f51df12bc8895daa69298575cf92da408848f79a4ce201" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_hierarchy", + "bevy_math", + "bevy_reflect", + "derive_more", +] + +[[package]] +name = "bevy_ui" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e534590222d044c875bf3511e5d0b3da78889bb21ad797953484ce011af77b46" +dependencies = [ + "accesskit", + "bevy_a11y", + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_image", + "bevy_input", + "bevy_math", + "bevy_picking", + "bevy_reflect", + "bevy_render", + "bevy_sprite", + "bevy_text", + "bevy_transform", + "bevy_utils", + "bevy_window", + "bytemuck", + "derive_more", + "nonmax", + "smallvec", + "taffy", +] + +[[package]] +name = "bevy_utils" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63c2174d43a0de99f863c98a472370047a2bfa7d1e5cec8d9d647fb500905d9d" +dependencies = [ + "ahash", + "bevy_utils_proc_macros", + "getrandom 0.2.15", + "hashbrown 0.14.5", + "thread_local", + "tracing", + "web-time", +] + +[[package]] +name = "bevy_utils_proc_macros" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94847541f6dd2e28f54a9c2b0e857da5f2631e2201ebc25ce68781cdcb721391" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_window" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e1e7c6713c04404a3e7cede48a9c47b76c30efc764664ec1246147f6fb9878" +dependencies = [ + "android-activity", + "bevy_a11y", + "bevy_app", + "bevy_ecs", + "bevy_input", + "bevy_math", + "bevy_reflect", + "bevy_utils", + "raw-window-handle", + "smol_str", +] + +[[package]] +name = "bevy_winit" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e158a73d6d896b1600a61bc115017707ecb467d1a5ad49231c5e58294f6f6e13" +dependencies = [ + "accesskit", + "accesskit_winit", + "approx", + "bevy_a11y", + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_hierarchy", + "bevy_image", + "bevy_input", + "bevy_log", + "bevy_math", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "bevy_window", + "bytemuck", + "cfg-if", + "crossbeam-channel", + "raw-window-handle", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winit", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.8.0", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec 0.6.3", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec 0.8.0", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1230237285e3e10cde447185e8975408ae24deaa67205ce684805c25bc0c7937" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "memmap2", +] + +[[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", +] + +[[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 = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.8.0", + "log", + "polling", + "rustix", + "slab", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +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 = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[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.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[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 = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-fnv1a-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "const_panic" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2459fc9262a1aa204eb4b5764ad4f189caec88aea9634389c0a25f8be7f6265e" + +[[package]] +name = "const_soft_float" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constgebra" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1aaf9b65849a68662ac6c0810c8893a765c960b907dd7cfab9c4a50bf764fbc" +dependencies = [ + "const_soft_float", +] + +[[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" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +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 0.9.4", + "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 0.9.4", + "libc", +] + +[[package]] +name = "coreaudio-rs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +dependencies = [ + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cosmic-text" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2" +dependencies = [ + "bitflags 2.8.0", + "fontdb", + "log", + "rangemap", + "rayon", + "rustc-hash", + "rustybuzz", + "self_cell", + "swash", + "sys-locale", + "ttf-parser 0.21.1", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk 0.8.0", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] + +[[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-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[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-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 = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix", + "windows-sys 0.59.0", +] + +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] +name = "data-encoding" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "disqualified" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" + +[[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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" + +[[package]] +name = "encase" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0a05902cf601ed11d564128448097b98ebe3c6574bd7b6a653a3d56d54aa020" +dependencies = [ + "const_panic", + "encase_derive", + "glam", + "thiserror", +] + +[[package]] +name = "encase_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "181d475b694e2dd56ae919ce7699d344d1fd259292d590c723a50d1189a2ea85" +dependencies = [ + "encase_derive_impl", +] + +[[package]] +name = "encase_derive_impl" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f97b51c5cc57ef7c5f7a0c57c250251c49ee4c28f819f87ac32f4aceabc36792" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener 5.4.0", + "pin-project-lite", +] + +[[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 = "file-id" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bc904b9bbefcadbd8e3a9fb0d464a9b979de6324c03b3c663e8994f46a5be36" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "font-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.20.0", +] + +[[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 = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[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", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "gilrs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb2c998745a3c1ac90f64f4f7b3a54219fd3612d7705e7798212935641ed18f" +dependencies = [ + "fnv", + "gilrs-core", + "log", + "uuid", + "vec_map", +] + +[[package]] +name = "gilrs-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ed3920aa2e2a5b02fb67182e269b7c988ffbba86e1278bb9f9bbe1815e3ae1" +dependencies = [ + "core-foundation 0.10.0", + "inotify 0.11.0", + "io-kit-sys", + "js-sys", + "libc", + "libudev-sys", + "log", + "nix", + "uuid", + "vec_map", + "wasm-bindgen", + "web-sys", + "windows 0.59.0", +] + +[[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 = "glam" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" +dependencies = [ + "bytemuck", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "glow" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gltf" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" +dependencies = [ + "byteorder", + "gltf-json", + "lazy_static", + "serde_json", +] + +[[package]] +name = "gltf-derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gltf-json" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + +[[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.8.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.8.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", + "windows 0.58.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca" +dependencies = [ + "bitflags 2.8.0", + "gpu-descriptor-types", + "hashbrown 0.15.2", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "grid" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be136d9dacc2a13cc70bb6c8f902b414fb2641f8db1314637c6b7933411a8f82" + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hexasphere" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c9e718d32b6e6b2b32354e1b0367025efdd0b11d6a740b905ddf5db1074679" +dependencies = [ + "constgebra", + "glam", + "tinyvec", +] + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "image" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", +] + +[[package]] +name = "immutable-chunkmap" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f97096f508d54f8f8ab8957862eee2ccd628847b6217af1a335e1c44dee578" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + +[[package]] +name = "inotify" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +dependencies = [ + "bitflags 2.8.0", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[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", + "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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[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 = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "ktx2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lewton" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" +dependencies = [ + "byteorder", + "ogg", + "tinyvec", +] + +[[package]] +name = "libc" +version = "0.2.170" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" + +[[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.8.0", + "libc", + "redox_syscall 0.5.9", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[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.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[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 = "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.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.8.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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "naga" +version = "23.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f" +dependencies = [ + "arrayvec", + "bit-set 0.8.0", + "bitflags 2.8.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "pp-rs", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "naga_oil" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ea1f080bb359927cd5404d0af1e5e6758f4f2d82ecfbebb0a0c434764e40f1" +dependencies = [ + "bit-set 0.5.3", + "codespan-reporting", + "data-encoding", + "indexmap", + "naga", + "once_cell", + "regex", + "regex-syntax 0.8.5", + "rustc-hash", + "thiserror", + "tracing", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.8.0", + "jni-sys", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.8.0", + "jni-sys", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[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 = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[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 = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + +[[package]] +name = "notify" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" +dependencies = [ + "bitflags 2.8.0", + "filetime", + "fsevent-sys", + "inotify 0.10.2", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.52.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcf855483228259b2353f89e99df35fc639b2b2510d1166e4858e3f67ec1afb" +dependencies = [ + "file-id", + "log", + "notify", + "notify-types", + "walkdir", +] + +[[package]] +name = "notify-types" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" +dependencies = [ + "instant", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[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-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-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-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.8.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[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.8.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "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", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.8.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "oboe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni", + "ndk 0.8.0", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] + +[[package]] +name = "offset-allocator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e234d535da3521eb95106f40f0b73483d80bfb3aacf27c40d7e2b72f1a3e00a2" +dependencies = [ + "log", + "nonmax", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" +dependencies = [ + "byteorder", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[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.9", + "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.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap", + "serde", + "serde_derive", +] + +[[package]] +name = "pin-project" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" +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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[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 = "pp-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "prettyplease" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "radsort" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy 0.8.21", +] + +[[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 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[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 = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "range-alloc" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" + +[[package]] +name = "rangemap" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[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 = "read-fonts" +version = "0.22.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "rectangle-pack" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" +dependencies = [ + "bitflags 2.8.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 = "rodio" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" +dependencies = [ + "cpal", + "lewton", + "thiserror", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.8.0", + "serde", + "serde_derive", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[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.8.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "rustybuzz" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +dependencies = [ + "bitflags 2.8.0", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.21.1", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "ruzstd" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[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 = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "self_cell" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + +[[package]] +name = "serde" +version = "1.0.218" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.218" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +dependencies = [ + "itoa", + "memchr", + "ryu", + "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 = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "skrifa" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[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.8.0", +] + +[[package]] +name = "stackfuture" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eae92052b72ef70dafa16eddbabffc77e5ca3574be2f7bc1127b36f0a7ad7f2" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "svg_fmt" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" + +[[package]] +name = "swash" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd59f3f359ddd2c95af4758c18270eddd9c730dde98598023cdabff472c2ca2" +dependencies = [ + "skrifa", + "yazi", + "zeno", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "windows 0.57.0", +] + +[[package]] +name = "taffy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cb893bff0f80ae17d3a57e030622a967b8dbc90e38284d9b4b1442e23873c94" +dependencies = [ + "arrayvec", + "grid", + "num-traits", + "serde", + "slotmap", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[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 = "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 = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "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-oslog" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528bdd1f0e27b5dd9a4ededf154e824b0532731e4af73bb531de46276e0aab1e" +dependencies = [ + "bindgen", + "cc", + "cfg-if", + "once_cell", + "parking_lot", + "tracing-core", + "tracing-subscriber", +] + +[[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 = "tracing-wasm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" +dependencies = [ + "tracing", + "tracing-subscriber", + "wasm-bindgen", +] + +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" + +[[package]] +name = "unicode-ccc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" + +[[package]] +name = "unicode-ident" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-script" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" + +[[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.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "uuid" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" +dependencies = [ + "getrandom 0.2.15", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[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.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +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 = "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 = "wgpu" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a" +dependencies = [ + "arrayvec", + "cfg_aliases 0.1.1", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "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 = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" +dependencies = [ + "arrayvec", + "bit-vec 0.8.0", + "bitflags 2.8.0", + "cfg_aliases 0.1.1", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set 0.8.0", + "bitflags 2.8.0", + "block", + "bytemuck", + "cfg_aliases 0.1.1", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "wgpu-types" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" +dependencies = [ + "bitflags 2.8.0", + "js-sys", + "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.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +dependencies = [ + "windows-core 0.59.0", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "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 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" +dependencies = [ + "windows-implement 0.59.0", + "windows-interface 0.59.0", + "windows-result 0.3.1", + "windows-strings 0.3.1", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +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-interface" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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-result" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + +[[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 0.52.6", + "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-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[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_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[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_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[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 = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winit" +version = "0.30.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" +dependencies = [ + "android-activity", + "atomic-waker", + "bitflags 2.8.0", + "block2", + "bytemuck", + "calloop", + "cfg_aliases 0.2.1", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "ndk 0.9.0", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[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 = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.8.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.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" + +[[package]] +name = "yazi" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" + +[[package]] +name = "zeno" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf01143b2dd5d134f11f545cf9f1431b13b749695cb33bcce051e7568f99478" +dependencies = [ + "zerocopy-derive 0.8.21", +] + +[[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.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712c8386f4f4299382c9abee219bee7084f78fb939d88b6840fcc1320d5f6da2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zorder" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea8734a87d9de83816351d459ad98e276a9f60adc993f524504606cc126fb01" +dependencies = [ + "num-traits", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f079b61 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "bevy-bloxel-test" +version = "0.1.0" +edition = "2021" + +# Enable a small amount of optimization in the dev profile. +[profile.dev] +opt-level = 1 + +# Enable a large amount of optimization in the dev profile for dependencies. +[profile.dev.package."*"] +opt-level = 3 + +[dependencies] +bevy = { version = "0.15.3", features = [ "file_watcher", "embedded_watcher" ] } +bitvec = "1.0.1" +overload = "0.1.1" +rand = "0.9.0" +zorder = "0.2.2" diff --git a/assets/terrain/clay.png b/assets/terrain/clay.png new file mode 100644 index 0000000..56b78ad Binary files /dev/null and b/assets/terrain/clay.png differ diff --git a/assets/terrain/clay_bricks.png b/assets/terrain/clay_bricks.png new file mode 100644 index 0000000..417aade Binary files /dev/null and b/assets/terrain/clay_bricks.png differ diff --git a/assets/terrain/dirt.png b/assets/terrain/dirt.png new file mode 100644 index 0000000..06d1124 Binary files /dev/null and b/assets/terrain/dirt.png differ diff --git a/assets/terrain/grass_side.png b/assets/terrain/grass_side.png new file mode 100644 index 0000000..e4510e1 Binary files /dev/null and b/assets/terrain/grass_side.png differ diff --git a/assets/terrain/grass_tall.png b/assets/terrain/grass_tall.png new file mode 100644 index 0000000..60cf7ee Binary files /dev/null and b/assets/terrain/grass_tall.png differ diff --git a/assets/terrain/grass_top.png b/assets/terrain/grass_top.png new file mode 100644 index 0000000..6d79392 Binary files /dev/null and b/assets/terrain/grass_top.png differ diff --git a/assets/terrain/gravel.png b/assets/terrain/gravel.png new file mode 100644 index 0000000..b0fabac Binary files /dev/null and b/assets/terrain/gravel.png differ diff --git a/assets/terrain/leaves.png b/assets/terrain/leaves.png new file mode 100644 index 0000000..b9e95e4 Binary files /dev/null and b/assets/terrain/leaves.png differ diff --git a/assets/terrain/planks.png b/assets/terrain/planks.png new file mode 100644 index 0000000..aa58fe3 Binary files /dev/null and b/assets/terrain/planks.png differ diff --git a/assets/terrain/rock.png b/assets/terrain/rock.png new file mode 100644 index 0000000..252586c Binary files /dev/null and b/assets/terrain/rock.png differ diff --git a/assets/terrain/sand.png b/assets/terrain/sand.png new file mode 100644 index 0000000..644e197 Binary files /dev/null and b/assets/terrain/sand.png differ diff --git a/assets/terrain/stone_bricks.png b/assets/terrain/stone_bricks.png new file mode 100644 index 0000000..5803518 Binary files /dev/null and b/assets/terrain/stone_bricks.png differ diff --git a/assets/terrain/trunk.png b/assets/terrain/trunk.png new file mode 100644 index 0000000..e9c10b3 Binary files /dev/null and b/assets/terrain/trunk.png differ diff --git a/assets/terrain/trunk_inner.png b/assets/terrain/trunk_inner.png new file mode 100644 index 0000000..0de4857 Binary files /dev/null and b/assets/terrain/trunk_inner.png differ diff --git a/src/bloxel/block.rs b/src/bloxel/block.rs new file mode 100644 index 0000000..aaac79f --- /dev/null +++ b/src/bloxel/block.rs @@ -0,0 +1,7 @@ +use bevy::prelude::*; + +#[derive(Component)] +pub struct Block; + +#[derive(Component, Deref)] +pub struct BlockTexture(pub Handle); diff --git a/src/bloxel/chunk.rs b/src/bloxel/chunk.rs new file mode 100644 index 0000000..ab7be3a --- /dev/null +++ b/src/bloxel/chunk.rs @@ -0,0 +1,26 @@ +use bevy::{prelude::*, utils::HashMap}; + +use super::{ + math::{ChunkPos, CHUNK_LENGTH}, + storage::PaletteBloxelStorage, +}; + +#[derive(Component, Default)] +pub struct Chunk; + +#[derive(Component, Deref, DerefMut)] +#[require(Chunk)] +pub struct ChunkData(PaletteBloxelStorage); + +impl ChunkData { + pub fn new(default: Entity) -> Self { + Self(PaletteBloxelStorage::new( + UVec3::splat(CHUNK_LENGTH as u32), + default, + )) + } +} + +#[derive(Component, Default, Deref, DerefMut)] +#[require(Transform, Visibility)] +pub struct ChunkMap(HashMap); diff --git a/src/bloxel/generic_math/mod.rs b/src/bloxel/generic_math/mod.rs new file mode 100644 index 0000000..c5f5eff --- /dev/null +++ b/src/bloxel/generic_math/mod.rs @@ -0,0 +1,5 @@ +mod pos; +mod region; + +pub use pos::Pos; +pub use region::Region; diff --git a/src/bloxel/generic_math/pos.rs b/src/bloxel/generic_math/pos.rs new file mode 100644 index 0000000..dc6cde4 --- /dev/null +++ b/src/bloxel/generic_math/pos.rs @@ -0,0 +1,212 @@ +use std::{ + marker::PhantomData, + ops::{Add, AddAssign, Index, IndexMut, Sub, SubAssign}, +}; + +use bevy::{ + ecs::component::Component, + math::{Dir3, IVec3, InvalidDirectionError}, +}; + +use super::Region; + +pub struct Pos { + pub x: i32, + pub y: i32, + pub z: i32, + _marker: PhantomData, +} + +impl Pos { + pub const ORIGIN: Self = Self::new(0, 0, 0); + + pub const fn new(x: i32, y: i32, z: i32) -> Self { + Self { + x, + y, + z, + _marker: PhantomData, + } + } + + pub fn region(self) -> Region { + Region::new_unchecked(self.into(), self.into()) + } + + pub fn distance_to(self, other: Self) -> f32 { + (self.distance_to_squared(other) as f32).sqrt() + } + + pub fn distance_to_squared(self, other: Self) -> i32 { + IVec3::distance_squared(self.into(), other.into()) + } + + pub fn direction_to(self, other: Self) -> Result { + Dir3::new((other - self).as_vec3()) + } + + pub fn min(self, rhs: Self) -> Self { + Self::new(self.x.min(rhs.x), self.y.min(rhs.y), self.z.min(rhs.z)) + } + + pub fn max(self, rhs: Self) -> Self { + Self::new(self.x.max(rhs.x), self.y.max(rhs.y), self.z.max(rhs.z)) + } +} + +impl std::fmt::Display for Pos { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[{}, {}, {}]", self.x, self.y, self.z) + } +} + +impl std::fmt::Debug for Pos { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fmt.debug_tuple(stringify!(Pos)) + .field(&self.x) + .field(&self.y) + .field(&self.z) + .finish() + } +} + +// Trait implementations that SHOULD be handled by #[derive] + +use bevy::ecs::component::StorageType; +impl Component for Pos { + const STORAGE_TYPE: StorageType = StorageType::Table; +} + +impl Default for Pos { + fn default() -> Self { + Self { + x: 0, + y: 0, + z: 0, + _marker: PhantomData, + } + } +} + +impl Clone for Pos { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for Pos {} + +impl PartialEq for Pos { + fn eq(&self, other: &Self) -> bool { + (self.x, self.y, self.z).eq(&(other.x, other.y, other.z)) + } +} + +impl Eq for Pos {} + +impl std::hash::Hash for Pos { + fn hash(&self, state: &mut H) { + (self.x, self.y, self.z).hash(state) + } +} + +// Conversion + +impl From<(i32, i32, i32)> for Pos { + fn from((x, y, z): (i32, i32, i32)) -> Self { + Self::new(x, y, z) + } +} +impl From> for (i32, i32, i32) { + fn from(Pos { x, y, z, .. }: Pos) -> Self { + (x, y, z) + } +} + +impl From<[i32; 3]> for Pos { + fn from([x, y, z]: [i32; 3]) -> Self { + Self::new(x, y, z) + } +} +impl From> for [i32; 3] { + fn from(Pos { x, y, z, .. }: Pos) -> Self { + [x, y, z] + } +} + +impl From for Pos { + fn from(IVec3 { x, y, z }: IVec3) -> Self { + Self::new(x, y, z) + } +} +impl From> for IVec3 { + fn from(Pos { x, y, z, .. }: Pos) -> Self { + Self::new(x, y, z) + } +} + +// Offsetting + +impl Add for Pos { + type Output = Pos; + fn add(self, rhs: IVec3) -> Self::Output { + Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) + } +} + +impl Sub for Pos { + type Output = Pos; + fn sub(self, rhs: IVec3) -> Self::Output { + Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) + } +} + +impl AddAssign for Pos { + fn add_assign(&mut self, rhs: IVec3) { + self.x += rhs.x; + self.y += rhs.y; + self.z += rhs.z; + } +} + +impl SubAssign for Pos { + fn sub_assign(&mut self, rhs: IVec3) { + self.x -= rhs.x; + self.y -= rhs.y; + self.z -= rhs.z; + } +} + +// Difference + +impl Sub> for Pos { + type Output = IVec3; + fn sub(self, rhs: Self) -> IVec3 { + IVec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) + } +} + +// Indexing + +impl Index for Pos { + type Output = i32; + fn index(&self, index: usize) -> &Self::Output { + match index { + 0 => &self.x, + 1 => &self.y, + 2 => &self.z, + _ => panic!("index out of bounds"), + } + } +} + +impl IndexMut for Pos { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match index { + 0 => &mut self.x, + 1 => &mut self.y, + 2 => &mut self.z, + _ => panic!("index out of bounds"), + } + } +} diff --git a/src/bloxel/generic_math/region.rs b/src/bloxel/generic_math/region.rs new file mode 100644 index 0000000..13f8225 --- /dev/null +++ b/src/bloxel/generic_math/region.rs @@ -0,0 +1,175 @@ +use std::{ + marker::PhantomData, + ops::{Add, AddAssign, Sub, SubAssign}, +}; + +use bevy::{ + ecs::component::Component, + math::{IVec3, UVec3}, +}; + +use super::Pos; + +pub struct Region { + min: IVec3, + max: IVec3, + _marker: PhantomData, +} + +impl Region { + pub fn new_unchecked(min: IVec3, max: IVec3) -> Self { + Self { + min, + max, + _marker: PhantomData, + } + } + + pub fn new_checked(min: Pos, max: Pos) -> Result { + let min: IVec3 = min.into(); + let max: IVec3 = max.into(); + if min.x <= max.x && min.y <= max.y && min.z <= max.z { + Ok(Self::new_unchecked(min, max)) + } else { + Err(()) + } + } + + pub fn new(a: Pos, b: Pos) -> Self { + let a: IVec3 = a.into(); + let b: IVec3 = b.into(); + let min = IVec3::new(a.x.min(b.x), a.y.min(b.y), a.z.min(b.z)); + let max = IVec3::new(a.x.max(b.x), a.y.max(b.y), a.z.max(b.z)); + Self::new_unchecked(min, max) + } + + pub fn size(&self) -> UVec3 { + (self.max - self.min + IVec3::ONE).as_uvec3() + } + + pub fn contains(&self, pos: Pos) -> bool { + let pos: IVec3 = pos.into(); + (pos.x >= self.min.x && pos.x <= self.max.x) + && (pos.y >= self.min.y && pos.y <= self.max.y) + && (pos.z >= self.min.z && pos.z <= self.max.z) + } + + pub fn intersects(&self, other: Self) -> bool { + (other.max.x > self.min.x && other.min.x < self.max.x) + && (other.max.y > self.min.y && other.min.y < self.max.y) + && (other.max.z > self.min.z && other.min.z < self.max.z) + } + + pub fn distance_to(&self, pos: Pos) -> f32 { + (self.distance_to_squared(pos) as f32).sqrt() + } + + pub fn distance_to_squared(&self, pos: Pos) -> i32 { + let pos: IVec3 = pos.into(); + let clamped = pos.max(self.min).min(self.max); + pos.distance_squared(clamped) + } + + pub fn expand(&self, amount: i32) -> Result { + Self::new_checked( + (self.min - IVec3::splat(amount)).into(), + (self.max + IVec3::splat(amount)).into(), + ) + } +} + +impl std::fmt::Display for Region { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} to {}", self.min, self.max) + } +} + +impl std::fmt::Debug for Region { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fmt.debug_struct(stringify!(Region)) + .field("min", &self.min) + .field("max", &self.max) + .finish() + } +} + +// Trait implementations that SHOULD be handled by #[derive] + +use bevy::ecs::component::StorageType; +impl Component for Region { + const STORAGE_TYPE: StorageType = StorageType::Table; +} + +impl Default for Region { + fn default() -> Self { + Self { + min: IVec3::ZERO, + max: IVec3::ZERO, + _marker: PhantomData, + } + } +} + +impl Clone for Region { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for Region {} + +impl PartialEq for Region { + fn eq(&self, other: &Self) -> bool { + (self.min, self.max).eq(&(other.min, other.max)) + } +} + +impl Eq for Region {} + +impl std::hash::Hash for Region { + fn hash(&self, state: &mut H) { + (self.min, self.max).hash(state) + } +} + +// Offsetting + +impl Add for Region { + type Output = Region; + fn add(self, rhs: IVec3) -> Self::Output { + Self::new_unchecked(self.min + rhs, self.max + rhs) + } +} +impl Add for &Region { + type Output = Region; + fn add(self, rhs: IVec3) -> Self::Output { + Region::new_unchecked(self.min + rhs, self.max + rhs) + } +} + +impl Sub for Region { + type Output = Region; + fn sub(self, rhs: IVec3) -> Self::Output { + Self::new_unchecked(self.min - rhs, self.max - rhs) + } +} +impl Sub for &Region { + type Output = Region; + fn sub(self, rhs: IVec3) -> Self::Output { + Region::new_unchecked(self.min - rhs, self.max - rhs) + } +} + +impl AddAssign for Region { + fn add_assign(&mut self, rhs: IVec3) { + self.min += rhs; + self.max += rhs; + } +} + +impl SubAssign for Region { + fn sub_assign(&mut self, rhs: IVec3) { + self.min -= rhs; + self.max -= rhs; + } +} diff --git a/src/bloxel/math/block_pos.rs b/src/bloxel/math/block_pos.rs new file mode 100644 index 0000000..83d46d5 --- /dev/null +++ b/src/bloxel/math/block_pos.rs @@ -0,0 +1,129 @@ +use std::ops::{self, Index, IndexMut}; + +use bevy::{ + ecs::component::Component, + math::{Dir3, IVec3, InvalidDirectionError}, +}; +use overload::overload; + +use super::BlockRegion; + +#[derive(Component, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct BlockPos { + pub x: i32, + pub y: i32, + pub z: i32, +} + +impl BlockPos { + pub const ORIGIN: BlockPos = Self::new(0, 0, 0); + + pub const fn new(x: i32, y: i32, z: i32) -> Self { + Self { x, y, z } + } + + pub fn region(self) -> BlockRegion { + BlockRegion::new_unchecked(self, self) + } + + pub fn distance_to(self, other: Self) -> f32 { + (self.distance_to_squared(other) as f32).sqrt() + } + + pub fn distance_to_squared(self, other: Self) -> i32 { + IVec3::distance_squared(self.into(), other.into()) + } + + pub fn direction_to(self, other: Self) -> Result { + Dir3::new((other - self).as_vec3()) + } + + pub fn min(self, rhs: Self) -> Self { + Self::new(self.x.min(rhs.x), self.y.min(rhs.y), self.z.min(rhs.z)) + } + + pub fn max(self, rhs: Self) -> Self { + Self::new(self.x.max(rhs.x), self.y.max(rhs.y), self.z.max(rhs.z)) + } + + pub fn offset(self, x: i32, y: i32, z: i32) -> Self { + Self::new(self.x + x, self.y + y, self.z + z) + } +} + +impl std::fmt::Display for BlockPos { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[{}, {}, {}]", self.x, self.y, self.z) + } +} + +// Offsetting + +overload!((l: BlockPos) + (r: IVec3) -> BlockPos { BlockPos::new(l.x + r.x, l.y + r.y, l.z + r.z) }); +overload!((l: BlockPos) - (r: IVec3) -> BlockPos { BlockPos::new(l.x - r.x, l.y - r.y, l.z - r.z) }); +overload!((s: &mut BlockPos) += (v: IVec3) { s.x += v.x; s.y += v.y; s.z += v.z; }); +overload!((s: &mut BlockPos) -= (v: IVec3) { s.x -= v.x; s.y -= v.y; s.z -= v.z; }); + +// Difference + +overload!((l: BlockPos) - (r: BlockPos) -> IVec3 { IVec3::new(l.x - r.x, l.y - r.y, l.z - r.z) }); + +// Indexing + +impl Index for BlockPos { + type Output = i32; + fn index(&self, index: usize) -> &Self::Output { + match index { + 0 => &self.x, + 1 => &self.y, + 2 => &self.z, + _ => panic!("index out of bounds"), + } + } +} + +impl IndexMut for BlockPos { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match index { + 0 => &mut self.x, + 1 => &mut self.y, + 2 => &mut self.z, + _ => panic!("index out of bounds"), + } + } +} + +// Conversion + +impl From<(i32, i32, i32)> for BlockPos { + fn from((x, y, z): (i32, i32, i32)) -> Self { + Self::new(x, y, z) + } +} +impl From for (i32, i32, i32) { + fn from(BlockPos { x, y, z }: BlockPos) -> Self { + (x, y, z) + } +} + +impl From<[i32; 3]> for BlockPos { + fn from([x, y, z]: [i32; 3]) -> Self { + Self::new(x, y, z) + } +} +impl From for [i32; 3] { + fn from(BlockPos { x, y, z }: BlockPos) -> Self { + [x, y, z] + } +} + +impl From for BlockPos { + fn from(IVec3 { x, y, z }: IVec3) -> Self { + Self::new(x, y, z) + } +} +impl From for IVec3 { + fn from(BlockPos { x, y, z }: BlockPos) -> Self { + Self::new(x, y, z) + } +} diff --git a/src/bloxel/math/block_region.rs b/src/bloxel/math/block_region.rs new file mode 100644 index 0000000..3af9d6e --- /dev/null +++ b/src/bloxel/math/block_region.rs @@ -0,0 +1,87 @@ +use std::ops; + +use bevy::{ + ecs::component::Component, + math::{IVec3, UVec3}, +}; +use overload::overload; + +use super::BlockPos; + +#[derive(Component, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct BlockRegion { + min: BlockPos, + max: BlockPos, +} + +impl BlockRegion { + pub fn new_unchecked(min: BlockPos, max: BlockPos) -> Self { + Self { min, max } + } + + pub fn new_checked(min: BlockPos, max: BlockPos) -> Result { + if min.x <= max.x && min.y <= max.y && min.z <= max.z { + Ok(Self::new_unchecked(min, max)) + } else { + Err(()) + } + } + + pub fn new(a: BlockPos, b: BlockPos) -> Self { + let min = BlockPos::new(a.x.min(b.x), a.y.min(b.y), a.z.min(b.z)); + let max = BlockPos::new(a.x.max(b.x), a.y.max(b.y), a.z.max(b.z)); + Self::new_unchecked(min, max) + } + + pub fn size(&self) -> UVec3 { + (self.max - self.min + IVec3::ONE).as_uvec3() + } + + pub fn contains(&self, pos: BlockPos) -> bool { + (pos.x >= self.min.x && pos.x <= self.max.x) + && (pos.y >= self.min.y && pos.y <= self.max.y) + && (pos.z >= self.min.z && pos.z <= self.max.z) + } + + pub fn intersects(&self, other: Self) -> bool { + (other.max.x > self.min.x && other.min.x < self.max.x) + && (other.max.y > self.min.y && other.min.y < self.max.y) + && (other.max.z > self.min.z && other.min.z < self.max.z) + } + + pub fn distance_to(&self, pos: BlockPos) -> f32 { + (self.distance_to_squared(pos) as f32).sqrt() + } + + pub fn distance_to_squared(&self, pos: BlockPos) -> i32 { + let clamped = pos.max(self.min).min(self.max); + pos.distance_to_squared(clamped) + } + + pub fn offset(&self, x: i32, y: i32, z: i32) -> Self { + Self { + min: self.min.offset(x, y, z), + max: self.max.offset(x, y, z), + } + } + + pub fn expand(&self, amount: i32) -> Result { + Self::new_checked( + self.min - IVec3::splat(amount), + self.max + IVec3::splat(amount), + ) + } +} + +impl std::fmt::Display for BlockRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} to {}", self.min, self.max) + } +} + +// Offsetting + +overload!((l: ?BlockRegion) + (r: IVec3) -> BlockRegion { BlockRegion::new_unchecked(l.min + r, l.max + r) }); +overload!((l: ?BlockRegion) - (r: IVec3) -> BlockRegion { BlockRegion::new_unchecked(l.min - r, l.max - r) }); +overload!((s: &mut BlockRegion) += (v: IVec3) { s.min += v; s.max += v; }); +overload!((s: &mut BlockRegion) -= (v: IVec3) { s.min -= v; s.max -= v; }); diff --git a/src/bloxel/math/chunk_pos.rs b/src/bloxel/math/chunk_pos.rs new file mode 100644 index 0000000..cfd13d0 --- /dev/null +++ b/src/bloxel/math/chunk_pos.rs @@ -0,0 +1,158 @@ +use std::ops::{self, Index, IndexMut}; + +use bevy::{ + ecs::component::Component, + math::{Dir3, IVec3, InvalidDirectionError}, + transform::components::Transform, +}; +use overload::overload; + +use super::{BlockPos, BlockRegion, ChunkRegion}; + +pub const CHUNK_SHIFT: i32 = 4; +pub const CHUNK_MASK: i32 = !(!0 << CHUNK_SHIFT); // = 0b1111 +pub const CHUNK_LENGTH: usize = 1 << CHUNK_SHIFT; // = 16 + +pub const CHUNK_MAX: IVec3 = IVec3::splat((CHUNK_LENGTH - 1) as i32); + +#[derive(Component, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct ChunkPos { + pub x: i32, + pub y: i32, + pub z: i32, +} + +impl ChunkPos { + pub const ORIGIN: ChunkPos = Self::new(0, 0, 0); + + pub const fn new(x: i32, y: i32, z: i32) -> Self { + Self { x, y, z } + } + + pub fn region(self) -> ChunkRegion { + ChunkRegion::new_unchecked(self, self) + } + + pub fn distance_to(self, other: Self) -> f32 { + (self.distance_to_squared(other) as f32).sqrt() + } + + pub fn distance_to_squared(self, other: Self) -> i32 { + IVec3::distance_squared(self.into(), other.into()) + } + + pub fn direction_to(self, other: Self) -> Result { + Dir3::new((other - self).as_vec3()) + } + + pub fn transform(self) -> Transform { + let pos: IVec3 = self.into(); + Transform::from_translation((pos << CHUNK_SHIFT).as_vec3()) + } + + pub fn min(self, rhs: Self) -> Self { + Self::new(self.x.min(rhs.x), self.y.min(rhs.y), self.z.min(rhs.z)) + } + + pub fn max(self, rhs: Self) -> Self { + Self::new(self.x.max(rhs.x), self.y.max(rhs.y), self.z.max(rhs.z)) + } + + pub fn offset(self, x: i32, y: i32, z: i32) -> Self { + Self::new(self.x + x, self.y + y, self.z + z) + } + + pub fn from_block_pos(pos: BlockPos) -> (Self, IVec3) { + let pos: IVec3 = pos.into(); + ((pos >> CHUNK_SHIFT).into(), pos & CHUNK_MASK) + } + + pub fn to_block_pos(self, relative: IVec3) -> BlockPos { + let pos: IVec3 = self.into(); + ((pos << CHUNK_SHIFT) + relative).into() + } + + pub fn to_block_region(self) -> BlockRegion { + BlockRegion::new_unchecked( + self.to_block_pos(IVec3::ZERO), + self.to_block_pos(IVec3::splat(CHUNK_LENGTH as i32 - 1)), + ) + } +} + +impl std::fmt::Display for ChunkPos { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[{}, {}, {}]", self.x, self.y, self.z) + } +} + +// Offsetting + +overload!((l: ChunkPos) + (r: IVec3) -> ChunkPos { ChunkPos::new(l.x + r.x, l.y + r.y, l.z + r.z) }); +overload!((l: ChunkPos) - (r: IVec3) -> ChunkPos { ChunkPos::new(l.x - r.x, l.y - r.y, l.z - r.z) }); +overload!((s: &mut ChunkPos) += (v: IVec3) { s.x += v.x; s.y += v.y; s.z += v.z; }); +overload!((s: &mut ChunkPos) -= (v: IVec3) { s.x -= v.x; s.y -= v.y; s.z -= v.z; }); + +// Difference + +overload!((l: ChunkPos) - (r: ChunkPos) -> IVec3 { IVec3::new(l.x - r.x, l.y - r.y, l.z - r.z) }); + +// Indexing + +impl Index for ChunkPos { + type Output = i32; + fn index(&self, index: usize) -> &Self::Output { + match index { + 0 => &self.x, + 1 => &self.y, + 2 => &self.z, + _ => panic!("index out of bounds"), + } + } +} + +impl IndexMut for ChunkPos { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match index { + 0 => &mut self.x, + 1 => &mut self.y, + 2 => &mut self.z, + _ => panic!("index out of bounds"), + } + } +} + +// Conversion + +impl From<(i32, i32, i32)> for ChunkPos { + fn from((x, y, z): (i32, i32, i32)) -> Self { + Self::new(x, y, z) + } +} +impl From for (i32, i32, i32) { + fn from(ChunkPos { x, y, z }: ChunkPos) -> Self { + (x, y, z) + } +} + +impl From<[i32; 3]> for ChunkPos { + fn from([x, y, z]: [i32; 3]) -> Self { + Self::new(x, y, z) + } +} +impl From for [i32; 3] { + fn from(ChunkPos { x, y, z }: ChunkPos) -> Self { + [x, y, z] + } +} + +impl From for ChunkPos { + fn from(IVec3 { x, y, z }: IVec3) -> Self { + Self::new(x, y, z) + } +} +impl From for IVec3 { + fn from(ChunkPos { x, y, z }: ChunkPos) -> Self { + Self::new(x, y, z) + } +} diff --git a/src/bloxel/math/chunk_region.rs b/src/bloxel/math/chunk_region.rs new file mode 100644 index 0000000..ba79b6f --- /dev/null +++ b/src/bloxel/math/chunk_region.rs @@ -0,0 +1,94 @@ +use std::ops; + +use bevy::{ + ecs::component::Component, + math::{IVec3, UVec3}, +}; +use overload::overload; + +use super::{BlockRegion, ChunkPos, CHUNK_MAX}; + +#[derive(Component, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct ChunkRegion { + min: ChunkPos, + max: ChunkPos, +} + +impl ChunkRegion { + pub fn new_unchecked(min: ChunkPos, max: ChunkPos) -> Self { + Self { min, max } + } + + pub fn new_checked(min: ChunkPos, max: ChunkPos) -> Result { + if min.x <= max.x && min.y <= max.y && min.z <= max.z { + Ok(Self::new_unchecked(min, max)) + } else { + Err(()) + } + } + + pub fn new(a: ChunkPos, b: ChunkPos) -> Self { + let min = ChunkPos::new(a.x.min(b.x), a.y.min(b.y), a.z.min(b.z)); + let max = ChunkPos::new(a.x.max(b.x), a.y.max(b.y), a.z.max(b.z)); + Self::new_unchecked(min, max) + } + + pub fn size(&self) -> UVec3 { + (self.max - self.min + IVec3::ONE).as_uvec3() + } + + pub fn contains(&self, pos: ChunkPos) -> bool { + (pos.x >= self.min.x && pos.x <= self.max.x) + && (pos.y >= self.min.y && pos.y <= self.max.y) + && (pos.z >= self.min.z && pos.z <= self.max.z) + } + + pub fn intersects(&self, other: Self) -> bool { + (other.max.x > self.min.x && other.min.x < self.max.x) + && (other.max.y > self.min.y && other.min.y < self.max.y) + && (other.max.z > self.min.z && other.min.z < self.max.z) + } + + pub fn distance_to(&self, pos: ChunkPos) -> f32 { + (self.distance_to_squared(pos) as f32).sqrt() + } + + pub fn distance_to_squared(&self, pos: ChunkPos) -> i32 { + let clamped = pos.max(self.min).min(self.max); + pos.distance_to_squared(clamped) + } + + pub fn offset(&self, x: i32, y: i32, z: i32) -> Self { + Self { + min: self.min.offset(x, y, z), + max: self.max.offset(x, y, z), + } + } + + pub fn expand(&self, amount: i32) -> Result { + Self::new_checked( + self.min - IVec3::splat(amount), + self.max + IVec3::splat(amount), + ) + } + + pub fn to_block_region(&self) -> BlockRegion { + BlockRegion::new_unchecked( + self.min.to_block_pos(IVec3::ZERO), + self.min.to_block_pos(CHUNK_MAX), + ) + } +} + +impl std::fmt::Display for ChunkRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} to {}", self.min, self.max) + } +} + +// Offsetting + +overload!((l: ?ChunkRegion) + (r: IVec3) -> ChunkRegion { ChunkRegion::new_unchecked(l.min + r, l.max + r) }); +overload!((l: ?ChunkRegion) - (r: IVec3) -> ChunkRegion { ChunkRegion::new_unchecked(l.min - r, l.max - r) }); +overload!((s: &mut ChunkRegion) += (v: IVec3) { s.min += v; s.max += v; }); +overload!((s: &mut ChunkRegion) -= (v: IVec3) { s.min -= v; s.max -= v; }); diff --git a/src/bloxel/math/mod.rs b/src/bloxel/math/mod.rs new file mode 100644 index 0000000..aa072c5 --- /dev/null +++ b/src/bloxel/math/mod.rs @@ -0,0 +1,11 @@ +mod block_pos; +mod block_region; +mod chunk_pos; +mod chunk_region; +mod z_order_index; + +pub use block_pos::*; +pub use block_region::*; +pub use chunk_pos::*; +pub use chunk_region::*; +pub use z_order_index::*; diff --git a/src/bloxel/math/z_order_index.rs b/src/bloxel/math/z_order_index.rs new file mode 100644 index 0000000..a313308 --- /dev/null +++ b/src/bloxel/math/z_order_index.rs @@ -0,0 +1,211 @@ +use std::ops; + +use bevy::math::IVec3; +use overload::overload; + +use super::ChunkPos; + +/// Helper function that creates a [`ZOrderIndex`], panicking if the supplied values +/// are not between [`ZOrderIndex::ELEMENT_MIN`] and [`ZOrderIndex::ELEMENT_MAX`]. +pub fn zorder(x: i32, y: i32, z: i32) -> ZOrderIndex { + ZOrderIndex::new(x, y, z).unwrap() +} + +/// Encodes 3 signed 21-bit integers into a 64-bit integer, their bits interleaved. +/// +/// This struct wraps an integer which represents an index into a space-filling curve called +/// [Z-Order Curve](https://en.wikipedia.org/wiki/Z-order_curve). This is also referred to as +/// Morton order, code, or encoding. +/// +/// By interleaving the 3 sub-elements into a single integer, some amount of packing can be +/// achieved, at the loss of some bits per elements. For example, with this 64-bit integer, +/// 21 bits per elements are available (`2_097_152` distinct values), which may be enough to +/// represent block coordinates in a bloxel game world. +/// +/// One upside of encoding separate coordinates into a single Z-Order index is that it can then +/// be effectively used to index into octrees, and certain operations such as bitwise shifting +/// are quite useful. +#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ZOrderIndex(u64); + +impl ZOrderIndex { + pub const ZERO: Self = Self::from_raw(0); + + const BITS_PER_ELEMENT: usize = (size_of::() * 8) / 3; + pub const ELEMENT_MIN: i32 = !0 << (Self::BITS_PER_ELEMENT - 1); + pub const ELEMENT_MAX: i32 = !Self::ELEMENT_MIN; + + const TOTAL_USABLE_BITS: usize = Self::BITS_PER_ELEMENT * 3; + const USABLE_BITS_MASK: u64 = !(!0 << Self::TOTAL_USABLE_BITS); + const SIGN_BITS_MASK: u64 = 0b111 << (Self::TOTAL_USABLE_BITS - 3); + + pub const fn from_raw(value: u64) -> Self { + Self(value & Self::USABLE_BITS_MASK) + } + + pub fn new(x: i32, y: i32, z: i32) -> Result { + if (x >= Self::ELEMENT_MIN && x <= Self::ELEMENT_MAX) + && (y >= Self::ELEMENT_MIN && y <= Self::ELEMENT_MAX) + && (z >= Self::ELEMENT_MIN && z <= Self::ELEMENT_MAX) + { + let raw = zorder::index_of([x as u32, y as u32, z as u32]); + Ok(Self::from_raw(raw as u64)) + } else { + Err(()) + } + } + + pub fn raw(self) -> u64 { + self.0 + } + + pub fn offset(self, x: i32, y: i32, z: i32) -> Result { + let (self_x, self_y, self_z) = self.into(); + Self::new(self_x + x, self_y + y, self_z + z) + } +} + +impl std::fmt::Display for ZOrderIndex { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let (x, y, z) = (*self).into(); + write!(f, "[{}, {}, {}]", x, y, z) + } +} + +impl std::fmt::Debug for ZOrderIndex { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let (x, y, z) = (*self).into(); + fmt.debug_tuple(stringify!(ZOrderIndex)) + .field(&x) + .field(&y) + .field(&z) + .finish() + } +} + +// Bitwise AND, OR, XOR + +overload!((l: ZOrderIndex) & (r: u64) -> ZOrderIndex { ZOrderIndex::from_raw(l.0 & r) }); +overload!((l: ZOrderIndex) | (r: u64) -> ZOrderIndex { ZOrderIndex::from_raw(l.0 | r) }); +overload!((l: ZOrderIndex) ^ (r: u64) -> ZOrderIndex { ZOrderIndex::from_raw(l.0 ^ r) }); +overload!((l: ZOrderIndex) & (r: ZOrderIndex) -> ZOrderIndex { l & r.0 }); +overload!((l: ZOrderIndex) | (r: ZOrderIndex) -> ZOrderIndex { l | r.0 }); +overload!((l: ZOrderIndex) ^ (r: ZOrderIndex) -> ZOrderIndex { l ^ r.0 }); + +// Bitshifting + +overload!((l: ZOrderIndex) << (r: usize) -> ZOrderIndex { + ZOrderIndex::from_raw(l.0 << (r * 3)) +}); + +overload!((l: ZOrderIndex) >> (r: usize) -> ZOrderIndex { + let mut result = l.0; + let sign_bits = result & ZOrderIndex::SIGN_BITS_MASK; + for _ in 0..r { result = (result >> 3) | sign_bits } + ZOrderIndex::from_raw(result) +}); + +// Conversion + +impl TryFrom<(i32, i32, i32)> for ZOrderIndex { + type Error = (); + fn try_from((x, y, z): (i32, i32, i32)) -> Result { + Self::new(x, y, z) + } +} +impl From for (i32, i32, i32) { + fn from(value: ZOrderIndex) -> Self { + const SHIFT: usize = (size_of::() * 8) - ZOrderIndex::BITS_PER_ELEMENT; + zorder::coord_of(value.0 as u128) + .map(|i| ((i as i32) << SHIFT) >> SHIFT) + .into() + } +} + +impl TryFrom<[i32; 3]> for ZOrderIndex { + type Error = (); + fn try_from([x, y, z]: [i32; 3]) -> Result { + Self::new(x, y, z) + } +} +impl From for [i32; 3] { + fn from(value: ZOrderIndex) -> Self { + Into::<(i32, i32, i32)>::into(value).into() + } +} + +impl TryFrom for ZOrderIndex { + type Error = (); + fn try_from(IVec3 { x, y, z }: IVec3) -> Result { + Self::new(x, y, z) + } +} +impl From for IVec3 { + fn from(value: ZOrderIndex) -> Self { + Into::<(i32, i32, i32)>::into(value).into() + } +} + +impl TryFrom for ZOrderIndex { + type Error = (); + fn try_from(ChunkPos { x, y, z }: ChunkPos) -> Result { + Self::new(x, y, z) + } +} +impl From for ChunkPos { + fn from(value: ZOrderIndex) -> Self { + Into::<(i32, i32, i32)>::into(value).into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encode_decode_into() { + assert_eq!((6, -16, 15), zorder(6, -16, 15).into()); + + let min = ZOrderIndex::ELEMENT_MIN; + let max = ZOrderIndex::ELEMENT_MAX; + assert_eq!((min, 0, max), zorder(min, 0, max).into()); + } + + #[test] + fn bounds_checking() { + let min = 0b11111111111_1_00000000000000000000u32 as i32; + let max = 0b00000000000_0_11111111111111111111u32 as i32; + + assert_eq!( + Ok((ZOrderIndex::ELEMENT_MIN, ZOrderIndex::ELEMENT_MAX, 0)), + ZOrderIndex::new(min, max, 0).map(Into::into) + ); + + assert!(ZOrderIndex::new(min - 1, max, 0).is_err()); + assert!(ZOrderIndex::new(min, max + 1, 0).is_err()); + } + + #[test] + #[rustfmt::skip] + fn raw() { + let x_mask: u64 = 0b0_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001_001_000; + let y_mask: u64 = 0b0_010_010_010_010_010_010_010_010_010_010_010_010_010_010_010_010_010_000_000_000_000; + let z_mask: u64 = 0b0_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_100_100_100_100; + + let raw = ZOrderIndex::from_raw(x_mask | y_mask | z_mask); + assert_eq!(raw, zorder(6, -16, 15)); + } + + #[test] + fn bitshift() { + let zero = ZOrderIndex::ZERO; + assert_eq!(zero, zero >> 2); + assert_eq!(zero, zero << 2); + + assert_eq!(zorder(4, 8, 12), zorder(1, 2, 3) << 2); + assert_eq!(zorder(1, 2, 3), zorder(4, 8, 12) >> 2); + + assert_eq!(zorder(-4, -8, -12), zorder(-1, -2, -3) << 2); + assert_eq!(zorder(-1, -2, -3), zorder(-4, -8, -12) >> 2); + } +} diff --git a/src/bloxel/mesh/mesh_generator.rs b/src/bloxel/mesh/mesh_generator.rs new file mode 100644 index 0000000..ad9405c --- /dev/null +++ b/src/bloxel/mesh/mesh_generator.rs @@ -0,0 +1,127 @@ +use bevy::{ + asset::RenderAssetUsages, prelude::*, render::mesh::Indices, render::mesh::PrimitiveTopology, +}; + +use crate::bloxel::{block::BlockTexture, prelude::*, storage::BloxelArray}; + +pub fn create_bloxel_mesh( + bloxels: &impl BloxelView, + layout: &TextureAtlasLayout, + sources: &TextureAtlasSources, + block_lookup: &Query<&BlockTexture, With>, +) -> Mesh { + let offset = -(bloxels.size().as_vec3() / 2.); + + let mut positions: Vec = vec![]; + let mut normals: Vec = vec![]; + let mut uvs: Vec = vec![]; + let mut indices = vec![]; + let mut num_vertices = 0; + + let mut append_vertex = |pos: Vec3, normal: Dir3, uv: Vec2| { + positions.push(pos); + normals.push(*normal); + uvs.push(uv); + }; + + let mut append_quad = |show: bool, points: [Vec3; 4], normal: Dir3, uvs: Rect| { + if show { + append_vertex(points[0], normal, (uvs.min.x, uvs.min.y).into()); + append_vertex(points[1], normal, (uvs.max.x, uvs.min.y).into()); + append_vertex(points[2], normal, (uvs.max.x, uvs.max.y).into()); + append_vertex(points[3], normal, (uvs.min.x, uvs.max.y).into()); + + for i in [0, 1, 2, 2, 3, 0] { + indices.push(num_vertices + i); + } + num_vertices += 4; + } + }; + + let mut append_cube = |pos: IVec3, uvs: Rect, sides: [bool; 6]| { + let min = offset + pos.as_vec3(); + let max = offset + (pos + IVec3::ONE).as_vec3(); + + // left/right, bottom/top, back/front + let lbb = Vec3::new(min.x, min.y, min.z); + let lbf = Vec3::new(min.x, max.y, max.z); + let ltb = Vec3::new(min.x, max.y, min.z); + let ltf = Vec3::new(min.x, min.y, max.z); + let rbb = Vec3::new(max.x, min.y, min.z); + let rbf = Vec3::new(max.x, max.y, max.z); + let rtb = Vec3::new(max.x, max.y, min.z); + let rtf = Vec3::new(max.x, min.y, max.z); + + append_quad(sides[0], [rbb, rtb, rbf, rtf], Dir3::X, uvs); // Right + append_quad(sides[1], [ltf, lbf, ltb, lbb], Dir3::NEG_X, uvs); // Left + append_quad(sides[2], [rtb, ltb, lbf, rbf], Dir3::Y, uvs); // Top + append_quad(sides[3], [rtf, ltf, lbb, rbb], Dir3::NEG_Y, uvs); // Bottom + append_quad(sides[4], [ltf, rtf, rbf, lbf], Dir3::Z, uvs); // Front + append_quad(sides[5], [ltb, rtb, rbb, lbb], Dir3::NEG_Z, uvs); // Back + }; + + // Shrinks the UV rectangle by a tiny amount to get rid of ugly seams at the edges of blocks, + // due to floating point inaccuracy when the color is looked up in the shader or something. + // Temporary fix until a more sophisticated graphics overhaul using texture arrays or so. + let shrink_amount = -0.1 / layout.size.x as f32; + + let size = bloxels.size().as_ivec3(); + + // Capture all textures, which is currently all we need to know about a block to render it, + // into a 3D array for us to look up, with a 1 block buffer so we can safely look up neighbors. + let mut textures = BloxelArray::new_with_default(bloxels.size() + UVec3::new(2, 2, 2)); + for z in 0..size.z { + for y in 0..size.y { + for x in 0..size.x { + let pos = IVec3::new(x, y, z); + let block = bloxels.get(pos); + textures[pos + IVec3::ONE] = block_lookup.get(block).ok().map(|t| &t.0); + } + } + } + + for z in 0..size.z { + for y in 0..size.y { + for x in 0..size.x { + let pos = IVec3::new(x, y, z); + if let Some(texture) = textures[pos + IVec3::ONE] { + if let Some(uvs) = uv_rect(sources, layout, texture) { + append_cube( + pos, + uvs.inflate(shrink_amount), + [ + textures[pos + IVec3::new(2, 1, 1)].is_none(), + textures[pos + IVec3::new(0, 1, 1)].is_none(), + textures[pos + IVec3::new(1, 2, 1)].is_none(), + textures[pos + IVec3::new(1, 0, 1)].is_none(), + textures[pos + IVec3::new(1, 1, 2)].is_none(), + textures[pos + IVec3::new(1, 1, 0)].is_none(), + ], + ); + } + } + } + } + } + + Mesh::new( + PrimitiveTopology::TriangleList, + RenderAssetUsages::default(), + ) + .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions) + .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) + .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) + .with_inserted_indices(Indices::U32(indices)) +} + +fn uv_rect( + sources: &TextureAtlasSources, + layout: &TextureAtlasLayout, + texture: impl Into>, +) -> Option { + sources.texture_rect(layout, texture).map(|rect| { + let rect = rect.as_rect(); + let size = layout.size.as_vec2(); + Rect::from_corners(rect.min / size, rect.max / size) + }) +} diff --git a/src/bloxel/mesh/mod.rs b/src/bloxel/mesh/mod.rs new file mode 100644 index 0000000..d20326d --- /dev/null +++ b/src/bloxel/mesh/mod.rs @@ -0,0 +1,46 @@ +use std::ops::Deref; + +use bevy::prelude::*; + +use crate::{ + bloxel::{block::BlockTexture, prelude::*}, + TerrainAtlas, TerrainMaterial, +}; + +mod mesh_generator; + +pub use mesh_generator::*; + +/// Generates meshes for chunks that have `ChunkStorage` but no `Mesh3d` yet. +pub fn generate_chunk_mesh( + mut commands: Commands, + mut meshes: ResMut>, + terrain_material: Option>, + terrain_atlas: Option>, + atlas_layouts: Res>, + chunks_without_meshes: Query<(Entity, &ChunkData), (With, Without)>, + block_lookup: Query<&BlockTexture, With>, +) { + // This system will run before `TerrainMaterial` is available, so to avoid + // the system failing, we'll make the material and atlas an `Option`. + let Some(terrain_material) = terrain_material else { + return; + }; + // Atlas and layout should exist at this point, if material does. + let terrain_atlas = terrain_atlas.unwrap(); + let terrain_atlas_layout = atlas_layouts.get(&terrain_atlas.layout).unwrap(); + + for (entity, storage) in chunks_without_meshes.iter() { + let mesh = create_bloxel_mesh( + storage.deref(), + terrain_atlas_layout, + &terrain_atlas.sources, + &block_lookup, + ); + + commands.entity(entity).insert(( + Mesh3d(meshes.add(mesh)), + MeshMaterial3d(terrain_material.0.clone()), + )); + } +} diff --git a/src/bloxel/mod.rs b/src/bloxel/mod.rs new file mode 100644 index 0000000..71602f9 --- /dev/null +++ b/src/bloxel/mod.rs @@ -0,0 +1,78 @@ +use bevy::prelude::*; + +pub mod block; +pub mod chunk; +pub mod generic_math; +pub mod math; +pub mod mesh; +pub mod storage; +pub mod worldgen; + +pub mod prelude { + pub use super::{ + block::*, + chunk::*, + math::*, + storage::{BloxelView, BloxelViewMut}, + BloxelPlugin, + }; +} + +use prelude::*; + +pub struct BloxelPlugin; + +impl Plugin for BloxelPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + Update, + ( + set_transform_on_chunkpos_changed, + worldgen::create_chunks_around_camera, + worldgen::generate_terrain, + mesh::generate_chunk_mesh, + ), + ) + .add_observer(add_chunks_to_chunkmap) + .add_observer(remove_chunks_from_chunkmap); + } +} + +fn set_transform_on_chunkpos_changed( + mut commands: Commands, + chunk_query: Query<(Entity, &ChunkPos), Changed>, +) { + for (chunk, pos) in chunk_query.iter() { + commands.entity(chunk).insert(pos.transform()); + } +} + +fn add_chunks_to_chunkmap( + trigger: Trigger, + chunk_query: Query<(&Parent, &ChunkPos)>, + mut map_query: Query<&mut ChunkMap>, +) { + let chunk = trigger.entity(); + let Ok((parent, pos)) = chunk_query.get(chunk) else { + // Trigger with a bundle doesn't work as expected. It triggers + // when ANY component is added, rather than when ALL are present. + return; + }; + let mut map = map_query.get_mut(parent.get()).unwrap(); + map.try_insert(*pos, chunk).expect("chunk already present"); +} + +fn remove_chunks_from_chunkmap( + trigger: Trigger, + chunk_query: Query<(&Parent, &ChunkPos)>, + mut map_query: Query<&mut ChunkMap>, +) { + let chunk = trigger.entity(); + let Ok((parent, pos)) = chunk_query.get(chunk) else { + // See above. + return; + }; + let mut map = map_query.get_mut(parent.get()).unwrap(); + map.remove(pos).expect("chunk not found"); + println!("Chunk {chunk} @ {pos:?} removed from {}", parent.get()); +} diff --git a/src/bloxel/storage/bloxel_array.rs b/src/bloxel/storage/bloxel_array.rs new file mode 100644 index 0000000..e76700c --- /dev/null +++ b/src/bloxel/storage/bloxel_array.rs @@ -0,0 +1,74 @@ +use std::ops::{Index, IndexMut}; + +use bevy::math::{IVec3, UVec3}; + +use super::bloxel_view::{ivec3_to_index, BloxelView, BloxelViewMut}; + +pub struct BloxelArray { + size: UVec3, + data: Vec, +} + +impl BloxelArray { + pub fn new(size: UVec3, fill: T) -> Self { + assert!(size.x > 0 && size.y > 0 && size.z > 0); + let len = (size.x * size.y * size.z) as usize; + let data = vec![fill; len]; + Self { size, data } + } + + pub fn new_with_default(size: UVec3) -> Self + where + T: Default, + { + Self::new(size, Default::default()) + } + + fn get_index(&self, pos: impl Into) -> usize { + let pos = pos.into(); + assert!(self.contains(pos)); + ivec3_to_index(pos, self.size) + } +} + +impl Index for BloxelArray { + type Output = T; + + fn index(&self, pos: IVec3) -> &Self::Output { + let index = self.get_index(pos); + &self.data[index] + } +} + +impl IndexMut for BloxelArray { + fn index_mut(&mut self, pos: IVec3) -> &mut Self::Output { + let index = self.get_index(pos); + &mut self.data[index] + } +} + +impl BloxelView for BloxelArray { + fn size(&self) -> UVec3 { + self.size + } + + fn contains(&self, pos: impl Into) -> bool { + let pos = pos.into(); + let size = self.size.as_ivec3(); + (pos.x >= 0 && pos.x < size.x) + && (pos.y >= 0 && pos.y < size.y) + && (pos.z >= 0 && pos.z < size.z) + } + + fn get(&self, pos: impl Into) -> T { + let index = self.get_index(pos); + self.data[index] + } +} + +impl BloxelViewMut for BloxelArray { + fn set(&mut self, pos: impl Into, value: T) { + let index = self.get_index(pos); + self.data[index] = value; + } +} diff --git a/src/bloxel/storage/bloxel_view.rs b/src/bloxel/storage/bloxel_view.rs new file mode 100644 index 0000000..b0a8e71 --- /dev/null +++ b/src/bloxel/storage/bloxel_view.rs @@ -0,0 +1,28 @@ +use bevy::math::{IVec3, UVec3}; + +pub trait BloxelView { + fn size(&self) -> UVec3; + + fn contains(&self, pos: impl Into) -> bool; + + fn get(&self, pos: impl Into) -> T; +} + +pub trait BloxelViewMut: BloxelView { + fn set(&mut self, pos: impl Into, value: T); +} + +pub fn ivec3_to_index(pos: impl Into, size: UVec3) -> usize { + let pos = pos.into(); + let size = size.as_ivec3(); + (pos.x + (pos.y * size.x) + (pos.z * size.x * size.y)) as usize +} + +pub fn index_to_ivec3(index: usize, size: UVec3) -> IVec3 { + let size = size.as_ivec3(); + let i = index as i32; + let x = i % size.x; + let y = i / size.x % size.y; + let z = i / size.x / size.y; + IVec3::new(x, y, z) +} diff --git a/src/bloxel/storage/chunked_octree.rs b/src/bloxel/storage/chunked_octree.rs new file mode 100644 index 0000000..8ecb62f --- /dev/null +++ b/src/bloxel/storage/chunked_octree.rs @@ -0,0 +1,375 @@ +use std::{array::from_fn, collections::BinaryHeap}; + +use bevy::{ + math::IVec3, + utils::{HashMap, HashSet}, +}; + +use crate::bloxel::math::{zorder, ChunkPos, ChunkRegion, ZOrderIndex}; + +const START_INDEX_LOOKUP: [usize; 11] = [ + 0, 1, 9, 73, 585, 4681, 37449, 299593, 2396745, 19173961, 153391689, +]; + +pub struct ChunkedOctree { + depth: usize, + regions: HashMap>, +} + +impl ChunkedOctree { + pub fn new(depth: usize) -> Self { + assert!(depth > 0 && depth < START_INDEX_LOOKUP.len()); + Self { + depth, + regions: Default::default(), + } + } + + pub fn get(&self, node: impl TryInto) -> T { + if let Ok(node) = node.try_into() { + if node.level <= self.depth { + return self + .regions + .get(&(node.pos >> (self.depth - node.level))) + .map(|region| region[node.index(self.depth)]) + .unwrap_or_default(); + } + } + Default::default() + } + + pub fn update(&mut self, chunk_pos: ChunkPos, update_fn: F) + where + F: Fn(OctreeNode, Option<&[T; 8]>, &mut T), + { + let pos: ZOrderIndex = chunk_pos.try_into().unwrap(); + let region = self.regions.entry(pos >> self.depth).or_insert_with(|| { + let size = START_INDEX_LOOKUP[self.depth + 1] + 1; + vec![Default::default(); size] + }); + + let mut node = OctreeNode::new(0, pos); + while node.level <= self.depth { + let parent_index = node.index(self.depth); + let (parent, children) = if let Some(children_index) = node.children_index(self.depth) { + let (left, right) = region.split_at_mut(children_index); + let parent = &mut left[parent_index]; + let children = right[0..8].try_into().unwrap(); + (parent, Some(children)) + } else { + let parent = &mut region[parent_index]; + (parent, None) + }; + + let previous = *parent; + update_fn(node, children, parent); + if *parent == previous { + break; // If no change was made, we don't have anything to propagate. + } + + node = node.parent(); + } + } + + pub fn find<'a, W, F>( + &'a self, + from: impl IntoIterator, + priority_fn: F, + ) -> OctreeIterator<'a, T, W, F> + where + W: Ord, + F: Fn(OctreeNode, T) -> Option, + { + OctreeIterator::new(self, from, priority_fn) + } +} + +pub struct OctreeIterator<'a, T, P, F> +where + T: Default + Copy + Eq, + P: Ord, + F: Fn(OctreeNode, T) -> Option

, +{ + octree: &'a ChunkedOctree, + checked: HashSet, + queue: BinaryHeap>, + priority_fn: F, +} + +impl<'a, T, P, F> OctreeIterator<'a, T, P, F> +where + T: Default + Copy + Eq, + P: Ord, + F: Fn(OctreeNode, T) -> Option

, +{ + fn new( + octree: &'a ChunkedOctree, + from: impl IntoIterator, + priority_fn: F, + ) -> Self { + let mut result = Self { + octree, + checked: Default::default(), + queue: Default::default(), + priority_fn, + }; + for pos in from { + let node_pos: ZOrderIndex = (*pos).try_into().unwrap(); + result.search_region(node_pos >> octree.depth); + } + result + } + + fn search_region(&mut self, region_pos: ZOrderIndex) { + if self.checked.insert(region_pos) { + self.push_item((self.octree.depth, region_pos).into()); + } + } + + fn push_item(&mut self, node: OctreeNode) { + let value = self.octree.get(node); + if let Some(priority) = (self.priority_fn)(node, value) { + self.queue.push(PriorityItem { + priority, + node, + value, + }); + } + } +} + +impl<'a, T, P, F> Iterator for OctreeIterator<'a, T, P, F> +where + T: Default + Copy + Eq, + P: Ord, + F: Fn(OctreeNode, T) -> Option

, +{ + type Item = (ChunkPos, T, P); + + fn next(&mut self) -> Option { + loop { + let PriorityItem { + priority, + node, + value, + } = self.queue.pop()?; + + if node.level == self.octree.depth { + // If the current highest priority item is a region, see if its + // neighboring regions are candidates to consider as well. + // NOTE: Faulty `priority_fn` could cause this to loop forever. + + // Add all the region's neighbors to the priority queue. + // NOTE: `search_region` skips any already added regions. + for neighbor in node.neighbors() { + self.search_region(neighbor.pos); + } + } + + if let Some(children) = node.children() { + // If current highest priority node has children, + // add them to the priority queue and continue. + for child in children { + self.push_item(child); + } + } else { + // If there are no children, then we're at `ChunkPos` level. + // Return this chunk as the highest priority item found. + let chunk_pos = node.pos.into(); + return Some((chunk_pos, value, priority)); + } + } + } +} + +#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct OctreeNode { + pub level: usize, + pub pos: ZOrderIndex, +} + +impl OctreeNode { + pub fn new(level: usize, pos: ZOrderIndex) -> Self { + Self { level, pos } + } + + pub fn parent(&self) -> Self { + Self::new(self.level + 1, self.pos >> 1) + } + + pub fn children(&self) -> Option<[Self; 8]> { + (self.level > 0).then(|| from_fn(|i| self.child_unchecked(i as u64))) + } + + pub fn neighbors(&self) -> [Self; 26] { + let (pos_x, pos_y, pos_z) = self.pos.into(); + let mut result = [OctreeNode::default(); 26]; + let mut index = 0; + for x in -1..1 { + for y in -1..1 { + for z in -1..1 { + if x != 0 && y != 0 && z != 0 { + let pos = zorder(pos_x + x, pos_y + y, pos_z + z); + result[index] = OctreeNode::new(self.level, pos); + index += 1; + } + } + } + } + result + } + + pub fn region(&self) -> ChunkRegion { + let min = (self.pos << self.level).into(); + let max = min + IVec3::splat((1 << self.level) - 1); + ChunkRegion::new_unchecked(min, max) + } + + fn index(&self, depth: usize) -> usize { + let local_pos = self.pos & !(!0 << ((depth - self.level) * 3)); + START_INDEX_LOOKUP[depth - self.level] + local_pos.raw() as usize + } + + fn children_index(&self, depth: usize) -> Option { + (self.level > 0).then(|| self.child_unchecked(0).index(depth)) + } + + /// Returns the child of this node with the specified index (within `0..8`). + /// No safety checks are done to ensure that `level` or `index` are valid. + fn child_unchecked(&self, index: u64) -> Self { + Self::new(self.level - 1, (self.pos << 1) | index) + } +} + +impl Into for (usize, ZOrderIndex) { + fn into(self) -> OctreeNode { + OctreeNode::new(self.0, self.1) + } +} + +impl TryInto for ChunkPos { + type Error = (); + fn try_into(self) -> Result { + Ok(OctreeNode::new(0, self.try_into()?)) + } +} + +impl TryInto for (i32, i32, i32) { + type Error = (); + fn try_into(self) -> Result { + Into::::into(self).try_into() + } +} + +struct PriorityItem { + priority: P, + node: OctreeNode, + value: T, +} + +impl Eq for PriorityItem {} + +impl PartialEq for PriorityItem { + fn eq(&self, other: &Self) -> bool { + self.priority.eq(&other.priority) + } +} + +impl Ord for PriorityItem { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.priority.cmp(&other.priority) + } +} + +impl PartialOrd for PriorityItem { + fn partial_cmp(&self, other: &Self) -> Option { + self.priority.partial_cmp(&other.priority) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn update() { + let mut octree = ChunkedOctree::::new(3); + + assert_eq!(false, octree.get((0, 0, 0))); + assert_eq!(false, octree.get((1, 1, 1))); + assert_eq!(false, octree.get((-1, -1, -1))); + + octree.update((0, 0, 0).into(), |_, _, parent| *parent = true); + assert_eq!(true, octree.get((0, 0, 0))); + + assert_eq!(true, octree.get((0, zorder(0, 0, 0)))); + assert_eq!(true, octree.get((1, zorder(0, 0, 0)))); + assert_eq!(true, octree.get((2, zorder(0, 0, 0)))); + assert_eq!(true, octree.get((3, zorder(0, 0, 0)))); + + assert_eq!(false, octree.get((0, zorder(1, 1, 1)))); + assert_eq!(false, octree.get((1, zorder(2, 2, 2)))); + assert_eq!(false, octree.get((2, zorder(4, 4, 4)))); + assert_eq!(false, octree.get((3, zorder(8, 8, 8)))); + + assert_eq!(false, octree.get((0, zorder(-1, -1, -1)))); + assert_eq!(false, octree.get((1, zorder(-1, -1, -1)))); + assert_eq!(false, octree.get((2, zorder(-1, -1, -1)))); + assert_eq!(false, octree.get((3, zorder(-1, -1, -1)))); + + octree.update(ChunkPos::new(-12, -17, -42), |_, _, parent| *parent = true); + assert_eq!(true, octree.get((-12, -17, -42))); + + assert_eq!(true, octree.get((0, zorder(-12, -17, -42)))); + assert_eq!(true, octree.get((1, zorder(-6, -9, -21)))); + assert_eq!(true, octree.get((2, zorder(-3, -5, -11)))); + assert_eq!(true, octree.get((3, zorder(-2, -3, -6)))); + } + + #[test] + #[rustfmt::skip] + fn find() { + let mut octree = ChunkedOctree::::new(3); + octree.update(( 2, 3, 4).into(), |_, _, parent| *parent = true); + octree.update((10, 10, 10).into(), |_, _, parent| *parent = true); + octree.update(( 8, 8, 8).into(), |_, _, parent| *parent = true); + octree.update(( 0, 16, -1).into(), |_, _, parent| *parent = true); + octree.update(( 9, 9, 9).into(), |_, _, parent| *parent = true); + + let from = ChunkPos::new(8, 8, 8); + let mut iterator = octree.find([&from], |node, value| { + value.then(|| -node.region().distance_to_squared(from)) + }); + + assert_eq!(Some((( 8, 8, 8).into(), true, -(0*0 + 0*0 + 0*0))), iterator.next()); + assert_eq!(Some((( 9, 9, 9).into(), true, -(1*1 + 1*1 + 1*1))), iterator.next()); + assert_eq!(Some(((10, 10, 10).into(), true, -(2*2 + 2*2 + 2*2))), iterator.next()); + assert_eq!(Some((( 2, 3, 4).into(), true, -(6*6 + 5*5 + 4*4))), iterator.next()); + assert_eq!(Some((( 0, 16, -1).into(), true, -(8*8 + 8*8 + 9*9))), iterator.next()); + assert_eq!(None, iterator.next()); + } + + #[test] + fn node_region() { + let chunk = |a: (i32, i32, i32), b: (i32, i32, i32)| -> ChunkRegion { + ChunkRegion::new(a.into(), b.into()) + }; + let node = |level: usize, pos: (i32, i32, i32)| -> ChunkRegion { + OctreeNode::new(level, pos.try_into().unwrap()).region() + }; + + assert_eq!(chunk((0, 0, 0), (0, 0, 0)), node(0, (0, 0, 0))); + assert_eq!(chunk((0, 0, 0), (1, 1, 1)), node(1, (0, 0, 0))); + assert_eq!(chunk((0, 0, 0), (3, 3, 3)), node(2, (0, 0, 0))); + assert_eq!(chunk((0, 0, 0), (7, 7, 7)), node(3, (0, 0, 0))); + + assert_eq!(chunk((-1, -1, -1), (-1, -1, -1)), node(0, (-1, -1, -1))); + assert_eq!(chunk((-2, -2, -2), (-1, -1, -1)), node(1, (-1, -1, -1))); + assert_eq!(chunk((-4, -4, -4), (-1, -1, -1)), node(2, (-1, -1, -1))); + assert_eq!(chunk((-8, -8, -8), (-1, -1, -1)), node(3, (-1, -1, -1))); + + assert_eq!(chunk((2, -3, -4), (2, -3, -4)), node(0, (2, -3, -4))); + assert_eq!(chunk((4, -6, -8), (5, -5, -7)), node(1, (2, -3, -4))); + assert_eq!(chunk((8, -12, -16), (11, -9, -13)), node(2, (2, -3, -4))); + } +} diff --git a/src/bloxel/storage/mod.rs b/src/bloxel/storage/mod.rs new file mode 100644 index 0000000..d561cc6 --- /dev/null +++ b/src/bloxel/storage/mod.rs @@ -0,0 +1,10 @@ +mod bloxel_array; +mod bloxel_view; +mod chunked_octree; +mod palette_bloxel_storage; +mod palette_storage; + +pub use bloxel_array::*; +pub use bloxel_view::*; +pub use chunked_octree::*; +pub use palette_bloxel_storage::*; diff --git a/src/bloxel/storage/palette_bloxel_storage.rs b/src/bloxel/storage/palette_bloxel_storage.rs new file mode 100644 index 0000000..8ffc2e1 --- /dev/null +++ b/src/bloxel/storage/palette_bloxel_storage.rs @@ -0,0 +1,63 @@ +use bevy::math::{IVec3, UVec3}; + +use super::{ + bloxel_view::{ivec3_to_index, BloxelView, BloxelViewMut}, + palette_storage::PaletteStorage, +}; + +pub struct PaletteBloxelStorage { + size: UVec3, + data: PaletteStorage, +} + +impl PaletteBloxelStorage { + pub fn new(size: UVec3, fill: T) -> Self { + assert!(size.x > 0 && size.y > 0 && size.z > 0); + let len = (size.x * size.y * size.z).try_into().unwrap(); + let data = PaletteStorage::new(len, fill); + Self { size, data } + } + + pub fn new_with_default(size: UVec3) -> Self + where + T: Default, + { + Self::new(size, Default::default()) + } + + pub fn get_used_count(&self, value: T) -> usize { + self.data.get_used_count(value) + } + + fn get_index(&self, pos: impl Into) -> usize { + let pos = pos.into(); + assert!(self.contains(pos)); + ivec3_to_index(pos, self.size) + } +} + +impl BloxelView for PaletteBloxelStorage { + fn size(&self) -> UVec3 { + self.size + } + + fn contains(&self, pos: impl Into) -> bool { + let pos = pos.into(); + let size = self.size.as_ivec3(); + (pos.x >= 0 && pos.x < size.x) + && (pos.y >= 0 && pos.y < size.y) + && (pos.z >= 0 && pos.z < size.z) + } + + fn get(&self, pos: impl Into) -> T { + let index = self.get_index(pos); + self.data.get(index) + } +} + +impl BloxelViewMut for PaletteBloxelStorage { + fn set(&mut self, pos: impl Into, value: T) { + let index = self.get_index(pos); + self.data.set(index, value); + } +} diff --git a/src/bloxel/storage/palette_storage.rs b/src/bloxel/storage/palette_storage.rs new file mode 100644 index 0000000..85e8531 --- /dev/null +++ b/src/bloxel/storage/palette_storage.rs @@ -0,0 +1,213 @@ +use bitvec::prelude::*; + +pub struct PaletteStorage { + len: usize, + bits: usize, + data: BitVec, + entries: Vec>, +} + +impl PaletteStorage { + pub fn new(len: usize, fill: T) -> Self { + Self { + len, + bits: 0, + data: bitvec![], + entries: vec![PaletteEntry { + value: Some(fill), + used: len, + }], + } + } + + pub fn new_with_default(len: usize) -> Self + where + T: Default, + { + Self::new(len, Default::default()) + } + + /// Gets the length of this `PaletteStorage`. That is, how many + /// elements can be accessed via the `get` and `set` functions. + pub fn len(&self) -> usize { + self.len + } + + /// Gets the number of bits each element takes up when stored. + /// + /// More bits means more palette entries can be stored, so more unique + /// values can be stored in this `PaletteStorage`, at the cost of more + /// memory. This will automatically increase as necessary. + pub fn bits(&self) -> usize { + self.bits + } + + /// Gets the number of times the specific value occurs in this `PaletteStorage`. + pub fn get_used_count(&self, value: T) -> usize { + self.find_existing_entry(value).map(|e| e.used).unwrap_or(0) + } + + pub fn get(&self, index: usize) -> T { + let palette_index = self.get_palette_index(index); + let entry = &self.entries[palette_index]; + entry.value.expect("invalid palette entry") + } + + pub fn set(&mut self, index: usize, value: T) -> T { + let prev_palette_index = self.get_palette_index(index); + let prev_entry = &mut self.entries[prev_palette_index]; + let prev_value = prev_entry.value.expect("invalid palette entry"); + + // If entry found at `index` already has this value, return early. + if prev_value == value { + return value; + } + + // Reduce the number of times the previously used palette for this + // `index` is in use. This potentially allows this entry to be reused. + prev_entry.used -= 1; + + // Find a palette entry for this value. Resizes palette if necessary. + let (new_palette_index, new_entry) = self.find_or_create_entry(value); + // increase the number of times it's in use + new_entry.used += 1; + + // Update the palette index in the actual `data` BitVec. + self.set_palette_index(index, new_palette_index); + + prev_value + } + + /// Gets the bit range into `data` for the specified index. + fn bit_range(&self, index: usize) -> std::ops::Range { + (index * self.bits)..((index + 1) * self.bits) + } + + /// Looks up the palette index (into `entries`) at the specified index. + fn get_palette_index(&self, index: usize) -> usize { + if self.bits > 0 { + let bit_range = self.bit_range(index); + self.data[bit_range].load() + } else { + 0 + } + } + + fn set_palette_index(&mut self, index: usize, value: usize) { + let bit_range = self.bit_range(index); + self.data[bit_range].store(value) + } + + fn find_existing_entry(&self, value: T) -> Option<&PaletteEntry> { + self.entries.iter().find(|e| e.value == Some(value)) + } + + fn find_or_create_entry(&mut self, value: T) -> (usize, &mut PaletteEntry) { + match self.find_entry_index(value) { + // The palette entry already exists, so just return it. + FindResult::Existing(index) => { + let entry = &mut self.entries[index]; + (index, entry) + } + // The entry didn't exist, but we found one we can reuse. + FindResult::Uninitialized(index) | FindResult::Unused(index) => { + let entry = &mut self.entries[index]; + entry.value = Some(value); + (index, entry) + } + // Everything in the palette is already in use. RESIZE! + FindResult::None => { + let index = self.entries.len(); + self.resize_palette(self.bits + 1); + let entry = &mut self.entries[index]; + entry.value = Some(value); + (index, entry) + } + } + } + + fn find_entry_index(&self, value: T) -> FindResult { + let mut result = FindResult::None; + for (index, entry) in self.entries.iter().enumerate() { + match entry { + // If the specified value is found in the palette, return it immediately. + PaletteEntry { value: v, .. } if *v == Some(value) => { + return FindResult::Existing(index) + } + // Store the first uninitialized entry in case we don't find the specified value. + PaletteEntry { value: None, .. } => match result { + FindResult::Existing(_) => unreachable!(), + FindResult::Uninitialized(_) => {} + _ => result = FindResult::Uninitialized(index), + }, + // Otherwise, pick the first initialized entry that's currently used. + PaletteEntry { used: 0, .. } => match result { + FindResult::Existing(_) => unreachable!(), + FindResult::Uninitialized(_) | FindResult::Unused(_) => {} + FindResult::None => result = FindResult::Unused(index), + }, + _ => {} + } + } + result + } + + fn resize_palette(&mut self, new_bits: usize) { + if new_bits == self.bits { + return; + } + + // TODO: Revisit this to see if we can optimize it. + // Create a new data BitVec and copy the bits from the old one over. + let mut new_data = BitVec::with_capacity(self.len * new_bits); + if new_bits == 0 { + // Nothing to do if we have nothing to copy to. + } else if self.bits == 0 { + // No data to copy from, so just fill with zeroes. + new_data.resize(self.len * new_bits, false); + } else if new_bits > self.bits { + let additional_bits = new_bits - self.bits; + for chunk in self.data.chunks_exact(self.bits) { + new_data.extend(chunk); + for _ in 0..additional_bits { + new_data.push(false); + } + } + } else { + for chunk in self.data.chunks_exact(self.bits) { + new_data.extend(&chunk[0..new_bits]); + } + } + self.data = new_data; + self.bits = new_bits; + + // Resize the palette itself. + let num_entries = 2usize.pow(new_bits as u32); + self.entries.resize_with(num_entries, Default::default); + } +} + +enum FindResult { + Existing(usize), + Uninitialized(usize), + Unused(usize), + None, +} + +// #[derive(Default)] +struct PaletteEntry { + value: Option, + used: usize, +} + +// NOTE: For some weird reason, deriving `Default` doesn't quite do what we want +// when later calling `Vec::resize_with`, so we're manually implementing +// the trait instead. [insert confused noises here] +impl Default for PaletteEntry { + fn default() -> Self { + Self { + value: None, + used: 0, + } + } +} diff --git a/src/bloxel/worldgen/mod.rs b/src/bloxel/worldgen/mod.rs new file mode 100644 index 0000000..f5c7e46 --- /dev/null +++ b/src/bloxel/worldgen/mod.rs @@ -0,0 +1,91 @@ +use bevy::prelude::*; +use rand::prelude::*; + +use crate::{ + bloxel::{prelude::*, storage::ChunkedOctree}, + camera_controller::ControlledCamera, + TerrainBlocks, +}; + +pub fn create_chunks_around_camera( + mut commands: Commands, + mut octree: Local, + camera: Single<&Transform, With>, + chunk_map: Single>, +) { + let block_pos = camera.translation.as_ivec3().into(); + let (from, _) = ChunkPos::from_block_pos(block_pos); + let mut iterator = octree.find([&from], |node, generated| { + if generated != Generated::All { + let distance = node.region().distance_to_squared(from); + if distance <= 6 * 6 { + return Some(-distance); + } + } + None + }); + + if let Some((chunk_pos, _, _)) = iterator.next() { + commands.entity(*chunk_map).with_child((Chunk, chunk_pos)); + octree.update(chunk_pos, |_node, children, parent| { + let children = children.map(|a| a.as_slice()).unwrap_or_default(); + *parent = if children.iter().all(|c| *c == Generated::All) { + Generated::All + } else { + Generated::Some + } + }); + } +} + +pub fn generate_terrain( + mut commands: Commands, + terrain_blocks: Option>, + chunks_without_data: Query<(Entity, &ChunkPos), (With, Without)>, +) { + let Some(terrain) = terrain_blocks else { + return; + }; + + let mut rng = rand::rng(); + let random_blocks = [terrain.grass, terrain.dirt, terrain.rock, terrain.sand]; + + for (entity, chunk_pos) in chunks_without_data.iter() { + let mut data = ChunkData::new(terrain.air); + let size = data.size().as_ivec3(); + for z in 0..size.z { + for y in 0..size.y { + for x in 0..size.x { + let relative = IVec3::new(x, y, z); + let block_pos = chunk_pos.to_block_pos(relative); + let chance = (-block_pos.y as f64 / 32.).clamp(0.001, 1.); + if rng.random_bool(chance) { + let block = *random_blocks.choose(&mut rng).unwrap(); + data.set(relative, block); + } + } + } + } + commands.entity(entity).insert(data); + } +} + +#[derive(Deref, DerefMut)] +pub struct GeneratedChunks { + octree: ChunkedOctree, +} + +impl Default for GeneratedChunks { + fn default() -> Self { + let octree = ChunkedOctree::new(5); + Self { octree } + } +} + +#[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum Generated { + #[default] + None, + Some, + All, +} diff --git a/src/camera_controller.rs b/src/camera_controller.rs new file mode 100644 index 0000000..73fcb0b --- /dev/null +++ b/src/camera_controller.rs @@ -0,0 +1,110 @@ +use bevy::{input::mouse::AccumulatedMouseMotion, prelude::*, window::CursorGrabMode}; + +const MOVEMENT_SPEED: f32 = 0.15; +const MOUSE_SENSITIVITY: Vec2 = Vec2::new(0.002, 0.002); + +pub struct CameraControllerPlugin; + +/// Marks an entity as being the camera controlled by this plugin. +#[derive(Component)] +pub struct ControlledCamera; + +impl Plugin for CameraControllerPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + Update, + ( + capture_mouse, + camera_mouse_rotation, + camera_keyboard_translation, + ) + .chain(), + ); + } +} + +fn capture_mouse( + mut window: Single<&mut Window>, + mouse: Res>, + key: Res>, +) { + if mouse.just_pressed(MouseButton::Left) { + window.cursor_options.visible = false; + window.cursor_options.grab_mode = CursorGrabMode::Locked; + } + + if key.just_pressed(KeyCode::Escape) { + window.cursor_options.visible = true; + window.cursor_options.grab_mode = CursorGrabMode::None; + } +} + +fn camera_mouse_rotation( + window: Single<&Window>, + mut camera: Query<&mut Transform, With>, + mouse_motion: Res, +) { + // Mouse must be grabbed by the window for this system to run. + if window.cursor_options.grab_mode != CursorGrabMode::Locked { + return; + } + + // We also need to have exactly one camera with the `ControlledCamera` component. + let Ok(mut transform) = camera.get_single_mut() else { + return; + }; + + let delta = mouse_motion.delta; + if delta != Vec2::ZERO { + let delta_yaw = -delta.x * MOUSE_SENSITIVITY.x; + let delta_pitch = -delta.y * MOUSE_SENSITIVITY.y; + + let rot_yaw = Quat::from_axis_angle(Vec3::Y, delta_yaw); + let rot_pitch = Quat::from_axis_angle(Vec3::X, delta_pitch); + transform.rotation = rot_yaw * transform.rotation * rot_pitch; + } +} + +fn camera_keyboard_translation( + window: Single<&Window>, + mut camera: Query<&mut Transform, With>, + key: Res>, +) { + // Mouse must be grabbed by the window for this system to run. + if window.cursor_options.grab_mode != CursorGrabMode::Locked { + return; + } + + // We also need to have exactly one camera with the `ControlledCamera` component. + let Ok(mut transform) = camera.get_single_mut() else { + return; + }; + + let mut input = Vec2::ZERO; + if key.pressed(KeyCode::KeyD) { + input.x += 1.; + } + if key.pressed(KeyCode::KeyA) { + input.x -= 1.; + } + if key.pressed(KeyCode::KeyW) { + input.y += 1.; + } + if key.pressed(KeyCode::KeyS) { + input.y -= 1.; + } + + let mut movement = input * MOVEMENT_SPEED; + if key.pressed(KeyCode::ShiftLeft) { + movement *= 4.; + } + + if movement.x != 0. { + let translation = transform.right() * movement.x; + transform.translation += translation; + } + if movement.y != 0. { + let translation = transform.forward() * movement.y; + transform.translation += translation; + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4feeeb2 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,145 @@ +use bevy::{asset::LoadedFolder, prelude::*}; + +mod bloxel; +mod camera_controller; + +use bloxel::block::BlockTexture; +use bloxel::prelude::*; +use camera_controller::{CameraControllerPlugin, ControlledCamera}; + +#[derive(Resource)] +pub struct TerrainTextures(Handle); + +#[derive(Resource)] +pub struct TerrainAtlas { + pub layout: Handle, + pub sources: TextureAtlasSources, + pub texture: Handle, +} + +#[derive(Resource)] +pub struct TerrainMaterial(Handle); + +#[derive(Resource)] +pub struct TerrainBlocks { + air: Entity, + grass: Entity, + dirt: Entity, + rock: Entity, + sand: Entity, +} + +fn main() { + App::new() + .add_plugins(( + DefaultPlugins.set(ImagePlugin::default_nearest()), + CameraControllerPlugin, + BloxelPlugin, + )) + .add_systems( + Startup, + ( + setup_sunlight, + setup_camera, + setup_terrain_blocks, + load_terrain_textures, + generate_sample_chunks, + ), + ) + .add_systems(Update, check_terrain_textures) + .run(); +} + +fn setup_terrain_blocks(mut commands: Commands, asset_server: Res) { + let air = commands.spawn((Block, Name::new("air"))).id(); + + let mut block = |name: &'static str, texture: &str| -> Entity { + let path = format!("terrain/{texture}.png"); + let texture = BlockTexture(asset_server.load(path)); + commands.spawn((Block, Name::new(name), texture)).id() + }; + + let blocks = TerrainBlocks { + air, + grass: block("grass", "grass_top"), + dirt: block("dirt", "dirt"), + rock: block("rock", "rock"), + sand: block("sand", "sand"), + }; + + commands.insert_resource(blocks); +} + +fn load_terrain_textures(mut commands: Commands, asset_server: Res) { + commands.insert_resource(TerrainTextures(asset_server.load_folder("terrain"))); +} + +/// Waits for all textures in `assets/terrain/` to be loaded, then builds an atlas +/// from those along with the [`TerrainMaterial`] and [`TerrainAtlas`] resources. +fn check_terrain_textures( + mut commands: Commands, + mut events: EventReader>, + terrain_textures: Res, + loaded_folders: Res>, + mut textures: ResMut>, + mut materials: ResMut>, + mut atlas_layouts: ResMut>, +) { + for event in events.read() { + if event.is_loaded_with_dependencies(&terrain_textures.0) { + let mut atlas_builder = TextureAtlasBuilder::default(); + + let folder = loaded_folders.get(&terrain_textures.0).unwrap(); + for handle in folder.handles.iter() { + let id = handle.id().typed_unchecked::(); + let Some(texture) = textures.get(id) else { + warn!( + "{:?} did not resolve to an `Image` asset.", + handle.path().unwrap() + ); + continue; + }; + atlas_builder.add_texture(Some(id), texture); + } + + let (layout, sources, texture) = atlas_builder.build().unwrap(); + let layout = atlas_layouts.add(layout); + let texture = textures.add(texture); + let material = materials.add(texture.clone()); + + commands.insert_resource(TerrainMaterial(material)); + + commands.insert_resource(TerrainAtlas { + layout, + sources, + texture, + }); + } + } +} + +fn generate_sample_chunks(mut commands: Commands) { + commands.spawn(ChunkMap::default()).with_children(|map| { + // map.spawn((Chunk, ChunkPos::new(0, 0, 0))); + // map.spawn((Chunk, ChunkPos::new(1, 0, 0))); + // map.spawn((Chunk, ChunkPos::new(-1, 0, 0))); + }); +} + +fn setup_sunlight(mut commands: Commands) { + commands.spawn(( + DirectionalLight { + shadows_enabled: true, + ..default() + }, + Transform::from_xyz(4., 8., 4.).looking_at(Vec3::ZERO, Vec3::Y), + )); +} + +fn setup_camera(mut commands: Commands) { + commands.spawn(( + ControlledCamera, + Camera3d::default(), + Transform::from_xyz(-24., 16., 16.).looking_at((0., 0., 0.).into(), Vec3::Y), + )); +}