diff --git a/Cargo.lock b/Cargo.lock index 807876b..d5c544f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,53 +20,66 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" -version = "0.21.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" +checksum = "5351dcebb14b579ccab05f288596b2ae097005be7ee50a7c3d4ca9d0d5a66f6a" +dependencies = [ + "uuid", +] [[package]] name = "accesskit_consumer" -version = "0.31.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db81010a6895d8707f9072e6ce98070579b43b717193d2614014abd5cb17dd43" +checksum = "53cf47daed85312e763fbf85ceca136e0d7abc68e0a7e12abe11f48172bc3b10" dependencies = [ "accesskit", - "hashbrown 0.15.5", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_consumer" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e0d7e25d06f4dc21d1774d67146e9e80d6789216cbd4d1e88185b0095dba60" +dependencies = [ + "accesskit", + "hashbrown 0.16.1", ] [[package]] name = "accesskit_macos" -version = "0.22.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0089e5c0ac0ca281e13ea374773898d9354cc28d15af9f0f7394d44a495b575" +checksum = "4c5c87e8d94f2ec10cce590aadff24c76f576dab5502d45d0aed9fc3065d4451" dependencies = [ "accesskit", - "accesskit_consumer", - "hashbrown 0.15.5", + "accesskit_consumer 0.36.0", + "hashbrown 0.16.1", "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] name = "accesskit_windows" -version = "0.29.2" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d63dd5041e49c363d83f5419a896ecb074d309c414036f616dc0b04faca971" +checksum = "eff7009f1a532e917d66970a1e80c965140c6cfbbabbdde3d64e5431e6c78e21" dependencies = [ "accesskit", - "accesskit_consumer", - "hashbrown 0.15.5", + "accesskit_consumer 0.35.0", + "hashbrown 0.16.1", "static_assertions", - "windows 0.61.3", - "windows-core 0.61.2", + "windows", + "windows-core", ] [[package]] name = "accesskit_winit" -version = "0.29.2" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cfabe59d0eaca7412bfb1f70198dd31e3b0496fee7e15b066f9c36a1a140a0" +checksum = "1fe9a94394896352cc4660ca2288bd4ef883d83238853c038b44070c8f134313" dependencies = [ "accesskit", "accesskit_macos", @@ -104,26 +117,10 @@ dependencies = [ ] [[package]] -name = "alsa" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" -dependencies = [ - "alsa-sys", - "bitflags 2.11.1", - "cfg-if", - "libc", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-activity" @@ -134,14 +131,13 @@ dependencies = [ "android-properties", "bitflags 2.11.1", "cc", - "jni 0.22.4", + "jni", "libc", "log", - "ndk 0.9.0", + "ndk", "ndk-context", - "ndk-sys 0.6.0+11769913", + "ndk-sys", "num_enum", - "simd_cesu8", "thiserror 2.0.18", ] @@ -327,9 +323,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -339,18 +335,35 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bevy" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd310426290cec560221f9750c2f4484be4a8eeea7de3483c423329b465c40e" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_internal", ] +[[package]] +name = "bevy-settings" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_ecs_macros", + "bevy_log", + "bevy_platform", + "bevy_reflect", + "bevy_tasks", + "bevy_time", + "serde", + "thiserror 2.0.18", + "toml", + "web-sys", +] + [[package]] name = "bevy_a11y" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e887b25c84f384ffe3278a17cf0e4b405eaa3c8fbc3db24d05d560a11780676d" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "accesskit", "bevy_app", @@ -361,18 +374,16 @@ dependencies = [ [[package]] name = "bevy_android" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c58de772ac1148884112e8a456c4f127a94b95a0e42ab5b160b7a11895a241" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "android-activity", ] [[package]] name = "bevy_animation" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5bf5b285f0d3fab983b4505e62e195e06930a29007ffc95bdabde834e163a2" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_animation_macros", "bevy_app", @@ -403,9 +414,8 @@ dependencies = [ [[package]] name = "bevy_animation_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf35516d0e7ac9ec25df533be1bf8cbaa20596a8e65f36838a3f7803a267d6d" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "quote", @@ -414,9 +424,8 @@ dependencies = [ [[package]] name = "bevy_anti_alias" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726cc494eb7d6a84ce6291c23636fd451fa4846604dc059fa93febca4e60a928" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -438,9 +447,8 @@ dependencies = [ [[package]] name = "bevy_app" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def9f41aa5bf9b9dec8beda307a332798609cffb9d44f71005e0cfb45164f2f6" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_derive", "bevy_ecs", @@ -448,7 +456,6 @@ dependencies = [ "bevy_reflect", "bevy_tasks", "bevy_utils", - "cfg-if", "console_error_panic_hook", "ctrlc", "downcast-rs 2.0.2", @@ -461,9 +468,8 @@ dependencies = [ [[package]] name = "bevy_asset" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f86fed15972b9fb1a3f7b092cf0390e67131caaedab15a2707c043e3a3c886" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "async-broadcast", "async-channel", @@ -504,9 +510,8 @@ dependencies = [ [[package]] name = "bevy_asset_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cb8d948365b06561b43b7d709282e62a6abb756baac5d8e295206d5e156168" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "proc-macro2", @@ -514,29 +519,10 @@ dependencies = [ "syn", ] -[[package]] -name = "bevy_audio" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d68da32468ce7f4bb2863b71326acfaaa88e9aef8da8306257cd487d40cede4" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_transform", - "coreaudio-sys", - "cpal", - "rodio", - "tracing", -] - [[package]] name = "bevy_camera" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ed9eed054e14341852236d06a7244597b1ace39ff9ae023fbd188ffde88619" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -558,11 +544,24 @@ dependencies = [ "wgpu-types", ] +[[package]] +name = "bevy_clipboard" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_log", + "bevy_platform", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "bevy_color" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb41e8310a85811d14a4e75cfc2d6c07ac70661d6a4883509fc960f622970a8" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_math", "bevy_reflect", @@ -574,32 +573,10 @@ dependencies = [ "wgpu-types", ] -[[package]] -name = "bevy_config" -version = "0.1.0" -dependencies = [ - "bevy", - "bevy_anti_alias", - "bevy_app", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_render", - "bevy_window", - "directories", - "ron", - "serde", - "serde_json", - "thiserror 2.0.18", - "web-sys", - "wgpu-types", -] - [[package]] name = "bevy_core_pipeline" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0810e85c2436e50c67448d48a83bf0bb1b5849899619ae2c7ea817221e9172" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -609,6 +586,8 @@ dependencies = [ "bevy_diagnostic", "bevy_ecs", "bevy_image", + "bevy_light", + "bevy_log", "bevy_math", "bevy_platform", "bevy_reflect", @@ -618,18 +597,14 @@ dependencies = [ "bevy_utils", "bevy_window", "bitflags 2.11.1", + "indexmap", "nonmax", - "radsort", - "smallvec", - "thiserror 2.0.18", - "tracing", ] [[package]] name = "bevy_derive" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318ee0532c3da93749859d18f89a889c638fbc56aabac4d866583df7b951d103" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "quote", @@ -638,19 +613,22 @@ dependencies = [ [[package]] name = "bevy_dev_tools" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f1464a3f5ef5c23d917987714ee89881f9f791e9ff97ecf6600ee846b9569e" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", "bevy_camera", "bevy_color", + "bevy_core_pipeline", "bevy_diagnostic", "bevy_ecs", "bevy_image", "bevy_input", + "bevy_log", "bevy_math", + "bevy_mesh", + "bevy_pbr", "bevy_picking", "bevy_reflect", "bevy_render", @@ -662,14 +640,14 @@ dependencies = [ "bevy_ui", "bevy_ui_render", "bevy_window", + "bevy_world_serialization", "tracing", ] [[package]] name = "bevy_diagnostic" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8543a0f7afd56d3499ba80ffab6ef0bad12f93c2d2ca9aa7b1f1b8816c3980" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "atomic-waker", "bevy_app", @@ -685,9 +663,8 @@ dependencies = [ [[package]] name = "bevy_ecs" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9cf7a3ee41342dd7b5a5d82e200d0e8efb933169247fce853b4ad633d51e87d" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "arrayvec", "bevy_ecs_macros", @@ -711,12 +688,23 @@ dependencies = [ "variadics_please", ] +[[package]] +name = "bevy_ecs_macro_logic" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bevy_ecs_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908baf585e2ea16bd53ef0da57b69580478af0059d2dbdb4369991ac9794b618" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ + "bevy_ecs_macro_logic", "bevy_macro_utils", "proc-macro2", "quote", @@ -725,9 +713,8 @@ dependencies = [ [[package]] name = "bevy_encase_derive" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fee46eeddcbc00a805ae00ffa973f224671fc5cf0fe1a796963804faeade90" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "encase_derive_impl", @@ -735,9 +722,8 @@ dependencies = [ [[package]] name = "bevy_feathers" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb29be8f8443c5cc44e1c4710bbe02877e73703c60228ca043f20529a5496c6" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "accesskit", "bevy_a11y", @@ -747,6 +733,7 @@ dependencies = [ "bevy_color", "bevy_derive", "bevy_ecs", + "bevy_input", "bevy_input_focus", "bevy_log", "bevy_math", @@ -754,6 +741,7 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_render", + "bevy_scene", "bevy_shader", "bevy_text", "bevy_ui", @@ -765,9 +753,8 @@ dependencies = [ [[package]] name = "bevy_gilrs" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611827ab0ce43b88c0a695e6603901b5f34687efecaf526c861456c9d8e6fedb" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", @@ -781,9 +768,8 @@ dependencies = [ [[package]] name = "bevy_gizmos" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaff0dd5f405c83d290c5cd591835f1ae8009894947ab19dadcb323062bd7e7" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -791,19 +777,21 @@ dependencies = [ "bevy_color", "bevy_ecs", "bevy_gizmos_macros", - "bevy_light", + "bevy_input", + "bevy_log", "bevy_math", + "bevy_mesh", "bevy_reflect", "bevy_time", "bevy_transform", "bevy_utils", + "bevy_window", ] [[package]] name = "bevy_gizmos_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6960ea308d7e94adcac5c712553ff86614bba6b663511f3f3812f6bec028b51e" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "quote", @@ -812,23 +800,25 @@ dependencies = [ [[package]] name = "bevy_gizmos_render" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d18c089102de4c5e9326023ad96ba618a6961029f8102a33640b966883237" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", "bevy_camera", + "bevy_color", "bevy_core_pipeline", "bevy_ecs", "bevy_gizmos", "bevy_image", + "bevy_log", + "bevy_material", "bevy_math", "bevy_mesh", "bevy_pbr", + "bevy_reflect", "bevy_render", "bevy_shader", - "bevy_sprite_render", "bevy_transform", "bevy_utils", "bytemuck", @@ -837,9 +827,8 @@ dependencies = [ [[package]] name = "bevy_gltf" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f37fb52655d0439656ca0a1db027d46926e463c81d893d4b1639668e5d7f1c1" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "async-lock", "base64", @@ -851,15 +840,14 @@ dependencies = [ "bevy_ecs", "bevy_image", "bevy_light", + "bevy_material", "bevy_math", "bevy_mesh", - "bevy_pbr", "bevy_platform", "bevy_reflect", - "bevy_render", - "bevy_scene", "bevy_tasks", "bevy_transform", + "bevy_world_serialization", "fixedbitset", "gltf", "itertools 0.14.0", @@ -869,13 +857,13 @@ dependencies = [ "smallvec", "thiserror 2.0.18", "tracing", + "wgpu-types", ] [[package]] name = "bevy_image" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71daf9b2afdd032c2b1122d1d501f99126218cb3e9983b3604ec381daa35f22" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -902,9 +890,8 @@ dependencies = [ [[package]] name = "bevy_input" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc8ffbd02df34dfc52faf420a5263985973765e228043adf542fd0d790a6b21" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", @@ -919,9 +906,8 @@ dependencies = [ [[package]] name = "bevy_input_focus" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d48a5bceccb9157549a39ab3de4017f5368b65db6471605e9a3f1c19d91bbc" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", @@ -936,9 +922,8 @@ dependencies = [ [[package]] name = "bevy_internal" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a11df62e49897def470471551c02f13c6fb488e55dddb5ab7ef098132e07754" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_a11y", "bevy_android", @@ -946,8 +931,8 @@ dependencies = [ "bevy_anti_alias", "bevy_app", "bevy_asset", - "bevy_audio", "bevy_camera", + "bevy_clipboard", "bevy_color", "bevy_core_pipeline", "bevy_derive", @@ -964,6 +949,7 @@ dependencies = [ "bevy_input_focus", "bevy_light", "bevy_log", + "bevy_material", "bevy_math", "bevy_mesh", "bevy_pbr", @@ -983,38 +969,41 @@ dependencies = [ "bevy_time", "bevy_transform", "bevy_ui", - "bevy_ui_render", "bevy_utils", "bevy_window", "bevy_winit", + "bevy_world_serialization", ] [[package]] name = "bevy_light" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d9d2ac64390a9baacb3c0fa0f5456ac1553959d5a387874c102a09aab8b92cc" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", "bevy_camera", "bevy_color", "bevy_ecs", + "bevy_gizmos", "bevy_image", + "bevy_log", "bevy_math", "bevy_mesh", "bevy_platform", "bevy_reflect", "bevy_transform", "bevy_utils", + "half", + "smallvec", "tracing", + "wgpu-types", ] [[package]] name = "bevy_log" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2aac1187f83a1ab2eae887564f7fb14b4abb3fbe8b2267a6426663463923120" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "android_log-sys", "bevy_app", @@ -1030,21 +1019,51 @@ dependencies = [ [[package]] name = "bevy_macro_utils" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b147843b81a7ec548876ff97fa7bfdc646ef2567cb465566259237b39664438" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "proc-macro2", "quote", "syn", - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit", +] + +[[package]] +name = "bevy_material" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_material_macros", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_shader", + "bevy_utils", + "encase", + "smallvec", + "thiserror 2.0.18", + "tracing", + "variadics_please", + "wgpu-types", +] + +[[package]] +name = "bevy_material_macros" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn", ] [[package]] name = "bevy_math" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e931fa969f89c83498b22c97432383afe90e90fd1a5e04fa07be8da4d3bcac84" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "approx", "arrayvec", @@ -1062,15 +1081,14 @@ dependencies = [ [[package]] name = "bevy_mesh" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288f590c8173d4cca3cae5f2ba579accd5ed1a35dd3fab338f427eb39d55f05e" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", "bevy_derive", "bevy_ecs", - "bevy_image", + "bevy_encase_derive", "bevy_math", "bevy_mikktspace", "bevy_platform", @@ -1079,6 +1097,9 @@ dependencies = [ "bitflags 2.11.1", "bytemuck", "derive_more", + "encase", + "glam", + "half", "hexasphere", "thiserror 2.0.18", "tracing", @@ -1087,16 +1108,16 @@ dependencies = [ [[package]] name = "bevy_mikktspace" -version = "0.17.0-dev" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59" +checksum = "bff34eb29ff4b8a8688bc7299f14fb6b597461ca80fec03ed7d22939ab33e48f" [[package]] name = "bevy_pbr" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab6944ffc6fd71604c0fbca68cc3e2a3654edfcdbfd232f9d8b88e3d20fdc0" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ + "arrayvec", "bevy_app", "bevy_asset", "bevy_camera", @@ -1105,34 +1126,38 @@ dependencies = [ "bevy_derive", "bevy_diagnostic", "bevy_ecs", + "bevy_gltf", "bevy_image", "bevy_light", "bevy_log", + "bevy_material", "bevy_math", "bevy_mesh", "bevy_platform", "bevy_reflect", "bevy_render", "bevy_shader", + "bevy_tasks", "bevy_transform", "bevy_utils", "bitflags 2.11.1", "bytemuck", "derive_more", "fixedbitset", + "indexmap", "nonmax", "offset-allocator", "smallvec", "static_assertions", "thiserror 2.0.18", "tracing", + "wgpu-types", ] [[package]] name = "bevy_picking" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d524dbc8f2c9e73f7ab70c148c8f7886f3c24b8aa8c252a38ba68ed06cbf10" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1154,13 +1179,13 @@ dependencies = [ [[package]] name = "bevy_platform" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6b36504169b644acd26a5469fd8d371aa6f1d73ee5c01b1b1181ae1cefbf9b" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "critical-section", "foldhash 0.2.0", "futures-channel", + "futures-lite", "hashbrown 0.16.1", "js-sys", "portable-atomic", @@ -1170,13 +1195,13 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-time", + "windows-sys 0.61.2", ] [[package]] name = "bevy_post_process" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f77a4e894aea992e3d6938f1d5898a1cdbb87dba6eebfb95cb4038d0a2600e9" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1191,12 +1216,7 @@ dependencies = [ "bevy_reflect", "bevy_render", "bevy_shader", - "bevy_transform", "bevy_utils", - "bevy_window", - "bitflags 2.11.1", - "nonmax", - "radsort", "smallvec", "thiserror 2.0.18", "tracing", @@ -1204,15 +1224,13 @@ dependencies = [ [[package]] name = "bevy_ptr" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a9329e8dc4e01ced480eeec4902e6d7cb56e56ec37f6fbc4323e5c937290a7" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" [[package]] name = "bevy_reflect" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1dfeb67a9fe4f59003a84f5f99ba6302141c70e926601cbc6abfd4a1eea9ca9" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "assert_type_match", "bevy_platform", @@ -1239,9 +1257,8 @@ dependencies = [ [[package]] name = "bevy_reflect_derive" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475f68c93e9cd5f17e9167635c8533a4f388f12d38245a202359e4c2721d87ba" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "indexmap", @@ -1253,9 +1270,8 @@ dependencies = [ [[package]] name = "bevy_render" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243523e33fe5dfcebc4240b1eb2fc16e855c5d4c0ea6a8393910740956770f44" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "async-channel", "bevy_app", @@ -1267,6 +1283,9 @@ dependencies = [ "bevy_ecs", "bevy_encase_derive", "bevy_image", + "bevy_log", + "bevy_material", + "bevy_material_macros", "bevy_math", "bevy_mesh", "bevy_platform", @@ -1283,10 +1302,10 @@ dependencies = [ "derive_more", "downcast-rs 2.0.2", "encase", - "fixedbitset", "glam", "image", "indexmap", + "itertools 0.14.0", "js-sys", "naga", "nonmax", @@ -1294,18 +1313,18 @@ dependencies = [ "send_wrapper", "smallvec", "thiserror 2.0.18", - "tracing", "variadics_please", "wasm-bindgen", + "weak-table", "web-sys", "wgpu", + "wgpu-types", ] [[package]] name = "bevy_render_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b6325e9c495a71270446784611e8d7f446f927eac8506c4c099fd10cb4c3ed" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "proc-macro2", @@ -1315,48 +1334,73 @@ dependencies = [ [[package]] name = "bevy_scene" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cc1047d85ec8048261b63ef675c12f1e6b5782dc0b422fbcee0c140d026bd4" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", - "bevy_camera", "bevy_derive", "bevy_ecs", + "bevy_log", "bevy_platform", "bevy_reflect", - "bevy_transform", + "bevy_scene_macros", "bevy_utils", - "derive_more", - "ron", - "serde", "thiserror 2.0.18", - "uuid", + "tracing", + "variadics_please", +] + +[[package]] +name = "bevy_scene_macros" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_ecs_macro_logic", + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_settings_plus" +version = "0.1.0" +dependencies = [ + "bevy", + "bevy-settings", + "bevy_anti_alias", + "bevy_app", + "bevy_ecs", + "bevy_log", + "bevy_reflect", + "bevy_render", + "bevy_window", + "wgpu-types", ] [[package]] name = "bevy_shader" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eea95f0273c32be13d6a0b799a93bc256ad7830759ede595c404d5234302da2" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_asset", "bevy_platform", "bevy_reflect", + "bevy_utils", "naga", "naga_oil", "serde", "thiserror 2.0.18", "tracing", + "wgpu-naga-bridge", "wgpu-types", ] [[package]] name = "bevy_sprite" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ec5bc0cbdee551b610a46f41d30374bbe42b8951ffc676253c6243ab2b9395" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1365,6 +1409,7 @@ dependencies = [ "bevy_derive", "bevy_ecs", "bevy_image", + "bevy_log", "bevy_math", "bevy_mesh", "bevy_picking", @@ -1379,9 +1424,8 @@ dependencies = [ [[package]] name = "bevy_sprite_render" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b82cb08905e7ddcea2694a95f757ae7f1fd01e6a7304076bad595d2158e4bfe0" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1391,6 +1435,7 @@ dependencies = [ "bevy_derive", "bevy_ecs", "bevy_image", + "bevy_material", "bevy_math", "bevy_mesh", "bevy_platform", @@ -1411,9 +1456,8 @@ dependencies = [ [[package]] name = "bevy_state" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae0682968e97d29c1eccc8c6bb6283f2678d362779bc03f1bb990967059473b" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", @@ -1427,9 +1471,8 @@ dependencies = [ [[package]] name = "bevy_state_macros" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d32f90f9cfcef5a44401db7ce206770daaa1707b0fb95eb7a96a6933f54f1b" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_macro_utils", "quote", @@ -1438,9 +1481,8 @@ dependencies = [ [[package]] name = "bevy_tasks" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384eb04d80aa38664d69988fd30cbbe03e937ecb65c66aa6abe60ce0bca826aa" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "async-channel", "async-executor", @@ -1452,17 +1494,17 @@ dependencies = [ "derive_more", "futures-lite", "heapless", - "pin-project", + "web-task", ] [[package]] name = "bevy_text" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc5233291dfc22e584de2535f2e37ae9766d37cb5a01652de2133ba202dcb9b" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", + "bevy_clipboard", "bevy_color", "bevy_derive", "bevy_ecs", @@ -1472,9 +1514,11 @@ dependencies = [ "bevy_platform", "bevy_reflect", "bevy_utils", - "cosmic-text", + "parley", "serde", "smallvec", + "smol_str", + "swash", "sys-locale", "thiserror 2.0.18", "tracing", @@ -1483,9 +1527,8 @@ dependencies = [ [[package]] name = "bevy_time" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ef9af4e523195e561074cf60fbfad0f4cb8d1db504855fee3c4ce8896c7244" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", @@ -1498,13 +1541,11 @@ dependencies = [ [[package]] name = "bevy_transform" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3bb3de7842fef699344beb03f22bdbff16599d788fe0f47fbb3b1e6fa320eb" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_ecs", - "bevy_log", "bevy_math", "bevy_reflect", "bevy_tasks", @@ -1516,9 +1557,8 @@ dependencies = [ [[package]] name = "bevy_ui" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1691a411014085e0d35f8bb8208e5f973edd7ace061a4b1c41c83de21579dc70" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "accesskit", "bevy_a11y", @@ -1531,17 +1571,21 @@ dependencies = [ "bevy_image", "bevy_input", "bevy_input_focus", + "bevy_log", "bevy_math", "bevy_picking", "bevy_platform", "bevy_reflect", "bevy_sprite", "bevy_text", + "bevy_time", "bevy_transform", "bevy_utils", "bevy_window", "derive_more", + "parley", "smallvec", + "swash", "taffy", "thiserror 2.0.18", "tracing", @@ -1550,9 +1594,8 @@ dependencies = [ [[package]] name = "bevy_ui_render" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c35402d8a052f512e3fec1f36b26e83eee713fcca57f965c244ee795e1fcb0" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1562,6 +1605,7 @@ dependencies = [ "bevy_derive", "bevy_ecs", "bevy_image", + "bevy_input_focus", "bevy_math", "bevy_mesh", "bevy_platform", @@ -1576,14 +1620,14 @@ dependencies = [ "bevy_utils", "bytemuck", "derive_more", + "indexmap", "tracing", ] [[package]] name = "bevy_ui_widgets" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a63cb818b0de41bdb14990e0ce1aaaa347f871750ab280f80c427e83d72712" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "accesskit", "bevy_a11y", @@ -1596,25 +1640,29 @@ dependencies = [ "bevy_math", "bevy_picking", "bevy_reflect", + "bevy_text", "bevy_ui", + "bevy_window", + "parley", + "smol_str", ] [[package]] name = "bevy_utils" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2111910cd7a4b1e6ce07eaaeb6f68a2c0ea0ca609ed0d0d506e3eb161101435b" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ + "async-channel", "bevy_platform", "disqualified", + "indexmap", "thread_local", ] [[package]] name = "bevy_window" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df06e6993a0896bae2fe7644ae6def29a1a92b45dfb1bcebbd92af782be3638" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "bevy_app", "bevy_asset", @@ -1631,9 +1679,8 @@ dependencies = [ [[package]] name = "bevy_winit" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2de1c13d32ab8528435b58eca7ab874a1068184c6d6f266ee11433ae99d4069" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" dependencies = [ "accesskit", "accesskit_winit", @@ -1654,7 +1701,6 @@ dependencies = [ "bevy_tasks", "bevy_window", "bytemuck", - "cfg-if", "js-sys", "tracing", "wasm-bindgen", @@ -1663,6 +1709,27 @@ dependencies = [ "winit", ] +[[package]] +name = "bevy_world_serialization" +version = "0.19.0-dev" +source = "git+https://github.com/bevyengine/bevy#654bcde0ed3610efaeb162241bba2f22652713c6" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_derive", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_transform", + "bevy_utils", + "derive_more", + "ron", + "serde", + "thiserror 2.0.18", + "uuid", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -1685,18 +1752,18 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" [[package]] name = "bitflags" @@ -1728,12 +1795,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - [[package]] name = "block2" version = "0.5.1" @@ -1767,9 +1828,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" @@ -1837,9 +1898,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.61" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1847,12 +1908,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cexpr" version = "0.6.0" @@ -1896,6 +1951,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + [[package]] name = "combine" version = "4.6.7" @@ -1981,16 +2047,6 @@ 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" @@ -2004,8 +2060,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", + "core-foundation", + "core-graphics-types", "foreign-types", "libc", ] @@ -2017,18 +2073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.11.1", - "core-foundation 0.10.1", + "core-foundation", "libc", ] @@ -2041,73 +2086,6 @@ dependencies = [ "libm", ] -[[package]] -name = "coreaudio-rs" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cosmic-text" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cadaea21e24c49c0c82116f2b465ae6a49d63c90e428b0f8d9ae1f638ac91f" -dependencies = [ - "bitflags 2.11.1", - "fontdb", - "harfrust", - "linebender_resource_handle", - "log", - "rangemap", - "rustc-hash 1.1.0", - "self_cell", - "skrifa 0.39.0", - "smol_str", - "swash", - "sys-locale", - "unicode-bidi", - "unicode-linebreak", - "unicode-script", - "unicode-segmentation", -] - -[[package]] -name = "cpal" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni 0.21.1", - "js-sys", - "libc", - "mach2", - "ndk 0.8.0", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.54.0", -] - [[package]] name = "cpufeatures" version = "0.3.0" @@ -2169,7 +2147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.31.2", + "nix 0.31.3", "windows-sys 0.61.2", ] @@ -2179,12 +2157,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - [[package]] name = "data-encoding" version = "2.11.0" @@ -2214,27 +2186,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "directories" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", -] - [[package]] name = "dispatch" version = "0.2.0" @@ -2253,6 +2204,17 @@ dependencies = [ "objc2 0.6.4", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "disqualified" version = "1.0.0" @@ -2270,15 +2232,14 @@ dependencies = [ [[package]] name = "dlss_wgpu" -version = "2.0.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a48466b369c931f926a628b516669404ee82a91e6788fca948de4bfea89db7a" +checksum = "75a51601d25ae0c9cc759d421fe40d3c5a031dd8c2e92970e9038a040ef178b4" dependencies = [ "ash", "bindgen", "bitflags 2.11.1", "cc", - "glam", "thiserror 2.0.18", "uuid", "wgpu", @@ -2313,9 +2274,9 @@ checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "encase" @@ -2460,15 +2421,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "font-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" -dependencies = [ - "bytemuck", -] - [[package]] name = "font-types" version = "0.11.3" @@ -2479,26 +2431,17 @@ dependencies = [ ] [[package]] -name = "fontconfig-parser" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" -dependencies = [ - "roxmltree", -] - -[[package]] -name = "fontdb" -version = "0.23.0" +name = "fontique" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +checksum = "7c20b425addb8661e97fe1d51c4d8bcec3ec29ed6ad0db983976a7521276b8f7" dependencies = [ - "fontconfig-parser", - "log", + "hashbrown 0.17.1", + "linebender_resource_handle", "memmap2", - "slotmap", - "tinyvec", - "ttf-parser", + "parlance", + "read-fonts 0.39.2", + "smallvec", ] [[package]] @@ -2599,18 +2542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.4", - "windows-link 0.2.1", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", + "windows-link", ] [[package]] @@ -2669,7 +2601,7 @@ dependencies = [ "vec_map", "wasm-bindgen", "web-sys", - "windows 0.62.2", + "windows", ] [[package]] @@ -2685,9 +2617,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.10" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" +checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" dependencies = [ "bytemuck", "encase", @@ -2704,9 +2636,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "glow" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" dependencies = [ "js-sys", "slotmap", @@ -2760,45 +2692,28 @@ dependencies = [ ] [[package]] -name = "gpu-alloc" -version = "0.6.0" +name = "gpu-allocator" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" dependencies = [ - "bitflags 2.11.1", - "gpu-alloc-types", + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror 2.0.18", + "windows", ] [[package]] -name = "gpu-alloc-types" -version = "0.3.0" +name = "gpu-descriptor" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ "bitflags 2.11.1", -] - -[[package]] -name = "gpu-allocator" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" -dependencies = [ - "log", - "presser", - "thiserror 1.0.69", - "windows 0.58.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.11.1", - "gpu-descriptor-types", - "hashbrown 0.15.5", + "gpu-descriptor-types", + "hashbrown 0.15.5", ] [[package]] @@ -2832,6 +2747,7 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ + "bytemuck", "cfg-if", "crunchy", "num-traits", @@ -2840,14 +2756,14 @@ dependencies = [ [[package]] name = "harfrust" -version = "0.4.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0caaee032384c10dd597af4579c67dee16650d862a9ccbe1233ff1a379abc07" +checksum = "551ed25397e4b444e89686602877d5cf3a7f6e3d548dcac37a8357d1e195f4df" dependencies = [ "bitflags 2.11.1", "bytemuck", "core_maths", - "read-fonts 0.36.0", + "read-fonts 0.39.2", "smallvec", ] @@ -2875,6 +2791,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", "equivalent", "foldhash 0.2.0", "serde", @@ -2883,15 +2800,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "heapless" -version = "0.9.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +checksum = "b1edcd5a338e64688fbdcb7531a846cfd3476a54784dcb918a0844682bc7ada5" dependencies = [ "hash32", "portable-atomic", @@ -2912,9 +2832,9 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hexasphere" -version = "16.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b" +checksum = "177ea6330876de4ef08e184f827b98acc037614a4ce409902c5b0d53a9c2e951" dependencies = [ "constgebra", "glam", @@ -2927,6 +2847,132 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", + "tinystr", + "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", + "serde", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locale_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c5f1d16b4c3a2642d3a719f18f6b06070ab0aef246a6418130c955ae08aa831" + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "serde", + "stable_deref_trait", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_segmenter" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a807a7488f3f758629ae86d99d9d30dce24da2fb2945d74c80a4f4a62c71db73" +dependencies = [ + "icu_collections", + "icu_locale", + "icu_provider", + "icu_segmenter_data", + "potential_utf", + "utf8_iter", + "zerovec", +] + +[[package]] +name = "icu_segmenter_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ebbb7321d9e21d25f5660366cb6c08201d0175898a3a6f7a41ee9685af21c80" + [[package]] name = "id-arena" version = "2.3.0" @@ -2935,9 +2981,9 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "image" -version = "0.25.10" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", @@ -2953,7 +2999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -3017,22 +3063,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys 0.3.1", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "jni" version = "0.22.4" @@ -3047,7 +3077,7 @@ dependencies = [ "simd_cesu8", "thiserror 2.0.18", "walkdir", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3103,9 +3133,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -3132,9 +3162,9 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "ktx2" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7f53bdf698e7aa7ec916411bbdc8078135da11b66db5182675b2227f6c0d07" +checksum = "1d50be8a24c37debdf3170be6ca396d5b5b165f37f94837891adac735ca416b8" dependencies = [ "bitflags 2.11.1", ] @@ -3151,17 +3181,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" version = "0.2.186" @@ -3175,7 +3194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3193,7 +3212,7 @@ dependencies = [ "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.4", + "redox_syscall 0.7.5", ] [[package]] @@ -3224,6 +3243,12 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + [[package]] name = "litrs" version = "1.0.0" @@ -3245,24 +3270,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "matchers" version = "0.2.0" @@ -3287,21 +3294,6 @@ dependencies = [ "libc", ] -[[package]] -name = "metal" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" -dependencies = [ - "bitflags 2.11.1", - "block", - "core-graphics-types 0.2.0", - "foreign-types", - "log", - "objc", - "paste", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3320,9 +3312,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.8.1" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" dependencies = [ "num-traits", "pxfm", @@ -3330,16 +3322,16 @@ dependencies = [ [[package]] name = "naga" -version = "27.0.3" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" +checksum = "0dd91265cc2454558f659b3b4b9640f0ddb8cc6521277f166b8a8c181c898079" dependencies = [ "arrayvec", "bit-set", "bitflags 2.11.1", "cfg-if", "cfg_aliases", - "codespan-reporting", + "codespan-reporting 0.13.1", "half", "hashbrown 0.16.1", "hexf-parse", @@ -3357,11 +3349,11 @@ dependencies = [ [[package]] name = "naga_oil" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310c347db1b30e69581f3b84dc9a5c311ed583f67851b39b77953cb7a066c97f" +checksum = "319f03062940ed85c03da020042618356bb8ca5263020322930883b05e30208e" dependencies = [ - "codespan-reporting", + "codespan-reporting 0.12.0", "data-encoding", "indexmap", "naga", @@ -3372,20 +3364,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.11.1", - "jni-sys 0.3.1", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror 1.0.69", -] - [[package]] name = "ndk" version = "0.9.0" @@ -3395,7 +3373,7 @@ dependencies = [ "bitflags 2.11.1", "jni-sys 0.3.1", "log", - "ndk-sys 0.6.0+11769913", + "ndk-sys", "num_enum", "raw-window-handle", "thiserror 1.0.69", @@ -3407,15 +3385,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys 0.3.1", -] - [[package]] name = "ndk-sys" version = "0.6.0+11769913" @@ -3439,9 +3408,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags 2.11.1", "cfg-if", @@ -3483,17 +3452,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -3526,15 +3484,6 @@ dependencies = [ "syn", ] -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - [[package]] name = "objc-sys" version = "0.3.5" @@ -3572,8 +3521,8 @@ dependencies = [ "objc2 0.5.2", "objc2-core-data", "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", ] [[package]] @@ -3586,7 +3535,7 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3597,7 +3546,7 @@ checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3609,7 +3558,7 @@ dependencies = [ "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3619,6 +3568,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.11.1", + "dispatch2", + "objc2 0.6.4", ] [[package]] @@ -3629,8 +3580,8 @@ checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", - "objc2-metal", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", ] [[package]] @@ -3642,7 +3593,7 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-contacts", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3664,6 +3615,17 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + [[package]] name = "objc2-io-kit" version = "0.3.2" @@ -3684,7 +3646,7 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3696,7 +3658,19 @@ dependencies = [ "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.11.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", ] [[package]] @@ -3708,8 +3682,21 @@ dependencies = [ "bitflags 2.11.1", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", - "objc2-metal", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", ] [[package]] @@ -3719,7 +3706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3735,9 +3722,9 @@ dependencies = [ "objc2-core-data", "objc2-core-image", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-link-presentation", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", "objc2-symbols", "objc2-uniform-type-identifiers", "objc2-user-notifications", @@ -3751,7 +3738,7 @@ checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3764,30 +3751,7 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni 0.21.1", - "ndk 0.8.0", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", + "objc2-foundation 0.2.2", ] [[package]] @@ -3800,32 +3764,17 @@ dependencies = [ "nonmax", ] -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "orbclient" -version = "0.3.53" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c6933ddbbd16539a7672e697bb8d41ac3a4e99ac43eeb40c07236bd7fcb2dd" +checksum = "a570f6bca41d29acb2139229a7c873ec99bc9a313bd10804081d89bfac8ff329" dependencies = [ "libc", "libredox", @@ -3875,14 +3824,41 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", +] + +[[package]] +name = "parlance" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6937eda350acc1a5d05872c3cbf99fe78619c269096e2be3d4a350058639d5" + +[[package]] +name = "parley" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fad031076f48f0d4d85ce1aea9b94b4e715a4d636a030a123038f8f5b5e4343" +dependencies = [ + "fontique", + "harfrust", + "hashbrown 0.17.1", + "icu_normalizer", + "icu_properties", + "icu_segmenter", + "linebender_resource_handle", + "parlance", + "parley_data", + "skrifa 0.42.1", ] [[package]] -name = "paste" -version = "1.0.15" +name = "parley_data" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "19ab9ace3fad1b9ed603ddac5b595e69931fc50263d7e04e4055015b77b02da5" +dependencies = [ + "icu_properties", +] [[package]] name = "percent-encoding" @@ -3905,18 +3881,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -3995,21 +3971,23 @@ dependencies = [ ] [[package]] -name = "pp-rs" -version = "0.2.1" +name = "potential_utf" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ - "unicode-xid", + "serde_core", + "writeable", + "zerovec", ] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "pp-rs" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" dependencies = [ - "zerocopy", + "unicode-xid", ] [[package]] @@ -4034,7 +4012,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit", ] [[package]] @@ -4048,9 +4026,9 @@ dependencies = [ [[package]] name = "profiling" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" [[package]] name = "pxfm" @@ -4060,9 +4038,9 @@ checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] name = "quick-xml" -version = "0.39.2" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] @@ -4096,38 +4074,25 @@ checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" [[package]] name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "ppv-lite86", + "getrandom 0.4.2", "rand_core", ] [[package]] name = "rand_core" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rand_distr" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +checksum = "4d431c2703ccf129de4d45253c03f49ebb22b97d6ad79ee3ecfc7e3f4862c1d8" dependencies = [ "num-traits", "rand", @@ -4139,12 +4104,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" -[[package]] -name = "rangemap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -4152,14 +4111,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] -name = "read-fonts" -version = "0.36.0" +name = "raw-window-metal" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eaa2941a4c05443ee3a7b26ab076a553c343ad5995230cc2b1d3e993bdc6345" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" dependencies = [ - "bytemuck", - "core_maths", - "font-types 0.10.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", ] [[package]] @@ -4169,7 +4129,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" dependencies = [ "bytemuck", - "font-types 0.11.3", + "font-types", +] + +[[package]] +name = "read-fonts" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4ed38b89c2c77ff968c524145ad65fb010f38af5c7a224b53b81d47ac2daa81" +dependencies = [ + "bytemuck", + "font-types", ] [[package]] @@ -4198,24 +4168,13 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ "bitflags 2.11.1", ] -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 2.0.18", -] - [[package]] name = "regex" version = "1.12.3" @@ -4251,16 +4210,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" -[[package]] -name = "rodio" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" -dependencies = [ - "cpal", - "lewton", -] - [[package]] name = "ron" version = "0.12.1" @@ -4275,12 +4224,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "roxmltree" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -4377,12 +4320,6 @@ dependencies = [ "tiny-skia", ] -[[package]] -name = "self_cell" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" - [[package]] name = "semver" version = "1.0.28" @@ -4427,9 +4364,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -4438,6 +4375,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4477,22 +4423,22 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "skrifa" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9eb0b904a04d09bd68c65d946617b8ff733009999050f3b851c32fb3cfb60e" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" dependencies = [ "bytemuck", - "read-fonts 0.36.0", + "read-fonts 0.37.0", ] [[package]] name = "skrifa" -version = "0.40.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +checksum = "0c34617370ae968efb7161bb2beb517d9084659aae19e24b89e3db25b46e4564" dependencies = [ "bytemuck", - "read-fonts 0.37.0", + "read-fonts 0.39.2", ] [[package]] @@ -4561,9 +4507,9 @@ dependencies = [ [[package]] name = "spirv" -version = "0.3.0+sdk-1.3.268.0" +version = "0.4.0+sdk-1.4.341.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" dependencies = [ "bitflags 2.11.1", ] @@ -4623,6 +4569,17 @@ dependencies = [ "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 = "sys-locale" version = "0.3.2" @@ -4634,23 +4591,23 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.37.2" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" dependencies = [ "libc", "memchr", "ntapi", "objc2-core-foundation", "objc2-io-kit", - "windows 0.61.3", + "windows", ] [[package]] name = "taffy" -version = "0.9.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ba83ebaf2954d31d05d67340fd46cebe99da2b7133b0dd68d70c65473a437b" +checksum = "aea22054047c16c3f34d3ac473a2170be1424b1115b2a3adcf28cfb067c88859" dependencies = [ "arrayvec", "grid", @@ -4741,6 +4698,17 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "serde_core", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.11.0" @@ -4757,12 +4725,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +name = "toml" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ + "indexmap", "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", ] [[package]] @@ -4774,18 +4748,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.23.10+spec-1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" -dependencies = [ - "indexmap", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "winnow 0.7.15", -] - [[package]] name = "toml_edit" version = "0.25.11+spec-1.1.0" @@ -4793,9 +4755,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ "indexmap", - "toml_datetime 1.1.1+spec-1.1.0", + "toml_datetime", "toml_parser", - "winnow 1.0.2", + "winnow", ] [[package]] @@ -4804,9 +4766,15 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.2", + "winnow", ] +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -4896,9 +4864,6 @@ name = "ttf-parser" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" -dependencies = [ - "core_maths", -] [[package]] name = "twox-hash" @@ -4918,30 +4883,12 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "214ca0b2191785cbc06209b9ca1861e048e39b5ba33574b3cedd58363d5bb5f6" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-script" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" - [[package]] name = "unicode-segmentation" version = "1.13.2" @@ -4960,6 +4907,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" version = "1.23.1" @@ -5011,19 +4964,13 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen 0.57.1", + "wit-bindgen 0.46.0", ] [[package]] @@ -5037,9 +4984,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -5050,9 +4997,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.70" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -5060,9 +5007,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5070,9 +5017,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -5083,9 +5030,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -5229,19 +5176,38 @@ checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" dependencies = [ "dlib", "log", + "once_cell", "pkg-config", ] +[[package]] +name = "weak-table" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" + [[package]] name = "web-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "web-task" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdc136a53ccd64a1211f107ccc34404769fbcc0f165f1afa065f5d88ab93538" +dependencies = [ + "async-task", + "cfg-if", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -5254,12 +5220,13 @@ dependencies = [ [[package]] name = "wgpu" -version = "27.0.1" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" +checksum = "bb3feacc458f7bee8bc1737149b42b6c731aa461039a4264a67bb6681646b250" dependencies = [ "arrayvec", "bitflags 2.11.1", + "bytemuck", "cfg-if", "cfg_aliases", "document-features", @@ -5281,9 +5248,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "27.0.3" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" +checksum = "02da3ad1b568337f25513b317870960ef87073ea0945502e44b864b67a8c77b7" dependencies = [ "arrayvec", "bit-set", @@ -5308,55 +5275,54 @@ dependencies = [ "wgpu-core-deps-wasm", "wgpu-core-deps-windows-linux-android", "wgpu-hal", + "wgpu-naga-bridge", "wgpu-types", ] [[package]] name = "wgpu-core-deps-apple" -version = "27.0.0" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +checksum = "62e51b5447e144b3dbba4feb01f80f4fa21696fa0cd99afb2c3df1affd6fdb28" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-wasm" -version = "27.0.0" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1027dcf3b027a877e44819df7ceb0e2e98578830f8cd34cd6c3c7c2a7a50b7" +checksum = "0c2f2fb042f36920771deb0b966543c5751b18f3d327760ffc90f74e20b2dcd4" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-windows-linux-android" -version = "27.0.0" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +checksum = "1bfb01076d0aa08b0ba9bd741e178b5cc440f5abe99d9581323a4c8b5d1a1916" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-hal" -version = "27.0.4" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" +checksum = "31f8e1a9e7a8512f276f7c62e018c7fa8d60954303fed2e5750114332049193f" dependencies = [ "android_system_properties", "arrayvec", "ash", "bit-set", "bitflags 2.11.1", - "block", + "block2 0.6.2", "bytemuck", "cfg-if", "cfg_aliases", - "core-graphics-types 0.2.0", "glow", "glutin_wgl_sys", - "gpu-alloc", "gpu-allocator", "gpu-descriptor", "hashbrown 0.16.1", @@ -5365,10 +5331,13 @@ dependencies = [ "libc", "libloading", "log", - "metal", "naga", - "ndk-sys 0.6.0+11769913", - "objc", + "ndk-sys", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", "once_cell", "ordered-float", "parking_lot", @@ -5377,28 +5346,42 @@ dependencies = [ "profiling", "range-alloc", "raw-window-handle", + "raw-window-metal", "renderdoc-sys", "smallvec", "thiserror 2.0.18", "wasm-bindgen", + "wayland-sys", "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", + "windows-result", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "29.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c654c483f058800972c3645e95388a7eca31bf9fe1933bc20e036588a0be02" +dependencies = [ + "naga", "wgpu-types", - "windows 0.58.0", - "windows-core 0.58.0", ] [[package]] name = "wgpu-types" -version = "27.0.1" +version = "29.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" +checksum = "a9bcc31518a0e9735aefebedb5f7a9ef3ed1c42549c9f4c882fa9060ceaac639" dependencies = [ "bitflags 2.11.1", "bytemuck", "js-sys", "log", + "raw-window-handle", "serde", - "thiserror 2.0.18", "web-sys", ] @@ -5433,58 +5416,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" -dependencies = [ - "windows-core 0.54.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections 0.2.0", - "windows-core 0.61.2", - "windows-future 0.2.1", - "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", ] [[package]] @@ -5493,43 +5434,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" -dependencies = [ - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -5538,22 +5443,11 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading 0.1.0", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -5562,20 +5456,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "windows-core", + "windows-link", + "windows-threading", ] [[package]] @@ -5589,17 +5472,6 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-interface" version = "0.59.3" @@ -5611,63 +5483,20 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - [[package]] name = "windows-numerics" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", -] - -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", + "windows-core", + "windows-link", ] [[package]] @@ -5676,26 +5505,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -5704,16 +5514,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-link", ] [[package]] @@ -5722,7 +5523,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -5731,7 +5532,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -5740,22 +5541,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-link", ] [[package]] @@ -5764,23 +5550,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -5789,39 +5566,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5834,48 +5593,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5897,17 +5632,17 @@ dependencies = [ "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation 0.9.4", + "core-foundation", "core-graphics", "cursor-icon", "dpi", "js-sys", "libc", "memmap2", - "ndk 0.9.0", + "ndk", "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-ui-kit", "orbclient", "percent-encoding", @@ -5936,21 +5671,18 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.15" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] [[package]] -name = "winnow" -version = "1.0.2" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" -dependencies = [ - "memchr", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wit-bindgen" @@ -5961,12 +5693,6 @@ dependencies = [ "wit-bindgen-rust-macro", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -6046,6 +5772,12 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + [[package]] name = "x11-dl" version = "2.21.0" @@ -6115,6 +5847,29 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeno" version = "0.3.3" @@ -6141,6 +5896,62 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "serde", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index 4c69437..65f1e4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,45 +1,37 @@ [package] -name = "bevy_config" +name = "bevy_settings_plus" version = "0.1.0" edition = "2024" rust-version = "1.85" license = "MIT OR Apache-2.0" -description = "Capability-aware configuration system for Bevy: adapter detection, platform defaults, user overrides, engine bindings." -repository = "https://github.com/pavlov-net/bevy_config" +description = "Capability-aware extension to bevy_settings: adapter detection, platform defaults, caps clamping, engine bindings." +repository = "https://github.com/pavlov-net/bevy_settings_plus" readme = "README.md" -keywords = ["bevy", "config", "settings", "options", "graphics"] +keywords = ["bevy", "settings", "config", "graphics"] categories = ["game-development", "config"] [features] -default = ["ron"] -ron = ["dep:ron"] +default = [] dlss = ["bevy_anti_alias/dlss"] [package.metadata.docs.rs] # DLSS pulls dlss_wgpu which requires the NVIDIA SDK at build time, which # docs.rs doesn't have — explicitly skip it. Add other features here if # they don't pull external SDKs. -features = ["ron"] +features = [] [dependencies] -bevy_app = "0.18.1" -bevy_ecs = "0.18.1" -bevy_reflect = "0.18.1" -bevy_render = "0.18.1" -bevy_window = "0.18.1" -bevy_anti_alias = "0.18.1" -bevy_log = "0.18.1" -serde = { version = "1", features = ["derive"] } -ron = { version = "0.12", optional = true } -thiserror = "2" -wgpu-types = { version = "27", default-features = false } - -[target.'cfg(not(target_family = "wasm"))'.dependencies] -directories = "6" - -[target.'cfg(target_family = "wasm")'.dependencies] -web-sys = { version = "0.3", features = ["Window", "Storage"] } -serde_json = "1" +bevy_app = { git = "https://github.com/bevyengine/bevy" } +bevy_ecs = { git = "https://github.com/bevyengine/bevy" } +bevy_reflect = { git = "https://github.com/bevyengine/bevy" } +bevy_render = { git = "https://github.com/bevyengine/bevy" } +bevy_window = { git = "https://github.com/bevyengine/bevy" } +bevy_anti_alias = { git = "https://github.com/bevyengine/bevy" } +bevy_log = { git = "https://github.com/bevyengine/bevy" } +# Upstream renamed the package to `bevy-settings` (matches its crates.io name); +# the Rust import name stays `bevy_settings`. +bevy-settings = { git = "https://github.com/bevyengine/bevy" } +wgpu-types = { version = "29", default-features = false } [dev-dependencies] -bevy = { version = "0.18.1", default-features = false, features = ["3d"] } +bevy = { git = "https://github.com/bevyengine/bevy", default-features = false, features = ["3d"] } diff --git a/README.md b/README.md index 4ee6035..e48fa8a 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,115 @@ -# bevy_config - -Capability-aware configuration system for [Bevy](https://bevy.org). - -The shape: **detect adapter caps → pick platform default → layer user overrides → bind to engine resources**. - -A single hardcoded set of graphics defaults is wrong on at least one platform. Wasm/WebGPU first-time visitors should get conservative defaults. Desktop with an RT-capable GPU should get the full picture. Adapter features (ray query, DLSS support, vendor, backend) decide whether features are even *available* before user preference comes in. - -`bevy_config` solves this with a small kernel: - -- `AdapterCaps` — wgpu features and limits → stable, plain bools/ints/enums in the main world -- `PlatformTarget` — Wasm / Windows / Linux / macOS / Other -- `Config` trait — `platform_default(target)`, `merge(&overrides)`, `clamp_to(&caps)`, `current_overrides()` -- `ConfigBackend` trait — load/store; default impls for native RON files (atomic write) and wasm `localStorage` -- `ConfigPlugin` — wires the lifecycle: load → merge → clamp → apply, on top of `Plugin::build`/`finish` - -…plus an opinionated universal schema (`CommonConfig`) covering display, render, and accessibility, and engine bindings for the graphics axes (window mode, anti-alias, MSAA, DLSS — feature-gated). - -Audio configuration is intentionally not part of `CommonConfig` because the bus convention is backend-specific (firewheel/seedling/kira/oddio all model differently). When the firewheel/seedling integration lands it will ship as its own `Config` type behind a cargo feature, registered alongside `CommonConfig` via a separate `ConfigPlugin`. - -Game-specific quality dials use the same `Config` trait with a custom type and a separate `ConfigPlugin` registration. +# bevy_settings_plus + +Capability-aware extension to [`bevy_settings`](https://docs.rs/bevy_settings) +for [Bevy](https://bevy.org). + +`bevy_settings` (in Bevy 0.19+) ships a polished settings persistence kernel: +TOML files, derive-driven `SettingsGroup` resources, change detection, +async + debounced saves. `bevy_settings_plus` layers the *graphics-aware* concerns +on top: + +- **Adapter caps detection** — `AdapterCaps` is a stable, plain-data summary + of the live wgpu adapter (backend, vendor, ray-query support, DLSS + reachability, …). Detected once and inserted as a main-world resource. +- **Caps clamping** — settings types implement `CapsAware` and register + `#[reflect(CapsAware)]`. `CapsAwarePlugin` discovers them by reflection + (mirroring how `bevy_settings` discovers `SettingsGroup` types) and runs + each type's `clamp_to(caps)` after settings have been loaded from disk. +- **Opinionated graphics schema** — `DisplaySettings`, `RenderSettings`, and + `AccessibilitySettings` resources with platform-aware defaults and engine + bindings that drive the primary window and tagged cameras. ## Usage ```rust use bevy::prelude::*; -use bevy_config::prelude::*; +use bevy_settings_plus::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugins(ConfigPlugin::::new( - FileBackend::::new("com", "example", "my_game"), - )) - .add_plugins(CommonBindingsPlugin) + .add_plugins(SettingsPlusPlugins::new("net.pavlov.my_game")) .add_systems(Startup, spawn_camera) .run(); } fn spawn_camera(mut commands: Commands) { - commands.spawn((Camera3d::default(), BevyConfigCamera)); + commands.spawn((Camera3d::default(), SettingsCamera)); } ``` -The camera marker tells the binding system which cameras to drive. Spawn it whenever — at `Startup`, on `OnEnter(GameState::Playing)`, after async asset load — the bindings apply on `Add` so deferred spawns work without ceremony. +The camera marker tells the binding system which cameras to drive. Spawn it +whenever — at `Startup`, on `OnEnter(GameState::Playing)`, after async asset +load — the bindings apply on `Add` so deferred spawns work +without ceremony. -To save a user's settings (e.g., from an "Apply" button in a menu): +To save user changes (e.g., from an "Apply" button or after dragging a +slider), use `bevy_settings`' commands directly: ```rust fn save_button(mut commands: Commands) { - commands.queue(SaveConfig::::default()); + // Debounced — coalesces bursts of changes into one write. + commands.queue(SavePreferencesDeferred::default()); +} + +fn save_now(mut commands: Commands) { + // Async, fire-once. + commands.queue(SavePreferences::IfChanged); +} +``` + +For a robust save-on-exit, the upstream pattern is to issue +`SavePreferencesDeferred` whenever the user changes something *and* a +synchronous `SavePreferencesSync::IfChanged` immediately before app exit. + +## Extending — your own caps-aware game settings + +```rust +use bevy::prelude::*; +use bevy_settings_plus::prelude::*; + +#[derive(Resource, SettingsGroup, Reflect, Default)] +#[reflect(Resource, SettingsGroup, CapsAware, Default)] +#[settings_group(group = "my_game")] +struct MyGameQuality { + ray_tracing: bool, + shadow_distance: f32, +} + +impl CapsAware for MyGameQuality { + fn clamp_to(&mut self, caps: AdapterCaps) { + if !caps.ray_query { + self.ray_tracing = false; + } + self.shadow_distance = self.shadow_distance.clamp(10.0, 1000.0); + } } + +// Then, in your plugin's `build`: +// app.register_type::(); ``` -See `examples/basic.rs` for the minimal setup and `examples/deferred_camera.rs` for the post-`Startup` spawn pattern. +`bevy_settings::PreferencesPlugin` (added by `SettingsPlusPlugins`) discovers +the type from the registry and loads it from `//settings.toml`. +`CapsAwarePlugin` then clamps it after the wgpu adapter is known. + +## Cargo features + +- `dlss` — wires [DLSS](https://developer.nvidia.com/rtx/dlss) via + `bevy_anti_alias`. Requires the NVIDIA DLSS SDK at build time; only + enable for shipping NVIDIA-targeted builds. ## Status -`v0.1.x` targets **Bevy 0.18.1**. API may change between minor versions. A `0.19-dev` branch tracks Bevy `main` for the next-release line. +`0.19-dev` is the active branch and tracks Bevy `main` (currently +`0.19.0-dev`). API may change between minor versions. + +This crate replaces `bevy_config` (the predecessor on the `main` branch, +which targeted Bevy 0.18.1 with its own persistence kernel before +`bevy_settings` landed upstream). + +See `examples/basic.rs` for the minimal setup and +`examples/deferred_camera.rs` for the post-`Startup` spawn pattern. ## License diff --git a/examples/basic.rs b/examples/basic.rs index 0febb9b..40863fa 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,7 +1,8 @@ -//! Minimal `bevy_config` example. +//! Minimal `bevy_settings_plus` example. //! -//! Adds the kernel + common bindings, observes `ConfigApplied`, and prints the -//! detected `AdapterCaps` and resolved `CommonConfig` once at startup. +//! Adds the plugin group, prints the detected `AdapterCaps` and resolved +//! per-axis settings once at startup, and spawns a `SettingsCamera` so +//! the render bindings have something to drive. //! //! Run with: //! @@ -10,26 +11,32 @@ //! ``` use bevy::prelude::*; -use bevy_config::prelude::*; +use bevy_settings_plus::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugins(ConfigPlugin::::new( - FileBackend::::new("net", "pavlov", "bevy_config_basic_example"), + .add_plugins(SettingsPlusPlugins::new( + "net.pavlov.bevy_settings_plus_basic_example", )) - .add_plugins(CommonBindingsPlugin) - .add_observer(on_config_applied) - .add_systems(Startup, spawn_camera) + .add_systems(Startup, (spawn_camera, log_resolved_settings)) .run(); } -fn on_config_applied( - _: On>, - config: Res, +fn spawn_camera(mut commands: Commands) { + commands.spawn(( + Camera3d::default(), + Transform::from_xyz(0.0, 0.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y), + SettingsCamera, + )); +} + +fn log_resolved_settings( caps: Option>, + display_cfg: Res, + render_cfg: Res, ) { - info!("=== bevy_config: ConfigApplied ==="); + info!("=== bevy_settings_plus: Startup ==="); if let Some(caps) = caps { info!( "AdapterCaps: backend={:?} vendor={:?} ray_query={} dlss_supported={}", @@ -39,22 +46,11 @@ fn on_config_applied( info!("AdapterCaps not yet inserted (running headless?)."); } info!( - "Display: window_mode={:?} vsync={:?}", - config.display.window_mode, config.display.vsync + "DisplaySettings: window_mode={:?} vsync={:?}", + display_cfg.window_mode, display_cfg.vsync ); info!( - "Render: anti_alias={:?} msaa={:?} upscaler={:?} ray_tracing={}", - config.render.anti_alias, - config.render.msaa, - config.render.upscaler, - config.render.ray_tracing + "RenderSettings: anti_alias={:?} msaa={:?} upscaler={:?} ray_tracing={}", + render_cfg.anti_alias, render_cfg.msaa, render_cfg.upscaler, render_cfg.ray_tracing ); } - -fn spawn_camera(mut commands: Commands) { - commands.spawn(( - Camera3d::default(), - Transform::from_xyz(0.0, 0.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y), - BevyConfigCamera, - )); -} diff --git a/examples/deferred_camera.rs b/examples/deferred_camera.rs index 43af425..255b82d 100644 --- a/examples/deferred_camera.rs +++ b/examples/deferred_camera.rs @@ -1,11 +1,10 @@ //! Demonstrates deferred camera spawning. //! -//! This is the realistic pattern for non-trivial games: the camera is -//! spawned after a state transition (e.g., `OnEnter(AppState::InGame)`) -//! or after async asset load — *not* at `Startup`. The -//! [`BevyConfigCamera`] marker still gets the right anti-alias / MSAA / -//! upscaler on its first frame, because [`CommonBindingsPlugin`] -//! registers an `On` observer. +//! The realistic pattern for non-trivial games: the camera is spawned after +//! a state transition (e.g., `OnEnter(AppState::InGame)`) or after async +//! asset load — *not* at `Startup`. The [`SettingsCamera`] marker still +//! gets the right anti-alias / MSAA / upscaler on its first frame, because +//! [`RenderSettingsPlugin`] registers an `On` observer. //! //! Run with: //! @@ -15,7 +14,7 @@ use bevy::prelude::*; use bevy_anti_alias::taa::TemporalAntiAliasing; -use bevy_config::prelude::*; +use bevy_settings_plus::prelude::*; #[derive(States, Default, Debug, Clone, Eq, PartialEq, Hash)] enum AppState { @@ -27,10 +26,9 @@ enum AppState { fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugins(ConfigPlugin::::new( - FileBackend::::new("net", "pavlov", "bevy_config_deferred_example"), + .add_plugins(SettingsPlusPlugins::new( + "net.pavlov.bevy_settings_plus_deferred_example", )) - .add_plugins(CommonBindingsPlugin) .init_state::() .add_systems(Startup, kick_off_loading) .add_systems(OnEnter(AppState::InGame), spawn_camera) @@ -47,21 +45,21 @@ fn kick_off_loading(mut next: ResMut>) { } fn spawn_camera(mut commands: Commands) { - info!("Entering InGame: spawning camera with BevyConfigCamera marker"); + info!("Entering InGame: spawning camera with SettingsCamera marker"); commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 0.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y), - BevyConfigCamera, + SettingsCamera, )); } /// Confirm the binding observer attached `TemporalAntiAliasing` (the /// desktop platform default) the moment the deferred camera was tagged -/// with `BevyConfigCamera`, despite the camera spawning *after* the -/// initial `ConfigApplied` pulse. +/// with `SettingsCamera`, despite the camera spawning *after* the +/// initial `RenderSettings`-changed pulse. fn verify_taa_attached( add: On, - cameras: Query<(), With>, + cameras: Query<(), With>, ) { if cameras.contains(add.entity) { info!( diff --git a/src/backend.rs b/src/backend.rs deleted file mode 100644 index eeaa941..0000000 --- a/src/backend.rs +++ /dev/null @@ -1,196 +0,0 @@ -//! Persistence: load and store sparse `Overrides` blobs. -//! -//! `bevy_config` ships two default backends: -//! -//! - [`FileBackend`] (native) — RON file at `//config.ron`, -//! written atomically (tmp + `sync_all` + rename). -//! - `LocalStorageBackend` (wasm) — JSON in `web_sys` localStorage under the -//! key `.bevy_config.`. -//! -//! Both implement [`ConfigBackend`]. Consumers can substitute their own -//! implementation by passing it to [`crate::plugin::ConfigPlugin::new`]. - -use core::marker::PhantomData; - -use thiserror::Error; - -use crate::config::Config; - -/// Errors a backend may surface from `store()`. `load()` returns `None` on any -/// error (no config + no override = "use platform defaults"), which is the -/// behavior expected on first launch. -#[derive(Debug, Error)] -pub enum BackendError { - #[error("io error: {0}")] - Io(String), - #[error("serialize error: {0}")] - Serialize(String), - /// Deserialisation error (reading). Surfaced from `store()` only when - /// re-reading; `load()` swallows and returns `None`. - #[error("deserialize error: {0}")] - Deserialize(String), - /// localStorage unavailable / not authorized (wasm). - #[error("unsupported: {0}")] - Unsupported(String), -} - -/// Persistence trait. Implementations are stored as a `Box>` -/// inside [`crate::plugin::ConfigPlugin`]. -pub trait ConfigBackend: Send + Sync + 'static { - /// Read the cached overrides. `None` on first run, missing file, or any - /// failure — the plugin falls back to `::platform_default`. - fn load(&self) -> Option; - - /// Write `overrides` to the underlying storage. - #[must_use = "persisting config should not silently drop a save error"] - fn store(&self, overrides: &C::Overrides) -> Result<(), BackendError>; -} - -// ─── Native: RON file with atomic write ────────────────────────────────────── - -#[cfg(not(target_family = "wasm"))] -mod native { - use super::*; - use std::fs::{self, File}; - use std::io::Write as _; - use std::path::PathBuf; - - /// File-backed RON storage at `//config.ron`. - /// - /// Path discovery uses [`directories::ProjectDirs`]. Writes go to - /// `config.ron.new`, `sync_all`, then `rename` — so an interrupted write - /// never leaves a half-written file in place of a previously-valid one. - pub struct FileBackend { - path: PathBuf, - _marker: PhantomData C>, - } - - impl FileBackend { - /// Create a backend rooted at the platform's config dir for - /// `qualifier.organization.application` (the [`directories::ProjectDirs`] - /// triple). On Linux this is `$XDG_CONFIG_HOME//`, on - /// Windows `%APPDATA%\\\config\`, on macOS - /// `~/Library/Application Support/../`. - pub fn new(qualifier: &str, organization: &str, application: &str) -> Self { - let dirs = directories::ProjectDirs::from(qualifier, organization, application) - .expect("could not determine a config directory for this platform"); - let path = dirs.config_dir().join("config.ron"); - Self { - path, - _marker: PhantomData, - } - } - - /// Create a backend at an explicit path (escape hatch / tests). - pub fn at_path(path: impl Into) -> Self { - Self { - path: path.into(), - _marker: PhantomData, - } - } - } - - impl ConfigBackend for FileBackend { - fn load(&self) -> Option { - let bytes = fs::read(&self.path).ok()?; - #[cfg(feature = "ron")] - { - ron::de::from_bytes::(&bytes).ok() - } - #[cfg(not(feature = "ron"))] - { - let _ = bytes; - None - } - } - - fn store(&self, overrides: &C::Overrides) -> Result<(), BackendError> { - #[cfg(feature = "ron")] - { - let serialized = - ron::ser::to_string_pretty(overrides, ron::ser::PrettyConfig::default()) - .map_err(|e| BackendError::Serialize(e.to_string()))?; - - if let Some(dir) = self.path.parent() { - fs::create_dir_all(dir).map_err(|e| BackendError::Io(e.to_string()))?; - } - - // Atomic-write: tmp → sync_all → rename. - let tmp = self.path.with_extension("ron.new"); - { - let mut f = File::create(&tmp).map_err(|e| BackendError::Io(e.to_string()))?; - f.write_all(serialized.as_bytes()) - .map_err(|e| BackendError::Io(e.to_string()))?; - f.sync_all().map_err(|e| BackendError::Io(e.to_string()))?; - } - fs::rename(&tmp, &self.path).map_err(|e| BackendError::Io(e.to_string()))?; - Ok(()) - } - #[cfg(not(feature = "ron"))] - { - let _ = overrides; - Err(BackendError::Unsupported( - "FileBackend requires the `ron` feature".into(), - )) - } - } - } -} - -#[cfg(not(target_family = "wasm"))] -pub use native::FileBackend; - -// ─── Wasm: localStorage with JSON ──────────────────────────────────────────── - -#[cfg(target_family = "wasm")] -mod wasm { - use super::*; - - /// Browser localStorage backend. Stores JSON under - /// `.bevy_config.`. - pub struct LocalStorageBackend { - key: String, - _marker: PhantomData C>, - } - - impl LocalStorageBackend { - pub fn new(app_id: &str) -> Self { - let type_name = core::any::type_name::(); - // Sanitise type name for the storage key. - let suffix: String = type_name - .chars() - .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' }) - .collect(); - Self { - key: format!("{app_id}.bevy_config.{suffix}"), - _marker: PhantomData, - } - } - - fn storage(&self) -> Result { - web_sys::window() - .and_then(|w| w.local_storage().ok().flatten()) - .ok_or_else(|| BackendError::Unsupported("localStorage unavailable".into())) - } - } - - impl ConfigBackend for LocalStorageBackend { - fn load(&self) -> Option { - let storage = self.storage().ok()?; - let raw = storage.get_item(&self.key).ok().flatten()?; - serde_json::from_str(&raw).ok() - } - - fn store(&self, overrides: &C::Overrides) -> Result<(), BackendError> { - let storage = self.storage()?; - let json = serde_json::to_string(overrides) - .map_err(|e| BackendError::Serialize(e.to_string()))?; - storage - .set_item(&self.key, &json) - .map_err(|e| BackendError::Io(format!("{e:?}"))) - } - } -} - -#[cfg(target_family = "wasm")] -pub use wasm::LocalStorageBackend; diff --git a/src/bindings/display.rs b/src/bindings/display.rs deleted file mode 100644 index a1eba90..0000000 --- a/src/bindings/display.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Apply [`Display`](crate::common::Display) to the -//! [`PrimaryWindow`](bevy_window::PrimaryWindow). - -use bevy_ecs::prelude::*; -use bevy_window::{ - MonitorSelection as BevyMonitorSelection, PresentMode, PrimaryWindow, VideoModeSelection, - Window, WindowMode as BevyWindowMode, -}; - -use crate::common::{ - CommonConfig, MonitorSelection, Resolution, VsyncMode, WindowMode as CfgWindowMode, -}; - -pub(super) fn apply_display( - config: Res, - mut window: Single<&mut Window, With>, -) { - let display = &config.display; - - let bevy_monitor = match display.monitor { - MonitorSelection::Primary => BevyMonitorSelection::Primary, - MonitorSelection::Index(i) => BevyMonitorSelection::Index(i as usize), - }; - - let target_mode = match display.window_mode { - CfgWindowMode::Windowed => BevyWindowMode::Windowed, - CfgWindowMode::BorderlessFullscreen => BevyWindowMode::BorderlessFullscreen(bevy_monitor), - CfgWindowMode::Fullscreen => { - BevyWindowMode::Fullscreen(bevy_monitor, VideoModeSelection::Current) - } - }; - if window.mode != target_mode { - window.mode = target_mode; - } - - let target_present = match display.vsync { - VsyncMode::Auto => PresentMode::AutoVsync, - VsyncMode::On => PresentMode::Fifo, - VsyncMode::Off => PresentMode::Immediate, - VsyncMode::Mailbox => PresentMode::Mailbox, - }; - if window.present_mode != target_present { - window.present_mode = target_present; - } - - if let Resolution::Custom { width, height } = display.resolution - && (window.resolution.physical_width() != width - || window.resolution.physical_height() != height) - { - window.resolution.set_physical_resolution(width, height); - } -} diff --git a/src/bindings/mod.rs b/src/bindings/mod.rs deleted file mode 100644 index aee3c26..0000000 --- a/src/bindings/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Engine bindings for [`CommonConfig`]. -//! -//! [`CommonBindingsPlugin`] owns the binding systems for the *graphics* axes -//! (display + render). They run in `PostUpdate.in_set(BevyConfigSet::ApplyBindings)`, -//! gated on `resource_changed::`. The first-frame run picks up -//! the initial insert+clamp. -//! -//! Audio bindings are deferred to a later release — see the crate-level -//! README. - -mod display; -mod render; - -use bevy_app::{App, Plugin, PostUpdate}; -use bevy_ecs::prelude::*; - -use crate::common::CommonConfig; -use crate::config::BevyConfigSet; - -/// Marker component on cameras whose anti-alias / MSAA / upscaler should be -/// driven by `bevy_config`. -/// -/// Spawn alongside `Camera3d` (or `Camera2d`): -/// -/// ```ignore -/// commands.spawn((Camera3d::default(), BevyConfigCamera)); -/// ``` -#[derive(Component, Debug, Clone, Copy, Default)] -pub struct BevyConfigCamera; - -/// Wires the graphics binding systems for [`CommonConfig`]. -/// -/// Add this *after* [`crate::plugin::ConfigPlugin`] for [`CommonConfig`]. -pub struct CommonBindingsPlugin; - -impl Plugin for CommonBindingsPlugin { - fn build(&self, app: &mut App) { - app.add_systems( - PostUpdate, - (display::apply_display, render::apply_render) - .in_set(BevyConfigSet::ApplyBindings) - .run_if(resource_changed::), - ); - // `apply_display` doesn't need a sibling observer — display config is - // window-scoped, not camera-scoped, and the primary window already - // exists by the time `Res` first changes. - app.add_observer(render::apply_render_on_camera_add); - } -} diff --git a/src/bindings/render.rs b/src/bindings/render.rs deleted file mode 100644 index 84e8e63..0000000 --- a/src/bindings/render.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! Apply [`Render`](crate::common::Render) to cameras carrying the -//! [`BevyConfigCamera`](super::BevyConfigCamera) marker. - -use bevy_anti_alias::fxaa::Fxaa; -use bevy_anti_alias::smaa::Smaa; -use bevy_anti_alias::taa::TemporalAntiAliasing; -use bevy_ecs::entity::Entity; -use bevy_ecs::prelude::*; -use bevy_log::warn; -use bevy_render::view::Msaa; - -use crate::caps::AdapterCaps; -use crate::common::{AntiAlias, CommonConfig, MsaaLevel, Render, Upscaler}; - -use super::BevyConfigCamera; - -/// Apply [`Render`] to a single camera entity. Called by both the -/// resource-changed system below and by the `Add, BevyConfigCamera` -/// observer in [`super::CommonBindingsPlugin`], so cameras spawned -/// after the initial config-applied tick still pick up the current -/// settings on their first frame. -pub(super) fn apply_render_to_entity( - commands: &mut Commands, - entity: Entity, - render: &Render, - caps: Option<&AdapterCaps>, -) { - apply_anti_alias(commands, entity, render.anti_alias); - apply_msaa(commands, entity, render.msaa); - apply_upscaler(commands, entity, render.upscaler, caps); -} - -pub(super) fn apply_render( - config: Res, - caps: Option>, - cameras: Query>, - mut commands: Commands, -) { - for entity in &cameras { - apply_render_to_entity(&mut commands, entity, &config.render, caps.as_deref()); - } -} - -/// Observer: apply current [`Render`] settings whenever a camera is -/// tagged with [`BevyConfigCamera`]. Fixes the deferred-spawn race -/// where `apply_render`'s `resource_changed::` first-tick -/// pulse fires before the consumer's `OnEnter(...)` system spawns the -/// camera, leaving it without configured AA/MSAA/upscaler. -pub(super) fn apply_render_on_camera_add( - add: On, - config: Res, - caps: Option>, - mut commands: Commands, -) { - apply_render_to_entity(&mut commands, add.entity, &config.render, caps.as_deref()); -} - -fn apply_anti_alias(commands: &mut Commands, entity: Entity, mode: AntiAlias) { - let mut e = commands.entity(entity); - match mode { - AntiAlias::None => { - e.remove::(); - e.remove::(); - e.remove::(); - } - AntiAlias::Fxaa => { - e.remove::(); - e.remove::(); - e.insert(Fxaa::default()); - } - AntiAlias::Smaa => { - e.remove::(); - e.remove::(); - e.insert(Smaa::default()); - } - AntiAlias::Taa => { - e.remove::(); - e.remove::(); - e.insert(TemporalAntiAliasing::default()); - } - } -} - -fn apply_msaa(commands: &mut Commands, entity: Entity, level: MsaaLevel) { - let msaa = match level { - MsaaLevel::Off => Msaa::Off, - MsaaLevel::Sample2 => Msaa::Sample2, - MsaaLevel::Sample4 => Msaa::Sample4, - MsaaLevel::Sample8 => Msaa::Sample8, - }; - commands.entity(entity).insert(msaa); -} - -fn apply_upscaler( - commands: &mut Commands, - entity: Entity, - upscaler: Upscaler, - caps: Option<&AdapterCaps>, -) { - // Always start by clearing any DLSS component; we re-insert below if the - // current selection demands it. - #[cfg(feature = "dlss")] - { - commands - .entity(entity) - .remove::>(); - } - - match upscaler { - Upscaler::Native => { - // Nothing to insert. (DLSS already removed above.) - let _ = (commands, entity, caps); - } - Upscaler::Dlss(_preset) => { - #[cfg(feature = "dlss")] - { - let supported = caps.is_some_and(|c| c.supports_dlss); - if !supported { - warn!( - "Upscaler::Dlss selected but adapter does not support DLSS \ - (Vulkan + NVIDIA required); falling back to Native" - ); - return; - } - use bevy_anti_alias::dlss::{ - Dlss, DlssPerfQualityMode, DlssSuperResolutionFeature, - }; - use core::marker::PhantomData; - let perf_quality_mode = match _preset { - crate::common::UpscalerPreset::Quality => DlssPerfQualityMode::Quality, - crate::common::UpscalerPreset::Balanced => DlssPerfQualityMode::Balanced, - crate::common::UpscalerPreset::Performance => DlssPerfQualityMode::Performance, - crate::common::UpscalerPreset::UltraPerformance => { - DlssPerfQualityMode::UltraPerformance - } - }; - commands - .entity(entity) - .insert(Dlss:: { - perf_quality_mode, - reset: false, - _phantom_data: PhantomData, - }); - } - #[cfg(not(feature = "dlss"))] - { - let _ = (commands, entity, caps); - warn!( - "Upscaler::Dlss selected but the `dlss` cargo feature is disabled; \ - falling back to Native" - ); - } - } - Upscaler::Fsr(_) | Upscaler::Xess(_) | Upscaler::Tsr(_) => { - let _ = (commands, entity, caps); - warn!( - "Upscaler {:?} is a schema slot in v0.1 and is not yet wired; \ - falling back to Native", - upscaler - ); - } - } -} diff --git a/src/caps.rs b/src/caps.rs index b073f17..1ebab04 100644 --- a/src/caps.rs +++ b/src/caps.rs @@ -3,7 +3,7 @@ //! [`AdapterCaps`] is a stable, plain-data summary of the wgpu adapter — bools, ints, //! enums. It is built from `RenderAdapterInfo` + `RenderDevice` once during //! [`Plugin::finish`](bevy_app::Plugin::finish) on -//! [`crate::plugin::ConfigPlugin`] and inserted into the main world as a +//! [`crate::caps_aware::CapsAwarePlugin`] and inserted into the main world as a //! resource. use bevy_app::App; @@ -16,8 +16,8 @@ use bevy_render::renderer::{RenderAdapterInfo, RenderDevice}; /// Stable summary of the active wgpu adapter, in the main world. /// /// Construct via [`detect_caps`]; published as a resource by -/// [`crate::plugin::ConfigPlugin`]. -#[derive(Resource, Reflect, Debug, Clone)] +/// [`crate::caps_aware::CapsAwarePlugin`]. +#[derive(Resource, Reflect, Debug, Clone, Copy)] #[reflect(Resource)] pub struct AdapterCaps { /// Selected graphics backend (Vulkan, DX12, Metal, …). @@ -119,16 +119,15 @@ impl PlatformTarget { } /// Read the active adapter from the [`RenderApp`] sub-app and project it onto -/// [`AdapterCaps`]. +/// [`AdapterCaps`]. Returns `None` for headless / `MinimalPlugins` apps where +/// no `RenderApp` is present. /// /// Call from [`bevy_app::Plugin::finish`] — sub-app resources aren't populated /// during `build`. -pub fn detect_caps(app: &mut App) -> AdapterCaps { - let render_app = app - .get_sub_app(RenderApp) - .expect("bevy_config requires the RenderPlugin (RenderApp sub-app missing)"); - let info = render_app.world().resource::(); - let device = render_app.world().resource::(); +pub fn detect_caps(app: &mut App) -> Option { + let render_app = app.get_sub_app(RenderApp)?; + let info = render_app.world().get_resource::()?; + let device = render_app.world().get_resource::()?; let features = device.features(); let limits = device.limits(); @@ -136,12 +135,12 @@ pub fn detect_caps(app: &mut App) -> AdapterCaps { let backend = Backend::from_wgpu(info.backend); let vendor = GpuVendor::from_pci_id(info.vendor); - AdapterCaps { + Some(AdapterCaps { backend, vendor, max_texture_dim_2d: limits.max_texture_dimension_2d, ray_query: features.contains(wgpu_types::Features::EXPERIMENTAL_RAY_QUERY), timestamp_query: features.contains(wgpu_types::Features::TIMESTAMP_QUERY), supports_dlss: matches!((backend, vendor), (Backend::Vulkan, GpuVendor::Nvidia)), - } + }) } diff --git a/src/caps_aware.rs b/src/caps_aware.rs new file mode 100644 index 0000000..4d59cb1 --- /dev/null +++ b/src/caps_aware.rs @@ -0,0 +1,137 @@ +//! Caps-aware extension to `bevy_settings`. +//! +//! [`CapsAware`] is a small trait that any settings [`Resource`] can implement +//! to declare a `clamp_to(caps)` step. [`CapsAwarePlugin`] runs once in +//! [`Plugin::finish`] — after `RenderApp` is populated and after +//! `bevy_settings::PreferencesPlugin` has loaded its files — and: +//! +//! 1. detects [`AdapterCaps`] from the live wgpu adapter and inserts the +//! resource into the main world; +//! 2. scans the type registry for every type carrying [`ReflectCapsAware`] +//! type-data and calls its `clamp_to` against the just-detected caps. +//! +//! ## Implementing +//! +//! ```ignore +//! use bevy::prelude::*; +//! use bevy_settings::SettingsGroup; +//! use bevy_settings_plus::prelude::*; +//! +//! #[derive(Resource, SettingsGroup, Reflect, Default)] +//! #[reflect(Resource, SettingsGroup, CapsAware, Default)] +//! struct MyGameQuality { +//! ray_tracing: bool, +//! } +//! +//! impl CapsAware for MyGameQuality { +//! fn clamp_to(&mut self, caps: AdapterCaps) { +//! if !caps.ray_query { self.ray_tracing = false; } +//! } +//! } +//! ``` +//! +//! Then `app.register_type::()` (typically inside the type's +//! own `Plugin::build`) and add [`CapsAwarePlugin`] once. + +use bevy_app::{App, Plugin}; +use bevy_ecs::component::Mutable; +use bevy_ecs::reflect::AppTypeRegistry; +use bevy_ecs::reflect::ReflectResource; +use bevy_ecs::resource::Resource; +use bevy_ecs::world::World; +use bevy_log::warn; +use bevy_reflect::{CreateTypeData, FromReflect, Reflect, TypePath, TypeRegistration}; + +use crate::caps::{AdapterCaps, detect_caps}; + +/// Settings types that need to be clamped against the active adapter's caps +/// implement this. Register the type with `#[reflect(CapsAware)]` so +/// [`CapsAwarePlugin`] discovers it. +/// +/// `Clone + PartialEq` are required so the clamp pass can avoid bumping the +/// resource's change tick when clamping is a no-op — otherwise the next +/// `bevy_settings::SavePreferencesDeferred` would re-write the file with +/// the clamped values, silently overwriting the user's stored intent on +/// hardware that doesn't support all features. +pub trait CapsAware: + Resource + Reflect + FromReflect + TypePath + Clone + PartialEq +{ + /// Mutate `self` to fit `caps`. Called once after settings are loaded + /// from disk and the wgpu adapter has been queried. + fn clamp_to(&mut self, caps: AdapterCaps); +} + +/// Reflection type-data for [`CapsAware`]. Add `CapsAware` to your type's +/// `#[reflect(...)]` list to install this. +#[derive(Clone)] +pub struct ReflectCapsAware { + clamp_in_world: fn(&mut World, AdapterCaps), +} + +impl CreateTypeData for ReflectCapsAware { + fn create_type_data(_input: ()) -> Self { + Self { + clamp_in_world: |world, caps| { + let candidate: T = match world.get_resource::() { + Some(current) => { + let mut c = current.clone(); + c.clamp_to(caps); + if *current == c { + return; + } + c + } + None => return, + }; + // Immutable borrow of world released; safe to take mutable now. + if let Some(mut r) = world.get_resource_mut::() { + *r = candidate; + } + }, + } + } + + // Mirror `ReflectSettingsGroup`'s convention: a `CapsAware` type is always + // a `Resource`, so installing this type-data implies `ReflectResource` + // is available too. + fn insert_dependencies(type_registration: &mut TypeRegistration) { + type_registration.register_type_data::(); + } +} + +/// Detects [`AdapterCaps`] in [`Plugin::finish`] and runs the clamp pass +/// over every type registered with [`ReflectCapsAware`]. +/// +/// Order matters: this plugin must be added *after* +/// `bevy_render::RenderPlugin` (so `RenderApp` is populated by the time +/// `finish` runs) and *after* `bevy_settings::PreferencesPlugin` (so +/// settings have been loaded from disk before clamping). The convenience +/// [`crate::SettingsPlusPlugins`] group wires the order correctly. +/// +/// If no `RenderApp` is present (headless / `MinimalPlugins`), the clamp +/// pass is skipped — settings remain as loaded from disk. +pub struct CapsAwarePlugin; + +impl Plugin for CapsAwarePlugin { + fn build(&self, app: &mut App) { + app.register_type::(); + } + + fn finish(&self, app: &mut App) { + let Some(caps) = detect_caps(app) else { + warn!("AdapterCaps not detected (no RenderApp); skipping clamp pass."); + return; + }; + app.insert_resource(caps); + + let registry = app.world().resource::().clone(); + let types = registry.read(); + let world = app.world_mut(); + + for ty in types.iter() { + if let Some(rca) = ty.data::() { + (rca.clamp_in_world)(world, caps); + } + } + } +} diff --git a/src/common/accessibility.rs b/src/common/accessibility.rs index 68702ce..d9c2862 100644 --- a/src/common/accessibility.rs +++ b/src/common/accessibility.rs @@ -1,46 +1,45 @@ -//! `Accessibility` axis: subtitles, motion, colour-blind modes. +//! `AccessibilitySettings` axis: subtitles, motion, colour-blind modes. +//! +//! No engine bindings yet — consumers read [`AccessibilitySettings`] directly and +//! adapt their UI / shaders themselves. +use bevy_app::{App, Plugin}; +use bevy_ecs::reflect::ReflectResource; +use bevy_ecs::resource::Resource; use bevy_reflect::Reflect; -use serde::{Deserialize, Serialize}; +use bevy_reflect::prelude::ReflectDefault; +use bevy_settings::{ReflectSettingsGroup, SettingsGroup}; use crate::caps::{AdapterCaps, PlatformTarget}; +use crate::caps_aware::{CapsAware, ReflectCapsAware}; -/// Colour-blind compensation mode (binding TBD — slot only in v0.1; consumers -/// can read the value and adapt their UI shaders/palettes themselves). -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +/// Colour-blind compensation mode (slot only — consumers can read the value +/// and adapt their UI shaders/palettes themselves). +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] #[non_exhaustive] pub enum ColorBlindMode { + #[default] None, Protanopia, Deuteranopia, Tritanopia, } -/// Populated accessibility config. -#[derive(Reflect, Debug, Clone, PartialEq)] -pub struct Accessibility { +/// AccessibilitySettings config resource. +#[derive(Resource, SettingsGroup, Reflect, Debug, Clone, PartialEq)] +#[reflect(Resource, SettingsGroup, CapsAware, Default)] +#[settings_group(group = "accessibility")] +pub struct AccessibilitySettings { pub subtitles_on: bool, pub subtitle_scale: f32, pub reduce_motion: bool, pub color_blind_mode: ColorBlindMode, } -/// Sparse on-disk overrides for [`Accessibility`]. -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -#[serde(default)] -pub struct AccessibilityOverrides { - #[serde(skip_serializing_if = "Option::is_none")] - pub subtitles_on: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub subtitle_scale: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub reduce_motion: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub color_blind_mode: Option, -} - -impl Accessibility { - pub(crate) fn platform_default(_target: PlatformTarget) -> Self { +impl AccessibilitySettings { + /// Conservative, platform-appropriate defaults. + pub fn platform_default(_target: PlatformTarget) -> Self { Self { subtitles_on: false, subtitle_scale: 1.0, @@ -48,35 +47,26 @@ impl Accessibility { color_blind_mode: ColorBlindMode::None, } } +} - pub(crate) fn merge(&mut self, o: &AccessibilityOverrides) { - if let Some(v) = o.subtitles_on { - self.subtitles_on = v; - } - if let Some(v) = o.subtitle_scale { - self.subtitle_scale = v; - } - if let Some(v) = o.reduce_motion { - self.reduce_motion = v; - } - if let Some(v) = o.color_blind_mode { - self.color_blind_mode = v; - } +impl Default for AccessibilitySettings { + fn default() -> Self { + Self::platform_default(PlatformTarget::detect()) } +} - pub(crate) fn clamp_to(&mut self, _caps: &AdapterCaps) { +impl CapsAware for AccessibilitySettings { + fn clamp_to(&mut self, _caps: AdapterCaps) { self.subtitle_scale = self.subtitle_scale.clamp(0.5, 3.0); } +} - pub(crate) fn diff(&self, default: &Self) -> AccessibilityOverrides { - AccessibilityOverrides { - subtitles_on: (self.subtitles_on != default.subtitles_on).then_some(self.subtitles_on), - subtitle_scale: (self.subtitle_scale != default.subtitle_scale) - .then_some(self.subtitle_scale), - reduce_motion: (self.reduce_motion != default.reduce_motion) - .then_some(self.reduce_motion), - color_blind_mode: (self.color_blind_mode != default.color_blind_mode) - .then_some(self.color_blind_mode), - } +/// Wires the [`AccessibilitySettings`] axis: registers the reflection type. No +/// binding systems today. +pub struct AccessibilitySettingsPlugin; + +impl Plugin for AccessibilitySettingsPlugin { + fn build(&self, app: &mut App) { + app.register_type::(); } } diff --git a/src/common/display.rs b/src/common/display.rs index a0301cf..20a9024 100644 --- a/src/common/display.rs +++ b/src/common/display.rs @@ -1,22 +1,43 @@ -//! `Display` axis: window mode, monitor, resolution, vsync, fps cap, HDR. +//! `DisplaySettings` axis: window mode, monitor, resolution, vsync, fps cap, HDR. +//! +//! Ships the [`DisplaySettings`] resource (a `bevy_settings::SettingsGroup`), leaf +//! enums (`WindowMode`, `VsyncMode`, `MonitorSelection`, `Resolution`, +//! `FpsCap`, `HdrPreference`), and [`DisplaySettingsPlugin`] which adds +//! the primary-window binding system. +use bevy_app::{App, Plugin, PostUpdate}; +use bevy_ecs::prelude::*; +use bevy_ecs::reflect::ReflectResource; +use bevy_ecs::resource::Resource; use bevy_reflect::Reflect; -use serde::{Deserialize, Serialize}; +use bevy_reflect::prelude::ReflectDefault; +use bevy_settings::{ReflectSettingsGroup, SettingsGroup}; +use bevy_window::{ + MonitorSelection as BevyMonitorSelection, PresentMode, PrimaryWindow, VideoModeSelection, + Window, WindowMode as BevyWindowMode, +}; +use crate::ApplyBindings; use crate::caps::{AdapterCaps, PlatformTarget}; +use crate::caps_aware::{CapsAware, ReflectCapsAware}; /// Window presentation mode. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] pub enum WindowMode { + #[default] Windowed, BorderlessFullscreen, Fullscreen, } /// Vsync intent. The binding maps these onto [`bevy_window::PresentMode`]. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] +#[non_exhaustive] pub enum VsyncMode { /// Driver-default vsync (maps to `AutoVsync`). + #[default] Auto, /// Force vsync on (maps to `Fifo`). On, @@ -27,38 +48,53 @@ pub enum VsyncMode { } /// Monitor selection. The binding maps onto [`bevy_window::MonitorSelection`]. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] #[non_exhaustive] pub enum MonitorSelection { + #[default] Primary, Index(u32), } /// Resolution choice. `Native` defers to the monitor's preferred mode. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] pub enum Resolution { + #[default] Native, - Custom { width: u32, height: u32 }, + Custom { + width: u32, + height: u32, + }, } /// Frame-rate cap. `Unlimited` disables capping. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] pub enum FpsCap { + #[default] Unlimited, Capped(u32), } /// HDR display preference (slot — auto-detect on Windows DXGI is deferred). -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] pub enum HdrPreference { + #[default] Off, On, Auto, } -/// Populated display config. -#[derive(Reflect, Debug, Clone, PartialEq, Eq)] -pub struct Display { +/// DisplaySettings config resource. Discovered by `bevy_settings::PreferencesPlugin` +/// via [`SettingsGroup`] and clamped to caps by +/// [`crate::CapsAwarePlugin`]. +#[derive(Resource, SettingsGroup, Reflect, Debug, Clone, PartialEq, Eq)] +#[reflect(Resource, SettingsGroup, CapsAware, Default)] +#[settings_group(group = "display")] +pub struct DisplaySettings { pub window_mode: WindowMode, pub monitor: MonitorSelection, pub resolution: Resolution, @@ -68,28 +104,11 @@ pub struct Display { pub hdr: HdrPreference, } -/// Sparse on-disk overrides for [`Display`]. -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(default)] -pub struct DisplayOverrides { - #[serde(skip_serializing_if = "Option::is_none")] - pub window_mode: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub monitor: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub resolution: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub refresh_rate: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub vsync: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub fps_cap: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub hdr: Option, -} - -impl Display { - pub(crate) fn platform_default(_target: PlatformTarget) -> Self { +impl DisplaySettings { + /// Conservative, platform-appropriate defaults. Used by the `Default` + /// impl (which is what `bevy_settings` constructs from when no value is + /// loaded from disk). + pub fn platform_default(_target: PlatformTarget) -> Self { Self { window_mode: WindowMode::Windowed, monitor: MonitorSelection::Primary, @@ -100,44 +119,74 @@ impl Display { hdr: HdrPreference::Off, } } +} - pub(crate) fn merge(&mut self, o: &DisplayOverrides) { - if let Some(v) = o.window_mode { - self.window_mode = v; - } - if let Some(v) = o.monitor { - self.monitor = v; - } - if let Some(v) = o.resolution { - self.resolution = v; - } - if let Some(v) = o.refresh_rate { - self.refresh_rate = v; - } - if let Some(v) = o.vsync { - self.vsync = v; - } - if let Some(v) = o.fps_cap { - self.fps_cap = v; - } - if let Some(v) = o.hdr { - self.hdr = v; - } +impl Default for DisplaySettings { + fn default() -> Self { + Self::platform_default(PlatformTarget::detect()) } +} + +impl CapsAware for DisplaySettings { + fn clamp_to(&mut self, _caps: AdapterCaps) { + // No display-axis caps clamping today. + } +} + +/// Wires the [`DisplaySettings`] axis: registers reflection types and adds +/// the primary-window binding system. +/// +/// Add this *before* `bevy_settings::PreferencesPlugin` so the type registry +/// is populated by the time it scans for [`SettingsGroup`] resources. +/// [`crate::SettingsPlusPlugins`] handles ordering for you. +pub struct DisplaySettingsPlugin; - pub(crate) fn clamp_to(&mut self, _caps: &AdapterCaps) { - // No display-axis caps clamping in v0.1. +impl Plugin for DisplaySettingsPlugin { + fn build(&self, app: &mut App) { + app.register_type::(); + app.add_systems( + PostUpdate, + apply_display + .in_set(ApplyBindings) + .run_if(resource_changed::), + ); } +} - pub(crate) fn diff(&self, default: &Self) -> DisplayOverrides { - DisplayOverrides { - window_mode: (self.window_mode != default.window_mode).then_some(self.window_mode), - monitor: (self.monitor != default.monitor).then_some(self.monitor), - resolution: (self.resolution != default.resolution).then_some(self.resolution), - refresh_rate: (self.refresh_rate != default.refresh_rate).then_some(self.refresh_rate), - vsync: (self.vsync != default.vsync).then_some(self.vsync), - fps_cap: (self.fps_cap != default.fps_cap).then_some(self.fps_cap), - hdr: (self.hdr != default.hdr).then_some(self.hdr), +pub(crate) fn apply_display( + display: Res, + mut window: Single<&mut Window, With>, +) { + let bevy_monitor = match display.monitor { + MonitorSelection::Primary => BevyMonitorSelection::Primary, + MonitorSelection::Index(i) => BevyMonitorSelection::Index(i as usize), + }; + + let target_mode = match display.window_mode { + WindowMode::Windowed => BevyWindowMode::Windowed, + WindowMode::BorderlessFullscreen => BevyWindowMode::BorderlessFullscreen(bevy_monitor), + WindowMode::Fullscreen => { + BevyWindowMode::Fullscreen(bevy_monitor, VideoModeSelection::Current) } + }; + if window.mode != target_mode { + window.mode = target_mode; + } + + let target_present = match display.vsync { + VsyncMode::Auto => PresentMode::AutoVsync, + VsyncMode::On => PresentMode::Fifo, + VsyncMode::Off => PresentMode::Immediate, + VsyncMode::Mailbox => PresentMode::Mailbox, + }; + if window.present_mode != target_present { + window.present_mode = target_present; + } + + if let Resolution::Custom { width, height } = display.resolution + && (window.resolution.physical_width() != width + || window.resolution.physical_height() != height) + { + window.resolution.set_physical_resolution(width, height); } } diff --git a/src/common/mod.rs b/src/common/mod.rs index e792c3b..d81b59c 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,12 +1,22 @@ -//! Universal `CommonConfig` schema: display, render, accessibility. +//! Opinionated graphics + accessibility schema. //! -//! Drop-in for projects that want a sensible baseline. Game-specific quality -//! dials live in a separate `Config`-implementing type the consumer defines -//! themselves. +//! Three independent axes, each one a `Resource + SettingsGroup + +//! CapsAware + Default`: +//! +//! - [`DisplaySettings`] — window mode, monitor, resolution, vsync, … +//! - [`RenderSettings`] — anti-alias, MSAA, upscaler, render scale, RT toggle. +//! - [`AccessibilitySettings`] — subtitles, motion, colour-blind mode. +//! +//! Each axis is its own self-contained module: the resource type, its leaf +//! enums, `Default`/`platform_default`/[`CapsAware`](crate::caps_aware::CapsAware) +//! impls, the binding system (where applicable), and a per-axis +//! `*SettingsPlugin`. //! //! Audio is intentionally absent — the bus convention is backend-specific -//! (firewheel/seedling/kira/oddio all model differently), so audio config -//! lives behind its own cargo feature with a backend-specific `Config` type. +//! (firewheel/seedling/kira/oddio all model differently). When the +//! firewheel/seedling integration lands it will ship as its own +//! [`SettingsGroup`](bevy_settings::SettingsGroup) resource behind a cargo +//! feature. mod accessibility; mod display; @@ -15,69 +25,3 @@ mod render; pub use accessibility::*; pub use display::*; pub use render::*; - -use bevy_ecs::reflect::ReflectResource; -use bevy_ecs::resource::Resource; -use bevy_reflect::Reflect; -use serde::{Deserialize, Serialize}; - -use crate::caps::{AdapterCaps, PlatformTarget}; -use crate::config::Config; - -/// Aggregate of the universal axes. Implements [`Config`]. -#[derive(Resource, Reflect, Debug, Clone, PartialEq)] -#[reflect(Resource)] -pub struct CommonConfig { - pub display: Display, - pub render: Render, - pub accessibility: Accessibility, -} - -/// Sparse on-disk overrides for [`CommonConfig`]. -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -#[serde(default)] -pub struct CommonConfigOverrides { - #[serde(skip_serializing_if = "is_default_overrides")] - pub display: DisplayOverrides, - #[serde(skip_serializing_if = "is_default_overrides")] - pub render: RenderOverrides, - #[serde(skip_serializing_if = "is_default_overrides")] - pub accessibility: AccessibilityOverrides, -} - -fn is_default_overrides(v: &T) -> bool { - *v == T::default() -} - -impl Config for CommonConfig { - type Overrides = CommonConfigOverrides; - - fn platform_default(target: PlatformTarget) -> Self { - Self { - display: Display::platform_default(target), - render: Render::platform_default(target), - accessibility: Accessibility::platform_default(target), - } - } - - fn merge(&mut self, overrides: &Self::Overrides) { - self.display.merge(&overrides.display); - self.render.merge(&overrides.render); - self.accessibility.merge(&overrides.accessibility); - } - - fn clamp_to(&mut self, caps: &AdapterCaps) { - self.display.clamp_to(caps); - self.render.clamp_to(caps); - self.accessibility.clamp_to(caps); - } - - fn current_overrides(&self, target: PlatformTarget) -> Self::Overrides { - let default = Self::platform_default(target); - CommonConfigOverrides { - display: self.display.diff(&default.display), - render: self.render.diff(&default.render), - accessibility: self.accessibility.diff(&default.accessibility), - } - } -} diff --git a/src/common/render.rs b/src/common/render.rs index 4aedd5e..b50d75d 100644 --- a/src/common/render.rs +++ b/src/common/render.rs @@ -1,15 +1,34 @@ -//! `Render` axis: anti-alias, MSAA, upscaler, render scale, sharpness, RT toggle. +//! `RenderSettings` axis: anti-alias, MSAA, upscaler, render scale, sharpness, RT toggle. +//! +//! Ships the [`RenderSettings`] resource (a `bevy_settings::SettingsGroup`), leaf +//! enums (`AntiAlias`, `MsaaLevel`, `Upscaler`, `UpscalerPreset`), the +//! [`SettingsCamera`] marker, and [`RenderSettingsPlugin`] which adds the +//! binding system + an `Add` observer. +use bevy_anti_alias::fxaa::Fxaa; +use bevy_anti_alias::smaa::Smaa; +use bevy_anti_alias::taa::TemporalAntiAliasing; +use bevy_app::{App, Plugin, PostUpdate}; +use bevy_ecs::prelude::*; +use bevy_ecs::reflect::ReflectResource; +use bevy_ecs::resource::Resource; +use bevy_log::warn; use bevy_reflect::Reflect; -use serde::{Deserialize, Serialize}; +use bevy_reflect::prelude::ReflectDefault; +use bevy_render::view::Msaa; +use bevy_settings::{ReflectSettingsGroup, SettingsGroup}; +use crate::ApplyBindings; use crate::caps::{AdapterCaps, PlatformTarget}; +use crate::caps_aware::{CapsAware, ReflectCapsAware}; /// Anti-aliasing technique. Mutually exclusive with the technique components /// — the binding inserts/removes the right one on tagged cameras. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] #[non_exhaustive] pub enum AntiAlias { + #[default] None, Fxaa, Smaa, @@ -17,20 +36,24 @@ pub enum AntiAlias { } /// MSAA sample count. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] +#[non_exhaustive] pub enum MsaaLevel { + #[default] Off, Sample2, Sample4, Sample8, } -/// Upscaler choice. Only `Native` and `Dlss` are wired in v0.1; the others are -/// schema slots — selecting them logs a warning and falls back to `Native` for -/// now. -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +/// Upscaler choice. Only `Native` and `Dlss` are wired today; the others are +/// schema slots — selecting them logs a warning and falls back to `Native`. +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] #[non_exhaustive] pub enum Upscaler { + #[default] Native, Dlss(UpscalerPreset), Fsr(UpscalerPreset), @@ -39,18 +62,68 @@ pub enum Upscaler { } /// Quality preset for upscalers (DLSS / FSR / XeSS / TSR). -#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +/// +/// `Auto` and `Dlaa` are DLSS-specific (`Auto` lets DLSS pick the perf tier +/// based on display resolution; `Dlaa` runs the DLSS network at native res +/// as a high-quality AA pass). FSR / XeSS / TSR don't have direct +/// equivalents — selecting either with a non-DLSS upscaler falls back to +/// the closest perf tier at apply time. +#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Default)] +#[reflect(Default)] #[non_exhaustive] pub enum UpscalerPreset { + /// DLSS-only: let the engine pick the perf tier based on display resolution. + Auto, + /// DLSS-only: run the DLSS network at native resolution as an AA pass. + Dlaa, + #[default] Quality, Balanced, Performance, UltraPerformance, } -/// Populated render config. -#[derive(Reflect, Debug, Clone, PartialEq)] -pub struct Render { +#[cfg(feature = "dlss")] +impl From for bevy_anti_alias::dlss::DlssPerfQualityMode { + fn from(preset: UpscalerPreset) -> Self { + match preset { + UpscalerPreset::Auto => Self::Auto, + UpscalerPreset::Dlaa => Self::Dlaa, + UpscalerPreset::Quality => Self::Quality, + UpscalerPreset::Balanced => Self::Balanced, + UpscalerPreset::Performance => Self::Performance, + UpscalerPreset::UltraPerformance => Self::UltraPerformance, + } + } +} + +/// Marker component on cameras whose anti-alias / MSAA / upscaler should be +/// driven by `bevy_settings_plus`. +/// +/// Spawn alongside the camera type you want: +/// +/// ```ignore +/// commands.spawn((Camera3d::default(), SettingsCamera)); +/// ``` +/// +/// The bindings apply on `Add` so cameras spawned after +/// the initial settings-loaded tick still get the current settings. +/// +/// **2D caveat**: the desktop platform default is `AntiAlias::Taa`, which +/// requires the depth + motion-vector prepasses and is 3D-only. If you +/// tag a `Camera2d` with `SettingsCamera`, override the AA setting to +/// `AntiAlias::Fxaa` or `AntiAlias::Smaa` before spawn — TAA on a 2D +/// camera will mis-render or fail Bevy's required-component checks. +#[derive(Component, Debug, Clone, Copy, Default)] +pub struct SettingsCamera; + +/// RenderSettings config resource. Discovered by `bevy_settings::PreferencesPlugin` +/// via [`SettingsGroup`] and clamped to caps by +/// [`crate::CapsAwarePlugin`]. +#[derive(Resource, SettingsGroup, Reflect, Debug, Clone, PartialEq)] +#[reflect(Resource, SettingsGroup, CapsAware, Default)] +#[settings_group(group = "render")] +pub struct RenderSettings { pub anti_alias: AntiAlias, pub msaa: MsaaLevel, pub upscaler: Upscaler, @@ -64,29 +137,11 @@ pub struct Render { pub ray_tracing: bool, } -/// Sparse on-disk overrides for [`Render`]. -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -#[serde(default)] -pub struct RenderOverrides { - #[serde(skip_serializing_if = "Option::is_none")] - pub anti_alias: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub msaa: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub upscaler: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub render_scale: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub sharpness: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub ray_tracing: Option, -} - -impl Render { - pub(crate) fn platform_default(target: PlatformTarget) -> Self { +impl RenderSettings { + /// Conservative, platform-appropriate defaults. + pub fn platform_default(target: PlatformTarget) -> Self { match target { PlatformTarget::Wasm => Self { - // Conservative wasm defaults: no temporal AA, no MSAA, no RT. anti_alias: AntiAlias::None, msaa: MsaaLevel::Off, upscaler: Upscaler::Native, @@ -104,29 +159,16 @@ impl Render { }, } } +} - pub(crate) fn merge(&mut self, o: &RenderOverrides) { - if let Some(v) = o.anti_alias { - self.anti_alias = v; - } - if let Some(v) = o.msaa { - self.msaa = v; - } - if let Some(v) = o.upscaler { - self.upscaler = v; - } - if let Some(v) = o.render_scale { - self.render_scale = v; - } - if let Some(v) = o.sharpness { - self.sharpness = v; - } - if let Some(v) = o.ray_tracing { - self.ray_tracing = v; - } +impl Default for RenderSettings { + fn default() -> Self { + Self::platform_default(PlatformTarget::detect()) } +} - pub(crate) fn clamp_to(&mut self, caps: &AdapterCaps) { +impl CapsAware for RenderSettings { + fn clamp_to(&mut self, caps: AdapterCaps) { // No RT support → force the master toggle off, regardless of override. if self.ray_tracing && !caps.ray_query { self.ray_tracing = false; @@ -140,15 +182,188 @@ impl Render { self.render_scale = self.render_scale.clamp(0.25, 1.0); self.sharpness = self.sharpness.clamp(0.0, 1.0); } +} + +/// Wires the [`RenderSettings`] axis: registers reflection types and adds +/// the binding system + the camera-add observer. +pub struct RenderSettingsPlugin; + +impl Plugin for RenderSettingsPlugin { + fn build(&self, app: &mut App) { + app.register_type::(); + app.add_systems( + PostUpdate, + apply_render + .in_set(ApplyBindings) + .run_if(resource_changed::), + ); + app.add_observer(apply_render_on_camera_add); + } +} + +fn apply_render_to_entity( + commands: &mut Commands, + entity: Entity, + render: &RenderSettings, + caps: Option<&AdapterCaps>, +) { + apply_anti_alias(commands, entity, render.anti_alias); + apply_msaa(commands, entity, render.msaa); + apply_upscaler(commands, entity, render.upscaler, caps); +} + +// Per-axis change detection: only re-apply the AA / MSAA / upscaler axes +// that actually changed since the last run. Re-inserting `TemporalAntiAliasing` +// every frame would otherwise discard accumulated TAA history when the user +// touches an unrelated field like `sharpness`. +pub(crate) fn apply_render( + render: Res, + caps: Option>, + cameras: Query>, + mut commands: Commands, + mut prev: Local>, +) { + let aa_changed = prev + .as_ref() + .is_none_or(|p| p.anti_alias != render.anti_alias); + let msaa_changed = prev.as_ref().is_none_or(|p| p.msaa != render.msaa); + let upscaler_changed = prev.as_ref().is_none_or(|p| p.upscaler != render.upscaler); + + if aa_changed || msaa_changed || upscaler_changed { + for entity in &cameras { + if aa_changed { + apply_anti_alias(&mut commands, entity, render.anti_alias); + } + if msaa_changed { + apply_msaa(&mut commands, entity, render.msaa); + } + if upscaler_changed { + apply_upscaler(&mut commands, entity, render.upscaler, caps.as_deref()); + } + } + } + + *prev = Some(render.clone()); +} + +// Observer for the deferred-spawn case: cameras tagged after the initial +// `resource_changed::` pulse still get their settings on frame 0. +// +// `RenderSettings` is `Option`al because the observer can fire before +// `PreferencesPlugin::build` inserts the resource (e.g., a user plugin's +// `build` synchronously spawns a `SettingsCamera` between when this +// observer is registered and when the resource is loaded). +pub(crate) fn apply_render_on_camera_add( + add: On, + render: Option>, + caps: Option>, + mut commands: Commands, +) { + let Some(render) = render else { return }; + apply_render_to_entity(&mut commands, add.entity, &render, caps.as_deref()); +} - pub(crate) fn diff(&self, default: &Self) -> RenderOverrides { - RenderOverrides { - anti_alias: (self.anti_alias != default.anti_alias).then_some(self.anti_alias), - msaa: (self.msaa != default.msaa).then_some(self.msaa), - upscaler: (self.upscaler != default.upscaler).then_some(self.upscaler), - render_scale: (self.render_scale != default.render_scale).then_some(self.render_scale), - sharpness: (self.sharpness != default.sharpness).then_some(self.sharpness), - ray_tracing: (self.ray_tracing != default.ray_tracing).then_some(self.ray_tracing), +fn apply_anti_alias(commands: &mut Commands, entity: Entity, mode: AntiAlias) { + let mut e = commands.entity(entity); + match mode { + AntiAlias::None => { + e.remove::(); + e.remove::(); + e.remove::(); + } + AntiAlias::Fxaa => { + e.remove::(); + e.remove::(); + e.insert(Fxaa::default()); + } + AntiAlias::Smaa => { + e.remove::(); + e.remove::(); + e.insert(Smaa::default()); + } + AntiAlias::Taa => { + e.remove::(); + e.remove::(); + e.insert(TemporalAntiAliasing::default()); } } } + +fn apply_msaa(commands: &mut Commands, entity: Entity, level: MsaaLevel) { + let msaa = match level { + MsaaLevel::Off => Msaa::Off, + MsaaLevel::Sample2 => Msaa::Sample2, + MsaaLevel::Sample4 => Msaa::Sample4, + MsaaLevel::Sample8 => Msaa::Sample8, + }; + commands.entity(entity).insert(msaa); +} + +fn apply_upscaler( + commands: &mut Commands, + entity: Entity, + upscaler: Upscaler, + caps: Option<&AdapterCaps>, +) { + clear_dlss_if_present(commands, entity); + match upscaler { + Upscaler::Native => {} + Upscaler::Dlss(preset) => apply_dlss(commands, entity, preset, caps), + Upscaler::Fsr(_) | Upscaler::Xess(_) | Upscaler::Tsr(_) => { + warn!( + "Upscaler {:?} is a schema slot today and is not yet wired; \ + falling back to Native", + upscaler + ); + } + } +} + +#[cfg(feature = "dlss")] +fn clear_dlss_if_present(commands: &mut Commands, entity: Entity) { + use bevy_anti_alias::dlss::{Dlss, DlssSuperResolutionFeature}; + commands + .entity(entity) + .remove::>(); +} + +#[cfg(not(feature = "dlss"))] +fn clear_dlss_if_present(_commands: &mut Commands, _entity: Entity) {} + +#[cfg(feature = "dlss")] +fn apply_dlss( + commands: &mut Commands, + entity: Entity, + preset: UpscalerPreset, + caps: Option<&AdapterCaps>, +) { + if !caps.is_some_and(|c| c.supports_dlss) { + warn!( + "Upscaler::Dlss selected but adapter does not support DLSS \ + (Vulkan + NVIDIA required); falling back to Native" + ); + return; + } + use bevy_anti_alias::dlss::{Dlss, DlssSuperResolutionFeature}; + use core::marker::PhantomData; + commands + .entity(entity) + .insert(Dlss:: { + perf_quality_mode: preset.into(), + reset: false, + _phantom_data: PhantomData, + }); +} + +#[cfg(not(feature = "dlss"))] +fn apply_dlss( + _commands: &mut Commands, + _entity: Entity, + _preset: UpscalerPreset, + _caps: Option<&AdapterCaps>, +) { + warn!( + "Upscaler::Dlss selected but the `dlss` cargo feature is disabled; \ + falling back to Native" + ); +} diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index 86a332d..0000000 --- a/src/config.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! The [`Config`] trait and associated lifecycle types. - -use core::marker::PhantomData; - -use bevy_ecs::event::Event; -use bevy_ecs::resource::Resource; -use bevy_ecs::schedule::SystemSet; -use serde::{Serialize, de::DeserializeOwned}; - -use crate::caps::{AdapterCaps, PlatformTarget}; - -/// Trait every configuration type implements. -/// -/// Resolution order, applied by [`crate::plugin::ConfigPlugin`]: -/// -/// 1. [`Self::platform_default`] — start with platform-appropriate defaults. -/// 2. [`Self::merge`] — layer cached user overrides on top. -/// 3. [`Self::clamp_to`] — strip features the adapter doesn't support. -/// -/// Clamping last (post-merge) means a user override loaded from disk cannot -/// re-enable a feature their hardware lacks. -pub trait Config: Resource + Send + Sync + 'static { - /// On-disk shape: every field is `Option` so the file only contains - /// values that diverge from the platform default. Mirrors the populated - /// type, but with optional fields. - type Overrides: Default + Serialize + DeserializeOwned + Send + Sync + 'static; - - /// Conservative, platform-appropriate defaults. - fn platform_default(target: PlatformTarget) -> Self; - - /// Apply any explicitly-set fields from `overrides` onto `self`. - fn merge(&mut self, overrides: &Self::Overrides); - - /// Mutate `self` to fit `caps` (e.g., disable ray tracing if the adapter - /// lacks `EXPERIMENTAL_RAY_QUERY`). Called after `merge`. - fn clamp_to(&mut self, caps: &AdapterCaps); - - /// Project the current state into a sparse `Overrides` containing only - /// values that differ from `platform_default(target)`. Used when saving: - /// a fresh install with no changes serialises to an effectively-empty - /// file. - fn current_overrides(&self, target: PlatformTarget) -> Self::Overrides; -} - -/// Fired once at startup, after the platform default has been merged with -/// cached overrides and clamped against [`AdapterCaps`]. -/// -/// Add an observer to react one-shot: -/// -/// ```ignore -/// app.add_observer(|_: On>, /* ... */| {}); -/// ``` -#[derive(Event)] -pub struct ConfigApplied(pub PhantomData); - -// Manual `Default` impl: `#[derive(Default)]` would add a bogus `C: Default` -// bound that `PhantomData` doesn't actually need. -impl Default for ConfigApplied { - fn default() -> Self { - Self(PhantomData) - } -} - -/// Centralized ordering for `bevy_config` systems. Drop your own systems into -/// these sets via `.in_set(BevyConfigSet::ApplyBindings)` (or `.before(...)`) -/// to slot them into the lifecycle. -#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] -pub enum BevyConfigSet { - /// Bindings systems that translate `Res` → engine resources, in - /// `PostUpdate`. - ApplyBindings, -} diff --git a/src/lib.rs b/src/lib.rs index 37005b9..a756caf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,65 +1,149 @@ -//! Capability-aware configuration system for Bevy. +//! Capability-aware extension to [`bevy_settings`]. //! -//! The model: **detect adapter caps → pick platform default → merge user -//! overrides → clamp to caps → apply to engine resources.** +//! `bevy_settings` already provides a polished settings persistence kernel +//! (TOML files, change detection, async + debounced saves). This crate +//! layers the *graphics-aware* concerns on top: //! -//! ## Modules -//! -//! - [`caps`] — [`AdapterCaps`](caps::AdapterCaps) and [`PlatformTarget`](caps::PlatformTarget) -//! - [`config`] — the [`Config`](config::Config) trait and lifecycle event -//! - [`backend`] — [`ConfigBackend`](backend::ConfigBackend) trait + native/wasm impls -//! - [`plugin`] — [`ConfigPlugin`](plugin::ConfigPlugin) wiring + [`SaveConfig`](plugin::SaveConfig) command -//! - [`common`] — universal schema [`CommonConfig`](common::CommonConfig) (display, render, accessibility) -//! - [`bindings`] — [`CommonBindingsPlugin`](bindings::CommonBindingsPlugin) and [`BevyConfigCamera`](bindings::BevyConfigCamera) -//! -//! Most consumers `use bevy_config::prelude::*;` and reach for everything from there. +//! - **Adapter caps detection** — [`AdapterCaps`](caps::AdapterCaps) is a +//! stable, plain-data summary of the live wgpu adapter (backend, vendor, +//! ray-query support, DLSS reachability, …). It is detected once during +//! [`Plugin::finish`](bevy_app::Plugin::finish) on [`CapsAwarePlugin`] +//! and inserted as a main-world resource. +//! - **Caps clamping** — settings types implement +//! [`CapsAware`](caps_aware::CapsAware) and register `#[reflect(CapsAware)]`. +//! [`CapsAwarePlugin`] discovers them by reflection and runs each type's +//! `clamp_to(caps)` after settings have been loaded. +//! - **Opinionated graphics schema** — [`DisplaySettings`](common::DisplaySettings), +//! [`RenderSettings`](common::RenderSettings), and [`AccessibilitySettings`](common::AccessibilitySettings) +//! resources with platform-aware defaults and the engine bindings that +//! drive the primary window and tagged cameras. //! //! ## Quickstart //! //! ```no_run //! use bevy::prelude::*; -//! use bevy_config::prelude::*; +//! use bevy_settings_plus::prelude::*; //! //! App::new() //! .add_plugins(DefaultPlugins) -//! .add_plugins(ConfigPlugin::::new( -//! FileBackend::::new("com", "example", "my_game"), -//! )) -//! .add_plugins(CommonBindingsPlugin) +//! .add_plugins(SettingsPlusPlugins::new("net.pavlov.my_game")) //! .add_systems(Startup, |mut commands: Commands| { -//! commands.spawn((Camera3d::default(), BevyConfigCamera)); +//! commands.spawn((Camera3d::default(), SettingsCamera)); //! }) //! .run(); //! ``` //! +//! To save user changes (e.g., from an "Apply" button): +//! +//! ```no_run +//! use bevy::prelude::*; +//! use bevy_settings_plus::prelude::*; +//! +//! fn save_button(mut commands: Commands) { +//! commands.queue(SavePreferencesDeferred::default()); +//! } +//! ``` +//! //! ## Cargo features //! -//! - `ron` (default) — RON serialisation for the native [`FileBackend`](backend::FileBackend). -//! - `dlss` — wires [DLSS](https://developer.nvidia.com/rtx/dlss) via `bevy_anti_alias`. Requires the NVIDIA DLSS SDK at build time; only enable for shipping NVIDIA-targeted builds. +//! - `dlss` — wires [DLSS](https://developer.nvidia.com/rtx/dlss) via +//! `bevy_anti_alias`. Requires the NVIDIA DLSS SDK at build time; only +//! enable for shipping NVIDIA-targeted builds. -pub mod backend; -pub mod bindings; pub mod caps; +pub mod caps_aware; pub mod common; -pub mod config; -pub mod plugin; + +use bevy_app::{PluginGroup, PluginGroupBuilder}; +use bevy_ecs::schedule::SystemSet; +use bevy_settings::PreferencesPlugin; + +use crate::caps_aware::CapsAwarePlugin; +use crate::common::{AccessibilitySettingsPlugin, DisplaySettingsPlugin, RenderSettingsPlugin}; + +/// Run-order anchor for the binding systems that translate settings +/// resources onto engine resources, in `PostUpdate`. +/// +/// Use `.in_set(ApplyBindings)` (or `.before(ApplyBindings)`) to slot your +/// own systems into the lifecycle. +#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)] +pub struct ApplyBindings; + +/// Convenience [`PluginGroup`] that wires the whole stack in the right order: +/// +/// 1. [`DisplaySettingsPlugin`] / [`RenderSettingsPlugin`] / +/// [`AccessibilitySettingsPlugin`] — register reflection types and +/// binding systems before `bevy_settings` scans the registry. +/// 2. [`bevy_settings::PreferencesPlugin`] — discover registered +/// [`SettingsGroup`](bevy_settings::SettingsGroup) resources and load +/// their values from the on-disk TOML. +/// 3. [`CapsAwarePlugin`] — runs in `finish()`: detects [`AdapterCaps`](caps::AdapterCaps) +/// and clamps every registered [`CapsAware`](caps_aware::CapsAware) +/// resource against it. +/// +/// Add this *after* `DefaultPlugins` (so `RenderApp` is initialized by the +/// time `CapsAwarePlugin::finish` runs). +/// +/// To opt out of any layer, use the standard `.disable::()` pattern: +/// +/// ```no_run +/// # use bevy::prelude::*; +/// # use bevy_settings_plus::prelude::*; +/// # use bevy_app::PluginGroup; +/// App::new() +/// .add_plugins(DefaultPlugins) +/// .add_plugins( +/// SettingsPlusPlugins::new("net.pavlov.my_game") +/// .build() +/// .disable::(), +/// ); +/// ``` +pub struct SettingsPlusPlugins { + app_name: String, +} + +impl SettingsPlusPlugins { + /// Wires the group with the given reverse-domain application id (e.g. + /// `"net.pavlov.my_game"`). Passed through to + /// [`PreferencesPlugin::new`] for on-disk path derivation. + pub fn new(app_name: impl Into) -> Self { + Self { + app_name: app_name.into(), + } + } +} + +impl PluginGroup for SettingsPlusPlugins { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + // Schema plugins first: they register their reflection types. + .add(DisplaySettingsPlugin) + .add(RenderSettingsPlugin) + .add(AccessibilitySettingsPlugin) + // Then the upstream loader, which scans the registry. + .add(PreferencesPlugin::new(&self.app_name)) + // Finally, caps detection + the reflection-driven clamp pass. + .add(CapsAwarePlugin) + } +} pub mod prelude { //! Re-exports of the most commonly used types. - #[cfg(not(target_family = "wasm"))] - pub use crate::backend::FileBackend; - #[cfg(target_family = "wasm")] - pub use crate::backend::LocalStorageBackend; - pub use crate::backend::{BackendError, ConfigBackend}; - pub use crate::bindings::{BevyConfigCamera, CommonBindingsPlugin}; pub use crate::caps::{AdapterCaps, Backend, GpuVendor, PlatformTarget}; + pub use crate::caps_aware::{CapsAware, CapsAwarePlugin, ReflectCapsAware}; pub use crate::common::{ - Accessibility, AccessibilityOverrides, AntiAlias, ColorBlindMode, CommonConfig, - CommonConfigOverrides, Display, DisplayOverrides, FpsCap, HdrPreference, MonitorSelection, - MsaaLevel, Render, RenderOverrides, Resolution, Upscaler, UpscalerPreset, VsyncMode, - WindowMode, + AccessibilitySettings, AccessibilitySettingsPlugin, AntiAlias, ColorBlindMode, + DisplaySettings, DisplaySettingsPlugin, FpsCap, HdrPreference, MonitorSelection, MsaaLevel, + RenderSettings, RenderSettingsPlugin, Resolution, SettingsCamera, Upscaler, UpscalerPreset, + VsyncMode, WindowMode, + }; + pub use crate::{ApplyBindings, SettingsPlusPlugins}; + + // Re-export the most commonly used `bevy_settings` surface so callers + // only need `bevy_settings_plus::prelude::*`. + pub use bevy_settings::{ + PreferencesPlugin, SavePreferences, SavePreferencesDeferred, SavePreferencesSync, + SettingsGroup, }; - pub use crate::config::{BevyConfigSet, Config, ConfigApplied}; - pub use crate::plugin::{ConfigPlugin, SaveConfig}; } diff --git a/src/plugin.rs b/src/plugin.rs deleted file mode 100644 index 828a235..0000000 --- a/src/plugin.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! [`ConfigPlugin`] — wires the lifecycle for a [`Config`]. - -use alloc::sync::Arc; -use core::marker::PhantomData; - -use bevy_app::{App, Plugin, Startup}; -use bevy_ecs::resource::Resource; -use bevy_ecs::system::{Command, Commands}; -use bevy_ecs::world::World; -use bevy_log::warn; - -use crate::backend::ConfigBackend; -use crate::caps::{PlatformTarget, detect_caps}; -use crate::config::{Config, ConfigApplied}; - -extern crate alloc; - -/// Wires a [`Config`] type into the app. -/// -/// In `build()`: -/// - read the cached overrides from the backend (none on first run); -/// - merge them onto `C::platform_default(target)`; -/// - insert the resulting populated `C` as a resource. -/// -/// In `finish()`: -/// - read [`crate::caps::AdapterCaps`] from the [`bevy_render::RenderApp`] sub-app; -/// - insert it as a main-world resource; -/// - call `C::clamp_to(&caps)` against the live resource. -/// -/// At `Startup`: -/// - trigger [`ConfigApplied`] so observers run. -pub struct ConfigPlugin { - backend: Arc>, -} - -impl ConfigPlugin { - /// Wrap a backend implementation. Most callers will want - /// [`crate::backend::FileBackend`] (native) or - /// `LocalStorageBackend` (wasm). - pub fn new>(backend: B) -> Self { - Self { - backend: Arc::new(backend), - } - } -} - -impl Plugin for ConfigPlugin { - fn build(&self, app: &mut App) { - let target = PlatformTarget::detect(); - let mut config = C::platform_default(target); - if let Some(overrides) = self.backend.load() { - config.merge(&overrides); - } - app.insert_resource(config); - app.insert_resource(BackendStore:: { - backend: self.backend.clone(), - }); - app.add_systems(Startup, trigger_config_applied::); - } - - fn finish(&self, app: &mut App) { - let caps = detect_caps(app); - app.insert_resource(caps.clone()); - if let Some(mut config) = app.world_mut().get_resource_mut::() { - config.clamp_to(&caps); - } - } -} - -fn trigger_config_applied(mut commands: Commands) { - commands.trigger(ConfigApplied::(PhantomData)); -} - -/// Internal: holds the backend so [`SaveConfig`] can reach it from a system. -#[derive(Resource)] -pub(crate) struct BackendStore { - pub(crate) backend: Arc>, -} - -/// Persist the current state of `Res` via the registered backend. -/// -/// Queue with `commands.queue(SaveConfig::::default())`. Errors are -/// logged via `warn!` and do not panic — saving config should never crash a -/// running game. -pub struct SaveConfig(PhantomData); - -// Manual `Default` impl: `#[derive(Default)]` would add a bogus `C: Default` -// bound that `PhantomData` doesn't actually need. -impl Default for SaveConfig { - fn default() -> Self { - Self(PhantomData) - } -} - -impl Command for SaveConfig { - fn apply(self, world: &mut World) { - let target = PlatformTarget::detect(); - let Some(config) = world.get_resource::() else { - warn!("SaveConfig: resource not present (was ConfigPlugin added?)"); - return; - }; - let overrides = config.current_overrides(target); - let Some(store) = world.get_resource::>() else { - warn!("SaveConfig: backend store not present (was ConfigPlugin added?)"); - return; - }; - let backend = store.backend.clone(); - if let Err(e) = backend.store(&overrides) { - warn!("SaveConfig: store failed: {e}"); - } - } -} diff --git a/tests/clamp.rs b/tests/clamp.rs new file mode 100644 index 0000000..773119c --- /dev/null +++ b/tests/clamp.rs @@ -0,0 +1,101 @@ +//! Caps-clamp correctness for each axis. +//! +//! Persistence (load/save/merge round-trip) lives in `bevy_settings` and is +//! exercised by upstream's tests; we focus on the caps-aware behaviour +//! that is unique to this crate. + +use bevy_settings_plus::prelude::*; + +fn nvidia_vulkan_caps() -> AdapterCaps { + AdapterCaps { + backend: Backend::Vulkan, + vendor: GpuVendor::Nvidia, + max_texture_dim_2d: 16384, + ray_query: true, + timestamp_query: true, + supports_dlss: true, + } +} + +fn integrated_intel_caps() -> AdapterCaps { + AdapterCaps { + backend: Backend::Vulkan, + vendor: GpuVendor::Intel, + max_texture_dim_2d: 8192, + ray_query: false, + timestamp_query: true, + supports_dlss: false, + } +} + +#[test] +fn render_platform_default_wasm_is_conservative() { + let r = RenderSettings::platform_default(PlatformTarget::Wasm); + assert!(matches!(r.anti_alias, AntiAlias::None)); + assert!(matches!(r.upscaler, Upscaler::Native)); + assert!(matches!(r.msaa, MsaaLevel::Off)); + assert!(!r.ray_tracing); +} + +#[test] +fn render_platform_default_desktop_uses_taa() { + let r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + assert!(matches!(r.anti_alias, AntiAlias::Taa)); +} + +#[test] +fn render_clamp_strips_ray_tracing_when_caps_lack_ray_query() { + let mut r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + r.ray_tracing = true; + r.clamp_to(integrated_intel_caps()); + assert!(!r.ray_tracing); +} + +#[test] +fn render_clamp_keeps_ray_tracing_when_caps_support_it() { + let mut r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + r.ray_tracing = true; + r.clamp_to(nvidia_vulkan_caps()); + assert!(r.ray_tracing); +} + +#[test] +fn render_clamp_falls_back_to_native_when_dlss_unavailable() { + let mut r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + r.upscaler = Upscaler::Dlss(UpscalerPreset::Quality); + r.clamp_to(integrated_intel_caps()); + assert!(matches!(r.upscaler, Upscaler::Native)); +} + +#[test] +fn render_clamp_keeps_dlss_when_supported() { + let mut r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + r.upscaler = Upscaler::Dlss(UpscalerPreset::Balanced); + r.clamp_to(nvidia_vulkan_caps()); + assert!(matches!(r.upscaler, Upscaler::Dlss(_))); +} + +#[test] +fn render_clamp_clamps_render_scale_and_sharpness() { + let mut r = RenderSettings::platform_default(PlatformTarget::LinuxDesktop); + r.render_scale = 1.5; + r.sharpness = -0.2; + r.clamp_to(nvidia_vulkan_caps()); + assert!((0.25..=1.0).contains(&r.render_scale)); + assert!((0.0..=1.0).contains(&r.sharpness)); +} + +#[test] +fn accessibility_clamp_clamps_subtitle_scale() { + let mut a = AccessibilitySettings::platform_default(PlatformTarget::LinuxDesktop); + a.subtitle_scale = 5.0; + a.clamp_to(nvidia_vulkan_caps()); + assert!((0.5..=3.0).contains(&a.subtitle_scale)); +} + +#[test] +fn default_resolves_to_platform_default() { + let d = DisplaySettings::default(); + let p = DisplaySettings::platform_default(PlatformTarget::detect()); + assert_eq!(d, p); +} diff --git a/tests/merge.rs b/tests/merge.rs deleted file mode 100644 index 853815b..0000000 --- a/tests/merge.rs +++ /dev/null @@ -1,149 +0,0 @@ -//! Sparse-overrides merge correctness, caps clamping, platform defaults. -//! -//! These tests do not touch the Bevy `App` — they exercise the `Config` -//! trait directly to keep the kernel's contract verifiable in isolation. - -use bevy_config::prelude::*; - -fn nvidia_vulkan_caps() -> AdapterCaps { - AdapterCaps { - backend: Backend::Vulkan, - vendor: GpuVendor::Nvidia, - max_texture_dim_2d: 16384, - ray_query: true, - timestamp_query: true, - supports_dlss: true, - } -} - -fn integrated_intel_caps() -> AdapterCaps { - AdapterCaps { - backend: Backend::Vulkan, - vendor: GpuVendor::Intel, - max_texture_dim_2d: 8192, - ray_query: false, - timestamp_query: true, - supports_dlss: false, - } -} - -#[test] -fn platform_default_wasm_is_conservative() { - let cfg = CommonConfig::platform_default(PlatformTarget::Wasm); - assert!(matches!(cfg.render.anti_alias, AntiAlias::None)); - assert!(matches!(cfg.render.upscaler, Upscaler::Native)); - assert!(matches!(cfg.render.msaa, MsaaLevel::Off)); - assert!(!cfg.render.ray_tracing); -} - -#[test] -fn platform_default_desktop_uses_taa() { - let cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - assert!(matches!(cfg.render.anti_alias, AntiAlias::Taa)); -} - -#[test] -fn merge_applies_sparse_overrides() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - - let mut overrides = CommonConfigOverrides::default(); - overrides.render.anti_alias = Some(AntiAlias::Smaa); - overrides.render.msaa = Some(MsaaLevel::Sample4); - overrides.accessibility.subtitles_on = Some(true); - - cfg.merge(&overrides); - - assert!(matches!(cfg.render.anti_alias, AntiAlias::Smaa)); - assert!(matches!(cfg.render.msaa, MsaaLevel::Sample4)); - assert!(cfg.accessibility.subtitles_on); - // Untouched fields keep platform defaults. - assert!(matches!(cfg.render.upscaler, Upscaler::Native)); -} - -#[test] -fn clamp_strips_ray_tracing_when_caps_lack_ray_query() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.ray_tracing = true; - - cfg.clamp_to(&integrated_intel_caps()); - - assert!(!cfg.render.ray_tracing); -} - -#[test] -fn clamp_keeps_ray_tracing_when_caps_support_it() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.ray_tracing = true; - - cfg.clamp_to(&nvidia_vulkan_caps()); - - assert!(cfg.render.ray_tracing); -} - -#[test] -fn clamp_falls_back_to_native_when_dlss_unavailable() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.upscaler = Upscaler::Dlss(UpscalerPreset::Quality); - - cfg.clamp_to(&integrated_intel_caps()); - - assert!(matches!(cfg.render.upscaler, Upscaler::Native)); -} - -#[test] -fn clamp_keeps_dlss_when_supported() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.upscaler = Upscaler::Dlss(UpscalerPreset::Balanced); - - cfg.clamp_to(&nvidia_vulkan_caps()); - - assert!(matches!(cfg.render.upscaler, Upscaler::Dlss(_))); -} - -#[test] -fn clamp_clamps_render_scale_and_sharpness() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.render_scale = 1.5; // > 1.0 - cfg.render.sharpness = -0.2; // < 0.0 - - cfg.clamp_to(&nvidia_vulkan_caps()); - - assert!(cfg.render.render_scale <= 1.0 && cfg.render.render_scale >= 0.25); - assert!(cfg.render.sharpness >= 0.0 && cfg.render.sharpness <= 1.0); -} - -#[test] -fn current_overrides_is_empty_when_unchanged() { - let cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - let overrides = cfg.current_overrides(PlatformTarget::LinuxDesktop); - assert_eq!(overrides, CommonConfigOverrides::default()); -} - -#[test] -fn current_overrides_captures_only_changes() { - let mut cfg = CommonConfig::platform_default(PlatformTarget::LinuxDesktop); - cfg.render.msaa = MsaaLevel::Sample4; - cfg.accessibility.subtitles_on = true; - - let overrides = cfg.current_overrides(PlatformTarget::LinuxDesktop); - assert_eq!(overrides.render.msaa, Some(MsaaLevel::Sample4)); - assert_eq!(overrides.accessibility.subtitles_on, Some(true)); - // Untouched fields are None in the diff. - assert_eq!(overrides.render.anti_alias, None); - assert_eq!(overrides.accessibility.reduce_motion, None); -} - -#[test] -fn roundtrip_merge_after_diff() { - let target = PlatformTarget::LinuxDesktop; - let mut original = CommonConfig::platform_default(target); - original.render.msaa = MsaaLevel::Sample8; - original.accessibility.subtitle_scale = 1.5; - - let overrides = original.current_overrides(target); - - let mut rebuilt = CommonConfig::platform_default(target); - rebuilt.merge(&overrides); - - assert_eq!(rebuilt, original); -}