From b5ced3af46c96ceb959fbbf1addfeba3bd4f76d5 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Wed, 15 Apr 2026 16:53:58 -0400 Subject: first commit. working body rendering --- .gitignore | 1 + Cargo.lock | 3550 +++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 20 + Makefile | 7 + assets/shaders/canvas.wgsl | 32 + assets/shaders/tacbody.wgsl | 79 + assets/systems/sol.csv | 3 + rust-toolchain.toml | 2 + shell.nix | 52 + src/canvas.rs | 176 +++ src/eguictx.rs | 143 ++ src/known_stars.rs | 24 + src/main.rs | 178 +++ src/solar_system.rs | 161 ++ src/tacmap.rs | 158 ++ src/tacmap/camera.rs | 272 ++++ src/tacmap/render.rs | 233 +++ src/texture.rs | 96 ++ src/timeman.rs | 69 + src/vertex.rs | 33 + src/wgpuctx/mod.rs | 245 +++ src/wgpuctx/pipeline.rs | 121 ++ src/window.rs | 148 ++ src/window/ui.rs | 96 ++ 24 files changed, 5899 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 assets/shaders/canvas.wgsl create mode 100644 assets/shaders/tacbody.wgsl create mode 100644 assets/systems/sol.csv create mode 100644 rust-toolchain.toml create mode 100644 shell.nix create mode 100644 src/canvas.rs create mode 100644 src/eguictx.rs create mode 100644 src/known_stars.rs create mode 100644 src/main.rs create mode 100644 src/solar_system.rs create mode 100644 src/tacmap.rs create mode 100644 src/tacmap/camera.rs create mode 100644 src/tacmap/render.rs create mode 100644 src/texture.rs create mode 100644 src/timeman.rs create mode 100644 src/vertex.rs create mode 100644 src/wgpuctx/mod.rs create mode 100644 src/wgpuctx/pipeline.rs create mode 100644 src/window.rs create mode 100644 src/window/ui.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f18c765 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3550 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[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.11.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "approx" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arboard" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" +dependencies = [ + "clipboard-win", + "image", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "windows-sys 0.60.2", + "x11rb", +] + +[[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 = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.11.0", + "polling", + "rustix 1.1.4", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.4", + "rustix 1.1.4", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgmath" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" +dependencies = [ + "approx", + "num-traits", +] + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +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 0.1.3", + "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 = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "ecolor" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "egui" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" +dependencies = [ + "ahash", + "bitflags 2.11.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "egui-wgpu" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "epaint", + "log", + "profiling", + "thiserror 2.0.18", + "type-map", + "web-time", + "wgpu", + "winit", +] + +[[package]] +name = "egui-winit" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" +dependencies = [ + "arboard", + "bytemuck", + "egui", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "profiling", + "raw-window-handle", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] + +[[package]] +name = "emath" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "env_filter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "epaint" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009d0dd3c2163823a0abdb899451ecbc78798dec545ee91b43aff1fa790bab62" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "log", + "nohash-hasher", + "parking_lot", + "profiling", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fbe202b6578d3d56428fa185cdf114a05e49da05f477b3c7f0fbb221f1862" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[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 = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.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.11.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "tiff", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jiff" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819b44bc7c87d9117eb522f14d46e918add69ff12713c475946b0a29363ed1c2" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "470252db18ecc35fd766c0891b1e3ec6cbbcd62507e85276c01bf75d8e94d4a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +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 = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +dependencies = [ + "bitflags 2.11.0", + "libc", + "plain", + "redox_syscall 0.7.3", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "metal" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" +dependencies = [ + "bitflags 2.11.0", + "block", + "core-graphics-types 0.2.0", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.18", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.11.0", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-graphics", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.11.0", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "orbclient" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ad2c6bae700b7aa5d1cc30c59bdd3a1c180b09dbaea51e2ae2b8e1cf211fdd" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + +[[package]] +name = "pxfm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[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.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.19.2", + "tiny-skia", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.14.4", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[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.11.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "stringreader" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913e7b03d63752f6cdd2df77da36749d82669904798fe8944b9ec3d23f159905" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "systemic4x" +version = "0.1.0" +dependencies = [ + "bytemuck", + "cgmath", + "csv", + "egui", + "egui-wgpu", + "egui-winit", + "env_logger", + "log", + "phf", + "pollster", + "serde", + "stringreader", + "wgpu", + "winit", +] + +[[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 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" +dependencies = [ + "rustc-hash 2.1.1", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[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 = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" +dependencies = [ + "bitflags 2.11.0", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.11.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +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 = "webbrowser" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" +dependencies = [ + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wgpu" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" +dependencies = [ + "arrayvec", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.11.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.18", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "27.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.0", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types 0.2.0", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.18", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-types" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "js-sys", + "log", + "thiserror 2.0.18", + "web-sys", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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.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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.11.0", + "block2", + "bytemuck", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.19.2", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.11.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.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..95edc86 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "systemic4x" +version = "0.1.0" +edition = "2024" + +[dependencies] +bytemuck = { version = "1.25.0", features = ["derive"]} +cgmath = "0.18.0" +csv = "1.4.0" +egui = "0.33.3" +egui-wgpu = { version = "0.33.3", features = [ "winit" ]} +egui-winit = "0.33.3" +env_logger = "0.11.8" +log = "0.4.29" +phf = { version = "0.13.1", features = ["macros"]} +pollster = "0.4.0" +serde = { version = "1.0.228", features = ["derive"]} +stringreader = "0.1.1" +wgpu = "27.0.1" +winit = { version = "0.30.12", features = ["wayland"]} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4967214 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: run + +run: + cargo run + +build: + cargo build diff --git a/assets/shaders/canvas.wgsl b/assets/shaders/canvas.wgsl new file mode 100644 index 0000000..3be1a77 --- /dev/null +++ b/assets/shaders/canvas.wgsl @@ -0,0 +1,32 @@ +struct VertexInput { + @location(0) position: vec3, + @location(1) uv: vec2 +}; + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) uv: vec2 +}; + +@vertex +fn vs_main( + model: VertexInput, +) -> VertexOutput { + var out: VertexOutput; + + out.clip_position = vec4(model.position, 1.0); + out.uv = model.uv; + + return out; +} + +@group(0) @binding(0) +var canvas_texture: texture_2d; +@group(0) @binding(1) +var canvas_sampler: sampler; + +@fragment +fn fs_main(in: VertexOutput +) -> @location(0) vec4 { + return textureSample(canvas_texture, canvas_sampler, in.uv); +} diff --git a/assets/shaders/tacbody.wgsl b/assets/shaders/tacbody.wgsl new file mode 100644 index 0000000..e8fb653 --- /dev/null +++ b/assets/shaders/tacbody.wgsl @@ -0,0 +1,79 @@ +struct VertexInput { + @location(0) position: vec3 +}; + +struct InstanceInput { + @location(2) position: vec3, + @location(3) radius: f32 +}; + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) local_position: vec3 +}; + +struct CameraUniform { + view: mat4x4, + proj: mat4x4, + scale: f32 +}; + +@group(0) @binding(0) +var camera: CameraUniform; + +@vertex +fn vs_main( + model: VertexInput, + instance: InstanceInput +) -> VertexOutput { + var out: VertexOutput; + + var view = camera.view; + + //Billboard the circle + view[0][0] = 1.0; + view[0][1] = 0.0; + view[0][2] = 0.0; + + view[1][0] = 0.0; + view[1][1] = 1.0; + view[1][2] = 0.0; + + view[2][0] = 0.0; + view[2][1] = 0.0; + view[2][2] = 1.0; + + let min_size = 0.025; + + //Scale the world around the camera scale. + let model_pos = model.position; + let instance_pos = instance.position * camera.scale; + + let view_proj = camera.proj * view; + + let center_view_pos = view_proj * vec4(instance_pos, 1.0); + let vertex_view_pos = view_proj * vec4(instance_pos + (model_pos * camera.scale), 1.0); + + let vertex_dist = length(vertex_view_pos - center_view_pos) / center_view_pos.w; + if vertex_dist < min_size { + out.clip_position = center_view_pos / center_view_pos.w; + out.clip_position += camera.proj * vec4(model_pos.xy * (min_size / 2), 0.0, 0.0); + }else{ + out.clip_position = vertex_view_pos; + } + + out.local_position = model.position; + + return out; +} + +@fragment +fn fs_main(in: VertexOutput +) -> @location(0) vec4 { + let point_dist = length(in.local_position); + var alpha = 1.0; + if point_dist > 1.0 { + alpha = 0.0; + } + return vec4(1.0, 1.0, 1.0, alpha); +} diff --git a/assets/systems/sol.csv b/assets/systems/sol.csv new file mode 100644 index 0000000..81fc14c --- /dev/null +++ b/assets/systems/sol.csv @@ -0,0 +1,3 @@ +name,orbits,mass,radius,eccentricity,inclination,long_asc_node,long_periapsis,sgp,mean_long,semi_major_axis +Sol,0,1.988475e30,695700.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +Earth,0,5.97217e24,6371.0,0.0167,0.1249,-0.1965,1.7966,3.986e14,1.7534,149598023 diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..292fe49 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..1ae9742 --- /dev/null +++ b/shell.nix @@ -0,0 +1,52 @@ +{ pkgs ? import {} }: +let + overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml)); + libPath = with pkgs; lib.makeLibraryPath [ + libGL + libxkbcommon + wayland + vulkan-loader + ]; +in { + devShell = with pkgs; mkShell { + nativeBuildInputs = [ + pkg-config + ]; + buildInputs = [ + clang + llvmPackages.bintools + rustup + rust-analyzer + ]; + + RUSTC_VERSION = overrides.toolchain.channel; + LIBCLANG_PATH = lib.makeLibraryPath [ llvmPackages_latest.libclang.lib ]; + + shellHook = '' + export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin + export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/ + ''; + + # Add precompiled library to rustc search path + RUSTFLAGS = (builtins.map (a: ''-L ${a}/lib'') [ + + ]); + + # Add glibc, clang, glib, and other headers to bindgen search path + BINDGEN_EXTRA_CLANG_ARGS = + # Includes normal include path + (builtins.map (a: ''-I"${a}/include"'') [ + # add dev libraries here (e.g. pkgs.libvmi.dev) + pkgs.glibc.dev + ]) + # Includes with special directory paths + ++ [ + ''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"'' + ''-I"${pkgs.glib.dev}/include/glib-2.0"'' + ''-I${pkgs.glib.out}/lib/glib-2.0/include/'' + ]; + + # RUST_LOG="debug"; + LD_LIBRARY_PATH=libPath; + }; +} diff --git a/src/canvas.rs b/src/canvas.rs new file mode 100644 index 0000000..dbcac7f --- /dev/null +++ b/src/canvas.rs @@ -0,0 +1,176 @@ +use wgpu::RenderPipeline; + +use crate::wgpuctx::WgpuCtx; +use crate::texture::Texture; +use crate::vertex::Vertex; +use crate::wgpuctx::pipeline::RenderPipelineBuilder; + +struct CanvasTexture +{ + pub texture: Texture, + buffer: wgpu::Buffer +} + +pub struct Canvas +{ + pipeline: wgpu::RenderPipeline, + vertex_buffer: wgpu::Buffer, + texture: CanvasTexture, + + position: winit::dpi::LogicalPosition, + size: winit::dpi::LogicalSize +} + +impl Canvas +{ + fn create_canvas_texture( + wgpuctx: &WgpuCtx, + canvas_size: winit::dpi::LogicalSize, + window_size: winit::dpi::PhysicalSize) + -> CanvasTexture + { + let canvas_physical_size = winit::dpi::PhysicalSize::::new( + (window_size.width as f32 * canvas_size.width).floor() as u32, + (window_size.height as f32 * canvas_size.height).floor() as u32 + ); + + CanvasTexture::new(wgpuctx, canvas_physical_size) + } + + pub fn new( + wgpuctx: &WgpuCtx, + window_size: winit::dpi::PhysicalSize, + position: winit::dpi::LogicalPosition, + size: winit::dpi::LogicalSize + ) -> Result { + + let pos_x = position.x * 2.0 - 1.0; + let pos_y = position.y * 2.0 - 1.0; + let size_x = size.width * 2.0; + let size_y = size.height * 2.0; + + let vertices: &[Vertex] = &[ + Vertex { position: [ pos_x, pos_y, 0.0 ], uv: [ 0.0, 1.0 ] }, + Vertex { position: [ pos_x+size_x, pos_y, 0.0 ], uv: [ 1.0, 1.0 ] }, + Vertex { position: [ pos_x+size_x, pos_y+size_y, 0.0 ], uv: [ 1.0, 0.0 ] }, + Vertex { position: [ pos_x+size_x, pos_y+size_y, 0.0 ], uv: [ 1.0, 0.0 ] }, + Vertex { position: [ pos_x, pos_y+size_y, 0.0 ], uv: [ 0.0, 0.0 ] }, + Vertex { position: [ pos_x, pos_y, 0.0 ], uv: [ 0.0, 1.0 ] }, + ]; + + let vertex_buffer = wgpuctx.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertices), + usage: wgpu::BufferUsages::VERTEX + } + ); + + let shader = wgpuctx.create_shader( + wgpu::include_wgsl!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/shaders/canvas.wgsl") + )); + + let canvas_texture = Canvas::create_canvas_texture(wgpuctx, size, window_size); + + let render_pipeline = RenderPipelineBuilder::new( + &shader) + .add_bindgroup(&canvas_texture.texture.bindgrouplayout) + .add_vertex_layout(Vertex::descr()) + .build(Some("Canvas render pipleine"), wgpuctx); + + Ok(Self { + pipeline: render_pipeline, + vertex_buffer: vertex_buffer, + texture: canvas_texture, + position: position, + size: size + }) + } + + pub fn resize( + &mut self, + wgpuctx: &WgpuCtx, + width: u32, + height: u32) + { + let window_size = winit::dpi::PhysicalSize::new(width, height); + self.texture = Canvas::create_canvas_texture(wgpuctx, self.size, window_size); + } + + pub fn present( + &mut self, + screen_pass: &mut wgpu::RenderPass + ) + -> Result<(), wgpu::SurfaceError> { + + screen_pass.set_pipeline(&self.pipeline); + self.texture.texture.use_on_pass(screen_pass, 0); + screen_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); + screen_pass.draw(0..6,0..1); + Ok(()) + } + + pub fn view(&self) + -> &wgpu::TextureView + { + self.texture.texture.view() + } +} //impl Canvas + +impl CanvasTexture +{ + pub fn new( + wgpuctx: &WgpuCtx, + size: winit::dpi::PhysicalSize) + -> Self + { + let u32_size = std::mem::size_of::() as u32; + + let buffer_size = (u32_size * size.width * size.height) as wgpu::BufferAddress; + let buffer_descr = wgpu::BufferDescriptor { + size: buffer_size, + usage: wgpu::BufferUsages::COPY_DST, + label: None, + mapped_at_creation: false + }; + + let texture = wgpuctx.new_render_texture(size); + let buffer = wgpuctx.create_buffer(&buffer_descr); + + Self { + texture: texture, + buffer: buffer + } + } +} + +impl WgpuCtx +{ + pub fn new_render_texture( + &self, + size: winit::dpi::PhysicalSize) + -> Texture + { + let descr = wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width: size.width, + height: size.height, + depth_or_array_layers: 1 + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Bgra8UnormSrgb, + view_formats: &[ + wgpu::TextureFormat::Bgra8UnormSrgb + ], + usage: wgpu::TextureUsages::TEXTURE_BINDING | + wgpu::TextureUsages::COPY_SRC | + wgpu::TextureUsages::RENDER_ATTACHMENT, + label: None + }; + self.new_texture(descr) + } +} diff --git a/src/eguictx.rs b/src/eguictx.rs new file mode 100644 index 0000000..572d352 --- /dev/null +++ b/src/eguictx.rs @@ -0,0 +1,143 @@ +use egui::{Context}; +use egui_wgpu::Renderer; +use egui_winit::{EventResponse, State}; +use wgpu::{CommandEncoder, CommandEncoderDescriptor, Operations, RenderPassDescriptor, TextureView}; +use winit::{event::WindowEvent, window::{Theme, Window}}; + +use crate::wgpuctx::WgpuCtx; + + +pub struct EguiCtx { + state: State, + renderer: Renderer, + context: Context, + ready: bool +} + +impl EguiCtx +{ + pub fn new( + window: &winit::window::Window, + wgpuctx: &WgpuCtx) + -> Self { + let ctx = egui::Context::default(); + + let viewport_id = ctx.viewport_id(); + let state = egui_winit::State::new( + ctx.clone(), + viewport_id, + window, + Some(window.scale_factor() as _), + Some(Theme::Light), + None); + + let renderer = Renderer::new( + wgpuctx.device(), + wgpuctx.surface_config().format, + egui_wgpu::RendererOptions { + depth_stencil_format: None, + msaa_samples: 1, + ..Default::default() + } + ); + + Self { + context: ctx, + state: state, + renderer: renderer, + ready: false + } + } + + pub fn context(&self) -> &Context + { self.state.egui_ctx() } + + pub fn window_event( + &mut self, + window: &Window, + event: &WindowEvent) + -> EventResponse + { + self.state.on_window_event(window, event) + } + + pub fn prepare( + &mut self, + window: &Window) + { + let raw_input = self.state.take_egui_input(window); + self.context().begin_pass(raw_input); + self.ready = true; + } + + pub fn present( + &mut self, + window: &Window, + wgpuctx: &WgpuCtx, + encoder: &mut CommandEncoder, + view: &TextureView) + + { + if !self.ready { + return; + } + self.ready = false; + + let full_output = self.context().end_pass(); + self.state.handle_platform_output(window, full_output.platform_output); + + let jobs = self.context().tessellate( + full_output.shapes, + full_output.pixels_per_point + ); + + let screen_descriptor = { + let view_size = view.texture().size(); + let (width, height) = (view_size.width, view_size.height); + egui_wgpu::ScreenDescriptor { + size_in_pixels: [width, height], + pixels_per_point: full_output.pixels_per_point + } + }; + + for (id, image_delta) in full_output.textures_delta.set { + self.renderer.update_texture(wgpuctx.device(), wgpuctx.queue(), id, &image_delta); + } + + self.renderer.update_buffers( + wgpuctx.device(), + wgpuctx.queue(), + encoder, + &jobs, + &screen_descriptor + ); + + { + let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor { + label: Some("EguiCtx render pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: view, + resolve_target: None, + ops: Operations { + load: wgpu::LoadOp::Load, + store: wgpu::StoreOp::Store + }, + depth_slice: None + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None + }); + + self.renderer.render( + &mut render_pass.forget_lifetime(), + &jobs, + &screen_descriptor + ); + } + + for id in &full_output.textures_delta.free { + self.renderer.free_texture(id); + } + } +} diff --git a/src/known_stars.rs b/src/known_stars.rs new file mode 100644 index 0000000..cf78aa2 --- /dev/null +++ b/src/known_stars.rs @@ -0,0 +1,24 @@ +use phf::phf_map; +use std::fmt; +use std::error::Error; + +#[derive(Debug)] +pub struct StarNotFoundError +{ + pub star: &'static str +} + +impl fmt::Display for StarNotFoundError { + fn fmt( + &self, + f: &mut fmt::Formatter<'_>) + -> fmt::Result { + write!(f, "Star {:0} is not known!", self.star) + } +} + +impl Error for StarNotFoundError {} + +pub static KNOWN_STARS: phf::Map<&'static str, &'static str> = phf_map! { + "sol" => include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/systems/sol.csv")) +}; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b6efdcd --- /dev/null +++ b/src/main.rs @@ -0,0 +1,178 @@ +mod window; +mod tacmap; +mod wgpuctx; +mod eguictx; +mod vertex; +mod texture; +mod canvas; +mod solar_system; +mod known_stars; +mod timeman; + +use std::cell::RefCell; +use std::thread; +use std::time::{Duration, Instant}; + +use winit::event::{KeyEvent, WindowEvent}; +use winit::event_loop::{EventLoop, ActiveEventLoop, ControlFlow}; +use winit::error::{EventLoopError}; +use winit::application::{ApplicationHandler}; +use winit::keyboard::PhysicalKey; +use winit::window::{Window, WindowId, WindowAttributes}; + +use solar_system::SolarSystem; + +use crate::timeman::TimeMan; +use crate::window::GameWindow; + +const TARGET_FPS: f32 = 100.0; +const TARGET_DT: Duration = Duration::from_millis((1000.0 / TARGET_FPS) as u64); + +struct SystemicApp +{ + window: Option, + wgpu_instance: wgpu::Instance, + + last_render_time: Instant, + game_state: Option> +} + +struct GameState +{ + timeman: TimeMan, + solar_systems: Vec +} + +impl SystemicApp +{ + fn create_window( + &mut self, + event_loop: &ActiveEventLoop) + { + self.window = Some(GameWindow::new( + &self.wgpu_instance, + event_loop).unwrap()); + + self.game_state = Some(RefCell::new(GameState::new())); + } +} + +impl GameState +{ + pub fn new() + -> Self { + let timeman = TimeMan::new(0); + let sol_system = match SolarSystem::new_from_known_star("sol") + { + Ok(system) => system, + Err(e) => panic!("Unable to create sol system : {}", e) + }; + + Self { + timeman: timeman, + solar_systems: vec![ sol_system ] + } + } + + pub fn solar_systems(&self) -> &[SolarSystem] + { self.solar_systems.as_slice() } + + pub fn timeman(&self) -> &TimeMan + { &self.timeman } + + pub fn timeman_mut(&mut self) -> &mut TimeMan + { &mut self.timeman } +} + +impl ApplicationHandler for SystemicApp +{ + fn resumed( + &mut self, + event_loop: &ActiveEventLoop + ) { + match self.window { + Some(_) => {} + None => self.create_window(event_loop) + } + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: WindowId, + event: winit::event::WindowEvent, + ) { + let window = match &mut self.window { + Some(w) => w, + None => return + }; + + let game_state = match &self.game_state { + Some(state) => state, + None => return + }; + + window.on_event(&event); + + match event { + WindowEvent::CloseRequested => { + event_loop.exit(); + } + WindowEvent::Resized(size) => { + window.resize(size.width, size.height); + } + WindowEvent::RedrawRequested => { + let now = Instant::now(); + let delta_time = now - self.last_render_time; + self.last_render_time = now; + + game_state.borrow_mut().timeman.update(); + { + window.update(game_state, delta_time); + } + match window.render(game_state) { + Ok(_) => {} + Err(wgpu::SurfaceError::Outdated | wgpu::SurfaceError::Lost) => { + let size = window.size(); + window.resize(size.width, size.height); + }, + Err(e) => { + log::error!("Unable to render: {}", e); + } + } + if delta_time < TARGET_DT { + thread::sleep(TARGET_DT - delta_time); + } + } + WindowEvent::KeyboardInput { + event: KeyEvent { + physical_key: PhysicalKey::Code(key_code), + state: key_state, + .. + }, + .. + } => { + window.keyboard_input(game_state, key_code, key_state); + } + _ => {} + } + } +} // impl ApplicationHandler for SystemicApp + +fn main() + -> Result<(), EventLoopError> +{ + env_logger::init(); + let event_loop = EventLoop::new().unwrap(); + + event_loop.set_control_flow(ControlFlow::Poll); + + let mut app = SystemicApp { + window: None, + wgpu_instance: wgpu::Instance::default(), + last_render_time: Instant::now(), + game_state: None + }; + + event_loop.run_app(&mut app) +} diff --git a/src/solar_system.rs b/src/solar_system.rs new file mode 100644 index 0000000..e8137f0 --- /dev/null +++ b/src/solar_system.rs @@ -0,0 +1,161 @@ +use serde::{Deserialize}; +use crate::{known_stars::{KNOWN_STARS, StarNotFoundError}, timeman::Second}; +use std::error::Error; + +const GRAVITATIONAL_CONSTANT: f64 = 6.67408e-11; + +pub type Kilograms = f64; +pub type Kilometers = f64; +pub type Percentage = f64; +pub type Angle = f64; + +pub type BodyId = usize; +pub type SystemId = usize; + +#[derive(Debug, Deserialize)] +pub struct SerialOrbitalBody +{ + name: String, + orbits: BodyId, + mass: Kilograms, + radius: Kilometers, + + eccentricity: Percentage, + inclination: Angle, + long_asc_node: Angle, + long_periapsis: Angle, + sgp: f64, + mean_long: Angle, + + semi_major_axis: Kilometers, +} + +pub struct OrbitalBody +{ + body: SerialOrbitalBody, + position: Option<(Second, cgmath::Point3)> +} + +pub struct SolarSystem +{ + name: String, + bodies: Vec, +} + +impl SolarSystem +{ + pub fn new_from_csv( + data: &'static str) + -> Result> { + let data_reader = stringreader::StringReader::new(data); + let mut body_reader = csv::Reader::from_reader(data_reader); + + let mut bodies = Vec::::new(); + + for result in body_reader.deserialize() { + let record: SerialOrbitalBody = result?; + + println!("New body: {:?}", record); + + bodies.push(OrbitalBody { body: record, position: None }); + } + + Ok(Self { + name: bodies[0].name().clone(), + bodies: bodies, + }) + } + + pub fn new_from_known_star( + star: &'static str) + -> Result> { + let star_csv = match KNOWN_STARS.get(star).copied() { + Some(csv) => csv, + None => return Err(Box::new(StarNotFoundError { star: star })) + }; + SolarSystem::new_from_csv(star_csv) + } + + pub fn name(&self) -> &String { &self.name } + + pub fn bodies(&self) + -> &[OrbitalBody] + { + self.bodies.as_slice() + } +} + +impl OrbitalBody +{ + pub fn name(&self) -> &String { &self.body.name } + pub fn radius(&self) -> f32 { self.body.radius as f32 } + + pub fn position(&self, time: Second) + -> Option> + { + match self.position { + Some((cache_time, pos)) => { + if time == cache_time { + return Some(pos); + } + return None; + }, + None => None + } + } + + fn calculate_orbit( + &self, + time: i64) + -> cgmath::Point3 { + cgmath::Point3 { x: 0.0, y: 0.0, z: 0.0 } + /*let arg_periapsis = self.long_periapsis - self.long_asc_node; + + + let mean_angular_motion: f64 = ( + self.sgp as f64 / (self.semi_major_axis as f64).powf(3.0) + ).sqrt(); + + let mean_anomaly = (self.mean_long - self.long_periapsis) + (mean_angular_motion * time as f64) as f32; + + let mut eccentric_anomaly = mean_anomaly + self.eccentricity * mean_anomaly.sin(); + for _ in 0..100 { + let new_eccentric = eccentric_anomaly + + (mean_anomaly - eccentric_anomaly + self.eccentricity * eccentric_anomaly.sin()) / + (1.0 - self.eccentricity * eccentric_anomaly.cos()); + if (new_eccentric - eccentric_anomaly).abs() < 1e-6 { + eccentric_anomaly = new_eccentric; + break; + } + eccentric_anomaly = new_eccentric; + } + + let beta = self.eccentricity / 1.0 + (1.0 - self.eccentricity * self.eccentricity).sqrt(); + let true_anomaly = eccentric_anomaly + 2.0 * + ((beta * eccentric_anomaly.sin()) / (1.0 - beta * eccentric_anomaly.cos())).atan(); + + let radius: f64 = self.semi_major_axis * (1.0 - self.eccentricity * eccentric_anomaly.cos()) as f64; + + let ohm_sin = self.long_asc_node.sin(); + let ohm_cos = self.long_asc_node.cos(); + + let inc_sin = self.inclination.sin(); + let inc_cos = self.inclination.cos(); + + let per_anom_sin = (arg_periapsis + true_anomaly).sin(); + let per_anom_cos = (arg_periapsis + true_anomaly).cos(); + + let x: f32 = (radius as f32) * ( + (ohm_cos * per_anom_cos) - + (ohm_sin * per_anom_sin * inc_cos)); + let y: f32 = (radius as f32) * ( + (ohm_sin * per_anom_cos) + + (ohm_cos * per_anom_sin * inc_cos)); + let z: f32 = (radius as f32) * (inc_sin * per_anom_sin); + + OrbitState { + position: cgmath::Vector3::new(x, y, z) + }*/ + } +} + diff --git a/src/tacmap.rs b/src/tacmap.rs new file mode 100644 index 0000000..89d21aa --- /dev/null +++ b/src/tacmap.rs @@ -0,0 +1,158 @@ +pub mod camera; +pub mod render; + +mod tacmap { + pub use super::render; + pub use super::camera; +} + +use std::cell::RefCell; +use std::time::Duration; + +use winit::event::ElementState; +use winit::keyboard::KeyCode; + +use crate::GameState; +use crate::canvas::Canvas; +use crate::solar_system::SolarSystem; +use crate::solar_system::SystemId; +use crate::wgpuctx::WgpuCtx; +use render::*; +use camera::*; +use crate::window::ui::GameWindowUiState; + +pub struct TacticalMap +{ + canvas: Canvas, + camera: Camera, + pmatrix: Projection, + + camera_controller: CameraController, + renderstate: Option<(SystemId, BodyRenderer)> +} + +impl TacticalMap +{ + pub fn new( + wgpuctx: &WgpuCtx, + position: winit::dpi::LogicalPosition, + size: winit::dpi::LogicalSize) + -> Self { + let surface_size = winit::dpi::PhysicalSize::new( + wgpuctx.surface_config().width, + wgpuctx.surface_config().height + ); + + let canvas = Canvas::new( + wgpuctx, + surface_size, + position, + size).unwrap(); + + let camera = Camera::new( + wgpuctx, + cgmath::Point3::::new(0.0, 0.0, 1.0), + cgmath::Deg(-90.0), + cgmath::Rad(0.0)); + + let projection = Projection::new( + surface_size.width, + surface_size.height, + cgmath::Deg(60.0), + (0.1, 1000.0)); + + Self { + canvas: canvas, + camera: camera, + pmatrix: projection, + camera_controller: CameraController::new(), + renderstate: None, + } + } + + pub fn resize( + &mut self, + wgpuctx: &WgpuCtx, + width: u32, + height: u32) + { + self.canvas.resize(wgpuctx, width, height); + self.pmatrix.resize(width, height); + } + + pub fn update( + &mut self, + game_state: &RefCell, + ui_state: &mut GameWindowUiState, + dt: Duration) + { + self.camera_controller.update(&mut self.camera, dt); + ui_state.camera_scale = self.camera.get_scale(); + } + + pub fn keyboard_input( + &mut self, + game_state: &RefCell, + key_code: KeyCode, + key_state: ElementState) + { + self.camera_controller.keyboard_input(key_code, key_state); + } + + pub fn draw( + &mut self, + wgpuctx: &WgpuCtx, + game_state: &RefCell, + current_system: Option) + -> Result<(), wgpu::SurfaceError> + { + let game_state = game_state.borrow(); + + let current_system_id = match current_system { + Some(system) => system, + None => return Ok(()) + }; + let solar_systems = game_state.solar_systems(); + let current_system = &solar_systems[current_system_id]; + + self.camera.update_buffer(wgpuctx, &self.pmatrix); + + let tacrender = match &mut self.renderstate { + Some((id, render)) => { + if *id != current_system_id { + *id = current_system_id; + render.mark_to_rebuild(); + } + render + }, + None => { + let tmp = render::BodyRenderer::new(wgpuctx); + self.renderstate = Some((current_system_id, tmp)); + &mut self.renderstate.as_mut().unwrap().1 + } + }; + + //Update buffers for the current system and time. + tacrender.rebuild(wgpuctx, current_system); + match tacrender.update( + wgpuctx, current_system, + game_state.timeman().seconds()) + { + Ok(()) => {}, + Err(e) => println!("Tactical map render update error: {}", e) + } + + tacrender.render(wgpuctx, &self.canvas, &self.camera); + + Ok(()) + } + + pub fn present( + &mut self, + screen_pass: &mut wgpu::RenderPass) + -> Result<(), wgpu::SurfaceError> + { + self.canvas.present(screen_pass)?; + Ok(()) + } +} // impl SystemViewport diff --git a/src/tacmap/camera.rs b/src/tacmap/camera.rs new file mode 100644 index 0000000..1a2787b --- /dev/null +++ b/src/tacmap/camera.rs @@ -0,0 +1,272 @@ +use std::time::Duration; + +use cgmath::{InnerSpace, Point3, Rad, Vector2, Vector3, Vector4, Zero, perspective}; +use winit::{event::ElementState, keyboard::KeyCode}; + +use crate::{solar_system::BodyId, wgpuctx::WgpuCtx}; + +pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::from_cols( + Vector4::new(1.0, 0.0, 0.0, 0.0), + Vector4::new(0.0, 1.0, 0.0, 0.0), + Vector4::new(0.0, 0.0, 0.5, 0.0), + Vector4::new(0.0, 0.0, 0.5, 1.0) +); + +pub struct Camera +{ + position: Point3, + pitch: Rad, + yaw: Rad, + scale: f32, + + target: Option, + + buffer: wgpu::Buffer, + staging_buffer: wgpu::Buffer, + bindgroup: wgpu::BindGroup +} + +pub struct CameraController +{ + position_pos_delta: Vector3, + position_neg_delta: Vector3, + rotation_pos_delta: Vector2, + rotation_neg_delta: Vector2, + scale_delta: Vector2, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +pub struct CameraUniform +{ + view: [[f32;4];4], + proj: [[f32;4];4], + scale: f32 +} + +pub struct Projection +{ + aspect: f32, + fovy: Rad, + clip: (f32, f32) +} + +impl Camera +{ + pub fn new< + V: Into>, + Y: Into>, + P: Into> + >( + wgpuctx: &WgpuCtx, + position: V, + yaw: Y, + pitch: P) + -> Self { + use wgpu::BufferUsages; + let buffer = wgpuctx.create_buffer( + &wgpu::BufferDescriptor { + label: Some("Camera buffer"), + size: 144, + usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, + mapped_at_creation: false + } + ); + + let staging_buffer = wgpuctx.create_buffer( + &wgpu::wgt::BufferDescriptor { + label: Some("Camera staging buffer"), + size: 144, + usage: BufferUsages::COPY_SRC | BufferUsages::COPY_DST, + mapped_at_creation: false + } + ); + + let bind_group_layout = Camera::bindgroup_layout(wgpuctx); + let bind_group = wgpuctx.device().create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Camera bind group"), + layout: &bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: buffer.as_entire_binding() + } + ] + } + ); + Self { + position: position.into(), + yaw: yaw.into(), + pitch: pitch.into(), + scale: 1.0, + target: None, + buffer: buffer, + staging_buffer: staging_buffer, + bindgroup: bind_group + } + } + + pub fn get_scale(&self) -> f32 + { self.scale } + + pub fn bindgroup_layout(wgpuctx: &WgpuCtx) + -> wgpu::BindGroupLayout + { + wgpuctx.device().create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { + label: Some("Camera bind group layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None + }, + count: None + } + ] + } + ) + } + + pub fn bindgroup(&self) + -> &wgpu::BindGroup + { &self.bindgroup } + + pub fn stage_changes( + &self, + encoder: &mut wgpu::CommandEncoder) + { + let buffer_size = size_of::(); + encoder.copy_buffer_to_buffer(&self.staging_buffer, 0, &self.buffer, 0, Some(buffer_size as u64)); + } + + pub fn update_buffer( + &self, + wgpuctx: &WgpuCtx, + projection: &Projection) + { + wgpuctx.queue().write_buffer(&self.staging_buffer, 0, bytemuck::cast_slice(&[self.uniform(projection)])); + } + + pub fn view_matrix( + &self) + -> cgmath::Matrix4 { + + let (yaw_sin, yaw_cos) = self.yaw.0.sin_cos(); + let (pitch_sin, pitch_cos) = self.pitch.0.sin_cos(); + + cgmath::Matrix4::look_to_rh( + self.position, + Vector3::new( + pitch_cos * yaw_cos, + pitch_sin, + pitch_cos * yaw_sin + ).normalize(), + Vector3::unit_y() + ) + } + + pub fn uniform( + &self, + projection: &Projection) + -> CameraUniform + { + CameraUniform { + view: (self.view_matrix()).into(), + proj: (OPENGL_TO_WGPU_MATRIX * projection.projection_matrix()).into(), + scale: self.scale + } + } +} //impl Camera + +impl CameraController +{ + pub fn new() -> Self { + Self { + position_pos_delta: Vector3::new(0.0, 0.0, 0.0), + position_neg_delta: Vector3::new(0.0, 0.0, 0.0), + rotation_pos_delta: Vector2::new(0.0, 0.0), + rotation_neg_delta: Vector2::new(0.0, 0.0), + scale_delta: Vector2::new(0.0, 0.0), + } + } + + pub fn keyboard_input( + &mut self, + key_code: KeyCode, + key_state: ElementState) + { + let press_q = if key_state == ElementState::Pressed { 1.0 } else { 0.0 }; + match key_code { + KeyCode::KeyW => { self.position_pos_delta.z = press_q; }, + KeyCode::KeyS => { self.position_neg_delta.z = press_q; }, + KeyCode::KeyA => { self.position_neg_delta.x = press_q; }, + KeyCode::KeyD => { self.position_pos_delta.x = press_q; }, + KeyCode::Space => { self.position_pos_delta.y = press_q; }, + KeyCode::ShiftLeft => { self.position_neg_delta.y = press_q; }, + + KeyCode::KeyQ => { self.scale_delta.x = press_q; }, + KeyCode::KeyE => { self.scale_delta.y = press_q; }, + _ => {} + } + } + + pub fn update( + &mut self, + camera: &mut Camera, + dt: Duration) + { + let dt = dt.as_secs_f32(); + let speed = 1.0; + + camera.pitch.0 += (self.rotation_pos_delta.x - self.rotation_neg_delta.x) * speed * dt; + camera.yaw.0 += (self.rotation_pos_delta.y - self.rotation_neg_delta.y) * speed * dt; + + let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos(); + let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); + let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); + let up = Vector3::new(0.0, 1.0, 0.0); + + camera.position += forward * (self.position_pos_delta.z - self.position_neg_delta.z) * speed * dt; + camera.position += right * (self.position_pos_delta.x - self.position_neg_delta.x) * speed * dt; + camera.position += up * (self.position_pos_delta.y - self.position_neg_delta.y) * speed * dt; + + camera.scale *= 1.0 + ((self.scale_delta.y - self.scale_delta.x) * 0.1); + camera.scale = f32::max(1e-16, f32::min(1.0, camera.scale)); + } +} + +impl Projection { + pub fn new< + F: Into> + >( + width: u32, + height: u32, + fovy: F, + clip: (f32, f32)) + -> Self { + Self { + aspect: width as f32 / height as f32, + fovy: fovy.into(), + clip: clip + } + } + + pub fn resize( + &mut self, + width: u32, + height: u32) + { + self.aspect = width as f32 / height as f32; + } + + pub fn projection_matrix( + &self) + -> cgmath::Matrix4 { + perspective(self.fovy, self.aspect, self.clip.0, self.clip.1) + } +} diff --git a/src/tacmap/render.rs b/src/tacmap/render.rs new file mode 100644 index 0000000..c22878e --- /dev/null +++ b/src/tacmap/render.rs @@ -0,0 +1,233 @@ +use std::{fmt::Display, num::NonZero}; +use std::error::Error; + +use crate::canvas::Canvas; +use crate::solar_system::Kilometers; +use crate::tacmap::camera::Camera; +use crate::wgpuctx::RenderPassBuilder; +use crate::{solar_system::{SolarSystem, SystemId}, timeman::Second, vertex::{self, Vertex}, wgpuctx::{WgpuCtx, pipeline::RenderPipelineBuilder}}; + +struct BodyInstance +{ + position: cgmath::Point3, + radius: f32 +} + +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct BodyInstanceRaw +{ + position: [f32;3], + radius: f32 +} + +#[derive(Debug, Clone)] +pub struct NeedsRebuildError; + +impl Display for NeedsRebuildError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RenderState needs to be rebuilt before updating!") + } +} + +impl Error for NeedsRebuildError {} + +pub struct BodyRenderer +{ + needs_rebuild: bool, + last_time: Option, + + pipeline: wgpu::RenderPipeline, + + body_vertex_buffer: wgpu::Buffer, + body_instance_buffer: Option<(usize, wgpu::Buffer)> +} + +impl BodyRenderer +{ + pub fn new( + wgpuctx: &WgpuCtx) + -> Self { + let quad_vertices = vertex::QUAD_VERTICES; + + let body_vertex_buffer = wgpuctx.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: None, + contents: bytemuck::cast_slice(quad_vertices), + usage: wgpu::BufferUsages::VERTEX + } + ); + + let shader = wgpuctx.create_shader( + wgpu::include_wgsl!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/assets/shaders/tacbody.wgsl") + )); + + let render_pipeline = RenderPipelineBuilder::new(&shader) + .add_bindgroup(&Camera::bindgroup_layout(wgpuctx)) + .add_vertex_layout(Vertex::descr()) + .add_vertex_layout(BodyInstanceRaw::descr()) + .build(Some("Tactical map render pipeline"), wgpuctx); + + Self { + needs_rebuild: true, + last_time: None, + pipeline: render_pipeline, + body_vertex_buffer, + body_instance_buffer: None + } + } + + pub fn mark_to_rebuild(&mut self) + { self.needs_rebuild = true; } + + pub fn rebuild( + &mut self, + wgpuctx: &WgpuCtx, + solar_system: &SolarSystem) + { + if self.body_instance_buffer.is_some() && !self.needs_rebuild { + return; + } + + match self.body_instance_buffer.as_mut() { + Some(buffer) => { + buffer.1.destroy(); + self.body_instance_buffer = None; + } + None => {} + } + + let bodies = solar_system.bodies(); + let buffer_len = bodies.len() * size_of::(); + + let buffer = wgpuctx.create_buffer( + &wgpu::BufferDescriptor { + label: Some("Tactical map bodies instance buffer"), + size: buffer_len as u64, + usage: wgpu::BufferUsages::COPY_DST | + wgpu::BufferUsages::VERTEX, + mapped_at_creation: false + } + ); + + self.last_time = None; + self.body_instance_buffer = Some((bodies.len(), buffer)); + } + + pub fn update( + &mut self, + wgpuctx: &WgpuCtx, + solar_system: &SolarSystem, + time: Second) + -> Result<(), Box> + { + //If the last updated time is the same, we don't need to update + //the positions of all the bodies. + match self.last_time { + Some(last_time) => { + if last_time == time { + return Ok(()); + } + } + None => {} + } + + self.last_time = Some(time); + let (_, bodies_buffer) = match &self.body_instance_buffer { + Some(tuple) => tuple, + None => return Err(Box::new(NeedsRebuildError)) + }; + + let bodies = solar_system.bodies(); + let body_instances = bodies.iter().map(|body| { + let position = match body.position(time) { + Some(pos) => pos, + None => return BodyInstanceRaw { + position: [0.0, 0.0, 0.0], + radius: body.radius() } + }; + BodyInstance { + position: position, + radius: body.radius() + }.raw() + }).collect::>(); + + wgpuctx.queue().write_buffer(bodies_buffer, 0, bytemuck::cast_slice(&body_instances)); + //Update the canvas texture. + + Ok(()) + } + + pub fn render( + &self, + wgpuctx: &WgpuCtx, + canvas: &Canvas, + camera: &Camera) + { + let (num_bodies, bodies_buffer) = match &self.body_instance_buffer { + Some(tuple) => tuple, + None => return + }; + + let mut encoder = wgpuctx.create_default_encoder("Tactical map renderer encoder"); + let view = canvas.view(); + + { + camera.stage_changes(&mut encoder); + } + { + let mut pass = RenderPassBuilder::new("Tactiacal map render pass", view) + .clear_color(wgpu::Color { r: 0.0, g: 0.0, b: 0.1, a: 1.0 }) + .build(&mut encoder); + + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, camera.bindgroup(), &[]); + + pass.set_vertex_buffer(0, self.body_vertex_buffer.slice(..)); + pass.set_vertex_buffer(1, bodies_buffer.slice(..)); + + pass.draw(0..6, 0..num_bodies.clone() as _); + } + + wgpuctx.submit_encoder(encoder); + } +} // impl RenderState + +impl BodyInstance +{ + fn raw(&self) -> BodyInstanceRaw + { + BodyInstanceRaw { + position: [ + self.position.x as f32, + self.position.y as f32, + self.position.z as f32 ], + radius: self.radius + } + } +} // impl BodyInstance + +impl BodyInstanceRaw +{ + fn descr() -> wgpu::VertexBufferLayout<'static> { + use std::mem; + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Instance, + attributes: &[ + wgpu::VertexAttribute { + offset: 0, + shader_location: 2, + format: wgpu::VertexFormat::Float32x3 + }, + wgpu::VertexAttribute { + offset: mem::size_of::<[f32;3]>() as wgpu::BufferAddress, + shader_location: 3, + format: wgpu::VertexFormat::Float32 + } + ] + } + } +} diff --git a/src/texture.rs b/src/texture.rs new file mode 100644 index 0000000..be07dd3 --- /dev/null +++ b/src/texture.rs @@ -0,0 +1,96 @@ +use crate::wgpuctx::WgpuCtx; + +pub struct Texture +{ + texture: wgpu::Texture, + view: wgpu::TextureView, + sampler: wgpu::Sampler, + pub bindgrouplayout: wgpu::BindGroupLayout, + bindgroup: wgpu::BindGroup, +} + +impl Texture +{ + pub fn new( + device: &wgpu::Device, + descr: wgpu::TextureDescriptor) + -> Self + { + let texture = device.create_texture(&descr); + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + let sampler = device.create_sampler( + &wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::Repeat, + address_mode_v: wgpu::AddressMode::Repeat, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + } + ); + + let bind_group_layout = device.create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { + filterable: true + }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false + }, + count: None + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None + } + ] + } + ); + + let bind_group = device.create_bind_group( + &wgpu::BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&view) + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&sampler) + } + ] + } + ); + + Self { + texture: texture, + view: view, + sampler: sampler, + bindgrouplayout: bind_group_layout, + bindgroup: bind_group, + } + } + + pub fn view(&self) + -> &wgpu::TextureView + { &self.view } + + pub fn use_on_pass( + &self, + pass: &mut wgpu::RenderPass, + index: u32) + { + pass.set_bind_group(index, &self.bindgroup, &[]); + } +} // impl Texture diff --git a/src/timeman.rs b/src/timeman.rs new file mode 100644 index 0000000..9d17999 --- /dev/null +++ b/src/timeman.rs @@ -0,0 +1,69 @@ +use std::cell::RefCell; +use std::time::Duration; +use std::{fmt::Display, string}; +use std::error::Error; + +use crate::GameState; +use crate::window::ui::GameWindowUiState; + +pub type Second = u64; + +pub struct TimeMan +{ + time: Second, + auto_tick: Option +} + +impl TimeMan +{ + pub fn new(time: Second) + -> Self { + Self { + time, + auto_tick: None + } + } + + pub fn seconds(&self) + -> Second { + self.time + } + + pub fn advance( + &mut self, + by: Second) + { + self.time += by; + } + + pub fn update( + &mut self) + { + match self.auto_tick { + Some(advance) => { self.time += advance; }, + None => {} + } + } + + pub fn format_duration(time: Second) -> String + { + let seconds = time % 60; + let minutes = (time / 60) % 60; + let hours = (time / (60 * 60)) % 24; + let days = (time / (60 * 60 * 24)) % 365; + let years = time / (60 * 60 * 24 * 365); + + if time == 0 { + return "0s".to_string(); + } + + format!("{}{}{}{}{}", + if seconds > 0 { format!("{}s", seconds) } else { format!("") }, + if minutes > 0 { format!("{}m", minutes) } else { format!("") }, + if hours > 0 { format!("{}h", hours) } else { format!("") }, + if days > 0 { format!("{}d", days) } else { format!("") }, + if years > 0 { format!("{}y", years) } else { format!("") }) + } + + +} //impl TimeMan diff --git a/src/vertex.rs b/src/vertex.rs new file mode 100644 index 0000000..aab7d02 --- /dev/null +++ b/src/vertex.rs @@ -0,0 +1,33 @@ +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +pub struct Vertex +{ + pub position: [f32;3], + pub uv: [f32;2] +} + +impl Vertex +{ + const ATTRIBS: [wgpu::VertexAttribute;2] = + wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2]; + + pub fn descr() + -> wgpu::VertexBufferLayout<'static> { + use std::mem; + + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &Self::ATTRIBS + } + } +} + +pub const QUAD_VERTICES: &[Vertex] = &[ + Vertex { position: [ -1.0, -1.0, 0.0 ], uv: [ 0.0, 1.0 ] }, + Vertex { position: [ 1.0, -1.0, 0.0 ], uv: [ 1.0, 1.0 ] }, + Vertex { position: [ 1.0, 1.0, 0.0 ], uv: [ 1.0, 0.0 ] }, + Vertex { position: [ 1.0, 1.0, 0.0 ], uv: [ 1.0, 0.0 ] }, + Vertex { position: [ -1.0, 1.0, 0.0 ], uv: [ 0.0, 0.0 ] }, + Vertex { position: [ -1.0, -1.0, 0.0 ], uv: [ 0.0, 1.0 ] } +]; diff --git a/src/wgpuctx/mod.rs b/src/wgpuctx/mod.rs new file mode 100644 index 0000000..f8aa3ec --- /dev/null +++ b/src/wgpuctx/mod.rs @@ -0,0 +1,245 @@ +use std::sync::Arc; +use std::error::Error; +use wgpu::util::DeviceExt; +use winit::window::{Window}; + +use crate::texture::Texture; + +pub mod pipeline; + +pub struct WgpuCtx +{ + surface: wgpu::Surface<'static>, + surface_conf: wgpu::SurfaceConfiguration, + surface_texture: Option, + is_configured: bool, + + adapter: wgpu::Adapter, + device: wgpu::Device, + queue: wgpu::Queue, +} + +pub struct RenderPassBuilder<'encoder> +{ + label: &'static str, + view: &'encoder wgpu::TextureView, + clear_color: wgpu::Color +} + +impl WgpuCtx +{ + pub async fn new( + instance: &wgpu::Instance, + window: Arc, + ) -> Self { + let surface = instance.create_surface(window.clone()).unwrap(); + + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + compatible_surface: Some(&surface), + ..Default::default() + }).await.expect("Failed to find valid adapter"); + + let (device, queue) = adapter + .request_device(&wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_defaults(), + experimental_features: wgpu::ExperimentalFeatures::disabled(), + memory_hints: wgpu::MemoryHints::Performance, + trace: wgpu::Trace::Off + }).await.expect("Failed to find device and queue"); + + let size = window.inner_size(); + let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + + Self { + surface: surface, + surface_conf: surface_config, + surface_texture: None, + is_configured: false, + adapter: adapter, + device: device, + queue: queue + } + } + + pub fn resize( + &mut self, + width: u32, + height: u32) + { + self.surface_conf.width = width; + self.surface_conf.height = height; + self.surface.configure(&self.device, &self.surface_conf); + self.is_configured = true; + } + + pub fn is_ready( + &self) + -> bool { + self.is_configured + } + + pub fn surface_config( + &self) + -> wgpu::SurfaceConfiguration { + self.surface_conf.clone() + } + + pub fn adapter( + &self) + -> &wgpu::Adapter { + &self.adapter + } + + pub fn device( + &self) + -> &wgpu::Device { + &self.device + } + + pub fn queue( + &self) + -> &wgpu::Queue { + &self.queue + } + + pub fn prepare_surface( + &mut self, + view_descr: &wgpu::TextureViewDescriptor) + -> Result + { + let texture = self.surface.get_current_texture()?; + let view = texture.texture.create_view(view_descr); + + self.surface_texture = Some(texture); + Ok(view) + } + + pub fn create_encoder( + &self, + descr: &wgpu::CommandEncoderDescriptor) + -> wgpu::CommandEncoder + { + self.device.create_command_encoder(descr) + } + + pub fn create_default_encoder( + &self, + label: &'static str) + -> wgpu::CommandEncoder { + self.create_encoder( + &wgpu::CommandEncoderDescriptor { + label: Some(label) + } + ) + } + + pub fn submit_encoder( + &self, + encoder: wgpu::CommandEncoder) + { + self.queue.submit(std::iter::once(encoder.finish())); + } + + pub fn present_surface( + &mut self) + { + let texture = self.surface_texture.take(); + match texture { + Some(t) => t.present(), + None => {} + } + } + + pub fn create_shader( + &self, + module_descr: wgpu::ShaderModuleDescriptor) + -> wgpu::ShaderModule { + self.device.create_shader_module(module_descr) + } + + pub fn create_pipeline_layout( + &self, + layout_descr: &wgpu::PipelineLayoutDescriptor) + -> wgpu::PipelineLayout { + self.device.create_pipeline_layout(layout_descr) + } + + pub fn create_render_pipeline( + &self, + pipeline_layout: &wgpu::RenderPipelineDescriptor) + -> wgpu::RenderPipeline { + self.device.create_render_pipeline(pipeline_layout) + } + + pub fn create_buffer_init( + &self, + descr: &wgpu::util::BufferInitDescriptor + ) -> wgpu::Buffer { + self.device.create_buffer_init(descr) + } + + pub fn create_buffer( + &self, + descr: &wgpu::BufferDescriptor) + -> wgpu::Buffer { + self.device.create_buffer(descr) + } + + pub fn new_texture( + &self, + descr: wgpu::TextureDescriptor) + -> Texture + { + Texture::new(&self.device, descr) + } + +} //impl WgpuCtx + +impl<'encoder> RenderPassBuilder<'encoder> +{ + pub fn new( + label: &'static str, + view: &'encoder wgpu::TextureView) + -> Self { + Self { + label: label, + view: view, + clear_color: wgpu::Color { r: 0.0, g: 0.0, b: 0.0, a: 1.0 } + } + } + + pub fn clear_color( + mut self, + color: wgpu::Color) + -> Self { + self.clear_color = color; + self + } + + pub fn build( + self, + encoder: &'encoder mut wgpu::CommandEncoder) + -> wgpu::RenderPass<'encoder> + { + encoder.begin_render_pass( + &wgpu::RenderPassDescriptor { + label: Some(self.label), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: self.view, + resolve_target: None, + depth_slice: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(self.clear_color), + store: wgpu::StoreOp::Store + } + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + } + ) + } +} diff --git a/src/wgpuctx/pipeline.rs b/src/wgpuctx/pipeline.rs new file mode 100644 index 0000000..7606203 --- /dev/null +++ b/src/wgpuctx/pipeline.rs @@ -0,0 +1,121 @@ + +use crate::wgpuctx::WgpuCtx; + +pub struct RenderPipelineBuilder<'a> +{ + bind_groups: Vec<&'a wgpu::BindGroupLayout>, + shader: &'a wgpu::ShaderModule, + + vertex_entry_point: Option<&'static str>, + fragment_entry_point: Option<&'static str>, + + vertex_comp_options: Option>, + fragment_comp_options: Option>, + + vertex_buffer_layouts: Vec> +} + +impl<'a> RenderPipelineBuilder<'a> +{ + pub fn new( + shader: &'a wgpu::ShaderModule) + -> Self { + Self { + bind_groups: Vec::new(), + shader: shader, + + vertex_entry_point: Some("vs_main"), + fragment_entry_point: Some("fs_main"), + + vertex_comp_options: None, + fragment_comp_options: None, + + vertex_buffer_layouts: Vec::new() + } + } + + pub fn add_bindgroup( + mut self, + bindgroup: &'a wgpu::BindGroupLayout) + -> Self { + self.bind_groups.push(bindgroup); + self + } + + pub fn add_vertex_layout( + mut self, + layout: wgpu::VertexBufferLayout<'a>) + -> Self { + self.vertex_buffer_layouts.push(layout); + self + } + + pub fn build( + self, + label: Option<&'static str>, + wgpuctx: &WgpuCtx) + -> wgpu::RenderPipeline + { + let layout_descr = wgpu::PipelineLayoutDescriptor { + label: label, + bind_group_layouts: self.bind_groups.as_slice(), + push_constant_ranges: &[] + }; + + let layout = wgpuctx.create_pipeline_layout(&layout_descr); + + wgpuctx.create_render_pipeline( + &wgpu::RenderPipelineDescriptor { + label: label, + layout: Some(&layout), + vertex: wgpu::VertexState { + module: self.shader, + entry_point: self.vertex_entry_point, + compilation_options: match self.vertex_comp_options { + Some(option) => option, + None => wgpu::PipelineCompilationOptions::default() + }, + buffers: self.vertex_buffer_layouts.as_slice() + }, + fragment: Some(wgpu::FragmentState { + module: self.shader, + entry_point: self.fragment_entry_point, + compilation_options: match self.fragment_comp_options { + Some(option) => option, + None => wgpu::PipelineCompilationOptions::default() + }, + targets: &[Some(wgpu::ColorTargetState { + format: wgpuctx.surface_config().format, + blend: Some(wgpu::BlendState{ + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::SrcAlpha, + dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, + operation: wgpu::BlendOperation::Add + }, + alpha: wgpu::BlendComponent::OVER + }), + write_mask: wgpu::ColorWrites::ALL + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false + }, + multiview: None, + cache: None + + } + ) + } +} diff --git a/src/window.rs b/src/window.rs new file mode 100644 index 0000000..0be88e7 --- /dev/null +++ b/src/window.rs @@ -0,0 +1,148 @@ +pub mod ui; + +mod window { + pub use super::ui; +} + +use std::cell::RefCell; +use std::sync::{Arc}; +use std::time::Duration; + +use winit::event::{ElementState, WindowEvent}; +use winit::keyboard::KeyCode; + +use crate::tacmap::TacticalMap; +use crate::{GameState, SystemicApp}; +use crate::solar_system::{SolarSystem, SystemId}; +use crate::wgpuctx::{RenderPassBuilder, WgpuCtx}; +use crate::eguictx::EguiCtx; + +use ui::*; + +pub struct GameWindow +{ + window: Arc, + wgpuctx: WgpuCtx, + eguictx: EguiCtx, + + tactical_map: TacticalMap, + + ui_state: GameWindowUiState +} + +impl GameWindow +{ + pub fn new( + instance: &wgpu::Instance, + event_loop: &winit::event_loop::ActiveEventLoop) + -> Result + { + let window_attrs = winit::window::Window::default_attributes() + .with_title("Systemic 4X") + .with_inner_size(winit::dpi::LogicalSize::new(640, 480)); + + let window = Arc::new(event_loop.create_window(window_attrs).unwrap()); + + let wgpuctx = pollster::block_on(WgpuCtx::new(instance, window.clone())); + let eguictx = EguiCtx::new(&window, &wgpuctx); + + let tacmap = TacticalMap::new( + &wgpuctx, + winit::dpi::LogicalPosition::new(0.0, 0.0), + winit::dpi::LogicalSize::new(1.0, 1.0)); + + Ok(Self { + window: window, + wgpuctx: wgpuctx, + eguictx: eguictx, + tactical_map: tacmap, + + ui_state: Default::default() + }) + } + + pub fn update( + &mut self, + game_state: &RefCell, + dt: Duration) + { + self.tactical_map.update(game_state, &mut self.ui_state, dt); + } + + pub fn keyboard_input( + &mut self, + game_state: &RefCell, + key_code: KeyCode, + key_state: ElementState) + { + self.tactical_map.keyboard_input(game_state, key_code, key_state); + } + + pub fn render( + &mut self, + game_state: &RefCell) + -> Result<(), wgpu::SurfaceError> { + if !self.wgpuctx.is_ready() { + return Ok(()); + } + + self.tactical_map.draw( + &self.wgpuctx, + game_state, + self.ui_state.current_system)?; + + let mut encoder = self.wgpuctx.create_default_encoder("Systemic window command encoder"); + let view = self.wgpuctx.prepare_surface(&wgpu::TextureViewDescriptor::default())?; + { + let mut pass = RenderPassBuilder::new("Systemic window render pass", &view) + .clear_color(wgpu::Color { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }) + .build(&mut encoder); + + //Draw the tactical map canvas. + self.tactical_map.present(&mut pass)?; + } + { + self.eguictx.prepare(&self.window); + self.ui_state = GameWindowUiState::render(&self.ui_state, game_state, &self.eguictx); + + self.eguictx.present( + &self.window, + &self.wgpuctx, + &mut encoder, + &view); + } + + self.wgpuctx.submit_encoder(encoder); + self.wgpuctx.present_surface(); + self.window.request_redraw(); + + Ok(()) + } + + pub fn on_event( + &mut self, + event: &WindowEvent) + { + if self.eguictx.window_event(&self.window, event).consumed { + return; + } + } + + pub fn resize( + &mut self, + width: u32, + height: u32 + ) { + if width > 0 && height > 0 { + self.wgpuctx.resize(width, height); + self.tactical_map.resize(&self.wgpuctx, width, height); + self.window.request_redraw(); + } + } + + pub fn size( + &self) + -> winit::dpi::PhysicalSize { + self.window.inner_size() + } +} diff --git a/src/window/ui.rs b/src/window/ui.rs new file mode 100644 index 0000000..4d13740 --- /dev/null +++ b/src/window/ui.rs @@ -0,0 +1,96 @@ +use std::cell::RefCell; + +use cgmath::Vector3; + +use crate::{GameState, eguictx::EguiCtx, solar_system, timeman::{Second, TimeMan}}; + +#[derive(Default, Clone)] +pub struct GameWindowUiState +{ + pub current_system: Option, + pub camera_scale: f32, + pub camera_target: Option, + pub auto_time: Option, + pub do_auto_tick: bool +} + +impl GameWindowUiState +{ + pub fn render( + old_state: &GameWindowUiState, + game_state: &RefCell, + eguictx: &EguiCtx) + -> Self + { + let mut new_state = old_state.clone(); + + { GameWindowUiState::render_topbar(&mut new_state, game_state, eguictx); } + + new_state + } + + fn render_topbar( + state: &mut GameWindowUiState, + game_state: &RefCell, + eguictx: &EguiCtx) + { + let mut game_state = game_state.borrow_mut(); + + egui::TopBottomPanel::top("topbar").show( + eguictx.context(), + |ui| { + + ui.horizontal(|ui| { + ui.menu_button("File", |ui| { + + }); + }); + + ui.horizontal(|ui| { + let solar_systems = game_state.solar_systems(); + let selected_label = match state.current_system { + Some(id) => solar_systems[id].name(), + None => "" + }; + + egui::ComboBox::from_label("Current System") + .selected_text(selected_label) + .show_ui(ui, |ui| { + + for (i, system) in solar_systems.iter().enumerate() { + ui.selectable_value( + &mut state.current_system, + Some(i), + system.name() + ); + } + }); + }); + + ui.horizontal(|ui| { + ui.label(format!("Time: {}", TimeMan::format_duration(game_state.timeman().seconds()))); + + let button_seconds = [1, 5, 30, 60, 60*5, 60*30, 60*60, 60*60*24, 60*60*24*5, 60*60*24*30]; + let selected_button = state.auto_time; + + button_seconds.iter().for_each(|&seconds| { + ui.vertical(|ui| { + let auto_selected = match selected_button { + Some(o) => o == seconds, + None => false + }; + let label = TimeMan::format_duration(seconds); + + if ui.button(label.clone()).clicked() { + game_state.timeman_mut().advance(seconds); + } + + if ui.add(egui::Button::new(label.clone()).selected(auto_selected)).clicked() { + state.auto_time = Some(seconds); + } + }); + }); + }); + }); + } +} -- cgit v1.2.3