diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d65b516..169c51f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: ./.github/actions/setup @@ -42,6 +44,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: ./.github/actions/setup with: @@ -55,6 +59,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: ./.github/actions/setup with: @@ -80,6 +86,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: ./.github/actions/setup diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b74a5e0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lygia"] + path = lygia + url = https://github.com/patriciogonzalezvivo/lygia.git diff --git a/Cargo.lock b/Cargo.lock index 676be54..0a629f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a191faf9cb278127e253ba80af4c588527b7b9d824c58220aca00bb162a5a460" +checksum = "53cf47daed85312e763fbf85ceca136e0d7abc68e0a7e12abe11f48172bc3b10" dependencies = [ "accesskit", "hashbrown 0.16.1", @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "accesskit_macos" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dceb1d10a043047187e8fc6f4f11e02ab0ed3f8b5848c10cf19fc1e2191e0c2" +checksum = "534bc3fdc89a64a1db3c46b33c198fde2b7c3c7d094e5809c8c8bf2970c18243" dependencies = [ "accesskit", "accesskit_consumer", @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4983e64eb7e317c7d8f6348363d24f955bed51c0216ad67c19857c2b8605e576" +checksum = "eff7009f1a532e917d66970a1e80c965140c6cfbbabbdde3d64e5431e6c78e21" dependencies = [ "accesskit", "accesskit_consumer", @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "accesskit_winit" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e019a33d56f1c81b5cc593c2e2bcbbe97177f38a8f6e387b1df7eb4d8b2d9e06" +checksum = "1fe9a94394896352cc4660ca2288bd4ef883d83238853c038b44070c8f134313" dependencies = [ "accesskit", "accesskit_macos", @@ -194,6 +194,17 @@ dependencies = [ "libc", ] +[[package]] +name = "annotate-snippets" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fc7650eedcb2fee505aad48491529e408f0e854c2d9f63eb86c1361b9b3f93" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + [[package]] name = "anstream" version = "0.6.21" @@ -303,6 +314,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "ascii-canvas" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" +dependencies = [ + "term", +] + [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -487,7 +507,7 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bevy" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_internal", ] @@ -495,7 +515,7 @@ dependencies = [ [[package]] name = "bevy_a11y" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "accesskit", "bevy_app", @@ -507,7 +527,7 @@ dependencies = [ [[package]] name = "bevy_android" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "android-activity", ] @@ -515,7 +535,7 @@ dependencies = [ [[package]] name = "bevy_animation" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_animation_macros", "bevy_app", @@ -534,7 +554,7 @@ dependencies = [ "derive_more", "downcast-rs 2.0.2", "either", - "petgraph", + "petgraph 0.8.3", "ron", "serde", "smallvec", @@ -547,7 +567,7 @@ dependencies = [ [[package]] name = "bevy_animation_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "quote", @@ -557,7 +577,7 @@ dependencies = [ [[package]] name = "bevy_anti_alias" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -579,7 +599,7 @@ dependencies = [ [[package]] name = "bevy_app" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_derive", "bevy_ecs", @@ -601,7 +621,7 @@ dependencies = [ [[package]] name = "bevy_asset" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "async-broadcast", "async-channel", @@ -644,7 +664,7 @@ dependencies = [ [[package]] name = "bevy_asset_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "proc-macro2", @@ -655,7 +675,7 @@ dependencies = [ [[package]] name = "bevy_audio" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -672,7 +692,7 @@ dependencies = [ [[package]] name = "bevy_camera" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -697,7 +717,7 @@ dependencies = [ [[package]] name = "bevy_color" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_math", "bevy_reflect", @@ -712,7 +732,7 @@ dependencies = [ [[package]] name = "bevy_core_pipeline" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -740,7 +760,7 @@ dependencies = [ [[package]] name = "bevy_derive" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "quote", @@ -750,7 +770,7 @@ dependencies = [ [[package]] name = "bevy_dev_tools" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -781,7 +801,7 @@ dependencies = [ [[package]] name = "bevy_diagnostic" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "atomic-waker", "bevy_app", @@ -798,7 +818,7 @@ dependencies = [ [[package]] name = "bevy_ecs" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "arrayvec", "bevy_ecs_macros", @@ -825,7 +845,7 @@ dependencies = [ [[package]] name = "bevy_ecs_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "proc-macro2", @@ -836,7 +856,7 @@ dependencies = [ [[package]] name = "bevy_encase_derive" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "encase_derive_impl", @@ -845,7 +865,7 @@ dependencies = [ [[package]] name = "bevy_feathers" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "accesskit", "bevy_a11y", @@ -874,7 +894,7 @@ dependencies = [ [[package]] name = "bevy_gilrs" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -889,7 +909,7 @@ dependencies = [ [[package]] name = "bevy_gizmos" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -908,7 +928,7 @@ dependencies = [ [[package]] name = "bevy_gizmos_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "quote", @@ -918,7 +938,7 @@ dependencies = [ [[package]] name = "bevy_gizmos_render" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -943,7 +963,7 @@ dependencies = [ [[package]] name = "bevy_gltf" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "async-lock", "base64", @@ -978,7 +998,7 @@ dependencies = [ [[package]] name = "bevy_image" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1006,7 +1026,7 @@ dependencies = [ [[package]] name = "bevy_input" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -1022,7 +1042,7 @@ dependencies = [ [[package]] name = "bevy_input_focus" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -1038,7 +1058,7 @@ dependencies = [ [[package]] name = "bevy_internal" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_a11y", "bevy_android", @@ -1094,7 +1114,7 @@ dependencies = [ [[package]] name = "bevy_light" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1118,7 +1138,7 @@ dependencies = [ [[package]] name = "bevy_log" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "android_log-sys", "bevy_app", @@ -1135,7 +1155,7 @@ dependencies = [ [[package]] name = "bevy_macro_utils" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "proc-macro2", "quote", @@ -1146,7 +1166,7 @@ dependencies = [ [[package]] name = "bevy_material" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_asset", "bevy_derive", @@ -1168,7 +1188,7 @@ dependencies = [ [[package]] name = "bevy_material_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "quote", @@ -1178,7 +1198,7 @@ dependencies = [ [[package]] name = "bevy_math" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "approx", "arrayvec", @@ -1197,13 +1217,13 @@ dependencies = [ [[package]] name = "bevy_mesh" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", "bevy_derive", "bevy_ecs", - "bevy_image", + "bevy_encase_derive", "bevy_math", "bevy_mikktspace", "bevy_platform", @@ -1212,6 +1232,8 @@ dependencies = [ "bitflags 2.11.0", "bytemuck", "derive_more", + "encase", + "glam", "hexasphere", "thiserror 2.0.18", "tracing", @@ -1240,11 +1262,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bff34eb29ff4b8a8688bc7299f14fb6b597461ca80fec03ed7d22939ab33e48f" +[[package]] +name = "bevy_naga_reflect" +version = "0.1.0" +source = "git+https://github.com/tychedelia/bevy_naga_reflect#98612a63a847401da144150d786e7455a32cd7e1" +dependencies = [ + "bevy", + "naga", +] + [[package]] name = "bevy_pbr" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ + "arrayvec", "bevy_app", "bevy_asset", "bevy_camera", @@ -1283,7 +1315,7 @@ dependencies = [ [[package]] name = "bevy_picking" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1306,7 +1338,7 @@ dependencies = [ [[package]] name = "bevy_platform" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "critical-section", "foldhash 0.2.0", @@ -1321,13 +1353,13 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-time", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "bevy_post_process" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1351,12 +1383,12 @@ dependencies = [ [[package]] name = "bevy_ptr" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" [[package]] name = "bevy_reflect" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "assert_type_match", "bevy_platform", @@ -1371,7 +1403,7 @@ dependencies = [ "glam", "indexmap", "inventory", - "petgraph", + "petgraph 0.8.3", "serde", "smallvec", "smol_str", @@ -1384,7 +1416,7 @@ dependencies = [ [[package]] name = "bevy_reflect_derive" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "indexmap", @@ -1397,7 +1429,7 @@ dependencies = [ [[package]] name = "bevy_render" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "async-channel", "bevy_app", @@ -1449,7 +1481,7 @@ dependencies = [ [[package]] name = "bevy_render_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "proc-macro2", @@ -1460,7 +1492,7 @@ dependencies = [ [[package]] name = "bevy_scene" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1481,7 +1513,7 @@ dependencies = [ [[package]] name = "bevy_shader" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_asset", "bevy_platform", @@ -1492,13 +1524,14 @@ dependencies = [ "serde", "thiserror 2.0.18", "tracing", + "wesl", "wgpu-types", ] [[package]] name = "bevy_sprite" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1523,7 +1556,7 @@ dependencies = [ [[package]] name = "bevy_sprite_render" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1555,7 +1588,7 @@ dependencies = [ [[package]] name = "bevy_state" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -1570,7 +1603,7 @@ dependencies = [ [[package]] name = "bevy_state_macros" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_macro_utils", "quote", @@ -1580,7 +1613,7 @@ dependencies = [ [[package]] name = "bevy_tasks" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "async-channel", "async-executor", @@ -1598,7 +1631,7 @@ dependencies = [ [[package]] name = "bevy_text" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1625,7 +1658,7 @@ dependencies = [ [[package]] name = "bevy_time" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -1639,7 +1672,7 @@ dependencies = [ [[package]] name = "bevy_transform" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_ecs", @@ -1656,7 +1689,7 @@ dependencies = [ [[package]] name = "bevy_ui" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "accesskit", "bevy_a11y", @@ -1690,7 +1723,7 @@ dependencies = [ [[package]] name = "bevy_ui_render" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1721,7 +1754,7 @@ dependencies = [ [[package]] name = "bevy_ui_widgets" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "accesskit", "bevy_a11y", @@ -1740,7 +1773,7 @@ dependencies = [ [[package]] name = "bevy_utils" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "async-channel", "bevy_platform", @@ -1751,7 +1784,7 @@ dependencies = [ [[package]] name = "bevy_window" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "bevy_app", "bevy_asset", @@ -1769,7 +1802,7 @@ dependencies = [ [[package]] name = "bevy_winit" version = "0.19.0-dev" -source = "git+https://github.com/bevyengine/bevy?branch=main#54b217b9a2d72ff4facb5caa8253e18078546630" +source = "git+https://github.com/bevyengine/bevy?branch=main#0dcba0d0c66974462282323b2d5ee34ffbb36119" dependencies = [ "accesskit", "accesskit_winit", @@ -1883,6 +1916,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -1898,7 +1940,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -2400,14 +2442,24 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix", + "nix 0.31.2", "windows-sys 0.61.2", ] @@ -2452,6 +2504,16 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -2460,14 +2522,14 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags 2.11.0", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -2529,6 +2591,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "ena" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" +dependencies = [ + "log", +] + [[package]] name = "encase" version = "0.12.0" @@ -2588,9 +2659,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", "serde_core", @@ -2866,6 +2937,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "1.1.0" @@ -2885,20 +2966,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -2937,7 +3018,7 @@ dependencies = [ "libc", "libudev-sys", "log", - "nix", + "nix 0.30.1", "objc2-core-foundation", "objc2-io-kit", "uuid", @@ -2960,9 +3041,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34627c5158214743a374170fed714833fdf4e4b0cbcc1ea98417866a4c5d4441" +checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" dependencies = [ "bytemuck", "encase", @@ -3117,6 +3198,7 @@ dependencies = [ "cfg-if", "crunchy", "num-traits", + "serde", "zerocopy", ] @@ -3225,9 +3307,9 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "image" -version = "0.25.9" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", @@ -3243,8 +3325,8 @@ dependencies = [ "rayon", "rgb", "tiff", - "zune-core 0.5.1", - "zune-jpeg 0.5.12", + "zune-core", + "zune-jpeg", ] [[package]] @@ -3292,9 +3374,9 @@ checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" [[package]] name = "inotify" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ "bitflags 2.11.0", "inotify-sys", @@ -3394,14 +3476,23 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.90" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dc6f6450b3f6d4ed5b16327f38fed626d375a886159ca555bd7822c0c3a5a6" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -3448,6 +3539,37 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "lalrpop" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.14.0", + "lalrpop-util", + "petgraph 0.7.1", + "regex", + "regex-syntax", + "sha3", + "string_cache", + "term", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" +dependencies = [ + "regex-automata", + "rustversion", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -3477,11 +3599,77 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "lexical" +version = "7.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc8a009b2ff1f419ccc62706f04fe0ca6e67b37460513964a3dfdb919bb37d6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +dependencies = [ + "lexical-parse-integer", + "lexical-util", +] + +[[package]] +name = "lexical-parse-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "lexical-util" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" + +[[package]] +name = "lexical-write-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +dependencies = [ + "lexical-util", + "lexical-write-integer", +] + +[[package]] +name = "lexical-write-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +dependencies = [ + "lexical-util", +] + [[package]] name = "libc" -version = "0.2.182" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libfuzzer-sys" @@ -3511,13 +3699,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags 2.11.0", "libc", - "redox_syscall 0.7.2", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -3575,6 +3764,38 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "logos" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" +dependencies = [ + "fnv", + "proc-macro2", + "quote", + "regex-automata", + "regex-syntax", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" +dependencies = [ + "logos-codegen", +] + [[package]] name = "loop9" version = "0.1.5" @@ -3586,9 +3807,9 @@ dependencies = [ [[package]] name = "lyon" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcb7d54d54c8937364c9d41902d066656817dce1e03a44e5533afebd1ef4352" +checksum = "bd0578bdecb7d6d88987b8b2b1e3a4e2f81df9d0ece1078623324a567904e7b7" dependencies = [ "lyon_algorithms", "lyon_tessellation", @@ -3596,9 +3817,9 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c0829e28c4f336396f250d850c3987e16ce6db057ffe047ce0dd54aab6b647" +checksum = "9815fac08e6fd96733a11dce4f9d15a3f338e96a2e2311ee21e1b738efc2bc0f" dependencies = [ "lyon_path", "num-traits", @@ -3606,9 +3827,9 @@ dependencies = [ [[package]] name = "lyon_geom" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e260b6de923e6e47adfedf6243013a7a874684165a6a277594ee3906021b2343" +checksum = "4336502e29e32af93cf2dad2214ed6003c17ceb5bd499df77b1de663b9042b92" dependencies = [ "arrayvec", "euclid", @@ -3617,9 +3838,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeca86bcfd632a15984ba029b539ffb811e0a70bf55e814ef8b0f54f506fdeb" +checksum = "5c463f9c428b7fc5ec885dcd39ce4aa61e29111d0e33483f6f98c74e89d8621e" dependencies = [ "lyon_geom", "num-traits", @@ -3627,9 +3848,9 @@ dependencies = [ [[package]] name = "lyon_tessellation" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f586142e1280335b1bc89539f7c97dd80f08fc43e9ab1b74ef0a42b04aa353" +checksum = "05a35a7dd71b845ff317ce1834c4185506b79790294bde397df8d5c23031e357" dependencies = [ "float_next_after", "lyon_path", @@ -3759,9 +3980,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.11" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ "num-traits", "pxfm", @@ -3789,6 +4010,7 @@ dependencies = [ "once_cell", "pp-rs", "rustc-hash 1.1.0", + "serde", "spirv", "thiserror 2.0.18", "unicode-ident", @@ -3882,6 +4104,18 @@ dependencies = [ "libc", ] +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -4071,9 +4305,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -4103,7 +4337,7 @@ dependencies = [ "bitflags 2.11.0", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-cloud-kit 0.3.2", "objc2-core-data 0.3.2", "objc2-core-foundation", @@ -4135,7 +4369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -4169,7 +4403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -4181,7 +4415,7 @@ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.11.0", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -4192,7 +4426,7 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.11.0", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] @@ -4215,7 +4449,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -4238,7 +4472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-core-graphics", ] @@ -4250,7 +4484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-core-graphics", "objc2-io-surface", @@ -4282,7 +4516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -4304,7 +4538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -4352,7 +4586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -4554,6 +4788,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "petgraph" version = "0.8.3" @@ -4567,20 +4811,29 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -4589,15 +4842,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -4610,6 +4863,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "png" version = "0.18.1" @@ -4670,6 +4929,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "presser" version = "0.3.1" @@ -4688,11 +4953,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.4+spec-1.1.0", ] [[package]] @@ -4747,11 +5012,13 @@ name = "processing_render" version = "0.1.0" dependencies = [ "bevy", + "bevy_naga_reflect", "crossbeam-channel", "half", "js-sys", "lyon", - "objc2 0.6.3", + "naga", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "processing_midi", "raw-window-handle", @@ -4761,6 +5028,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "wesl", "windows 0.58.0", ] @@ -4798,12 +5066,9 @@ dependencies = [ [[package]] name = "pxfm" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" -dependencies = [ - "num-traits", -] +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" [[package]] name = "pyo3" @@ -4883,18 +5148,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -4905,6 +5170,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radsort" version = "0.1.1" @@ -4927,7 +5198,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "rand_core 0.10.0", ] @@ -4968,9 +5239,9 @@ dependencies = [ [[package]] name = "range-alloc" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" [[package]] name = "rav1e" @@ -5009,9 +5280,9 @@ dependencies = [ [[package]] name = "ravif" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" dependencies = [ "avif-serialize", "imgref", @@ -5085,9 +5356,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d94dd2f7cd932d4dc02cc8b2b50dfd38bd079a4e5d79198b99743d7fcf9a4b4" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags 2.11.0", ] @@ -5317,6 +5588,16 @@ dependencies = [ "serde_core", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -5347,6 +5628,12 @@ dependencies = [ "quote", ] +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + [[package]] name = "skrifa" version = "0.37.0" @@ -5457,6 +5744,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.11.1" @@ -5502,9 +5801,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.38.0" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe840c5b1afe259a5657392a4dbb74473a14c8db999c3ec2f4ae812e028a94da" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" dependencies = [ "libc", "memchr", @@ -5539,12 +5838,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", ] +[[package]] +name = "term" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -5605,16 +5913,16 @@ dependencies = [ [[package]] name = "tiff" -version = "0.10.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" dependencies = [ "fax", "flate2", "half", "quick-error", "weezl", - "zune-jpeg 0.4.21", + "zune-jpeg", ] [[package]] @@ -5677,7 +5985,7 @@ dependencies = [ "indexmap", "serde_core", "serde_spanned", - "toml_datetime", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", "winnow", @@ -5692,26 +6000,35 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.24.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "01f2eadbbc6b377a847be05f60791ef1058d9f696ecb51d2c07fe911d8569d8e" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] [[package]] name = "toml_edit" -version = "0.24.1+spec-1.1.0" +version = "0.25.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01f2eadbbc6b377a847be05f60791ef1058d9f696ecb51d2c07fe911d8569d8e" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 1.0.0+spec-1.1.0", "toml_parser", "winnow", ] @@ -5833,6 +6150,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "typewit" version = "1.14.2" @@ -5877,11 +6200,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -5963,9 +6286,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.113" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60722a937f594b7fde9adb894d7c092fc1bb6612897c46368d18e7a20208eff2" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -5976,9 +6299,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.63" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a89f4650b770e4521aa6573724e2aed4704372151bd0de9d16a3bbabb87441a" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -5990,9 +6313,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.113" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac8c6395094b6b91c4af293f4c79371c163f9a6f56184d2c9a85f5a95f3950" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6000,9 +6323,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.113" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3fabce6159dc20728033842636887e4877688ae94382766e00b180abac9d60" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", @@ -6013,9 +6336,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.113" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0e091bdb824da87dc01d967388880d017a0a9bc4f3bdc0d86ee9f9336e3bb5" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -6056,9 +6379,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" +checksum = "aa75f400b7f719bcd68b3f47cd939ba654cedeef690f486db71331eec4c6a406" dependencies = [ "cc", "downcast-rs 1.2.1", @@ -6070,9 +6393,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.12" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" +checksum = "ab51d9f7c071abeee76007e2b742499e535148035bb835f97aaed1338cf516c3" dependencies = [ "bitflags 2.11.0", "rustix 1.1.4", @@ -6093,9 +6416,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.12" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" +checksum = "4b3298683470fbdc6ca40151dfc48c8f2fd4c41a26e13042f801f85002384091" dependencies = [ "rustix 1.1.4", "wayland-client", @@ -6104,9 +6427,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.10" +version = "0.32.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" +checksum = "b23b5df31ceff1328f06ac607591d5ba360cf58f90c8fad4ac8d3a55a3c4aec7" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6116,9 +6439,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +checksum = "d392fc283a87774afc9beefcd6f931582bb97fe0e6ced0b306a62cb1d026527c" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6129,9 +6452,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" +checksum = "78248e4cc0eff8163370ba5c158630dcae1f3497a586b826eca2ef5f348d6235" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6142,9 +6465,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.8" +version = "0.31.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" +checksum = "c86287151a309799b821ca709b7345a048a2956af05957c89cb824ab919fa4e3" dependencies = [ "proc-macro2", "quick-xml", @@ -6153,9 +6476,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" +checksum = "374f6b70e8e0d6bf9461a32988fd553b59ff630964924dad6e4a4eb6bd538d17" dependencies = [ "dlib", "log", @@ -6164,9 +6487,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.90" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705eceb4ce901230f8625bd1d665128056ccbe4b7408faa625eec1ba80f59a97" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -6188,6 +6511,37 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "wesl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be113b462f90d3e303324739a4431bc63dfd0b463d7582cc76c1fd2093b5d470" +dependencies = [ + "annotate-snippets", + "derive_more", + "half", + "itertools 0.14.0", + "num-traits", + "proc-macro2", + "quote", + "thiserror 2.0.18", + "wesl-macros", + "wgsl-parse", + "wgsl-types", +] + +[[package]] +name = "wesl-macros" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d321ea9e1cc0a2e3de41c02e3a7586695a9c03beccb5460e938a7ccf00cb612" +dependencies = [ + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "wgpu" version = "28.0.0" @@ -6219,9 +6573,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "28.0.0" +version = "28.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb4c8b5db5f00e56f1f08869d870a0dff7c8bc7ebc01091fec140b0cf0211a9" +checksum = "d23f4642f53f666adcfd2d3218ab174d1e6681101aef18696b90cbe64d1c10f9" dependencies = [ "arrayvec", "bit-set", @@ -6278,9 +6632,9 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "28.0.0" +version = "28.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293080d77fdd14d6b08a67c5487dfddbf874534bb7921526db56a7b75d7e3bef" +checksum = "44d6cb474beb218824dcc9e1ce679d973f719262789bfb27407da560cac20eeb" dependencies = [ "android_system_properties", "arrayvec", @@ -6338,6 +6692,34 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wgsl-parse" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "946419efa46664a8070c512fb358ac4acfc6e6215c2396ae5afeb9b72dd6ca7d" +dependencies = [ + "annotate-snippets", + "derive_more", + "itertools 0.14.0", + "lalrpop", + "lalrpop-util", + "lexical", + "logos", + "thiserror 2.0.18", + "wgsl-types", +] + +[[package]] +name = "wgsl-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aed068ca1dc8fb182f574c9f2ace45ec988c71ba050f6dd334883fe3b8a88e2" +dependencies = [ + "half", + "itertools 0.14.0", + "num-traits", +] + [[package]] name = "winapi" version = "0.3.9" @@ -6849,9 +7231,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" -version = "0.30.12" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" dependencies = [ "ahash", "android-activity", @@ -6901,9 +7283,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] @@ -7085,18 +7467,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", @@ -7125,12 +7507,6 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - [[package]] name = "zune-core" version = "0.5.1" @@ -7146,20 +7522,11 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "zune-jpeg" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" -dependencies = [ - "zune-core 0.4.12", -] - [[package]] name = "zune-jpeg" version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "410e9ecef634c709e3831c2cfdb8d9c32164fae1c67496d5b68fff728eec37fe" dependencies = [ - "zune-core 0.5.1", + "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index d873fef..525ca13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,10 @@ type_complexity = "allow" too_many_arguments = "allow" [workspace.dependencies] -bevy = { git = "https://github.com/bevyengine/bevy", branch = "main" } +bevy = { git = "https://github.com/bevyengine/bevy", branch = "main", features = ["file_watcher", "shader_format_wesl"] } +bevy_naga_reflect = { git = "https://github.com/tychedelia/bevy_naga_reflect" } +naga = { version = "28", features = ["wgsl-in"] } +wesl = { version = "0.3", default-features = false } processing = { path = "." } processing_pyo3 = { path = "crates/processing_pyo3" } processing_render = { path = "crates/processing_render" } @@ -86,6 +89,10 @@ path = "examples/midi.rs" name = "gltf_load" path = "examples/gltf_load.rs" +[[example]] +name = "custom_material" +path = "examples/custom_material.rs" + [profile.wasm-release] inherits = "release" opt-level = "z" diff --git a/assets/shaders/custom_material.wesl b/assets/shaders/custom_material.wesl new file mode 100644 index 0000000..cc67c35 --- /dev/null +++ b/assets/shaders/custom_material.wesl @@ -0,0 +1,15 @@ +import { lygia::generative::snoise::snoise33 }; +import { processing::{globals, VertexOutput} }; + +@group(3) @binding(0) var color: vec4; + +@fragment +fn fragment(mesh: VertexOutput) -> @location(0) vec4 { + let p = mesh.world_position.xyz * 0.02 + globals.time * 0.1; + let n = snoise33(p) * 0.5 + 0.5; + + let light_dir = normalize(vec3(0.5, 1.0, 0.3)); + let diffuse = max(dot(normalize(mesh.world_normal), light_dir), 0.15); + + return vec4(n * diffuse, 1.0) * color; +} diff --git a/crates/processing_midi/src/lib.rs b/crates/processing_midi/src/lib.rs index 3e6186f..505f235 100644 --- a/crates/processing_midi/src/lib.rs +++ b/crates/processing_midi/src/lib.rs @@ -12,9 +12,7 @@ impl Plugin for MidiPlugin { } } -enum MidiCommand {} - -pub fn connect(port: usize) { +pub fn connect(_port: usize) { // we need to work with the ECS // do we pass a MidiCommand to Bevy? } diff --git a/crates/processing_pyo3/assets b/crates/processing_pyo3/assets new file mode 120000 index 0000000..b1726c0 --- /dev/null +++ b/crates/processing_pyo3/assets @@ -0,0 +1 @@ +/Users/char/src/github.com/processing/libprocessing/assets/ \ No newline at end of file diff --git a/crates/processing_pyo3/examples/custom_material.py b/crates/processing_pyo3/examples/custom_material.py new file mode 100644 index 0000000..14fb50f --- /dev/null +++ b/crates/processing_pyo3/examples/custom_material.py @@ -0,0 +1,21 @@ +from processing import * + +mat = None + +def setup(): + global mat + size(800, 600) + mode_3d() + + shader = Shader.load("shaders/custom_material.wesl") + mat = Material(shader, color=[1.0, 0.2, 0.4, 1.0]) + +def draw(): + camera_position(0.0, 0.0, 200.0) + camera_look_at(0.0, 0.0, 0.0) + background(12, 12, 18) + + use_material(mat) + box(80.0, 80.0, 80.0) + +run() diff --git a/crates/processing_pyo3/src/gltf.rs b/crates/processing_pyo3/src/gltf.rs index ee617de..9764beb 100644 --- a/crates/processing_pyo3/src/gltf.rs +++ b/crates/processing_pyo3/src/gltf.rs @@ -46,8 +46,8 @@ impl Gltf { #[pyfunction] #[pyo3(pass_module)] pub fn load_gltf(module: &Bound<'_, PyModule>, path: &str) -> PyResult { - let graphics = get_graphics(module)? - .ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; + let graphics = + get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; let entity = gltf_load(graphics.entity, path).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; Ok(Gltf { entity }) diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index f67b645..a765e0f 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -12,6 +12,7 @@ mod glfw; mod gltf; mod graphics; pub(crate) mod material; +pub(crate) mod shader; use graphics::{Geometry, Graphics, Image, Light, Topology, get_graphics, get_graphics_mut}; use material::Material; @@ -20,10 +21,11 @@ use pyo3::{ prelude::*, types::{PyDict, PyTuple}, }; +use shader::Shader; use std::ffi::{CStr, CString}; -use gltf::Gltf; use bevy::log::warn; +use gltf::Gltf; use std::env; /// Get a shared ref to the Graphics context, or return Ok(()) if not yet initialized. @@ -44,6 +46,7 @@ fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_function(wrap_pyfunction!(gltf::load_gltf, m)?)?; m.add_function(wrap_pyfunction!(size, m)?)?; m.add_function(wrap_pyfunction!(run, m)?)?; @@ -368,7 +371,7 @@ fn push_matrix(module: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfunction] #[pyo3(pass_module)] fn pop_matrix(module: &Bound<'_, PyModule>) -> PyResult<()> { - graphics!(module).push_matrix() + graphics!(module).pop_matrix() } #[pyfunction] diff --git a/crates/processing_pyo3/src/material.rs b/crates/processing_pyo3/src/material.rs index 544ded1..354abda 100644 --- a/crates/processing_pyo3/src/material.rs +++ b/crates/processing_pyo3/src/material.rs @@ -1,32 +1,75 @@ use bevy::prelude::Entity; use processing::prelude::*; +use pyo3::types::PyDict; use pyo3::{exceptions::PyRuntimeError, prelude::*}; +use crate::shader::Shader; + #[pyclass(unsendable)] pub struct Material { pub(crate) entity: Entity, } +fn py_to_material_value(value: &Bound<'_, PyAny>) -> PyResult { + if let Ok(v) = value.extract::() { + return Ok(material::MaterialValue::Float(v)); + } + if let Ok(v) = value.extract::() { + return Ok(material::MaterialValue::Int(v)); + } + + if let Ok(v) = value.extract::<[f32; 4]>() { + return Ok(material::MaterialValue::Float4(v)); + } + if let Ok(v) = value.extract::<[f32; 3]>() { + return Ok(material::MaterialValue::Float3(v)); + } + if let Ok(v) = value.extract::<[f32; 2]>() { + return Ok(material::MaterialValue::Float2(v)); + } + + Err(PyRuntimeError::new_err(format!( + "unsupported material value type: {}", + value.get_type().name()? + ))) +} + #[pymethods] impl Material { #[new] - pub fn new() -> PyResult { - let entity = material_create_pbr().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; - Ok(Self { entity }) - } + #[pyo3(signature = (shader=None, **kwargs))] + pub fn new(shader: Option<&Shader>, kwargs: Option<&Bound<'_, PyDict>>) -> PyResult { + let entity = if let Some(shader) = shader { + material_create_custom(shader.entity) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))? + } else { + material_create_pbr().map_err(|e| PyRuntimeError::new_err(format!("{e}")))? + }; - pub fn set_float(&self, name: &str, value: f32) -> PyResult<()> { - material_set(self.entity, name, material::MaterialValue::Float(value)) - .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + let mat = Self { entity }; + if let Some(kwargs) = kwargs { + for (key, value) in kwargs.iter() { + let name: String = key.extract()?; + let mat_value = py_to_material_value(&value)?; + material_set(mat.entity, &name, mat_value) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + } + } + Ok(mat) } - pub fn set_float4(&self, name: &str, r: f32, g: f32, b: f32, a: f32) -> PyResult<()> { - material_set( - self.entity, - name, - material::MaterialValue::Float4([r, g, b, a]), - ) - .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + #[pyo3(signature = (**kwargs))] + pub fn set(&self, kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<()> { + let Some(kwargs) = kwargs else { + return Ok(()); + }; + for (key, value) in kwargs.iter() { + let name: String = key.extract()?; + let mat_value = py_to_material_value(&value)?; + material_set(self.entity, &name, mat_value) + .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + } + Ok(()) } } diff --git a/crates/processing_pyo3/src/shader.rs b/crates/processing_pyo3/src/shader.rs new file mode 100644 index 0000000..8960575 --- /dev/null +++ b/crates/processing_pyo3/src/shader.rs @@ -0,0 +1,29 @@ +use bevy::prelude::Entity; +use processing::prelude::*; +use pyo3::{exceptions::PyRuntimeError, prelude::*}; + +#[pyclass(unsendable)] +pub struct Shader { + pub(crate) entity: Entity, +} + +#[pymethods] +impl Shader { + #[new] + pub fn new(source: &str) -> PyResult { + let entity = shader_create(source).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + Ok(Self { entity }) + } + + #[staticmethod] + pub fn load(path: &str) -> PyResult { + let entity = shader_load(path).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; + Ok(Self { entity }) + } +} + +impl Drop for Shader { + fn drop(&mut self) { + let _ = shader_destroy(self.entity); + } +} diff --git a/crates/processing_render/Cargo.toml b/crates/processing_render/Cargo.toml index 64a976d..afccd18 100644 --- a/crates/processing_render/Cargo.toml +++ b/crates/processing_render/Cargo.toml @@ -13,6 +13,9 @@ x11 = ["bevy/x11"] [dependencies] bevy = { workspace = true } +bevy_naga_reflect = { workspace = true } +naga = { workspace = true } +wesl = { workspace = true } lyon = "1.0" raw-window-handle = "0.6" thiserror = "2" @@ -22,6 +25,9 @@ half = "2.7" crossbeam-channel = "0.5" processing_midi = { workspace = true } +[build-dependencies] +wesl = { workspace = true, features = ["package"] } + [target.'cfg(target_os = "macos")'.dependencies] objc2 = { version = "0.6", default-features = false } objc2-app-kit = { version = "0.3", features = ["NSWindow", "NSView"] } diff --git a/crates/processing_render/build.rs b/crates/processing_render/build.rs new file mode 100644 index 0000000..d5b62aa --- /dev/null +++ b/crates/processing_render/build.rs @@ -0,0 +1,17 @@ +// packages wesl libraries for processing and lygia +// note that bevy does not (as of yet) understand how to use these packages +// they are, instead, used by us as part of shader pre-processing in the +// processing_render crate +fn main() { + wesl::PkgBuilder::new("processing") + .scan_root("shaders/processing") + .expect("failed to scan processing WESL files") + .build_artifact() + .expect("failed to build processing package artifact"); + + wesl::PkgBuilder::new("lygia") + .scan_root("../../lygia") + .expect("failed to scan Lygia WESL files") + .build_artifact() + .expect("failed to build Lygia package artifact"); +} diff --git a/crates/processing_render/shaders/processing.wesl b/crates/processing_render/shaders/processing.wesl new file mode 100644 index 0000000..04ba620 --- /dev/null +++ b/crates/processing_render/shaders/processing.wesl @@ -0,0 +1,15 @@ +struct Globals { + time: f32, + delta_time: f32, + frame_count: u32, +} + +@group(0) @binding(11) var globals: Globals; + +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) world_position: vec4, + @location(1) world_normal: vec3, + @location(2) uv: vec2, + @location(5) color: vec4, +} diff --git a/crates/processing_render/src/error.rs b/crates/processing_render/src/error.rs index 9a3ab90..2e52a83 100644 --- a/crates/processing_render/src/error.rs +++ b/crates/processing_render/src/error.rs @@ -36,4 +36,8 @@ pub enum ProcessingError { UnknownMaterialProperty(String), #[error("GLTF load error: {0}")] GltfLoadError(String), + #[error("Shader compilation error: {0}")] + ShaderCompilationError(String), + #[error("Shader not found")] + ShaderNotFound, } diff --git a/crates/processing_render/src/geometry/mod.rs b/crates/processing_render/src/geometry/mod.rs index 02572a6..a11fd1e 100644 --- a/crates/processing_render/src/geometry/mod.rs +++ b/crates/processing_render/src/geometry/mod.rs @@ -250,8 +250,9 @@ pub fn vertex( .get(geometry.layout) .map_err(|_| ProcessingError::LayoutNotFound)?; - let mut mesh = meshes + let mesh = meshes .get_mut(&geometry.handle) + .map(|m| m.into_inner()) .ok_or(ProcessingError::GeometryNotFound)?; if let Some(VertexAttributeValues::Float32x3(positions)) = @@ -323,8 +324,9 @@ pub fn index( .get(entity) .map_err(|_| ProcessingError::GeometryNotFound)?; - let mut mesh = meshes + let mesh = meshes .get_mut(&geometry.handle) + .map(|m| m.into_inner()) .ok_or(ProcessingError::GeometryNotFound)?; match mesh.indices_mut() { diff --git a/crates/processing_render/src/graphics.rs b/crates/processing_render/src/graphics.rs index a4737bd..a351a73 100644 --- a/crates/processing_render/src/graphics.rs +++ b/crates/processing_render/src/graphics.rs @@ -28,7 +28,7 @@ use bevy::{ use crate::{ Flush, error::{ProcessingError, Result}, - image::{Image, bytes_to_pixels, create_readback_buffer, pixel_size, pixels_to_bytes}, + image::{Image, create_readback_buffer, pixel_size, pixels_to_bytes}, render::{ RenderState, command::{CommandBuffer, DrawCommand}, @@ -457,8 +457,6 @@ pub fn flush(app: &mut App, entity: Entity) -> Result<()> { Ok(()) } -/// Present the current frame to the surface. Flushes any pending draw commands, -/// enables camera output for one frame, then disables it again. pub fn present(app: &mut App, entity: Entity) -> Result<()> { graphics_mut!(app, entity) .get_mut::() @@ -473,41 +471,6 @@ pub fn present(app: &mut App, entity: Entity) -> Result<()> { .ok_or(ProcessingError::GraphicsNotFound)? .output_mode = CameraOutputMode::Skip; - // // Sync ViewTarget textures: copy main_texture → main_texture_other. - // // This ensures both A and B have identical content regardless of whether - // // post-processing effects called post_process_write() (which swaps A/B). - // app.world_mut() - // .run_system_cached_with(sync_view_target_textures, entity) - // .unwrap()?; - - Ok(()) -} - -/// Copy the current main_texture to main_texture_other so both ViewTarget -/// textures have identical content. This ensures pixel persistence works -/// regardless of post-processing effects that may swap the A/B texture selector. -fn sync_view_target_textures( - In(entity): In, - graphics_query: Query<&Graphics>, - graphics_targets: Res, - render_device: Res, - render_queue: Res, -) -> Result<()> { - let graphics = graphics_query - .get(entity) - .map_err(|_| ProcessingError::GraphicsNotFound)?; - - let view_target = graphics_targets - .get(&entity) - .ok_or(ProcessingError::GraphicsNotFound)?; - - let src = view_target.main_texture(); - let dst = view_target.main_texture_other(); - - let mut encoder = render_device.create_command_encoder(&CommandEncoderDescriptor::default()); - encoder.copy_texture_to_texture(src.as_image_copy(), dst.as_image_copy(), graphics.size); - render_queue.submit(std::iter::once(encoder.finish())); - Ok(()) } @@ -528,7 +491,6 @@ pub fn record_command( Ok(()) } -/// Raw readback result containing bytes and format metadata. pub struct ReadbackData { pub bytes: Vec, pub format: TextureFormat, @@ -648,10 +610,6 @@ pub fn update_region_write( .ok_or(ProcessingError::GraphicsNotFound)?; let texture = view_target.main_texture(); - eprintln!( - "update_region: writing to texture {:p} at ({}, {}) size {}x{}", - texture as *const _, x, y, width, height - ); let bytes_per_row = width * px_size; render_queue.write_texture( diff --git a/crates/processing_render/src/lib.rs b/crates/processing_render/src/lib.rs index b603247..0d1eac0 100644 --- a/crates/processing_render/src/lib.rs +++ b/crates/processing_render/src/lib.rs @@ -18,14 +18,13 @@ use config::*; #[cfg(not(target_arch = "wasm32"))] use bevy::log::tracing_subscriber; use bevy::render::RenderPlugin; -use bevy::render::settings::{RenderCreation, WgpuSettings}; use bevy::{ app::{App, AppExit}, asset::{AssetEventSystems, io::AssetSourceBuilder}, prelude::*, render::render_resource::{Extent3d, TextureFormat}, }; -use render::material::add_standard_materials; +use render::material::{add_custom_materials, add_standard_materials}; use render::{activate_cameras, clear_transient_meshes, flush_draw_commands}; use tracing::debug; @@ -282,11 +281,16 @@ fn create_app(config: Config) -> App { LightPlugin, material::MaterialPlugin, MidiPlugin, + material::custom::CustomMaterialPlugin, )); app.add_systems(First, (clear_transient_meshes, activate_cameras)) .add_systems( Update, - (flush_draw_commands, add_standard_materials) + ( + flush_draw_commands, + add_standard_materials, + add_custom_materials, + ) .chain() .before(AssetEventSystems), ); @@ -1303,6 +1307,40 @@ pub fn poll_for_sketch_updates() -> error::Result> { }) } +pub fn shader_create(source: &str) -> error::Result { + app_mut(|app| { + app.world_mut() + .run_system_cached_with(material::custom::create_shader, source.to_string()) + .unwrap() + }) +} + +/// Load a shader from a file path. +pub fn shader_load(path: &str) -> error::Result { + let path = std::path::PathBuf::from(path); + app_mut(|app| { + app.world_mut() + .run_system_cached_with(material::custom::load_shader, path) + .unwrap() + }) +} + +pub fn shader_destroy(entity: Entity) -> error::Result<()> { + app_mut(|app| { + app.world_mut() + .run_system_cached_with(material::custom::destroy_shader, entity) + .unwrap() + }) +} + +pub fn material_create_custom(shader: Entity) -> error::Result { + app_mut(|app| { + app.world_mut() + .run_system_cached_with(material::custom::create_custom, shader) + .unwrap() + }) +} + pub fn material_create_pbr() -> error::Result { app_mut(|app| { Ok(app diff --git a/crates/processing_render/src/material/custom.rs b/crates/processing_render/src/material/custom.rs new file mode 100644 index 0000000..02c5651 --- /dev/null +++ b/crates/processing_render/src/material/custom.rs @@ -0,0 +1,496 @@ +use std::any::TypeId; +use std::borrow::Cow; +use std::sync::Arc; + +use bevy::platform::collections::hash_map::Entry; +use wesl::PkgResolver; +use wesl::syntax::{ModulePath, PathOrigin}; + +wesl::wesl_pkg!(processing); +wesl::wesl_pkg!(lygia); + +use bevy::{ + asset::{AsAssetId, AssetEventSystems}, + core_pipeline::core_3d::Opaque3d, + ecs::system::{ + SystemParamItem, + lifetimeless::{SRes, SResMut}, + }, + material::{MaterialProperties, key::ErasedMeshPipelineKey}, + pbr::{ + DrawMaterial, EntitiesNeedingSpecialization, MainPassOpaqueDrawFunction, + MaterialBindGroupAllocator, MaterialBindGroupAllocators, MaterialFragmentShader, + MaterialVertexShader, MeshPipelineKey, PreparedMaterial, RenderMaterialBindings, + RenderMaterialInstance, RenderMaterialInstances, base_specialize, + }, + prelude::*, + reflect::{PartialReflect, ReflectMut, ReflectRef, structs::Struct}, + render::{ + Extract, RenderApp, RenderStartup, + camera::{DirtySpecializationSystems, DirtySpecializations}, + erased_render_asset::{ErasedRenderAsset, ErasedRenderAssetPlugin, PrepareAssetError}, + render_asset::RenderAssets, + render_phase::DrawFunctions, + render_resource::{BindGroupLayoutDescriptor, BindingResources, UnpreparedBindGroup}, + renderer::RenderDevice, + sync_world::MainEntity, + texture::GpuImage, + }, +}; + +use bevy_naga_reflect::dynamic_shader::DynamicShader; + +use bevy::shader::Shader as ShaderAsset; + +use crate::config::{Config, ConfigKey}; +use crate::error::{ProcessingError, Result}; +use crate::material::MaterialValue; +use crate::render::material::UntypedMaterial; + +#[derive(Asset, TypePath, Clone)] +pub struct CustomMaterial { + pub shader: DynamicShader, + pub shader_handle: Handle, + pub has_vertex: bool, + pub has_fragment: bool, +} + +#[derive(Component)] +pub struct Shader { + pub module: naga::Module, + pub shader_handle: Handle, +} + +#[derive(Component, Clone)] +pub struct CustomMaterial3d(pub Handle); + +impl AsAssetId for CustomMaterial3d { + type Asset = CustomMaterial; + fn as_asset_id(&self) -> AssetId { + self.0.id() + } +} + +struct ProcessingResolver<'a> { + entry_source: &'a str, + pkg_resolver: PkgResolver, +} + +impl wesl::Resolver for ProcessingResolver<'_> { + fn resolve_source<'a>( + &'a self, + path: &ModulePath, + ) -> std::result::Result, wesl::ResolveError> { + // Check for the entry module first (its parsed path has Package origin) + if path.to_string() == "entry" { + return Ok(Cow::Borrowed(self.entry_source)); + } + + match &path.origin { + PathOrigin::Package(pkg) => { + // Self-referential package imports: within a package, imports to + // the same package stack the name (e.g. "lygia/lygia/lygia/..."). + // Collapse to the root package name before resolving. + let root = pkg.split('/').next().unwrap(); + let mut fixed = path.clone(); + fixed.origin = PathOrigin::Package(root.to_string()); + self.pkg_resolver.resolve_source(&fixed) + } + _ => Err(wesl::ResolveError::ModuleNotFound( + path.clone(), + format!("unknown module: {}", path), + )), + } + } +} + +fn compile_shader(source: &str) -> Result<(String, naga::Module)> { + let mut pkg_resolver = PkgResolver::new(); + pkg_resolver.add_package(&processing::PACKAGE); + pkg_resolver.add_package(&lygia::PACKAGE); + + let resolver = ProcessingResolver { + entry_source: source, + pkg_resolver, + }; + let module_path: ModulePath = "entry".parse().unwrap(); + let options = wesl::CompileOptions { + imports: true, + strip: false, + ..Default::default() + }; + let compiled = wesl::compile(&module_path, &resolver, &wesl::EscapeMangler, &options) + .map_err(|e| ProcessingError::ShaderCompilationError(e.to_string()))?; + let wgsl = compiled.to_string(); + let module = naga::front::wgsl::parse_str(&wgsl) + .map_err(|e| ProcessingError::ShaderCompilationError(e.to_string()))?; + Ok((wgsl, module)) +} + +pub fn create_shader( + In(source): In, + mut commands: Commands, + mut shaders: ResMut>, +) -> Result { + let (compiled_wgsl, module) = compile_shader(&source)?; + let shader_handle = shaders.add(ShaderAsset::from_wgsl(compiled_wgsl, "custom_material")); + Ok(commands + .spawn(Shader { + module, + shader_handle, + }) + .id()) +} + +pub fn load_shader(In(path): In, world: &mut World) -> Result { + use bevy::asset::{ + AssetPath, LoadState, handle_internal_asset_events, + io::{AssetSourceId, embedded::GetAssetServer}, + }; + use bevy::ecs::system::RunSystemOnce; + + let config = world.resource::(); + let asset_path: AssetPath = match config.get(ConfigKey::AssetRootPath) { + Some(_) => { + AssetPath::from_path_buf(path).with_source(AssetSourceId::from("assets_directory")) + } + None => AssetPath::from_path_buf(path), + }; + + let handle: Handle = world.get_asset_server().load(asset_path); + + while let LoadState::Loading = world.get_asset_server().load_state(&handle) { + world.run_system_once(handle_internal_asset_events).unwrap(); + } + + let source = { + let shader_assets = world.resource::>(); + let shader = shader_assets + .get(&handle) + .ok_or(ProcessingError::ShaderNotFound)?; + match &shader.source { + bevy::shader::Source::Wesl(s) | bevy::shader::Source::Wgsl(s) => s.to_string(), + _ => { + return Err(ProcessingError::ShaderCompilationError( + "Unsupported shader source format".to_string(), + )); + } + } + }; + + let (compiled_wgsl, module) = compile_shader(&source)?; + + let shader_handle = world + .resource_mut::>() + .add(ShaderAsset::from_wgsl(compiled_wgsl, "custom_material")); + + Ok(world + .spawn(Shader { + module, + shader_handle, + }) + .id()) +} + +pub fn destroy_shader(In(entity): In, mut commands: Commands) -> Result<()> { + commands.entity(entity).despawn(); + Ok(()) +} + +pub fn create_custom( + In(shader_entity): In, + mut commands: Commands, + shader_programs: Query<&Shader>, + mut custom_materials: ResMut>, +) -> Result { + let program = shader_programs + .get(shader_entity) + .map_err(|_| ProcessingError::ShaderNotFound)?; + + let has_vertex = program + .module + .entry_points + .iter() + .any(|ep| ep.stage == naga::ShaderStage::Vertex); + let has_fragment = program + .module + .entry_points + .iter() + .any(|ep| ep.stage == naga::ShaderStage::Fragment); + + let mut shader = DynamicShader::new(program.module.clone()) + .map_err(|e| ProcessingError::ShaderCompilationError(e.to_string()))?; + shader.init(); + + let material = CustomMaterial { + shader, + shader_handle: program.shader_handle.clone(), + has_vertex, + has_fragment, + }; + let handle = custom_materials.add(material); + Ok(commands.spawn(UntypedMaterial(handle.untyped())).id()) +} + +pub fn set_property( + material: &mut CustomMaterial, + name: &str, + value: &MaterialValue, +) -> Result<()> { + let reflect_value: Box = material_value_to_reflect(value)?; + + if let Some(field) = material.shader.field_mut(name) { + field.apply(&*reflect_value); + return Ok(()); + } + + let param_name = find_param_containing_field(&material.shader, name); + if let Some(param_name) = param_name { + if let Some(param) = material.shader.field_mut(¶m_name) { + if let ReflectMut::Struct(s) = param.reflect_mut() { + if let Some(field) = s.field_mut(name) { + field.apply(&*reflect_value); + return Ok(()); + } + } + } + } + + Err(ProcessingError::UnknownMaterialProperty(name.to_string())) +} + +fn material_value_to_reflect(value: &MaterialValue) -> Result> { + Ok(match value { + MaterialValue::Float(v) => Box::new(*v), + MaterialValue::Float2(v) => Box::new(Vec2::from_array(*v)), + MaterialValue::Float3(v) => Box::new(Vec3::from_array(*v)), + MaterialValue::Float4(v) => Box::new(Vec4::from_array(*v)), + MaterialValue::Int(v) => Box::new(*v), + MaterialValue::Int2(v) => Box::new(IVec2::from_array(*v)), + MaterialValue::Int3(v) => Box::new(IVec3::from_array(*v)), + MaterialValue::Int4(v) => Box::new(IVec4::from_array(*v)), + MaterialValue::UInt(v) => Box::new(*v), + MaterialValue::Mat4(v) => Box::new(Mat4::from_cols_array(v)), + MaterialValue::Texture(_) => { + return Err(ProcessingError::UnknownMaterialProperty( + "Texture properties not yet supported for custom materials".to_string(), + )); + } + }) +} + +fn find_param_containing_field(shader: &DynamicShader, field_name: &str) -> Option { + for i in 0..shader.field_len() { + if let Some(field) = shader.field_at(i) { + if let ReflectRef::Struct(s) = field.reflect_ref() { + if s.field(field_name).is_some() { + return shader.name_at(i).map(|s: &str| s.to_string()); + } + } + } + } + None +} + +pub struct CustomMaterialPlugin; + +impl Plugin for CustomMaterialPlugin { + fn build(&self, app: &mut App) { + app.init_asset::() + .add_plugins(ErasedRenderAssetPlugin::::default()) + .add_systems( + PostUpdate, + check_entities_needing_specialization.after(AssetEventSystems), + ) + .init_resource::>(); + + let Some(render_app) = app.get_sub_app_mut(RenderApp) else { + return; + }; + + render_app + .add_systems(RenderStartup, init_custom_material_resources) + .add_systems( + ExtractSchedule, + ( + extract_custom_materials, + extract_custom_materials_needing_specialization + .in_set(DirtySpecializationSystems::CheckForChanges), + extract_custom_materials_that_need_specializations_removed + .in_set(DirtySpecializationSystems::CheckForRemovals), + ), + ); + } +} + +fn init_custom_material_resources( + mut bind_group_allocators: ResMut, + render_device: Res, +) { + let bind_group_layout = BindGroupLayoutDescriptor::new("custom_material_layout", &[]); + + bind_group_allocators.insert( + TypeId::of::(), + MaterialBindGroupAllocator::new( + &render_device, + "custom_material_allocator", + None, + bind_group_layout, + None, + ), + ); +} + +impl ErasedRenderAsset for CustomMaterial { + type SourceAsset = CustomMaterial; + type ErasedAsset = PreparedMaterial; + type Param = ( + SRes>, + SRes, + SRes, + SResMut, + SResMut, + SRes>, + ); + + fn prepare_asset( + source_asset: Self::SourceAsset, + asset_id: AssetId, + ( + opaque_draw_functions, + _asset_server, + render_device, + bind_group_allocators, + render_material_bindings, + gpu_images, + ): &mut SystemParamItem, + ) -> std::result::Result> { + let reflection = source_asset.shader.reflection(); + + let layout_entries = reflection.bind_group_layout(3); + let bind_group_layout = + BindGroupLayoutDescriptor::new("custom_material_bind_group", &layout_entries); + + let bindings = + reflection.create_bindings(3, &source_asset.shader, render_device, gpu_images); + + let unprepared = UnpreparedBindGroup { + bindings: BindingResources(bindings), + }; + + let bind_group_allocator = bind_group_allocators + .get_mut(&TypeId::of::()) + .unwrap(); + + let binding = match render_material_bindings.entry(asset_id.into()) { + Entry::Occupied(mut occupied_entry) => { + bind_group_allocator.free(*occupied_entry.get()); + let new_binding = + bind_group_allocator.allocate_unprepared(unprepared, &bind_group_layout); + *occupied_entry.get_mut() = new_binding; + new_binding + } + Entry::Vacant(vacant_entry) => *vacant_entry + .insert(bind_group_allocator.allocate_unprepared(unprepared, &bind_group_layout)), + }; + + let draw_function = opaque_draw_functions.read().id::(); + + let mut properties = MaterialProperties { + mesh_pipeline_key_bits: ErasedMeshPipelineKey::new(MeshPipelineKey::empty()), + base_specialize: Some(base_specialize), + material_layout: Some(bind_group_layout), + ..Default::default() + }; + properties.add_draw_function(MainPassOpaqueDrawFunction, draw_function); + if source_asset.has_vertex { + properties.add_shader(MaterialVertexShader, source_asset.shader_handle.clone()); + } + if source_asset.has_fragment { + properties.add_shader(MaterialFragmentShader, source_asset.shader_handle.clone()); + } + + Ok(PreparedMaterial { + binding, + properties: Arc::new(properties), + }) + } +} + +fn extract_custom_materials( + mut material_instances: ResMut, + changed_query: Extract< + Query< + (Entity, &ViewVisibility, &CustomMaterial3d), + Or<(Changed, Changed)>, + >, + >, +) { + let last_change_tick = material_instances.current_change_tick; + for (entity, view_visibility, material) in &changed_query { + let vis = view_visibility.get(); + if vis { + material_instances.instances.insert( + entity.into(), + RenderMaterialInstance { + asset_id: material.0.id().untyped(), + last_change_tick, + }, + ); + } else { + material_instances + .instances + .remove(&MainEntity::from(entity)); + } + } +} + +fn extract_custom_materials_needing_specialization( + entities: Extract>>, + mut dirty: ResMut, +) { + for entity in entities.changed.iter() { + dirty.changed_renderables.insert(MainEntity::from(*entity)); + } +} + +fn extract_custom_materials_that_need_specializations_removed( + entities: Extract>>, + mut dirty: ResMut, +) { + for entity in entities.removed.iter() { + dirty.removed_renderables.insert(MainEntity::from(*entity)); + } +} + +fn check_entities_needing_specialization( + needs_specialization: Query< + Entity, + ( + Or<( + Changed, + AssetChanged, + Changed, + AssetChanged, + )>, + With, + ), + >, + mut entities: ResMut>, + mut removed_mesh: RemovedComponents, + mut removed_material: RemovedComponents, +) { + entities.changed.clear(); + entities.removed.clear(); + + for entity in &needs_specialization { + entities.changed.push(entity); + } + + for entity in removed_mesh.read() { + entities.removed.push(entity); + } + for entity in removed_material.read() { + entities.removed.push(entity); + } +} diff --git a/crates/processing_render/src/material/mod.rs b/crates/processing_render/src/material/mod.rs index 1148c81..954d30b 100644 --- a/crates/processing_render/src/material/mod.rs +++ b/crates/processing_render/src/material/mod.rs @@ -1,3 +1,4 @@ +pub mod custom; pub mod pbr; use bevy::prelude::*; @@ -57,20 +58,29 @@ pub fn set_property( In((entity, name, value)): In<(Entity, String, MaterialValue)>, material_handles: Query<&UntypedMaterial>, mut standard_materials: ResMut>, + mut custom_materials: ResMut>, ) -> Result<()> { let untyped = material_handles .get(entity) .map_err(|_| ProcessingError::MaterialNotFound)?; - let handle = untyped - .0 - .clone() - .try_typed::() - .map_err(|_| ProcessingError::MaterialNotFound)?; - let mut standard = standard_materials - .get_mut(&handle) - .ok_or(ProcessingError::MaterialNotFound)?; - pbr::set_property(&mut standard, &name, &value)?; - Ok(()) + + // Try StandardMaterial + if let Ok(handle) = untyped.0.clone().try_typed::() { + let mut standard = standard_materials + .get_mut(&handle) + .ok_or(ProcessingError::MaterialNotFound)?; + return pbr::set_property(&mut standard, &name, &value); + } + + // Try CustomMaterial + if let Ok(handle) = untyped.0.clone().try_typed::() { + let mut mat = custom_materials + .get_mut(&handle) + .ok_or(ProcessingError::MaterialNotFound)?; + return custom::set_property(&mut mat, &name, &value); + } + + Err(ProcessingError::MaterialNotFound) } pub fn destroy( @@ -78,6 +88,7 @@ pub fn destroy( mut commands: Commands, material_handles: Query<&UntypedMaterial>, mut standard_materials: ResMut>, + mut custom_materials: ResMut>, ) -> Result<()> { let untyped = material_handles .get(entity) @@ -85,6 +96,9 @@ pub fn destroy( if let Ok(handle) = untyped.0.clone().try_typed::() { standard_materials.remove(&handle); } + if let Ok(handle) = untyped.0.clone().try_typed::() { + custom_materials.remove(&handle); + } commands.entity(entity).despawn(); Ok(()) } diff --git a/crates/processing_render/src/render/material.rs b/crates/processing_render/src/render/material.rs index 0351a48..bdbc67b 100644 --- a/crates/processing_render/src/render/material.rs +++ b/crates/processing_render/src/render/material.rs @@ -1,14 +1,11 @@ use bevy::prelude::*; use std::ops::Deref; -/// A component that holds an untyped handle to a material. This allows the main render loop -/// to be agnostic of the specific material types being used, and allows for dynamic material -/// creation based on the `MaterialKey`. +use crate::material::custom::{CustomMaterial, CustomMaterial3d}; + #[derive(Component, Deref)] pub struct UntypedMaterial(pub UntypedHandle); -/// Defines the current material for a batch, which can be used to determine when to flush the -/// current batch and start a new one. #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum MaterialKey { Color { @@ -73,15 +70,11 @@ impl MaterialKey { }; materials.add(mat).untyped() } - MaterialKey::Custom(_entity) => { - todo!("implement custom materials") - } + MaterialKey::Custom(_) => unreachable!(), } } } -/// A system that adds a `MeshMaterial3d` component to any entity with an `UntypedMaterial` that can -/// be typed as a `StandardMaterial`. pub fn add_standard_materials(mut commands: Commands, meshes: Query<(Entity, &UntypedMaterial)>) { for (entity, handle) in meshes.iter() { let handle = handle.deref().clone(); @@ -90,3 +83,12 @@ pub fn add_standard_materials(mut commands: Commands, meshes: Query<(Entity, &Un } } } + +pub fn add_custom_materials(mut commands: Commands, meshes: Query<(Entity, &UntypedMaterial)>) { + for (entity, handle) in meshes.iter() { + let handle = handle.deref().clone(); + if let Ok(handle) = handle.try_typed::() { + commands.entity(entity).insert(CustomMaterial3d(handle)); + } + } +} diff --git a/crates/processing_render/src/render/mod.rs b/crates/processing_render/src/render/mod.rs index 3de4b67..187187b 100644 --- a/crates/processing_render/src/render/mod.rs +++ b/crates/processing_render/src/render/mod.rs @@ -223,25 +223,35 @@ pub fn flush_draw_commands( }; } DrawCommand::Rect { x, y, w, h, radii } => { - add_fill(&mut res, &mut batch, &state, |mesh, color| { - rect(mesh, x, y, w, h, radii, color, TessellationMode::Fill) - }); - - add_stroke(&mut res, &mut batch, &state, |mesh, color, weight| { - rect( - mesh, - x, - y, - w, - h, - radii, - color, - TessellationMode::Stroke(weight), - ) - }); + add_fill( + &mut res, + &mut batch, + &state, + |mesh, color| rect(mesh, x, y, w, h, radii, color, TessellationMode::Fill), + &p_material_handles, + ); + + add_stroke( + &mut res, + &mut batch, + &state, + |mesh, color, weight| { + rect( + mesh, + x, + y, + w, + h, + radii, + color, + TessellationMode::Stroke(weight), + ) + }, + &p_material_handles, + ); } DrawCommand::BackgroundColor(color) => { - flush_batch(&mut res, &mut batch); + flush_batch(&mut res, &mut batch, &p_material_handles); let mesh = create_ndc_background_quad(world_from_clip, color, false); let mesh_handle = res.meshes.add(mesh); @@ -268,7 +278,7 @@ pub fn flush_draw_commands( continue; }; - flush_batch(&mut res, &mut batch); + flush_batch(&mut res, &mut batch, &p_material_handles); let mesh = create_ndc_background_quad(world_from_clip, Color::WHITE, true); let mesh_handle = res.meshes.add(mesh); @@ -315,7 +325,7 @@ pub fn flush_draw_commands( _ => material_key.to_material(&mut res.materials), }; - flush_batch(&mut res, &mut batch); + flush_batch(&mut res, &mut batch, &p_material_handles); let z_offset = -(batch.draw_index as f32 * 0.001); let mut transform = state.transform.to_bevy_transform(); @@ -347,7 +357,13 @@ pub fn flush_draw_commands( height, depth, } => { - add_shape3d(&mut res, &mut batch, &state, box_mesh(width, height, depth)); + add_shape3d( + &mut res, + &mut batch, + &state, + box_mesh(width, height, depth), + &p_material_handles, + ); } DrawCommand::Sphere { radius, @@ -359,12 +375,13 @@ pub fn flush_draw_commands( &mut batch, &state, sphere_mesh(radius, sectors, stacks), + &p_material_handles, ); } } } - flush_batch(&mut res, &mut batch); + flush_batch(&mut res, &mut batch, &p_material_handles); } } @@ -386,7 +403,13 @@ pub fn clear_transient_meshes( } } -fn spawn_mesh(res: &mut RenderResources, batch: &mut BatchState, mesh: Mesh, z_offset: f32) { +fn spawn_mesh( + res: &mut RenderResources, + batch: &mut BatchState, + mesh: Mesh, + z_offset: f32, + material_handles: &Query<&UntypedMaterial>, +) { let Some(key) = &batch.material_key else { return; }; @@ -400,7 +423,16 @@ fn spawn_mesh(res: &mut RenderResources, batch: &mut BatchState, mesh: Mesh, z_o scale, }; - let material_handle = key.to_material(&mut res.materials); + let material_handle = match key { + MaterialKey::Custom(entity) => match material_handles.get(*entity) { + Ok(handle) => handle.0.clone(), + Err(_) => { + warn!("Custom material entity {:?} not found", entity); + return; + } + }, + _ => key.to_material(&mut res.materials), + }; res.commands.spawn(( Mesh3d(mesh_handle), @@ -422,8 +454,9 @@ fn start_batch( batch: &mut BatchState, state: &RenderState, material_key: MaterialKey, + material_handles: &Query<&UntypedMaterial>, ) { - flush_batch(res, batch); + flush_batch(res, batch, material_handles); batch.material_key = Some(material_key); batch.transform = state.transform.current(); batch.current_mesh = Some(empty_mesh()); @@ -465,6 +498,7 @@ fn add_fill( batch: &mut BatchState, state: &RenderState, tessellate: impl FnOnce(&mut Mesh, Color), + material_handles: &Query<&UntypedMaterial>, ) { let Some(color) = state.fill_color else { return; @@ -472,7 +506,7 @@ fn add_fill( let material_key = material_key_with_color(&state.material_key, color); if needs_batch(batch, state, &material_key) { - start_batch(res, batch, state, material_key); + start_batch(res, batch, state, material_key, material_handles); } if let Some(ref mut mesh) = batch.current_mesh { @@ -485,6 +519,7 @@ fn add_stroke( batch: &mut BatchState, state: &RenderState, tessellate: impl FnOnce(&mut Mesh, Color, f32), + material_handles: &Query<&UntypedMaterial>, ) { let Some(color) = state.stroke_color else { return; @@ -493,7 +528,7 @@ fn add_stroke( let material_key = material_key_with_color(&state.material_key, color); if needs_batch(batch, state, &material_key) { - start_batch(res, batch, state, material_key); + start_batch(res, batch, state, material_key, material_handles); } if let Some(ref mut mesh) = batch.current_mesh { @@ -501,21 +536,41 @@ fn add_stroke( } } -fn flush_batch(res: &mut RenderResources, batch: &mut BatchState) { +fn flush_batch( + res: &mut RenderResources, + batch: &mut BatchState, + material_handles: &Query<&UntypedMaterial>, +) { if let Some(mesh) = batch.current_mesh.take() { let z_offset = -(batch.draw_index as f32 * 0.001); - spawn_mesh(res, batch, mesh, z_offset); + spawn_mesh(res, batch, mesh, z_offset, material_handles); batch.draw_index += 1; } batch.material_key = None; } -fn add_shape3d(res: &mut RenderResources, batch: &mut BatchState, state: &RenderState, mesh: Mesh) { - flush_batch(res, batch); +fn add_shape3d( + res: &mut RenderResources, + batch: &mut BatchState, + state: &RenderState, + mesh: Mesh, + material_handles: &Query<&UntypedMaterial>, +) { + flush_batch(res, batch, material_handles); let mesh_handle = res.meshes.add(mesh); let material_key = material_key_with_fill(state); - let material_handle = material_key.to_material(&mut res.materials); + + let material_handle = match &material_key { + MaterialKey::Custom(entity) => match material_handles.get(*entity) { + Ok(handle) => handle.0.clone(), + Err(_) => { + warn!("Custom material entity {:?} not found", entity); + return; + } + }, + _ => material_key.to_material(&mut res.materials), + }; let z_offset = -(batch.draw_index as f32 * 0.001); let mut transform = state.transform.to_bevy_transform(); diff --git a/crates/processing_render/src/render/primitive/shape3d.rs b/crates/processing_render/src/render/primitive/shape3d.rs index 2a630e2..d3ce5db 100644 --- a/crates/processing_render/src/render/primitive/shape3d.rs +++ b/crates/processing_render/src/render/primitive/shape3d.rs @@ -1,11 +1,30 @@ use bevy::prelude::*; +use bevy::render::mesh::VertexAttributeValues; + +/// Ensure a mesh has vertex colors, inserting default white if missing. +fn ensure_vertex_colors(mesh: &mut Mesh) { + if mesh.attribute(Mesh::ATTRIBUTE_COLOR).is_none() { + let vertex_count = mesh + .attribute(Mesh::ATTRIBUTE_POSITION) + .map(|a| a.len()) + .unwrap_or(0); + mesh.insert_attribute( + Mesh::ATTRIBUTE_COLOR, + VertexAttributeValues::Float32x4(vec![[1.0, 1.0, 1.0, 1.0]; vertex_count]), + ); + } +} pub fn box_mesh(width: f32, height: f32, depth: f32) -> Mesh { let cuboid = bevy::math::primitives::Cuboid::new(width, height, depth); - Mesh::from(cuboid) + let mut mesh = Mesh::from(cuboid); + ensure_vertex_colors(&mut mesh); + mesh } pub fn sphere_mesh(radius: f32, sectors: u32, stacks: u32) -> Mesh { let sphere = bevy::math::primitives::Sphere::new(radius); - sphere.mesh().uv(sectors, stacks) + let mut mesh = sphere.mesh().uv(sectors, stacks); + ensure_vertex_colors(&mut mesh); + mesh } diff --git a/examples/custom_material.rs b/examples/custom_material.rs new file mode 100644 index 0000000..d8ed3c7 --- /dev/null +++ b/examples/custom_material.rs @@ -0,0 +1,67 @@ +mod glfw; + +use glfw::GlfwContext; +use processing::prelude::*; +use processing_render::render::command::DrawCommand; + +fn main() { + match sketch() { + Ok(_) => { + eprintln!("Sketch completed successfully"); + exit(0).unwrap(); + } + Err(e) => { + eprintln!("Sketch error: {:?}", e); + exit(1).unwrap(); + } + }; +} + +fn sketch() -> error::Result<()> { + let width = 400; + let height = 400; + let mut glfw_ctx = GlfwContext::new(width, height)?; + init(Config::default())?; + + let surface = glfw_ctx.create_surface(width, height, 1.0)?; + let graphics = graphics_create(surface, width, height, TextureFormat::Rgba16Float)?; + let box_geo = geometry_box(100.0, 100.0, 100.0)?; + + graphics_mode_3d(graphics)?; + transform_set_position(graphics, 100.0, 100.0, 300.0)?; + transform_look_at(graphics, 0.0, 0.0, 0.0)?; + + let shader = shader_load("shaders/custom_material.wesl")?; + let mat = material_create_custom(shader)?; + material_set( + mat, + "color", + material::MaterialValue::Float4([1.0, 0.2, 0.4, 1.0]), + )?; + + let mut angle = 0.0; + + while glfw_ctx.poll_events() { + graphics_begin_draw(graphics)?; + + graphics_record_command( + graphics, + DrawCommand::BackgroundColor(bevy::color::Color::srgb(0.1, 0.1, 0.15)), + )?; + + graphics_record_command(graphics, DrawCommand::PushMatrix)?; + graphics_record_command(graphics, DrawCommand::Rotate { angle })?; + graphics_record_command(graphics, DrawCommand::Material(mat))?; + graphics_record_command(graphics, DrawCommand::Geometry(box_geo))?; + graphics_record_command(graphics, DrawCommand::PopMatrix)?; + + graphics_end_draw(graphics)?; + + angle += 0.02; + } + + material_destroy(mat)?; + shader_destroy(shader)?; + + Ok(()) +} diff --git a/lygia b/lygia new file mode 160000 index 0000000..409bf5f --- /dev/null +++ b/lygia @@ -0,0 +1 @@ +Subproject commit 409bf5f92d3ab1cfeb8cf086a46d1d8e5231b37a