diff --git a/Cargo.lock b/Cargo.lock index e1b6adb..d36cc29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,15 +14,15 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -46,6 +46,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android-activity" version = "0.6.0" @@ -53,7 +59,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.9.1", + "bitflags 2.10.0", "cc", "cesu8", "jni", @@ -64,7 +70,7 @@ dependencies = [ "ndk-context", "ndk-sys", "num_enum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -75,9 +81,38 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +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.3", + "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" @@ -111,9 +146,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -121,7 +156,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -130,6 +165,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bit_field" version = "0.10.3" @@ -144,9 +185,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block2" @@ -165,9 +206,23 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +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" @@ -183,9 +238,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "calloop" @@ -193,12 +248,25 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "log", "polling", "rustix 0.38.44", "slab", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +dependencies = [ + "bitflags 2.10.0", + "polling", + "rustix 1.1.2", + "slab", + "tracing", ] [[package]] @@ -207,18 +275,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop", + "calloop 0.13.0", "rustix 0.38.44", "wayland-backend", "wayland-client", ] [[package]] -name = "cc" -version = "1.2.31" +name = "calloop-wayland-source" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ + "calloop 0.14.3", + "rustix 1.1.2", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" +dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -232,9 +313,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -252,10 +333,13 @@ dependencies = [ ] [[package]] -name = "chlorine" -version = "1.0.13" +name = "clipboard-win" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] [[package]] name = "combine" @@ -286,6 +370,16 @@ dependencies = [ "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" @@ -299,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types", "libc", @@ -312,7 +406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] @@ -374,8 +468,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", +] + +[[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]] @@ -393,12 +498,129 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "downcast-rs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" + [[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084980ebede2fb1ad6c4f54285b3e489052ef2b6aa4016e4c19349417adc75c5" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "egui" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75645894de4ca1695ab3ab7201c7953bb95c1725aafeefa6822dc901ad2a81b" +dependencies = [ + "ahash", + "bitflags 2.10.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "egui-winit" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4772ed5f16fa8ec2ba295e58f62b58ee83fcf49e67ec13d2b7ddf4e9a2dea34e" +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 = "egui_glium" +version = "0.31.1" +source = "git+https://github.com/reo6/egui_glium.git#66dbadcb16b3e6c827847eaa51a0ca9bd296d768" +dependencies = [ + "ahash", + "bytemuck", + "egui", + "egui-winit", + "glium", + "log", + "raw-window-handle", + "winit", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "emath" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e561352ae95c22ad179fb56c38d6e6eecd86cf4925cf5c70e738dd01df9b620" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + +[[package]] +name = "epaint" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a909ce8cee63e8350fb0c251ad39277a5b24f19add60787e84a3b3ab3f2bd83a" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "log", + "nohash-hasher", + "parking_lot", + "profiling", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9649446c23368ae138716910e3e28143995691b598fbb9de16b42b0722cbcc" + [[package]] name = "equivalent" version = "1.0.2" @@ -407,19 +629,25 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] -name = "exr" -version = "1.73.0" +name = "error-code" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", "half", @@ -430,6 +658,26 @@ dependencies = [ "zune-inflate", ] +[[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" @@ -440,10 +688,16 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.1.2" +name = "find-msvc-tools" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -455,6 +709,18 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[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" @@ -483,32 +749,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] -name = "gethostname" -version = "0.4.3" +name = "form_urlencoded" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ - "libc", - "windows-targets 0.48.5", + "percent-encoding", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.2", + "windows-link", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi", + "wasip2", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "gl_generator" @@ -523,15 +798,105 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.8" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" +checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da" + +[[package]] +name = "glam" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b" + +[[package]] +name = "glam" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16" + +[[package]] +name = "glam" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776" + +[[package]] +name = "glam" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34" + +[[package]] +name = "glam" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca" + +[[package]] +name = "glam" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f" + +[[package]] +name = "glam" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815" + +[[package]] +name = "glam" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" + +[[package]] +name = "glam" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" + +[[package]] +name = "glam" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" + +[[package]] +name = "glam" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" + +[[package]] +name = "glam" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" + +[[package]] +name = "glam" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" + +[[package]] +name = "glam" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" + +[[package]] +name = "glam" +version = "0.30.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd47b05dddf0005d850e5644cae7f2b14ac3df487979dbfff3b56f20b1a6ae46" [[package]] name = "glium" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a3028d1f135b5395e6e4336916b424bc5dd2b38c6e378ce2704e4b8f4a617ed" +checksum = "8cf52ce4f5ce1501bb056627f35484a819e812d1d93f0f3da413676421b1bbe0" dependencies = [ "backtrace", "fnv", @@ -589,7 +954,7 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cfg_aliases", "cgl", "dispatch2", @@ -597,10 +962,10 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "libloading", - "objc2 0.6.1", - "objc2-app-kit 0.3.1", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "raw-window-handle", "wayland-sys", @@ -651,12 +1016,22 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", ] [[package]] @@ -670,9 +1045,33 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] [[package]] name = "hecs" @@ -691,10 +1090,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "image" -version = "0.25.8" +name = "icu_collections" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[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", @@ -702,63 +1203,19 @@ dependencies = [ "moxcms", "num-traits", "png", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "imgui" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8addafa5cecf0515812226e806913814e02ce38d10215778082af5174abe5669" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "imgui-sys", - "mint", - "parking_lot", -] - -[[package]] -name = "imgui-glium-renderer" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781e53a393214a132c89c62e6e4b817645ad38832d3e334b2ad543f2c3df5106" -dependencies = [ - "glium", - "imgui", -] - -[[package]] -name = "imgui-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ead193f9f4b60398e8b8f4ab1483e2321640d87aeebdaa3e5f44c55633ccd804" -dependencies = [ - "cc", - "cfg-if", - "chlorine", - "mint", -] - -[[package]] -name = "imgui-winit-support" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7fcccfa9efab56c94274c0fec9939bb14149342b49e6a425883a5b7dda6a3f" -dependencies = [ - "imgui", - "winit", + "tiff", + "zune-core 0.5.0", + "zune-jpeg 0.5.5", ] [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", ] [[package]] @@ -784,7 +1241,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -797,9 +1254,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom", "libc", @@ -807,9 +1264,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -835,29 +1292,35 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] [[package]] -name = "libredox" -version = "0.1.9" +name = "libm" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "libc", - "redox_syscall 0.5.17", + "redox_syscall 0.5.18", ] [[package]] @@ -868,37 +1331,52 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg", + "rawpointer", +] [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", ] @@ -922,35 +1400,72 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mint" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" - [[package]] name = "moxcms" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" dependencies = [ "num-traits", "pxfm", ] +[[package]] +name = "nalgebra" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f" +dependencies = [ + "approx", + "glam 0.14.0", + "glam 0.15.2", + "glam 0.16.0", + "glam 0.17.3", + "glam 0.18.0", + "glam 0.19.0", + "glam 0.20.5", + "glam 0.21.3", + "glam 0.22.0", + "glam 0.23.0", + "glam 0.24.2", + "glam 0.25.0", + "glam 0.27.0", + "glam 0.28.0", + "glam 0.29.3", + "glam 0.30.9", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ndk" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "jni-sys", "log", "ndk-sys", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -968,6 +1483,62 @@ 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-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -975,13 +1546,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -989,9 +1561,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1017,9 +1589,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" dependencies = [ "objc2-encode", ] @@ -1030,7 +1602,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "libc", "objc2 0.5.2", @@ -1042,14 +1614,15 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-core-graphics", + "objc2-foundation 0.3.2", ] [[package]] @@ -1058,7 +1631,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-core-location", @@ -1082,7 +1655,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1090,13 +1663,26 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "dispatch2", - "objc2 0.6.1", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -1135,7 +1721,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "dispatch", "libc", @@ -1144,12 +1730,23 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", + "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.10.0", + "objc2 0.6.3", "objc2-core-foundation", ] @@ -1171,7 +1768,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1183,7 +1780,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1206,7 +1803,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-cloud-kit", @@ -1238,7 +1835,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-core-location", @@ -1247,9 +1844,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1262,13 +1859,22 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "orbclient" -version = "0.3.48" +version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +checksum = "247ad146e19b9437f8604c21f8652423595cf710ad108af40e77d3ae6e96b827" dependencies = [ "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" @@ -1280,9 +1886,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1290,22 +1896,56 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.17", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] -name = "percent-encoding" -version = "2.3.1" +name = "parry3d" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "e99471b7b6870f7fe406d5611dd4b4c9b07aa3e5436b1d27e1515f9832bb0c6b" +dependencies = [ + "approx", + "arrayvec", + "bitflags 2.10.0", + "downcast-rs 2.0.2", + "either", + "ena", + "foldhash 0.2.0", + "hashbrown 0.16.0", + "log", + "nalgebra", + "num-derive", + "num-traits", + "ordered-float", + "rstar", + "simba", + "slab", + "smallvec", + "spade", + "static_assertions", + "thiserror 2.0.17", +] + +[[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 = "pin-project" @@ -1345,7 +1985,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "crc32fast", "fdeflate", "flate2", @@ -1354,45 +1994,79 @@ dependencies = [ [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.8", - "windows-sys 0.60.2", + "rustix 1.1.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", ] [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] -name = "pxfm" -version = "0.1.24" +name = "profiling" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f9b339b02259ada5c0f4a389b7fb472f933aa17ce176fd2ad98f28bb401fde" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" dependencies = [ "num-traits", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.37.5" @@ -1404,9 +2078,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -1417,6 +2091,19 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "raidillon_app" +version = "0.1.0" +dependencies = [ + "raidillon_assets", + "raidillon_core", + "raidillon_ecs", + "raidillon_engine", + "raidillon_glium", + "raidillon_physics", + "raidillon_platform", +] + [[package]] name = "raidillon_assets" version = "0.1.0" @@ -1425,8 +2112,8 @@ version = "0.1.0" name = "raidillon_core" version = "0.1.0" dependencies = [ + "egui", "hecs", - "imgui", "indexmap", "raidillon_assets", "winit", @@ -1436,19 +2123,22 @@ dependencies = [ name = "raidillon_ecs" version = "0.1.0" dependencies = [ - "glam", + "glam 0.30.9", "raidillon_assets", + "rapier3d", ] [[package]] name = "raidillon_engine" version = "0.1.0" dependencies = [ - "glam", + "egui", + "glam 0.30.9", "hecs", "indexmap", "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_platform", "winit", ] @@ -1457,13 +2147,11 @@ dependencies = [ name = "raidillon_game" version = "0.1.0" dependencies = [ - "glam", - "raidillon_assets", - "raidillon_core", - "raidillon_ecs", - "raidillon_engine", - "raidillon_glium", - "raidillon_platform", + "egui", + "glam 0.30.9", + "hecs", + "raidillon_app", + "rapier3d", "winit", ] @@ -1472,14 +2160,13 @@ name = "raidillon_glium" version = "0.1.0" dependencies = [ "anyhow", + "egui", + "egui_glium", "exr", - "glam", + "glam 0.30.9", "glium", "gltf", "image", - "imgui", - "imgui-glium-renderer", - "imgui-winit-support", "indexmap", "raidillon_assets", "raidillon_core", @@ -1489,22 +2176,64 @@ dependencies = [ "winit", ] +[[package]] +name = "raidillon_physics" +version = "0.1.0" +dependencies = [ + "glam 0.30.9", + "raidillon_ecs", + "rapier3d", +] + [[package]] name = "raidillon_platform" version = "0.1.0" dependencies = [ - "glam", + "glam 0.30.9", "raidillon_assets", "raidillon_core", + "serde", + "toml", "winit", ] +[[package]] +name = "rapier3d" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd27b8eb36d0833fa0f2aea40164fabfad0fc34b9932286ae9e84f3452f5364" +dependencies = [ + "approx", + "arrayvec", + "bit-vec", + "bitflags 2.10.0", + "downcast-rs 2.0.2", + "log", + "nalgebra", + "num-derive", + "num-traits", + "ordered-float", + "parry3d", + "profiling", + "rustc-hash", + "simba", + "static_assertions", + "thiserror 2.0.17", + "wide", +] + [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon-core" version = "1.13.0" @@ -1526,11 +2255,28 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", +] + +[[package]] +name = "robust" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" + +[[package]] +name = "rstar" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" +dependencies = [ + "heapless", + "num-traits", + "smallvec", ] [[package]] @@ -1539,13 +2285,19 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +[[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.9.1", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -1554,22 +2306,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -1577,6 +2329,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1607,24 +2368,34 @@ dependencies = [ "ab_glyph", "log", "memmap2", - "smithay-client-toolkit", + "smithay-client-toolkit 0.19.2", "tiny-skia", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +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.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1633,14 +2404,24 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", ] [[package]] @@ -1649,6 +2430,19 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simba" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1657,9 +2451,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -1673,15 +2467,15 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.9.1", - "calloop", - "calloop-wayland-source", + "bitflags 2.10.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", "cursor-icon", "libc", "log", "memmap2", "rustix 0.38.44", - "thiserror", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1692,6 +2486,44 @@ dependencies = [ "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.10.0", + "calloop 0.14.3", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.2", + "thiserror 2.0.17", + "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" @@ -1701,12 +2533,36 @@ dependencies = [ "serde", ] +[[package]] +name = "spade" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" +dependencies = [ + "hashbrown 0.15.5", + "num-traits", + "robust", + "smallvec", +] + [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[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" @@ -1715,22 +2571,42 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" 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 = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", ] [[package]] @@ -1744,6 +2620,31 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +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 0.4.21", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -1770,28 +2671,73 @@ dependencies = [ ] [[package]] -name = "toml_datetime" -version = "0.6.11" +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ "indexmap", "toml_datetime", + "toml_parser", "winnow", ] +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] @@ -1809,10 +2755,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] -name = "unicode-ident" -version = "1.0.18" +name = "typenum" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-segmentation" @@ -1820,12 +2772,30 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "urlencoding" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "version_check" version = "0.9.5" @@ -1843,45 +2813,32 @@ dependencies = [ ] [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -1892,9 +2849,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1902,22 +2859,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -1929,8 +2886,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ "cc", - "downcast-rs", - "rustix 1.0.8", + "downcast-rs 1.2.1", + "rustix 1.1.2", "scoped-tls", "smallvec", "wayland-sys", @@ -1942,8 +2899,8 @@ version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ - "bitflags 2.9.1", - "rustix 1.0.8", + "bitflags 2.10.0", + "rustix 1.1.2", "wayland-backend", "wayland-scanner", ] @@ -1954,7 +2911,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cursor-icon", "wayland-backend", ] @@ -1965,7 +2922,7 @@ version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" dependencies = [ - "rustix 1.0.8", + "rustix 1.1.2", "wayland-client", "xcursor", ] @@ -1976,19 +2933,45 @@ version = "0.32.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.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.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2001,7 +2984,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2033,9 +3016,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -2052,19 +3035,51 @@ dependencies = [ ] [[package]] -name = "winapi-util" -version = "0.1.9" +name = "webbrowser" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" dependencies = [ - "windows-sys 0.59.0", + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2 0.6.3", + "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 = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[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-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -2099,7 +3114,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "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]] @@ -2117,21 +3141,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -2150,19 +3159,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "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]] @@ -2171,12 +3180,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2185,9 +3188,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -2195,12 +3198,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -2209,9 +3206,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -2219,12 +3216,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2233,9 +3224,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -2245,9 +3236,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -2255,12 +3246,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -2269,9 +3254,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -2279,12 +3264,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -2293,9 +3272,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -2303,12 +3282,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -2317,9 +3290,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -2327,12 +3300,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -2341,9 +3308,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" @@ -2354,13 +3321,13 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "bytemuck", - "calloop", + "calloop 0.13.0", "cfg_aliases", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics", "cursor-icon", "dpi", @@ -2379,7 +3346,7 @@ dependencies = [ "redox_syscall 0.4.1", "rustix 0.38.44", "sctk-adwaita", - "smithay-client-toolkit", + "smithay-client-toolkit 0.19.2", "smol_str", "tracing", "unicode-segmentation", @@ -2399,21 +3366,24 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x11-dl" @@ -2428,24 +3398,24 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", "libloading", "once_cell", - "rustix 0.38.44", + "rustix 1.1.2", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xcursor" @@ -2459,7 +3429,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "dlib", "log", "once_cell", @@ -2474,24 +3444,101 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +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.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +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", @@ -2504,6 +3551,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -2515,9 +3568,18 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "zune-core", + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fb7703e32e9a07fb3f757360338b3a567a5054f21b5f52a666752e333d58e" +dependencies = [ + "zune-core 0.5.0", ] diff --git a/Cargo.toml b/Cargo.toml index 23332d0..3741214 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ members = [ "game", "ecs", "engine", + "physics", "app", ] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 0000000..081dae0 --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "raidillon_app" +version = "0.1.0" +edition = "2024" + +[dependencies] +raidillon_engine = { path = "../engine" } +raidillon_platform = { path = "../platform" } +raidillon_assets = { path = "../asset" } +raidillon_ecs = { path = "../ecs" } +raidillon_physics = { path = "../physics" } +raidillon_glium = { path = "../glium_platform", optional = true } +raidillon_core = { path = "../core" } + +[features] +glium = ["raidillon_glium"] diff --git a/app/src/lib.rs b/app/src/lib.rs new file mode 100644 index 0000000..a5b875a --- /dev/null +++ b/app/src/lib.rs @@ -0,0 +1,45 @@ +pub mod prelude; + +pub use prelude::*; + +pub struct App { + pub engine: Option, +} + +impl App { + pub fn new() -> Self { + let engine = Engine::new(); + Self { engine: Some(engine) } + } + + pub fn add_system(&mut self) -> &mut Self { + self.engine.as_mut().unwrap().system_manager.add::(); + self + } + + pub fn add_scene(&mut self, id: SceneID, scene: Scene) -> &mut Self { + self.engine.as_mut().unwrap().scene_manager.add_scene(id, scene); + self + } + + pub fn set_active_scene(&mut self, id: SceneID) -> &mut Self { + self.engine.as_mut().unwrap().scene_manager.set_active_scene(id); + self + } + + pub fn run(&mut self, title: String, width: u32, height: u32) { + #[cfg(feature = "glium")] + { + let platform = GliumPlatform::initialize( + self.engine.take().unwrap(), + title, + width, + height, + ); + platform.run(); + } + + #[cfg(not(any(feature = "glium")))] + compile_error!("No platform feature enabled."); + } +} diff --git a/app/src/prelude.rs b/app/src/prelude.rs new file mode 100644 index 0000000..fc9cdc1 --- /dev/null +++ b/app/src/prelude.rs @@ -0,0 +1,47 @@ +pub use raidillon_engine::{ + Engine, + system::System, + EngineResources, + InputState, + system::SystemContext, +}; + +pub use raidillon_platform::{ + Platform, + Camera, + PlatformContext, + TimeContext, + DebugWireframes, + DebugWireframesRef, + DebugWireframeVertex, + settings::{Settings, WindowMode}, +}; + +pub use raidillon_assets::{ + ModelManagerRef, + model_path, +}; + +pub use raidillon_ecs::{ + components::{ + CameraMode, + CharacterBodyComponent, + ModelHandle, + RigidBodyComponent, + Transform, + }, +}; + +pub use raidillon_physics::Physics; + +pub use raidillon_core::{ + scene::{Scene, SceneID}, + EguiQueue, + engine::EngineTrait, +}; + +#[cfg(feature = "glium")] +pub use raidillon_glium::{ + GliumPlatform, + RenderingSystem, +}; diff --git a/assets/models/checkered-sphere.glb b/assets/models/checkered-sphere.glb new file mode 100644 index 0000000..ad55283 --- /dev/null +++ b/assets/models/checkered-sphere.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36498b406df94ee6990c72a932082101fe0427af52260893e299e4d1a44de084 +size 1796992 diff --git a/assets/models/plane.glb b/assets/models/plane.glb new file mode 100644 index 0000000..e755152 --- /dev/null +++ b/assets/models/plane.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b54f00f327a5edc76c03f83d4efa2a4400215d7ca9c961b38537e7f836bca710 +size 1240 diff --git a/assets/models/sphere.glb b/assets/models/sphere.glb new file mode 100644 index 0000000..ea99045 --- /dev/null +++ b/assets/models/sphere.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78583ec562098f7fa4eaf95c6e21b7d1ced53416eb4c71351e246d53f93aa0a3 +size 24744 diff --git a/assets/shaders/debug_wireframe.frag b/assets/shaders/debug_wireframe.frag new file mode 100644 index 0000000..96d53b9 --- /dev/null +++ b/assets/shaders/debug_wireframe.frag @@ -0,0 +1,9 @@ +#version 330 core + +in vec4 v_color; + +out vec4 frag_color; + +void main() { + frag_color = v_color; +} diff --git a/assets/shaders/debug_wireframe.vert b/assets/shaders/debug_wireframe.vert new file mode 100644 index 0000000..7a53438 --- /dev/null +++ b/assets/shaders/debug_wireframe.vert @@ -0,0 +1,14 @@ +#version 330 core + +in vec3 position; +in vec4 color; + +uniform mat4 view; +uniform mat4 projection; + +out vec4 v_color; + +void main() { + v_color = color; + gl_Position = projection * view * vec4(position, 1.0); +} diff --git a/assets/shaders/gl_textured.frag b/assets/shaders/gl_textured.frag index b264f77..abfa702 100644 --- a/assets/shaders/gl_textured.frag +++ b/assets/shaders/gl_textured.frag @@ -6,28 +6,37 @@ in vec3 v_position; out vec4 frag_color; -uniform vec3 u_light; +uniform vec3 u_light; // direction TO the light (normalized) uniform sampler2D tex; -uniform vec3 color; // base colour factor (acts as solid colour when no texture) +uniform vec3 color; // base colour factor (acts as solid colour when no texture) void main() { // Combine base texture (or constant white) with colour factor supplied by CPU. vec3 base_col = texture(tex, v_tex).rgb * color; - vec3 ambient_color = base_col * 0.2; - vec3 diffuse_color = base_col * 0.6; - vec3 specular_color = vec3(1.0); + vec3 N = normalize(v_normal); + vec3 L = normalize(u_light); - // u_light is the direction **from the light towards the fragment**. - float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0); + // Classic Blinn-Phong lighting + // Ambient: always present + vec3 ambient = base_col * 0.15; - vec3 camera_dir = normalize(-v_position); - vec3 half_dir = normalize(normalize(u_light) + camera_dir); - float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0); + // Diffuse: N dot L, clamped + float NdotL = max(dot(N, L), 0.0); + vec3 diffuse = base_col * NdotL * 0.7; - vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color; + // Specular: only on surfaces facing the light (NdotL > 0) + float specular = 0.0; + if (NdotL > 0.0) { + vec3 V = normalize(-v_position); // view direction (camera at origin in view space) + vec3 H = normalize(L + V); // half-vector + float NdotH = max(dot(N, H), 0.0); + specular = pow(NdotH, 32.0) * 0.5; // tighter highlight, moderated intensity + } - // Convert from linear to sRGB for display (approximate γ-correction) + vec3 result = ambient + diffuse + vec3(specular); + + // Convert from linear to sRGB for display (approximate gamma correction) result = pow(result, vec3(1.0 / 2.2)); frag_color = vec4(result, 1.0); diff --git a/assets/shaders/skybox.frag b/assets/shaders/skybox.frag index 864be50..ce28e95 100644 --- a/assets/shaders/skybox.frag +++ b/assets/shaders/skybox.frag @@ -9,15 +9,19 @@ uniform sampler2D equirect; const vec2 inv_atan = vec2(0.15915494309, 0.31830988618); vec2 sample_spherical_map(vec3 v) { - vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + vec2 uv = vec2(atan(v.z, v.x), asin(clamp(v.y, -1.0, 1.0))); uv *= inv_atan; uv += 0.5; + uv.x = fract(uv.x); return uv; } void main() { vec2 uv = sample_spherical_map(normalize(direction)); uv.y = 1.0 - uv.y; + vec2 size = vec2(textureSize(equirect, 0)); + float epsY = 0.5 / max(size.y, 1.0); + uv.y = clamp(uv.y, epsY, 1.0 - epsY); vec3 color = texture(equirect, uv).rgb; frag_color = vec4(color, 1.0); } diff --git a/core/Cargo.toml b/core/Cargo.toml index fc6b73f..9b3f82f 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,4 +8,4 @@ hecs = "0.10.5" indexmap = "2.10.0" raidillon_assets = { path = "../asset" } winit = "0.30.12" -imgui = "0.12.0" \ No newline at end of file +egui = "0.33.2" \ No newline at end of file diff --git a/core/src/debug_ui.rs b/core/src/debug_ui.rs deleted file mode 100644 index df3b9f1..0000000 --- a/core/src/debug_ui.rs +++ /dev/null @@ -1,50 +0,0 @@ -pub enum UICommand { - Text(String), - Separator, - SliderF32 { label: String, min: f32, max: f32, value: std::rc::Rc> }, -} - -pub struct DebugUIBuffer { - cmds: Vec, -} - -impl DebugUIBuffer { - pub fn new() -> DebugUIBuffer { - DebugUIBuffer { cmds: vec![] } - } - - // Commands - pub fn text(&mut self, text: String) { - self.cmds.push(UICommand::Text(text)); - } - - pub fn separator(&mut self) { - self.cmds.push(UICommand::Separator); - } - - pub fn slider_f32>(&mut self, label: T, min: f32, max: f32, value: std::rc::Rc>) { - self.cmds.push(UICommand::SliderF32 { label: label.into(), min, max, value }); - } - // End of commands - - pub fn write_buffer(&self, ui: &imgui::Ui) { - for cmd in &self.cmds { - match cmd { - UICommand::Text(s) => { - ui.text(s); - } - UICommand::Separator => { - ui.separator(); - } - UICommand::SliderF32 { label, min, max, value } => { - let mut v = value.borrow_mut(); - ui.slider_config(label.as_str(), *min, *max).build(&mut *v); - } - } - } - } - - pub fn reset_buffer(&mut self) { - self.cmds = vec![]; - } -} diff --git a/core/src/egui_queue.rs b/core/src/egui_queue.rs new file mode 100644 index 0000000..fbbb789 --- /dev/null +++ b/core/src/egui_queue.rs @@ -0,0 +1,22 @@ +pub struct EguiQueue { + pub queue_vec: Vec>, +} + +impl EguiQueue { + pub fn new() -> Self { + Self { queue_vec: Vec::new() } + } + + pub fn queue(&mut self, func: impl FnOnce(&egui::Context) + Send + 'static) { + self.queue_vec.push(Box::new(func)); + } + + pub fn clear(&mut self) { + self.queue_vec.clear() + } + + pub fn run(&mut self, ctx: &egui::Context) { + self.queue_vec.drain(..).for_each(|func| func(ctx)); + self.clear(); + } +} diff --git a/core/src/engine.rs b/core/src/engine.rs index b70a945..5890063 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -1,6 +1,3 @@ -use std::cell::RefCell; -use std::rc::Rc; -use crate::DebugUIBuffer; use crate::scene::Scene; pub trait EngineTrait { @@ -12,7 +9,4 @@ pub trait EngineTrait { fn handle_event(&mut self, platform_context: Self::PlatformCtx); fn current_scene_mut(&mut self) -> &mut Scene; fn current_scene(&self) -> &Scene; - fn get_debug_ui_buffer(&self) -> &DebugUIBuffer; - fn reset_debug_ui_buffer(&mut self); - // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Self::Scene, &DebugUIBuffer); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 238d5a6..759393d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,7 +1,7 @@ pub mod engine; -pub mod debug_ui; pub mod time; pub mod utils; pub mod scene; +mod egui_queue; -pub use debug_ui::*; +pub use egui_queue::EguiQueue; diff --git a/core/src/scene.rs b/core/src/scene.rs index 1a075bf..e586be5 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use crate::{define_typemap, DebugUIBuffer}; +use crate::{define_typemap}; pub struct Scene { pub title: String, @@ -23,10 +23,7 @@ impl Scene { s } - pub fn load_default_resources(&mut self) { - let dbg = DebugUIBuffer::new(); - self.resources.insert(dbg); - } + pub fn load_default_resources(&mut self) {} } impl Scene {} @@ -43,7 +40,7 @@ impl AsMut for Scene { } } -type SceneID = &'static str; +pub type SceneID = &'static str; pub struct SceneManager { scenes: HashMap, diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml index 0e1efb5..a47173d 100644 --- a/ecs/Cargo.toml +++ b/ecs/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] glam = "0.30.5" raidillon_assets = { path = "../asset" } +rapier3d = "0.30.1" diff --git a/ecs/src/components.rs b/ecs/src/components.rs index 758f0f4..3c20ec7 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -15,3 +15,16 @@ impl Transform { } pub struct ModelHandle(pub ModelID); + +#[derive(Copy, Clone)] +pub struct RigidBodyComponent(pub rapier3d::dynamics::RigidBodyHandle); + +#[derive(Copy, Clone)] +pub struct CharacterBodyComponent(pub rapier3d::dynamics::RigidBodyHandle); + +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] +pub enum CameraMode { + #[default] + Kinematic, + Debug, +} diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 98202e4..1264629 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -7,7 +7,9 @@ edition = "2024" raidillon_assets = { path = "../asset" } raidillon_core = { path = "../core" } raidillon_platform = { path = "../platform" } +raidillon_ecs = { path = "../ecs" } winit = "0.30.12" hecs = "0.10.5" indexmap = "2.10.0" -glam = "0.30.8" \ No newline at end of file +glam = "0.30.8" +egui = "0.33.2" \ No newline at end of file diff --git a/engine/src/engine.rs b/engine/src/engine.rs index a5c8a1d..ec9841f 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use raidillon_core::scene::{Scene, SceneManager}; use crate::system::{SystemContext, SystemManager}; use raidillon_platform::PlatformContext; -use raidillon_core::{define_typemap, DebugUIBuffer}; +use raidillon_core::{define_typemap}; use raidillon_core::engine::EngineTrait; use crate::input::InputState; use crate::resources::EngineResources; @@ -50,7 +50,6 @@ impl EngineTrait for Engine { /// Update the engine fn frame_update(&mut self, platform_context: PlatformContext) { - self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { @@ -86,17 +85,4 @@ impl EngineTrait for Engine { fn current_scene(&self) -> &Scene { self.scene_manager.current() } - - fn get_debug_ui_buffer(&self) -> &DebugUIBuffer { - self.scene_manager.current().resources.get::().unwrap() - } - - fn reset_debug_ui_buffer(&mut self) { - self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); - } - - // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, &DebugUIBuffer) { - // let (sm, dub) = (&mut self.scene_manager, self.scene_manager.current().resources.get::().unwrap()); - // (sm.current_mut(), dub) - // } } diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 9a87556..a7ad724 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -6,3 +6,4 @@ mod resources; pub use crate::engine::Engine; pub use crate::resources::EngineResources; +pub use input::InputState; diff --git a/engine/src/system.rs b/engine/src/system.rs index 55cccb1..420da1b 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -1,6 +1,5 @@ use indexmap::IndexMap; use raidillon_core::scene::Scene; -use raidillon_core::DebugUIBuffer; use raidillon_platform::PlatformContext; use std::any::TypeId; use std::cell::RefCell; @@ -11,7 +10,6 @@ use crate::resources::EngineResources; pub struct SystemContext<'a> { pub scene: &'a mut Scene, pub platform_context: PlatformContext, - pub debug_ui_buffer: Rc>, pub input_state: Rc>, } diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs deleted file mode 100644 index 0d98577..0000000 --- a/engine/src/systems/fps_camera.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::system::{System, SystemContext}; -use glam::{Quat, Vec3}; -use winit::event::DeviceEvent::MouseMotion; -use winit::event::{ElementState, Event, MouseButton, WindowEvent}; -use winit::keyboard::{KeyCode, PhysicalKey}; -use winit::window::CursorGrabMode; -use raidillon_assets::model_path; -use raidillon_platform::{Camera, PlatformContext}; -use crate::input::InputState; -use crate::resources::EngineResources; -use raidillon_core::scene::Scene; - -pub struct FPSDebugCameraSystem { - mouse_delta: (f64, f64), - mouse_enabled: bool, - position: Vec3, - yaw: f32, - pitch: f32, - speed: f32, - sensitivity: f32, -} - -impl Default for FPSDebugCameraSystem { - fn default() -> Self { - Self { - mouse_delta: Default::default(), - mouse_enabled: Default::default(), - position: Vec3::new(0.0, 0.0, 2.0), - yaw: -90.0, - pitch: 0.0, - speed: 3.0, - sensitivity: 0.1, - } - } -} - -impl System for FPSDebugCameraSystem { - fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - scene.world.spawn((Camera { - eye: Vec3::new(0.0, 0.0, 2.0), - center: Vec3::ZERO, - up: Vec3::Y, - fovy: 60_f32.to_radians(), - aspect: pctx.frame_width / pctx.frame_height, - znear: 0.1, - zfar: 100.0, - },)); - } - - fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - let event2 = pctx.current_event.clone(); - match event2 { - Event::DeviceEvent { device_id, event} => { - match event { - MouseMotion { delta } => { - self.mouse_delta.0 += delta.0; - self.mouse_delta.1 += delta.1; - }, - _ => {} - } - }, - Event::WindowEvent { event, .. } => match event { - WindowEvent::MouseInput { state, button, .. } => { - if button == MouseButton::Right { - // blood and tear - let window = pctx.window.lock().unwrap(); - match state { - ElementState::Pressed => { - if window - .set_cursor_grab(CursorGrabMode::Confined) - .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) - .is_ok() - { - window.set_cursor_visible(false); - self.mouse_enabled = true; - } - } - ElementState::Released => { - let _ = window.set_cursor_grab(CursorGrabMode::None); - window.set_cursor_visible(true); - self.mouse_enabled = false; - } - } - } - } - _ => {}, - }, - _ => {}, - } - } - - fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); - - if self.mouse_enabled { - self.yaw += self.mouse_delta.0 as f32 * self.sensitivity; - self.pitch -= self.mouse_delta.1 as f32 * self.sensitivity; - self.pitch = self.pitch.clamp(-89.0, 89.0); - } - - let front = self.front(); - let right_vec = front.cross(Vec3::Y).normalize(); - - if input.key_held(KeyCode::KeyW) { - self.position += front * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyS) { - self.position -= front * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyA) { - self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyD) { - self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; - } - - scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { - camera.eye = self.position; - camera.center = self.position + front; - }); - self.mouse_delta = (0.0, 0.0); - } -} - -impl FPSDebugCameraSystem { - pub fn front(&self) -> Vec3 { - let yaw_rad = self.yaw.to_radians(); - let pitch_rad = self.pitch.to_radians(); - Vec3::new( - yaw_rad.cos() * pitch_rad.cos(), - pitch_rad.sin(), - yaw_rad.sin() * pitch_rad.cos(), - ).normalize() - } -} diff --git a/engine/src/systems/mod.rs b/engine/src/systems/mod.rs index 8489571..e69de29 100644 --- a/engine/src/systems/mod.rs +++ b/engine/src/systems/mod.rs @@ -1 +0,0 @@ -pub mod fps_camera; diff --git a/game/Cargo.toml b/game/Cargo.toml index 484e434..0a28217 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -3,16 +3,10 @@ name = "raidillon_game" version = "0.1.0" edition = "2024" -[features] -default = ["glium"] -glium = ["raidillon_glium"] - [dependencies] -raidillon_core = { path = "../core" } -raidillon_platform = { path = "../platform" } -raidillon_assets = { path = "../asset" } -raidillon_ecs = { path = "../ecs" } -raidillon_engine = { path = "../engine" } -raidillon_glium = { path = "../glium_platform", optional = true } +raidillon_app = { path = "../app", features = ["glium"] } glam = "0.30.5" winit = "0.30.12" +rapier3d = "0.30.1" +hecs = "0.10.5" +egui = "0.33.2" diff --git a/game/src/main.rs b/game/src/main.rs index ad230cf..a619cb3 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,23 +1,19 @@ -use std::fmt::format; +use raidillon_app::prelude::*; + +mod systems; use glam::{Quat, Vec3}; -use raidillon_engine::{Engine, system::System, EngineResources}; -use raidillon_engine::system::SystemContext; -use raidillon_platform::{Platform, Camera, PlatformContext}; -use raidillon_assets::model_path; -use raidillon_core::engine::EngineTrait; -use raidillon_ecs::components::ModelHandle; -use raidillon_ecs::Transform; -use raidillon_core::scene::Scene; -#[cfg(feature = "glium")] -use raidillon_glium::GliumPlatform; -use winit::event::{ElementState, Event, WindowEvent}; -use winit::event::DeviceEvent::MouseMotion; -use winit::keyboard::{KeyCode, PhysicalKey}; -use raidillon_core::DebugUIBuffer; -use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; - -const TEST_GLTF: &str = "pink-monkey.gltf"; +use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType}; +use rapier3d::prelude::ColliderBuilder; +use winit::event::{Event, WindowEvent}; +use systems::debug_camera::FPSDebugCameraSystem; +use crate::systems::common::should_draw_menu; +use crate::systems::{ + DisplaySettings, KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem, + PhysicsDebugSystem, +}; +const TEST_GLTF: &str = "checkered-sphere.glb"; +const PLANE_GLTF: &str = "plane.glb"; const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] @@ -40,78 +36,105 @@ impl System for UpdateAspectRatioSystem { } #[derive(Default)] -struct RenderingTestSystem { - rotation_speed: std::rc::Rc>, -} +struct MainSystem; -impl System for RenderingTestSystem { +impl System for MainSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = scene.resources.get_mut::().expect("Physics missing"); - self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); + // Spawn Sphere + { + let tr = Transform { + translation: Vec3::new(0.0, 5.0, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), + }; + let collider = ColliderBuilder::ball(1.0) + .restitution(0.7) + .restitution_combine_rule(CoefficientCombineRule::Max) + .build(); + let rb_handle = physics.add_rigid_body(RigidBodyType::Dynamic, tr, collider); + pctx.asset_manager.borrow_mut().load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); + scene.world.spawn(( + tr, + ModelHandle(TEST_GLTF), + RigidBodyComponent(rb_handle), + )); + } + // Spawn Plane + { + let tr = Transform { + translation: Vec3::new(0.0, 0.0, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(10.0, 1.0, 10.0), + }; + let collider = ColliderBuilder::cuboid(10.0, 0.01, 10.0).build(); + let rb_handle = physics.add_rigid_body(RigidBodyType::Fixed, tr, collider); + pctx.asset_manager.borrow_mut().load_gltf(PLANE_GLTF, &model_path(PLANE_GLTF)); + scene.world.spawn(( + tr, + ModelHandle(PLANE_GLTF), + RigidBodyComponent(rb_handle), + )); + } - let mut am = pctx.asset_manager.borrow_mut(); - - am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); - - scene.world.spawn(( - Transform { - translation: Vec3::new(0.0, 0.0, 0.0), - rotation: Quat::IDENTITY, - scale: Vec3::new(1.0, 1.0, 1.0), - }, - ModelHandle(TEST_GLTF), + scene.world.spawn((Camera { + eye: Vec3::new(0.0, 2.0, 3.0), + center: Vec3::ZERO, + up: Vec3::Y, + fovy: 60_f32.to_radians(), + aspect: pctx.frame_width / pctx.frame_height, + znear: 0.1, + zfar: 100.0}, + CameraMode::default(), )); } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - let dbg_ui = scene.resources.get_mut::().unwrap(); + let ( + pctx, + input, + ) = res.get_many_mut::<( + PlatformContext, + InputState, + )>().unwrap(); - dbg_ui.text("Hello World!".to_owned()); - dbg_ui.text(format!("Frame Delta: {}", pctx.time_ctx.frame_dt)); - dbg_ui.text(format!("Fixed Delta: {}", pctx.time_ctx.fixed_dt)); - dbg_ui.text(format!("FPS: {}", 1.0 / pctx.time_ctx.frame_dt)); - dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone()); - } + let mut egui_queue = pctx.egui_queue.borrow_mut(); + let time_ctx = pctx.time_ctx.clone(); + let mut character_pos = Vec3::ZERO; + for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { + character_pos = tr.translation; + } + egui_queue.queue(move |egui_ctx| { + // disable text selection on all labels. + egui_ctx.style_mut(|style| { + style.interaction.selectable_labels = false; + }); - fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - - scene.world.query_mut::<(&mut Transform, &ModelHandle)>().into_iter().for_each(|(_, (t, _))| { - t.rotation *= Quat::from_rotation_y(*self.rotation_speed.borrow() * pctx.time_ctx.fixed_dt); + egui::Window::new("Debug").show(egui_ctx, |ui| { + ui.label("Hello World!"); + ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt)); + ui.label(format!("Fixed Delta: {:.3}", time_ctx.fixed_dt)); + ui.label(format!("FPS: {:.3}", 1.0 / time_ctx.frame_dt)); + ui.label(format!("Character POS: {character_pos:.3}")); + }); }); } - } fn main() { - let mut engine = Engine::new(); - // Define systems - engine.system_manager.add::(); - engine.system_manager.add::(); - engine.system_manager.add::(); - // engine.system_manager.add::(); - - // Set up the scene - let main_scene = Scene::new( - MAIN_SCENE_ID.to_owned(), - None, - ); - engine.scene_manager.add_scene(MAIN_SCENE_ID, main_scene); - engine.scene_manager.set_active_scene(MAIN_SCENE_ID); - - #[cfg(feature = "glium")] - { - let platform = GliumPlatform::initialize( - engine, - "Raidillon".to_string(), - 2560, - 1080, - ); - platform.run() - }; - - #[cfg(not(any(feature = "glium")))] - compile_error!("No platform feature enabled."); + raidillon_app::App::new() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_scene(MAIN_SCENE_ID, Scene::new(MAIN_SCENE_ID.to_owned(), None)) + .set_active_scene(MAIN_SCENE_ID) + .run("Raidillon".to_string(), 2560, 1080); } diff --git a/game/src/systems/common.rs b/game/src/systems/common.rs new file mode 100644 index 0000000..8863f2e --- /dev/null +++ b/game/src/systems/common.rs @@ -0,0 +1,34 @@ +use glam::Vec3; +use raidillon_app::prelude::*; +use crate::systems::menu::MenuState; + +pub fn is_camera_mode_valid(scene: &mut Scene, mode: CameraMode) -> bool { + let mut q = scene.world.query::<(&Camera, &CameraMode)>(); + let (cam_ent, (cam, cam_mode)) = q + .iter() + .next() + .unwrap(); + *cam_mode == mode +} + +pub fn is_mouse_look_enabled(scene: &mut Scene) -> bool { + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, mode) = q.iter().next().unwrap(); + *mode == MenuState::Closed +} + +pub fn camera_front(yaw: f32, pitch: f32) -> Vec3 { + let yaw_rad = yaw.to_radians(); + let pitch_rad = pitch.to_radians(); + Vec3::new( + yaw_rad.cos() * pitch_rad.cos(), + pitch_rad.sin(), + yaw_rad.sin() * pitch_rad.cos(), + ).normalize() +} + +pub fn should_draw_menu(scene: &mut Scene) -> bool { + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, mode) = q.iter().next().unwrap(); + *mode == MenuState::Open +} diff --git a/game/src/systems/debug_camera.rs b/game/src/systems/debug_camera.rs new file mode 100644 index 0000000..b687e08 --- /dev/null +++ b/game/src/systems/debug_camera.rs @@ -0,0 +1,89 @@ +use glam::{Quat, Vec3}; +use winit::event::DeviceEvent::MouseMotion; +use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::keyboard::{KeyCode, PhysicalKey}; +use winit::window::CursorGrabMode; +use raidillon_app::prelude::*; + +use crate::systems::common::{camera_front, is_camera_mode_valid, is_mouse_look_enabled}; +use crate::systems::menu::MenuState; + +pub struct FPSDebugCameraSystem { + mouse_delta: (f64, f64), + position: Vec3, + yaw: f32, + pitch: f32, + speed: f32, + sensitivity: f32, +} + +impl Default for FPSDebugCameraSystem { + fn default() -> Self { + Self { + mouse_delta: Default::default(), + position: Vec3::new(0.0, 0.0, 2.0), + yaw: -90.0, + pitch: 0.0, + speed: 8.0, + sensitivity: 0.1, + } + } +} + +impl System for FPSDebugCameraSystem { + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + if !(is_camera_mode_valid(scene, CameraMode::Debug) && is_mouse_look_enabled(scene)) { + return + } + let pctx = res.get::().unwrap(); + let event2 = pctx.current_event.clone(); + match event2 { + Event::DeviceEvent { device_id, event} => { + match event { + MouseMotion { delta } => { + self.mouse_delta.0 += delta.0; + self.mouse_delta.1 += delta.1; + }, + _ => {} + } + }, + _ => {}, + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); + + if is_mouse_look_enabled(scene) { + self.yaw += self.mouse_delta.0 as f32 * self.sensitivity; + self.pitch -= self.mouse_delta.1 as f32 * self.sensitivity; + self.pitch = self.pitch.clamp(-89.0, 89.0); + } + + let front = camera_front(self.yaw, self.pitch); + let right_vec = front.cross(Vec3::Y).normalize(); + + if is_mouse_look_enabled(scene) { + if input.key_held(KeyCode::KeyW) { + self.position += front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyS) { + self.position -= front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyA) { + self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyD) { + self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; + } + } + + if is_camera_mode_valid(scene, CameraMode::Debug) { + scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { + camera.eye = self.position; + camera.center = self.position + front; + }); + } + self.mouse_delta = (0.0, 0.0); + } +} diff --git a/game/src/systems/display_settings.rs b/game/src/systems/display_settings.rs new file mode 100644 index 0000000..5d8455c --- /dev/null +++ b/game/src/systems/display_settings.rs @@ -0,0 +1,94 @@ +use std::sync::{Arc, Mutex}; +use raidillon_app::prelude::*; +use crate::systems::common::should_draw_menu; + +#[derive(Clone, Copy, PartialEq, Eq)] +enum SettingsTab { + Display, +} + +impl Default for SettingsTab { + fn default() -> Self { + SettingsTab::Display + } +} + +#[derive(Clone, Default)] +struct DisplaySettingsUiState { + selected_fullscreen_mode: WindowMode, + active_tab: SettingsTab, +} + +#[derive(Default)] +pub struct DisplaySettings { + ui_state: Arc>, +} + +impl System for DisplaySettings { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get_mut::().unwrap(); + + // sync the settings with UI state once + if let (Ok(settings_handle), Ok(mut state)) = (pctx.settings.read(), self.ui_state.lock()) { + state.selected_fullscreen_mode = settings_handle.display_settings.fullscreen_mode; + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + if should_draw_menu(scene) { + let pctx = res.get_mut::().unwrap(); + let settings = pctx.settings.clone(); + let ui_state = self.ui_state.clone(); + + pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { + egui::Window::new("Settings").default_open(false).show(egui_ctx, |ui| { + let mut state = ui_state.lock().unwrap(); + + ui.horizontal(|ui| { + ui.selectable_value(&mut state.active_tab, SettingsTab::Display, "Display Settings"); + }); + ui.separator(); + + match state.active_tab { + SettingsTab::Display => { + ui.label("Window Mode"); + egui::ComboBox::from_id_salt("window_mode") + .selected_text(window_mode_label(state.selected_fullscreen_mode)) + .show_ui(ui, |ui| { + for mode in [ + WindowMode::Windowed, + WindowMode::BorderlessFullscreen, + WindowMode::ExclusiveFullscreen, + ] { + ui.selectable_value( + &mut state.selected_fullscreen_mode, + mode, + window_mode_label(mode), + ); + } + }); + + ui.add_space(8.0); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + if ui.button("Apply").clicked() { + if let Ok(mut settings_handle) = settings.write() { + settings_handle.display_settings.fullscreen_mode = state.selected_fullscreen_mode; + settings_handle.display_settings.dirty = true; + } + } + }); + } + } + }); + }); + } + } +} + +fn window_mode_label(mode: WindowMode) -> &'static str { + match mode { + WindowMode::Windowed => "Windowed", + WindowMode::BorderlessFullscreen => "Borderless Fullscreen", + WindowMode::ExclusiveFullscreen => "Exclusive Fullscreen", + } +} diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs new file mode 100644 index 0000000..5519969 --- /dev/null +++ b/game/src/systems/keybinds.rs @@ -0,0 +1,69 @@ +use winit::keyboard::KeyCode; +use raidillon_app::prelude::*; + +use crate::systems::{common::should_draw_menu, menu::MenuState}; + +#[derive(Default)] +pub struct KeybindsSystem { + camera_toggle_held: bool, +} + +impl System for KeybindsSystem { + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let input = res.get::().unwrap(); + if input.key_held(KeyCode::F5) { + if self.camera_toggle_held { return } + self.toggle_camera_mode(scene); + self.camera_toggle_held = true; + } else { + self.camera_toggle_held = false; + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + if should_draw_menu(scene) { + let pctx = res.get_mut::().unwrap(); + let mut q = scene.world.query::<(&Camera, &CameraMode)>(); + let (cam_ent, (cam, cam_mode)) = q + .iter() + .next() + .unwrap(); + let cam_mode_str = format!("Camera Mode: {:?}", cam_mode); + + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, menu_state) = q + .iter() + .next() + .unwrap(); + + let menu_state_str = format!("Menu State: {:?}", menu_state); + + pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { + egui::Window::new("Camera").show(egui_ctx, |ui| { + ui.label("F5 to switch camera"); + ui.label(cam_mode_str); + ui.label(menu_state_str) + }); + }); + } + } +} + +impl KeybindsSystem { + fn toggle_camera_mode(&mut self, scene: &mut Scene) { + let q = scene.world.query_mut::<(&mut Camera, &mut CameraMode)>(); + let (cam_ent, (cam, cam_mode)) = q + .into_iter() + .next() + .unwrap(); + + match *cam_mode { + CameraMode::Kinematic => { + *cam_mode = CameraMode::Debug; + } + CameraMode::Debug => { + *cam_mode = CameraMode::Kinematic; + } + } + } +} diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs new file mode 100644 index 0000000..b27450a --- /dev/null +++ b/game/src/systems/kinematic_character_controller.rs @@ -0,0 +1,187 @@ +use glam::{Quat, Vec3}; +use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder, RigidBodyType}; +use rapier3d::prelude::vector; +use rapier3d::control::{CharacterCollision, KinematicCharacterController as RapierKinematicCharacterController}; +use rapier3d::na::{Isometry3, Vector3}; +use winit::event::DeviceEvent::MouseMotion; +use winit::event::Event; +use winit::keyboard::KeyCode; +use raidillon_app::prelude::*; + +use crate::systems::common::{camera_front, is_camera_mode_valid, is_mouse_look_enabled}; +use crate::systems::menu::MenuState; + +#[derive(Default)] +pub struct KinematicCharacterController { + character_controller: RapierKinematicCharacterController, + character_collider: ColliderBuilder, + + desired_movement: Vec3, + last_position: Vector3, + yaw: f32, + pitch: f32, + speed: f32, + sensitivity: f32, + mouse_delta: (f64, f64), + + vertical_velocity: f32, + gravity: f32, + max_fall_speed: f32, +} + +impl System for KinematicCharacterController { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + // create the rigid body, add it to the body set + let p = scene.resources.get_mut::().expect("Physics missing"); + let rb = RigidBodyBuilder::kinematic_position_based().build(); + let rb_handle = p.rigid_body_set.insert(rb); + self.character_collider = ColliderBuilder::capsule_y(1.0, 1.0); + p.collider_set.insert_with_parent(self.character_collider.build(), rb_handle, &mut p.rigid_body_set); + let tr = Transform { + translation: Vec3::new(0.0, 2.0, 3.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), + }; + self.last_position = vector![ + tr.translation.x, + tr.translation.y, + tr.translation.z, + ]; + scene.world.spawn(( + tr, + CharacterBodyComponent(rb_handle), + )); + + self.speed = 5.0; + self.sensitivity = 0.05; + self.gravity = -9.81; + self.max_fall_speed = -50.0; + self.vertical_velocity = 0.0; + } + + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + if !is_camera_mode_valid(scene, CameraMode::Kinematic) { + return + } + + let pctx = res.get::().unwrap(); + let event2 = pctx.current_event.clone(); + match event2 { + Event::DeviceEvent { device_id, event } => { + match event { + MouseMotion { delta } => { + self.mouse_delta.0 += delta.0; + self.mouse_delta.1 += delta.1; + }, + _ => {} + } + }, + _ => {}, + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let front = camera_front(self.yaw, self.pitch); + let right_vec = front.cross(Vec3::Y).normalize(); + + if is_camera_mode_valid(scene, CameraMode::Kinematic) && is_mouse_look_enabled(scene) { + let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); + + self.yaw += (self.mouse_delta.0 as f32) * self.sensitivity; + self.pitch -= (self.mouse_delta.1 as f32) * self.sensitivity; + self.pitch = self.pitch.clamp(-89.0, 89.0); + + if input.key_held(KeyCode::KeyW) { + self.desired_movement += front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyS) { + self.desired_movement -= front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyA) { + self.desired_movement -= right_vec * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyD) { + self.desired_movement += right_vec * pctx.time_ctx.frame_dt * self.speed; + } + } + + if is_camera_mode_valid(scene, CameraMode::Kinematic) { + let pos = Physics::rapier_translation_to_glam(&self.last_position); + + scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { + // INTERPOLATION NEEDED. + camera.eye = pos; + camera.center = pos + front; + }); + } + + self.mouse_delta = (0.0, 0.0); + } + + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let p = scene.resources.get_mut::().unwrap(); + let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); + + let (ch_ent, (ch_tr, ch_component)) = scene + .world + .query_mut::<(&mut Transform, &mut CharacterBodyComponent)>() + .into_iter() + .next() + .expect("no character entity in world"); + + let query_pipeline = p.broad_phase.as_query_pipeline( + p.narrow_phase.query_dispatcher(), + &p.rigid_body_set, + &p.collider_set, + QueryFilter::default().exclude_rigid_body(ch_component.0), + ); + + self.vertical_velocity = (self.vertical_velocity + self.gravity * pctx.time_ctx.fixed_dt) + .max(self.max_fall_speed); + let mut total_displacement = self.desired_movement; + total_displacement.y += self.vertical_velocity * pctx.time_ctx.fixed_dt; + + let mut collisions: Vec = Vec::new(); + let corrected_movement = self.character_controller.move_shape( + pctx.time_ctx.fixed_dt, + &query_pipeline, + &*self.character_collider.shape, + &Isometry3::from(self.last_position), + vector![total_displacement.x, total_displacement.y, total_displacement.z], + |collision| collisions.push(collision), + ); + + // update character rigid body with the new translation. + if let Some(body) = p.get_rigid_body_mut(ch_component.0) { + self.last_position = vector![ + self.last_position.x + corrected_movement.translation.x, + self.last_position.y + corrected_movement.translation.y, + self.last_position.z + corrected_movement.translation.z, + ]; + body.set_next_kinematic_position(Isometry3::from(self.last_position)); + ch_tr.translation = Physics::rapier_translation_to_glam(&self.last_position); + // reset vertical velocity if grounded + if corrected_movement.grounded { + self.vertical_velocity = 0.0; + } + } + + // apply impulses to dynamic bodies the character collided with + let character_push_force = 50.0; + for collision in collisions { + if let Some(collider) = p.collider_set.get(collision.handle) { + if let Some(rb_handle) = collider.parent() { + if let Some(rb) = p.rigid_body_set.get_mut(rb_handle) { + if rb.body_type() == RigidBodyType::Dynamic { + let push_direction = -collision.hit.normal1.into_inner(); + let impulse = push_direction * character_push_force * pctx.time_ctx.fixed_dt; + rb.apply_impulse(impulse, true); + } + } + } + } + } + + self.desired_movement = Vec3::ZERO; + } +} diff --git a/game/src/systems/menu.rs b/game/src/systems/menu.rs new file mode 100644 index 0000000..8a4b0d5 --- /dev/null +++ b/game/src/systems/menu.rs @@ -0,0 +1,85 @@ +use egui::Id; +use raidillon_app::prelude::*; +use winit::{dpi::{LogicalPosition, Position}, keyboard::KeyCode, window::CursorGrabMode}; + +#[derive(Default)] +pub struct MenuSystem { + escape_key_held: bool, + /// Unoptimal solution to fix windows event delay + times_ran_initial_win_event: u32, +} + +#[derive(Default, Eq, PartialEq, Debug)] +pub enum MenuState { + Open, + #[default] + Closed, +} + +impl System for MenuSystem { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + scene.world.spawn((MenuState::Closed,)); + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + // Windows won't register some events in the first miliseconds after initialization + if self.times_ran_initial_win_event < 20 { + let window = res.get::().unwrap().window.lock().unwrap(); + window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); + window.set_cursor_visible(false); + self.times_ran_initial_win_event += 1 + } + + let mut egui_queue = res.get::().unwrap().egui_queue.borrow_mut(); + egui_queue.queue(|egui_ctx| { + egui::Area::new(Id::new("esc to pause")) + .anchor(egui::Align2::RIGHT_TOP, [-10.0, 10.0]) + .show(egui_ctx, |ui| { + ui.label( + egui::RichText::new("ESC to pause").size(24.0).color(egui::Color32::BLACK) + ); + }); + }); + } + + + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + // The menu is toggled by pressing the escape key + let input = res.get::().unwrap(); + if input.key_held(KeyCode::Escape) { + if self.escape_key_held { return } + self.toggle_menu(res, scene); + self.escape_key_held = true; + } else { + self.escape_key_held = false; + } + } +} + +impl MenuSystem { + fn toggle_menu(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let q = scene.world.query_mut::<(&mut MenuState)>(); + let (menu_ent, menu_state) = q + .into_iter() + .next() + .unwrap(); + + let pctx = res.get::().unwrap(); + let window = pctx.window.lock().unwrap(); + + match *menu_state { + MenuState::Open => { + *menu_state = MenuState::Closed; + window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); + window.set_cursor_visible(false); + pctx.should_egui_receive_input_events.set(false); + }, + MenuState::Closed => { + *menu_state = MenuState::Open; + window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + pctx.should_egui_receive_input_events.set(true); + }, + } + } +} diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs new file mode 100644 index 0000000..08c54ab --- /dev/null +++ b/game/src/systems/mod.rs @@ -0,0 +1,15 @@ +mod physics; +mod physics_debug; +mod kinematic_character_controller; +mod keybinds; +mod menu; +pub mod debug_camera; +pub mod common; +mod display_settings; + +pub use physics::PhysicsSystem; +pub use physics_debug::PhysicsDebugSystem; +pub use kinematic_character_controller::KinematicCharacterController; +pub use keybinds::KeybindsSystem; +pub use menu::MenuSystem; +pub use display_settings::DisplaySettings; diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs new file mode 100644 index 0000000..f660526 --- /dev/null +++ b/game/src/systems/physics.rs @@ -0,0 +1,30 @@ +use raidillon_app::prelude::*; + +/// Do physics calculations and apply to world. +#[derive(Default)] +pub struct PhysicsSystem; + +impl System for PhysicsSystem { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let p = Physics::default(); + scene.resources.insert(p); + } + + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = scene.resources.get_mut::().expect("Physics missing"); + physics.step(pctx.time_ctx.fixed_dt); + + // apply calculations to dynamic bodies + let mut query = scene.world.query::<(&mut Transform, &RigidBodyComponent)>(); + for (_ent, (tr, rb_component)) in query.iter() { + if let Some(body) = physics.get_rigid_body(rb_component.0) { + let pos = body.position(); + let translation = Physics::rapier_translation_to_glam(&pos.translation.vector); + let rotation = Physics::rapier_rotation_to_glam(&pos.rotation); + tr.translation = translation; + tr.rotation = rotation; + } + } + } +} diff --git a/game/src/systems/physics_debug.rs b/game/src/systems/physics_debug.rs new file mode 100644 index 0000000..33364d2 --- /dev/null +++ b/game/src/systems/physics_debug.rs @@ -0,0 +1,35 @@ +use raidillon_app::prelude::*; + +/// renders aabb wireframes for all physics colliders +#[derive(Default)] +pub struct PhysicsDebugSystem; + +impl System for PhysicsDebugSystem { + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().expect("PlatformContext missing").clone(); + + let mut debug_wireframes = pctx.debug_wireframes.borrow_mut(); + if !debug_wireframes.enabled { + return; + } + + let physics = match scene.resources.get::() { + Some(p) => p, + None => return, + }; + + let color = [1.0, 0.0, 0.0, 1.0]; + + for (_, collider) in physics.collider_set.iter() { + let aabb = collider.compute_aabb(); + let min = aabb.mins; + let max = aabb.maxs; + + debug_wireframes.add_box( + [min.x, min.y, min.z], + [max.x, max.y, max.z], + color, + ); + } + } +} diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index 6e51be6..109fc57 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] anyhow = "1.0.98" glam = "0.30.5" -glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +glium = { version = "0.36.0", features = ["glutin_backend", "simple_window_builder"] } gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } raidillon_platform = { path = "../platform" } raidillon_core = { path = "../core" } @@ -15,8 +15,7 @@ raidillon_ecs = { path = "../ecs" } raidillon_engine = { path = "../engine" } winit = "0.30.12" indexmap = "2.10.0" -imgui = "0.12.0" -imgui-winit-support = "0.13.0" -imgui-glium-renderer = "0.13.0" exr = "1.73.0" image = { version = "0.25.8", default-features = false, features = ["exr"] } +egui = "0.33.2" +egui_glium = { version = "0.31.1", git = "https://github.com/reo6/egui_glium.git" } diff --git a/glium_platform/src/assets.rs b/glium_platform/src/assets.rs index 1b3b4e1..c8cb1d4 100644 --- a/glium_platform/src/assets.rs +++ b/glium_platform/src/assets.rs @@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - pub models: HashMap, + pub models: HashMap>, facade: Box, } @@ -28,8 +28,8 @@ impl GliumAssetManager { impl ModelManager for GliumAssetManager { fn load_gltf(&mut self, id: ModelID, path: &Path) { - let model = load_gltf(path, self.facade.as_ref()).unwrap(); - self.models.insert(id, model); + let models = load_gltf(path, self.facade.as_ref()).unwrap(); + self.models.insert(id, models); } fn unload_model(&mut self, id: ModelID) { @@ -48,6 +48,6 @@ impl ModelManager for GliumAssetManager { // } fn get_model(&self, id: &ModelID) -> Option<&dyn Any> { - self.models.get(id).map(|model| model as &dyn Any) + self.models.get(id).map(|models| models as &dyn Any) } } diff --git a/glium_platform/src/gltf_loader.rs b/glium_platform/src/gltf_loader.rs index e41bbfb..fe4ec37 100644 --- a/glium_platform/src/gltf_loader.rs +++ b/glium_platform/src/gltf_loader.rs @@ -1,4 +1,4 @@ -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use glium::{backend::Facade, IndexBuffer, VertexBuffer}; use glium::index::PrimitiveType; use std::{fmt::Debug, path::Path}; @@ -8,31 +8,16 @@ use glium::uniforms::{SamplerWrapFunction, MinifySamplerFilter, MagnifySamplerFi use gltf::image::Format as GltfFormat; use glam::Vec2; -/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. -pub fn load_gltf

(path: P, facade: &dyn Facade) -> Result +/// Load a glTF 2.0 file from disk and upload all primitives to the GPU. +/// +/// Returns one [`Model`] per glTF primitive (across all meshes). +pub fn load_gltf

(path: P, facade: &dyn Facade) -> Result> where P: AsRef + Debug, { // -- parse the asset & bring buffer blobs into memory -- let (doc, buffers, images) = gltf::import(path.as_ref()).context("failed to import glTF file")?; - // -- grab the very first mesh / primitive -- - let mesh = doc.meshes().next().context("glTF has no meshes")?; - let primitive = mesh.primitives().next().context("mesh has no primitives")?; - - // ---------- MATERIAL ---------- - let mut mat = Material::default(); - - let mat_idx = primitive.material().index().context("primitive has no material")?; - let material = doc.materials().nth(mat_idx).unwrap(); - let pbr = material.pbr_metallic_roughness(); - - // Factors -------------------------------------------------- - mat.base_color_factor = pbr.base_color_factor(); - mat.metal_factor = pbr.metallic_factor(); - mat.roughness_factor = pbr.roughness_factor(); - mat.emissive_factor = material.emissive_factor(); - // Helper to update sampler settings from glTF sampler fn update_sampler(mat: &mut Material, t: &gltf::texture::Texture<'_>) { let sampler_info = t.sampler(); @@ -64,64 +49,92 @@ where } } - // Base-color texture (sRGB) - if let Some(info) = pbr.base_color_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); - } + let mut out: Vec = Vec::new(); - // Metallic-Roughness (linear) - if let Some(info) = pbr.metallic_roughness_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); - } + for mesh in doc.meshes() { + for primitive in mesh.primitives() { + // ---------- MATERIAL ---------- + let mut mat = Material::default(); + let material = primitive.material(); + let pbr = material.pbr_metallic_roughness(); - // Normal map (linear) - if let Some(info) = primitive.material().normal_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.normal = Some(glium_linear_texture(facade, &images[view])?); - } + // Factors -------------------------------------------------- + mat.base_color_factor = pbr.base_color_factor(); + mat.metal_factor = pbr.metallic_factor(); + mat.roughness_factor = pbr.roughness_factor(); + mat.emissive_factor = material.emissive_factor(); - // Occlusion (linear) - if let Some(info) = primitive.material().occlusion_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); - } + // Base-color texture (sRGB) + if let Some(info) = pbr.base_color_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); + } - // Emissive (sRGB) - if let Some(info) = primitive.material().emissive_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); - } + // Metallic-Roughness (linear) + if let Some(info) = pbr.metallic_roughness_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); + } - // KHR_texture_transform - if let Some(tex) = pbr.base_color_texture() { - if let Some(xform) = tex.texture_transform() { - mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); - mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + // Normal map (linear) + if let Some(info) = material.normal_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.normal = Some(glium_linear_texture(facade, &images[view])?); + } + + // Occlusion (linear) + if let Some(info) = material.occlusion_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); + } + + // Emissive (sRGB) + if let Some(info) = material.emissive_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); + } + + // KHR_texture_transform (base color only, for now) + if let Some(tex) = pbr.base_color_texture() { + if let Some(xform) = tex.texture_transform() { + mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); + mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + } + } + + // ---- Vertex/index data ---- + let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + + let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); + let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); + let tex_coords: Vec<[f32; 2]> = reader + .read_tex_coords(0) + .map(|tc| tc.into_f32().collect()) + .unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); + let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); + + // Interleave + let vertices: Vec = (0..positions.len()) + .map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }) + .collect(); + + let vbuf = VertexBuffer::immutable(facade, &vertices)?; + let ibuf = IndexBuffer::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + out.push(Model { mesh: Mesh { vbuf, ibuf }, material: mat }); } } - // ---- Vertex/index data ---- - let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + if out.is_empty() { + bail!("glTF has no mesh primitives"); + } - let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); - let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); - let tex_coords: Vec<[f32; 2]> = reader.read_tex_coords(0).map(|tc| tc.into_f32().collect()).unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); - let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); - - // Interleave - let vertices: Vec = (0..positions.len()).map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }).collect(); - - let vbuf = VertexBuffer::immutable(facade, &vertices)?; - let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; - - Ok(Model { mesh: Mesh { vbuf, ibuf }, material: mat }) + Ok(out) } /// Linear-space texture (RGBA8) from glTF image data. diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index db8e56e..8f00d92 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,7 +1,7 @@ -use std::cell::RefCell; +use std::cell::{RefCell, Cell}; use std::rc::Rc; -use std::sync::{Arc, Mutex}; -use raidillon_platform::{Platform, PlatformContext, TimeContext}; +use std::sync::{Arc, Mutex, RwLock}; +use raidillon_platform::{Platform, PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef}; use glium::backend::glutin::Display; use glium::backend::glutin::SimpleWindowBuilder; use glium::glutin::surface::WindowSurface; @@ -14,11 +14,12 @@ use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; use raidillon_core::time; use raidillon_core::time::Time; -use crate::render::debug_ui::ImguiBridge; -use crate::render::{BasicMeshRenderingSystem, SkyboxRenderingSystem}; +use crate::render::{BasicMeshRenderingSystem, DebugWireframeRenderingSystem, EguiRenderer, SkyboxRenderingSystem}; use crate::GliumAssetManager; use glam::Vec3; use winit::event::DeviceEvent::MouseMotion; +use raidillon_core::EguiQueue; +use raidillon_platform::settings::{Settings, default_config_path}; pub struct GliumPlatform> { event_loop: EventLoop<()>, @@ -28,6 +29,10 @@ pub struct GliumPlatform> { asset_manager: ModelManagerRef, engine: E, time: time::Time, + egui_queue: Rc>, + settings: Arc>, + debug_wireframes: DebugWireframesRef, + should_egui_receive_input_events: Rc>, } impl> Platform for GliumPlatform { @@ -50,9 +55,20 @@ impl> Platform for GliumPlatfor let window = Arc::new(Mutex::new(window)); // Install rendering systems in order - rendering_system_manager.add::(&display, window.clone()); - rendering_system_manager.add::(&display, window.clone()); - rendering_system_manager.add::(&display, window.clone()); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + + let egui_queue = Rc::new(RefCell::new(EguiQueue::new())); + + let settings = Arc::new( + RwLock::new( + Settings::load_or_default(default_config_path()).unwrap() + ) + ); + let debug_wireframes = Rc::new(RefCell::new(DebugWireframes::new())); + let should_egui_receive_input_events = Rc::new(Cell::new(false)); Self { event_loop, @@ -62,6 +78,10 @@ impl> Platform for GliumPlatfor asset_manager, engine, time, + egui_queue, + settings, + debug_wireframes, + should_egui_receive_input_events, } } @@ -77,9 +97,21 @@ impl> Platform for GliumPlatfor frame_height: h as f32, time_ctx: self.construct_time_ctx(), window: self.window.clone(), + egui_queue: self.egui_queue.clone(), + settings: self.settings.clone(), + debug_wireframes: self.debug_wireframes.clone(), + should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; self.engine.initialize(ctx.clone()); + self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap()); + let _ = &self.event_loop.run(move |event, el| { + let settings_handle = self.settings.read().unwrap(); + if settings_handle.display_settings.dirty { + settings_handle.display_settings.apply(&*self.window.lock().unwrap()); + } + drop(settings_handle); + self.rendering_system_manager .systems .values_mut() @@ -91,24 +123,30 @@ impl> Platform for GliumPlatfor match event { Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(size) => { + if size.width > 0 && size.height > 0 { + self.display.resize((size.width, size.height)); + } + }, WindowEvent::CloseRequested => { // TODO: Run uninitialize on renderer and engine + self.settings.read().unwrap().save_to_file(default_config_path()); el.exit(); }, WindowEvent::RedrawRequested => { let mut target = self.display.draw(); target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); - let (scene, debug_ui_buffer) = ( - self.engine.current_scene(), - self.engine.get_debug_ui_buffer(), - ); + let scene = self.engine.current_scene(); let mut context = RenderingContext { scene, target: &mut target, + display: &self.display, asset_manager: self.asset_manager.clone(), window: self.window.clone(), - debug_ui_buffer, + egui_queue: self.egui_queue.clone(), + debug_wireframes: self.debug_wireframes.clone(), env_light_dir: Vec3::new(0.0, -1.0, 0.0), + should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; self.rendering_system_manager @@ -116,6 +154,9 @@ impl> Platform for GliumPlatfor .values_mut() .for_each(|system| system.render(&mut context)); + // clear debug wireframes after rendering + self.debug_wireframes.borrow_mut().clear(); + target.finish().unwrap(); } _ => {}, diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 663b2dd..6553cc0 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -9,6 +9,8 @@ use raidillon_assets::include_shader; pub use raidillon_platform::Camera; use glam::Vec3; use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; +use winit::event::Event; +use winit::event_loop::EventLoop; use raidillon_ecs::{Transform, ModelID}; use raidillon_ecs::components::ModelHandle; use crate::model::Model; @@ -21,7 +23,7 @@ pub struct BasicMeshRenderingSystem { } impl RenderingSystem for BasicMeshRenderingSystem { - fn initialize(display: &Display, _window: Arc>) -> Self { + fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self { const VERT_SRC: &str = include_shader!("gl_textured.vert"); const FRAG_SRC: &str = include_shader!("gl_textured.frag"); @@ -57,7 +59,11 @@ impl RenderingSystem for BasicMeshRenderingSystem { }; // Use HDR-derived environment light direction if provided, otherwise default to downward - let light_dir: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) }; + let light_dir_world: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) }; + + // Transform light direction to view space (normals/positions are in view space) + let view_mat3 = glam::Mat3::from_mat4(cam.view()); + let light_dir_view = (view_mat3 * light_dir_world).normalize(); let asset_manager = ctx.asset_manager.borrow(); @@ -67,41 +73,43 @@ impl RenderingSystem for BasicMeshRenderingSystem { _ => continue, }; - let model = match model.downcast_ref::() { - Some(model) => model, + let models = match model.downcast_ref::>() { + Some(models) => models, None => continue, }; - let mesh = &model.mesh; - let mat = &model.material; + for model in models { + let mesh = &model.mesh; + let mat = &model.material; - let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); + let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); - let mut sampler = tex_ref.sampled(); - sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); - sampler = sampler.minify_filter(MinifySamplerFilter::Linear); - sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + let mut sampler = tex_ref.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); - let c = mat.base_color_factor; + let c = mat.base_color_factor; - let uniforms = uniform! { - model: tr.matrix().to_cols_array_2d(), - view: cam.view().to_cols_array_2d(), - projection: cam.projection().to_cols_array_2d(), - u_light: [light_dir.x, light_dir.y, light_dir.z], - tex: sampler, - color: [c[0], c[1], c[2]], - uv_offset: [mat.uv_offset.x, mat.uv_offset.y], - uv_scale: [mat.uv_scale.x, mat.uv_scale.y], - }; + let uniforms = uniform! { + model: tr.matrix().to_cols_array_2d(), + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + u_light: [light_dir_view.x, light_dir_view.y, light_dir_view.z], + tex: sampler, + color: [c[0], c[1], c[2]], + uv_offset: [mat.uv_offset.x, mat.uv_offset.y], + uv_scale: [mat.uv_scale.x, mat.uv_scale.y], + }; - ctx.target.draw( - &mesh.vbuf, - &mesh.ibuf, - &self.program, - &uniforms, - &self.params, - ).unwrap(); + ctx.target.draw( + &mesh.vbuf, + &mesh.ibuf, + &self.program, + &uniforms, + &self.params, + ).unwrap(); + } } } } diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs deleted file mode 100644 index ac4a06e..0000000 --- a/glium_platform/src/render/debug_ui.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::sync::{Arc, Mutex}; -use std::time::Instant; -use glium::Display; -use glium::glutin::surface::WindowSurface; -use imgui::{Context as ImguiContext}; -use imgui_winit_support::{HiDpiMode, WinitPlatform}; -use imgui_glium_renderer::Renderer as ImguiGliumRenderer; -use winit::window::Window; -use winit::event::Event; -use glium::Frame; -use crate::RenderingSystem; -use crate::system::RenderingContext; - -pub struct ImguiBridge { - imgui: ImguiContext, - platform: WinitPlatform, - renderer: ImguiGliumRenderer, - last_frame: Instant, - rendered_this_frame: bool, -} - -impl RenderingSystem for ImguiBridge { - fn handle_event(&mut self, window: Arc>, event: Event<()>) { - let window = window.lock().unwrap(); - self.platform.handle_event(self.imgui.io_mut(), &*window, &event); - } - - fn prepare_frame(&mut self, window: Arc>) { - self.rendered_this_frame = false; - let now = Instant::now(); - self.imgui.io_mut().update_delta_time(now - self.last_frame); - self.last_frame = now; - let window = window.lock().unwrap(); - self.platform - .prepare_frame(self.imgui.io_mut(), &*window) - .expect("Failed to prepare frame"); - } - - fn render(&mut self, ctx: &mut RenderingContext) { - if self.rendered_this_frame { return; } - self.rendered_this_frame = true; - - let ui = self.imgui.frame(); - ctx.debug_ui_buffer.write_buffer(&ui); - - { - let window = ctx.window.lock().unwrap(); - self.platform.prepare_render(&ui, &*window); - } - let draw_data = self.imgui.render(); - if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 { - return; - } - - self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); - } - - fn initialize(display: &Display, window: Arc>) -> Self { - let mut imgui = ImguiContext::create(); - imgui.set_ini_filename(None); - let mut platform = WinitPlatform::new(&mut imgui); - let window = window.lock().unwrap(); - platform.attach_window(imgui.io_mut(), &*window, HiDpiMode::Default); - imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); - let renderer = ImguiGliumRenderer::new(&mut imgui, display).unwrap(); - - Self { - imgui, - platform, - renderer, - last_frame: Instant::now(), - rendered_this_frame: false, - } - } -} diff --git a/glium_platform/src/render/debug_wireframe.rs b/glium_platform/src/render/debug_wireframe.rs new file mode 100644 index 0000000..2f259e9 --- /dev/null +++ b/glium_platform/src/render/debug_wireframe.rs @@ -0,0 +1,80 @@ +use std::sync::{Arc, Mutex}; +use glium::{Display, Program, Surface, VertexBuffer, implement_vertex}; +use glium::glutin::surface::WindowSurface; +use glium::index::PrimitiveType; +use glium::uniform; +use winit::event_loop::EventLoop; +use raidillon_assets::include_shader; +use crate::system::RenderingContext; +use crate::RenderingSystem; +pub use raidillon_platform::Camera; + +#[derive(Copy, Clone)] +struct DebugVertex { + position: [f32; 3], + color: [f32; 4], +} + +implement_vertex!(DebugVertex, position, color); + +/// renders debug wireframes from the shared buffer +pub struct DebugWireframeRenderingSystem { + program: Program, + params: glium::DrawParameters<'static>, +} + +impl RenderingSystem for DebugWireframeRenderingSystem { + fn initialize(display: &Display, _window: Arc>, _event_loop: &EventLoop<()>) -> Self { + const VERT_SRC: &str = include_shader!("debug_wireframe.vert"); + const FRAG_SRC: &str = include_shader!("debug_wireframe.frag"); + + let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: false, + ..Default::default() + }, + line_width: Some(1.0), + ..Default::default() + }; + + Self { program, params } + } + + fn render(&mut self, ctx: &mut RenderingContext) { + let debug_wireframes = ctx.debug_wireframes.borrow(); + + if !debug_wireframes.enabled || debug_wireframes.vertices.is_empty() { + return; + } + + let cam = match ctx.scene.world.query::<&Camera>().iter().next() { + Some((_, cam)) => *cam, + None => return, + }; + + let vertices: Vec = debug_wireframes.vertices.iter() + .map(|v| DebugVertex { position: v.position, color: v.color }) + .collect(); + + let vbuf = match VertexBuffer::new(ctx.display, &vertices) { + Ok(vb) => vb, + Err(_) => return, + }; + + let uniforms = uniform! { + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + }; + + ctx.target.draw( + &vbuf, + glium::index::NoIndices(PrimitiveType::LinesList), + &self.program, + &uniforms, + &self.params, + ).ok(); + } +} diff --git a/glium_platform/src/render/egui.rs b/glium_platform/src/render/egui.rs new file mode 100644 index 0000000..3cd0583 --- /dev/null +++ b/glium_platform/src/render/egui.rs @@ -0,0 +1,74 @@ +use std::sync::{Arc, Mutex}; +use egui::ViewportId; +use glium::{Display, Frame}; +use glium::glutin::surface::WindowSurface; +use winit::window::Window; +use crate::RenderingSystem; +use crate::system::RenderingContext; +use egui_glium::EguiGlium; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::EventLoop; +use std::cell::Cell; +use std::rc::Rc; + +pub struct EguiRenderer { + egui_glium: EguiGlium, + should_egui_receive_input_events: Option>>, +} + +impl RenderingSystem for EguiRenderer { + fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self + where + Self: Sized, + { + let window = window.lock().unwrap(); + let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop); + + Self { egui_glium: egui_glium, should_egui_receive_input_events: None } + } + + fn render(&mut self, ctx: &mut RenderingContext) { + if self.should_egui_receive_input_events.is_none() { + self.should_egui_receive_input_events = Some(ctx.should_egui_receive_input_events.clone()); + } + + let window = ctx.window.lock().unwrap(); + + self.egui_glium.run(&window, |egui_ctx| { + ctx.egui_queue.borrow_mut().run(egui_ctx); + }); + + self.egui_glium.paint(ctx.display, ctx.target); + } + + fn handle_event(&mut self, window: Arc>, event: Event<()>) { + let window = window.lock().unwrap(); + match event { + Event::WindowEvent { event, .. } => { + let should_egui_receive_input_events = match self.should_egui_receive_input_events.as_ref() { + Some(v) => v.get(), + None => true, + }; + + let should_send_event = if should_egui_receive_input_events { + true + } else { + !matches!(event, + WindowEvent::KeyboardInput { .. } | + WindowEvent::ModifiersChanged(_) | + WindowEvent::CursorMoved { .. } | + WindowEvent::MouseInput { .. } | + WindowEvent::MouseWheel { .. } | + WindowEvent::Touch(_) | + WindowEvent::Ime(_) + ) + }; + + if should_send_event { + let _ = self.egui_glium.on_event(&window, &event); + } + } + _ => {}, + } + } +} diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index f49e308..22aa047 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,6 +1,9 @@ mod basic; -pub mod debug_ui; mod skybox; +mod egui; +mod debug_wireframe; pub use basic::BasicMeshRenderingSystem; pub use skybox::SkyboxRenderingSystem; +pub use egui::EguiRenderer; +pub use debug_wireframe::DebugWireframeRenderingSystem; diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs index ac22210..d11683b 100644 --- a/glium_platform/src/render/skybox.rs +++ b/glium_platform/src/render/skybox.rs @@ -7,7 +7,9 @@ use glium::glutin::surface::WindowSurface; use glium::index::PrimitiveType; use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d}; use glium::uniform; +use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; use glam::{Mat4, Vec2, Vec3}; +use winit::event_loop::EventLoop; use raidillon_assets::include_shader; use crate::system::RenderingContext; use crate::RenderingSystem; @@ -109,7 +111,7 @@ impl SkyboxRenderingSystem { } impl RenderingSystem for SkyboxRenderingSystem { - fn initialize(display: &Display, _window: Arc>) -> Self { + fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self { const VERT_SRC: &str = include_shader!("skybox.vert"); const FRAG_SRC: &str = include_shader!("skybox.frag"); let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); @@ -117,7 +119,7 @@ impl RenderingSystem for SkyboxRenderingSystem { // Load EXR from assets/exr let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let path = std::path::Path::new(manifest_dir).join("../assets/exr/qwantani_sunset_puresky_2k.exr"); + let path = std::path::Path::new(manifest_dir).join("../assets/exr/citrus_orchard_road_puresky_4k.exr"); let (equirect_srgb, light_dir) = Self::load_hdr_equirect_and_analyze(display, &path); Self { program, quad_vb, quad_ib, equirect_srgb, light_dir } } @@ -131,10 +133,15 @@ impl RenderingSystem for SkyboxRenderingSystem { let mut view = cam.view(); // remove translation from view matrix (only orientation) view.col_mut(3).x = 0.0; view.col_mut(3).y = 0.0; view.col_mut(3).z = 0.0; + let mut sampler = self.equirect_srgb.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + let uniforms = uniform! { view: view.to_cols_array_2d(), projection: cam.projection().to_cols_array_2d(), - equirect: &self.equirect_srgb, + equirect: sampler, }; let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLessOrEqual, write: false, ..Default::default() }, ..Default::default() }; ctx.target.draw(&self.quad_vb, &self.quad_ib, &self.program, &uniforms, ¶ms).ok(); diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 51a292f..cf5f945 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -6,17 +6,23 @@ use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; -use raidillon_core::{define_typemap, DebugUIBuffer}; +use raidillon_core::{define_typemap, EguiQueue}; use raidillon_core::scene::Scene; +use raidillon_platform::DebugWireframesRef; use glam::Vec3; +use winit::event_loop::EventLoop; +use std::cell::Cell; pub struct RenderingContext<'a> { pub scene: &'a Scene, pub target: &'a mut Frame, pub window: Arc>, + pub display: &'a Display, pub asset_manager: ModelManagerRef, - pub debug_ui_buffer: &'a DebugUIBuffer, + pub egui_queue: Rc>, + pub debug_wireframes: DebugWireframesRef, pub env_light_dir: Vec3, + pub should_egui_receive_input_events: Rc> } /// The internal "rendering system" trait of glium_platform. @@ -30,7 +36,7 @@ pub trait RenderingSystem { } fn prepare_frame(&mut self, _window: Arc>) {} fn render(&mut self, ctx: &mut RenderingContext); - fn initialize(display: &Display, window: Arc>) -> Self + fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self where Self: Sized; } @@ -48,11 +54,11 @@ impl RenderingSystemManager { } } - pub fn add(&mut self, display: &Display, window: Arc>) + pub fn add(&mut self, display: &Display, window: Arc>, event_loop: &EventLoop<()>) where R: RenderingSystem + 'static, { - let system = R::initialize(display, window); + let system = R::initialize(display, window, event_loop); self.systems.insert(TypeId::of::(), Box::new(system)); } diff --git a/physics/Cargo.toml b/physics/Cargo.toml new file mode 100644 index 0000000..dc34e98 --- /dev/null +++ b/physics/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "raidillon_physics" +version = "0.1.0" +edition = "2024" + +[dependencies] +rapier3d = "0.30.1" +raidillon_ecs = { path = "../ecs" } +glam = "0.30.8" \ No newline at end of file diff --git a/physics/src/lib.rs b/physics/src/lib.rs new file mode 100644 index 0000000..a5dafc6 --- /dev/null +++ b/physics/src/lib.rs @@ -0,0 +1,3 @@ +mod physics; + +pub use crate::physics::Physics; diff --git a/physics/src/physics.rs b/physics/src/physics.rs new file mode 100644 index 0000000..5eff699 --- /dev/null +++ b/physics/src/physics.rs @@ -0,0 +1,82 @@ +use glam::{Quat, Vec3}; +use rapier3d::na::{Quaternion, UnitQuaternion}; +use rapier3d::prelude::*; +use raidillon_ecs::Transform; + +/// Tiny wrapper around rapier3d. +pub struct Physics { + pub rigid_body_set: RigidBodySet, + pub collider_set: ColliderSet, + physics_pipeline: PhysicsPipeline, + island_manager: IslandManager, + pub broad_phase: DefaultBroadPhase, + pub narrow_phase: NarrowPhase, + impulse_joint_set: ImpulseJointSet, + multibody_joint_set: MultibodyJointSet, + ccd_solver: CCDSolver, + gravity: Vector, + integration_parameters: IntegrationParameters, +} + +impl Default for Physics { + fn default() -> Self { + Self { + gravity: vector![0.0, -9.81, 0.0], + rigid_body_set: Default::default(), + collider_set: Default::default(), + physics_pipeline: Default::default(), + island_manager: Default::default(), + broad_phase: Default::default(), + narrow_phase: Default::default(), + impulse_joint_set: Default::default(), + multibody_joint_set: Default::default(), + ccd_solver: Default::default(), + integration_parameters: Default::default(), + } + } +} + +impl Physics { + pub fn step(&mut self, dt: f32) { + self.integration_parameters.dt = dt; + self.physics_pipeline.step( + &self.gravity, + &self.integration_parameters, + &mut self.island_manager, + &mut self.broad_phase, + &mut self.narrow_phase, + &mut self.rigid_body_set, + &mut self.collider_set, + &mut self.impulse_joint_set, + &mut self.multibody_joint_set, + &mut self.ccd_solver, + &(), + &(), + ); + } + + pub fn add_rigid_body(&mut self, kind: RigidBodyType, transform: Transform, collider: Collider) -> RigidBodyHandle { + let rb = RigidBodyBuilder::new(kind) + .translation(vector![transform.translation.x, transform.translation.y, transform.translation.z]) + .build(); + let rb_handle = self.rigid_body_set.insert(rb); + self.collider_set.insert_with_parent(collider, rb_handle, &mut self.rigid_body_set); + rb_handle + } + + pub fn get_rigid_body(&self, handle: RigidBodyHandle) -> Option<&RigidBody> { + self.rigid_body_set.get(handle) + } + + pub fn get_rigid_body_mut(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> { + self.rigid_body_set.get_mut(handle) + } + + pub fn rapier_translation_to_glam(v: &Vector) -> Vec3 { + Vec3::new(v.x, v.y, v.z) + } + + pub fn rapier_rotation_to_glam(r: &UnitQuaternion) -> Quat { + Quat::from_xyzw(r.i, r.j, r.k, r.w) + } +} diff --git a/platform/Cargo.toml b/platform/Cargo.toml index 3b42bac..16fec56 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -8,3 +8,5 @@ winit = "0.30.12" raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } glam = "0.30.5" +serde = { version = "1.0.228", features = ["derive"] } +toml = "0.9.8" diff --git a/platform/src/context.rs b/platform/src/context.rs index 892b69e..31bd6cb 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -1,6 +1,66 @@ -use std::sync::{Arc, Mutex}; +use std::cell::Cell; +use std::{cell::RefCell, rc::Rc}; +use std::sync::{Arc, Mutex, RwLock}; use winit::event::Event; use raidillon_assets::ModelManagerRef; +use raidillon_core::EguiQueue; +use crate::settings::Settings; + +/// a single debug wireframe vertex with position and color +#[derive(Clone, Copy)] +pub struct DebugWireframeVertex { + pub position: [f32; 3], + pub color: [f32; 4], +} + +/// shared buffer for debug wireframe rendering +#[derive(Clone, Default)] +pub struct DebugWireframes { + pub vertices: Vec, + pub enabled: bool, +} + +impl DebugWireframes { + pub fn new() -> Self { + Self { vertices: Vec::new(), enabled: true } + } + + pub fn clear(&mut self) { + self.vertices.clear(); + } + + /// add a single line segment + pub fn add_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) { + self.vertices.push(DebugWireframeVertex { position: start, color }); + self.vertices.push(DebugWireframeVertex { position: end, color }); + } + + /// add a wireframe box from min/max corners + pub fn add_box(&mut self, min: [f32; 3], max: [f32; 3], color: [f32; 4]) { + let [x0, y0, z0] = min; + let [x1, y1, z1] = max; + + // bottom face edges + self.add_line([x0, y0, z0], [x1, y0, z0], color); + self.add_line([x1, y0, z0], [x1, y0, z1], color); + self.add_line([x1, y0, z1], [x0, y0, z1], color); + self.add_line([x0, y0, z1], [x0, y0, z0], color); + + // top face edges + self.add_line([x0, y1, z0], [x1, y1, z0], color); + self.add_line([x1, y1, z0], [x1, y1, z1], color); + self.add_line([x1, y1, z1], [x0, y1, z1], color); + self.add_line([x0, y1, z1], [x0, y1, z0], color); + + // vertical edges + self.add_line([x0, y0, z0], [x0, y1, z0], color); + self.add_line([x1, y0, z0], [x1, y1, z0], color); + self.add_line([x1, y0, z1], [x1, y1, z1], color); + self.add_line([x0, y0, z1], [x0, y1, z1], color); + } +} + +pub type DebugWireframesRef = Rc>; #[derive(Clone)] pub struct PlatformContext { @@ -10,6 +70,12 @@ pub struct PlatformContext { pub frame_height: f32, pub time_ctx: TimeContext, pub window: Arc>, + pub egui_queue: Rc>, + pub settings: Arc>, + /// shared debug wireframe buffer + pub debug_wireframes: DebugWireframesRef, + /// sets whether or not egui will receive input events + pub should_egui_receive_input_events: Rc>, } #[derive(Clone)] diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 8875d35..ef88e08 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -2,7 +2,8 @@ pub mod platform; mod camera; mod event; pub mod context; +pub mod settings; pub use platform::Platform; pub use camera::Camera; -pub use context::{PlatformContext, TimeContext}; +pub use context::{PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef, DebugWireframeVertex}; diff --git a/platform/src/settings.rs b/platform/src/settings.rs new file mode 100644 index 0000000..a901137 --- /dev/null +++ b/platform/src/settings.rs @@ -0,0 +1,166 @@ +use winit::monitor::{MonitorHandle, VideoModeHandle}; +use winit::window::{Fullscreen, Window}; +use serde::{Serialize, Deserialize}; +use std::error::Error; +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +pub fn default_config_path() -> PathBuf { + let exe_path = std::env::current_exe().unwrap(); + let exe_dir = exe_path + .parent() + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "executable has no parent")).unwrap(); + + exe_dir.join("settings.toml") +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "snake_case")] +pub enum WindowMode { + BorderlessFullscreen, + ExclusiveFullscreen, + #[default] + Windowed, +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct Settings { + pub display_settings: DisplaySettings, +} + +impl Settings { + pub fn load_from_file(path: impl AsRef) -> Result> { + let path = path.as_ref(); + let text = fs::read_to_string(path)?; + let settings: Settings = toml::from_str(&text)?; + Ok(settings) + } + + pub fn save_to_file(&self, path: impl AsRef) -> Result<(), Box> { + let path = path.as_ref(); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let toml_str = toml::to_string_pretty(self)?; + fs::write(path, toml_str)?; + Ok(()) + } + + pub fn load_or_default(path: impl AsRef) -> Result> { + let path = path.as_ref(); + + match fs::read_to_string(path) { + Ok(text) => { + let settings: Settings = toml::from_str(&text)?; + Ok(settings) + } + Err(err) if err.kind() == io::ErrorKind::NotFound => { + let settings = Settings::default(); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let toml_str = toml::to_string_pretty(&settings)?; + fs::write(path, toml_str)?; + Ok(settings) + } + Err(err) => Err(Box::new(err)), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct DisplaySettings { + pub fullscreen_mode: WindowMode, + #[serde(skip)] + pub dirty: bool, +} + +impl Default for DisplaySettings { + fn default() -> Self { + Self { + fullscreen_mode: WindowMode::Windowed, + dirty: false, + } + } +} + +impl DisplaySettings { + pub fn apply(&self, window: &Window) { + // apply fullscreen mode + match self.fullscreen_mode { + WindowMode::BorderlessFullscreen => { + let monitor = window.current_monitor().or_else(|| window.primary_monitor()); + window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); + } + WindowMode::ExclusiveFullscreen => { + let monitor = window.current_monitor().or_else(|| window.primary_monitor()); + match monitor { + Some(monitor) => { + if let Some(video_mode) = pick_best_video_mode(&monitor) { + window.set_fullscreen(Some(Fullscreen::Exclusive(video_mode))); + } else { + // fallback to borderless + window.set_fullscreen(Some(Fullscreen::Borderless(Some(monitor)))); + } + } + None => { + // no monitor info, fallback to windowed + window.set_fullscreen(None); + } + } + } + WindowMode::Windowed => { + window.set_fullscreen(None); + }, + } + } +} + +fn pick_best_video_mode(monitor: &MonitorHandle) -> Option { + let target_size = monitor.size(); + + let mut best_native: Option = None; + let mut best_any: Option = None; + + for mode in monitor.video_modes() { + if mode.size() == target_size { + let replace = match best_native.as_ref() { + None => true, + Some(best) => { + (mode.refresh_rate_millihertz(), mode.bit_depth()) + > (best.refresh_rate_millihertz(), best.bit_depth()) + } + }; + if replace { + best_native = Some(mode.clone()); + } + } + + let replace = match best_any.as_ref() { + None => true, + Some(best) => is_better_video_mode(&mode, best), + }; + if replace { + best_any = Some(mode); + } + } + + best_native.or(best_any) +} + +fn is_better_video_mode(a: &VideoModeHandle, b: &VideoModeHandle) -> bool { + let a_size = a.size(); + let b_size = b.size(); + let a_area = u64::from(a_size.width) * u64::from(a_size.height); + let b_area = u64::from(b_size.width) * u64::from(b_size.height); + + match a_area.cmp(&b_area) { + std::cmp::Ordering::Greater => true, + std::cmp::Ordering::Less => false, + std::cmp::Ordering::Equal => { + (a.refresh_rate_millihertz(), a.bit_depth()) > (b.refresh_rate_millihertz(), b.bit_depth()) + } + } +}