DEVELOPMENT ENVIRONMENT

~liljamo/bevy_dice

5e9076f71cb49dfdfc80a5cf421c4408fa1e98e7 — Jonni Liljamo 5 days ago 2922dfd
feat: initial version with demo
45 files changed, 899 insertions(+), 1213 deletions(-)

A .cargo/config.toml
M .gitignore
M Cargo.lock
M Cargo.toml
A LICENSE
A README.md
A assets/export/D6.glb
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Percent_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d12_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d20_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d4_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d6_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d8_Numbers.xcf
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Percent_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d12_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d20_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d4_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d6_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d8_Numbers.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d10.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d12.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d20.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d4.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d6.png
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d8.png
A assets/ext/Dice/Dice.blend
A assets/ext/Dice/Dice_Textured.blend
A assets/ext/Dice/Dice_Textured.blend1
A assets/ext/Dice/Dice_Textured.glb
A assets/ext/dice.zip
A assets/raw/D6.blend
A assets/raw/D6.blend1
A crates/bevy_dice/Cargo.toml
A crates/bevy_dice/src/die.rs
A crates/bevy_dice/src/face.rs
A crates/bevy_dice/src/lib.rs
A crates/bevy_dice_demo/Cargo.toml
A crates/bevy_dice_demo/src/main.rs
D examples/simple.rs
M flake.nix
M justfile
M rust-toolchain.toml
D src/lib.rs
A .cargo/config.toml => .cargo/config.toml +6 -0
@@ 0,0 1,6 @@
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

[target.wasm32-unknown-unknown]
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

M .gitignore => .gitignore +1 -5
@@ 1,8 1,4 @@
/.direnv/
/.pre-commit-config.yaml
/out-demo-wasm/
/target/


# Added by cargo

/target

M Cargo.lock => Cargo.lock +150 -1121
@@ 60,8 60,8 @@ dependencies = [
 "hashbrown",
 "paste",
 "static_assertions",
 "windows 0.58.0",
 "windows-core 0.58.0",
 "windows",
 "windows-core",
]

[[package]]


@@ 118,28 118,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"

[[package]]
name = "alsa"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43"
dependencies = [
 "alsa-sys",
 "bitflags 2.9.1",
 "cfg-if",
 "libc",
]

[[package]]
name = "alsa-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
dependencies = [
 "libc",
 "pkg-config",
]

[[package]]
name = "android-activity"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 153,7 131,7 @@ dependencies = [
 "jni-sys",
 "libc",
 "log",
 "ndk 0.9.0",
 "ndk",
 "ndk-context",
 "ndk-sys 0.6.0+11769913",
 "num_enum",


@@ 395,8 373,6 @@ dependencies = [
 "itertools 0.13.0",
 "nalgebra",
 "parry3d",
 "parry3d-f64",
 "thread_local",
]

[[package]]


@@ 442,16 418,6 @@ dependencies = [
]

[[package]]
name = "bevy-dice"
version = "0.1.0"
dependencies = [
 "avian3d",
 "bevy",
 "bevy-inspector-egui",
 "bevy_egui",
]

[[package]]
name = "bevy-inspector-egui"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 510,40 476,6 @@ dependencies = [
]

[[package]]
name = "bevy_animation"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3647b67c6bfd456922b2720ccef980dec01742d155d0eb454dc3d8fdc65e7aff"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_color",
 "bevy_derive",
 "bevy_ecs",
 "bevy_log",
 "bevy_math",
 "bevy_mesh",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_time",
 "bevy_transform",
 "bevy_utils",
 "blake3",
 "derive_more",
 "downcast-rs 2.0.1",
 "either",
 "petgraph",
 "ron",
 "serde",
 "smallvec",
 "thiserror 2.0.12",
 "thread_local",
 "tracing",
 "uuid",
]

[[package]]
name = "bevy_app"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 619,24 551,6 @@ dependencies = [
]

[[package]]
name = "bevy_audio"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74e54154e6369abdbaf5098e20424d59197c9b701d4f79fe8d0d2bde03d25f12"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_derive",
 "bevy_ecs",
 "bevy_math",
 "bevy_reflect",
 "bevy_transform",
 "cpal",
 "rodio",
 "tracing",
]

[[package]]
name = "bevy_color"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 708,7 622,30 @@ dependencies = [
 "const-fnv1a-hash",
 "log",
 "serde",
 "sysinfo",
]

[[package]]
name = "bevy_dice"
version = "0.1.0"
dependencies = [
 "avian3d",
 "bevy",
 "bevy_rand",
 "lazy_static",
 "rand 0.9.1",
]

[[package]]
name = "bevy_dice_demo"
version = "0.1.0"
dependencies = [
 "avian3d",
 "bevy",
 "bevy-inspector-egui",
 "bevy_dice",
 "bevy_egui",
 "bevy_embedded_assets",
 "console_error_panic_hook",
]

[[package]]


@@ 766,7 703,6 @@ dependencies = [
 "bevy_input",
 "bevy_log",
 "bevy_math",
 "bevy_picking",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",


@@ 783,36 719,31 @@ dependencies = [
 "wasm-bindgen",
 "wasm-bindgen-futures",
 "web-sys",
 "webbrowser",
 "wgpu-types",
 "winit",
]

[[package]]
name = "bevy_encase_derive"
version = "0.16.0"
name = "bevy_embedded_assets"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb31dc1090c6f8fabbf6b21994d19a12766e786885ee48ffc547f0f1fa7863"
checksum = "c81ee60b1b01ca7414c43815d88043c8fe3adf11f1fdaf21eafcbcae84337292"
dependencies = [
 "bevy_macro_utils",
 "encase_derive_impl",
 "bevy_app",
 "bevy_asset",
 "bevy_ecs",
 "cargo-emit",
 "thiserror 2.0.12",
]

[[package]]
name = "bevy_gilrs"
name = "bevy_encase_derive"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "950c84596dbff8a9691a050c37bb610ef9398af56369c2c2dd6dc41ef7b717a5"
checksum = "b8bb31dc1090c6f8fabbf6b21994d19a12766e786885ee48ffc547f0f1fa7863"
dependencies = [
 "bevy_app",
 "bevy_ecs",
 "bevy_input",
 "bevy_platform",
 "bevy_time",
 "bevy_utils",
 "gilrs",
 "thiserror 2.0.12",
 "tracing",
 "bevy_macro_utils",
 "encase_derive_impl",
]

[[package]]


@@ 832,7 763,6 @@ dependencies = [
 "bevy_pbr",
 "bevy_reflect",
 "bevy_render",
 "bevy_sprite",
 "bevy_time",
 "bevy_transform",
 "bevy_utils",


@@ 859,7 789,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa25b809ee024ef2682bafc1ca22ca8275552edb549dc6f69a030fdffd976c63"
dependencies = [
 "base64 0.22.1",
 "bevy_animation",
 "bevy_app",
 "bevy_asset",
 "bevy_color",


@@ 966,16 895,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "526ffd64c58004cb97308826e896c07d0e23dc056c243b97492e31cdf72e2830"
dependencies = [
 "bevy_a11y",
 "bevy_animation",
 "bevy_app",
 "bevy_asset",
 "bevy_audio",
 "bevy_color",
 "bevy_core_pipeline",
 "bevy_derive",
 "bevy_diagnostic",
 "bevy_ecs",
 "bevy_gilrs",
 "bevy_gizmos",
 "bevy_gltf",
 "bevy_image",


@@ 984,7 910,6 @@ dependencies = [
 "bevy_log",
 "bevy_math",
 "bevy_pbr",
 "bevy_picking",
 "bevy_platform",
 "bevy_ptr",
 "bevy_reflect",


@@ 993,10 918,8 @@ dependencies = [
 "bevy_sprite",
 "bevy_state",
 "bevy_tasks",
 "bevy_text",
 "bevy_time",
 "bevy_transform",
 "bevy_ui",
 "bevy_utils",
 "bevy_window",
 "bevy_winit",


@@ 1044,7 967,7 @@ dependencies = [
 "glam",
 "itertools 0.14.0",
 "libm",
 "rand",
 "rand 0.8.5",
 "rand_distr",
 "serde",
 "smallvec",


@@ 1121,31 1044,6 @@ dependencies = [
]

[[package]]
name = "bevy_picking"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f73674f62b1033006bd75c89033f5d3516386cfd7d43bb9f7665012c0ab14d22"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_derive",
 "bevy_ecs",
 "bevy_input",
 "bevy_math",
 "bevy_mesh",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_time",
 "bevy_transform",
 "bevy_utils",
 "bevy_window",
 "crossbeam-channel",
 "tracing",
 "uuid",
]

[[package]]
name = "bevy_platform"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1164,12 1062,35 @@ dependencies = [
]

[[package]]
name = "bevy_prng"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41c76ebff351c2123628086ccef32fb9ae476519dc13f605d3680c17da5c40fb"
dependencies = [
 "rand_core 0.9.3",
 "wyrand",
]

[[package]]
name = "bevy_ptr"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f1275dfb4cfef4ffc90c3fa75408964864facf833acc932413d52aa5364ba4"

[[package]]
name = "bevy_rand"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ae51425b1886ff7c5a4a74fe2f4d0191b8e59f6409e3c84a3fccdbc8b63a93"
dependencies = [
 "bevy_app",
 "bevy_ecs",
 "bevy_prng",
 "getrandom 0.3.3",
 "rand_core 0.9.3",
]

[[package]]
name = "bevy_reflect"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1186,7 1107,6 @@ dependencies = [
 "erased-serde",
 "foldhash",
 "glam",
 "petgraph",
 "serde",
 "smallvec",
 "smol_str",


@@ 1308,13 1228,11 @@ dependencies = [
 "bevy_ecs",
 "bevy_image",
 "bevy_math",
 "bevy_picking",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_transform",
 "bevy_utils",
 "bevy_window",
 "bitflags 2.9.1",
 "bytemuck",
 "derive_more",


@@ 1375,36 1293,6 @@ dependencies = [
]

[[package]]
name = "bevy_text"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ef071262c5a9afbc39caba4c0b282c7d045fbb5cf33bdab1924bd2343403833"
dependencies = [
 "bevy_app",
 "bevy_asset",
 "bevy_color",
 "bevy_derive",
 "bevy_ecs",
 "bevy_image",
 "bevy_log",
 "bevy_math",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_sprite",
 "bevy_transform",
 "bevy_utils",
 "bevy_window",
 "cosmic-text",
 "serde",
 "smallvec",
 "sys-locale",
 "thiserror 2.0.12",
 "tracing",
 "unicode-bidi",
]

[[package]]
name = "bevy_time"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1447,41 1335,6 @@ dependencies = [
]

[[package]]
name = "bevy_ui"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "110dc5d0059f112263512be8cd7bfe0466dfb7c26b9bf4c74529355249fd23f9"
dependencies = [
 "accesskit",
 "bevy_a11y",
 "bevy_app",
 "bevy_asset",
 "bevy_color",
 "bevy_core_pipeline",
 "bevy_derive",
 "bevy_ecs",
 "bevy_image",
 "bevy_input",
 "bevy_math",
 "bevy_picking",
 "bevy_platform",
 "bevy_reflect",
 "bevy_render",
 "bevy_sprite",
 "bevy_text",
 "bevy_transform",
 "bevy_utils",
 "bevy_window",
 "bytemuck",
 "derive_more",
 "nonmax",
 "smallvec",
 "taffy",
 "thiserror 2.0.12",
 "tracing",
]

[[package]]
name = "bevy_utils"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1522,10 1375,8 @@ dependencies = [
 "approx",
 "bevy_a11y",
 "bevy_app",
 "bevy_asset",
 "bevy_derive",
 "bevy_ecs",
 "bevy_image",
 "bevy_input",
 "bevy_input_focus",
 "bevy_log",


@@ 1535,14 1386,12 @@ dependencies = [
 "bevy_tasks",
 "bevy_utils",
 "bevy_window",
 "bytemuck",
 "cfg-if",
 "crossbeam-channel",
 "raw-window-handle",
 "tracing",
 "wasm-bindgen",
 "web-sys",
 "wgpu-types",
 "winit",
]



@@ 1741,6 1590,12 @@ dependencies = [
]

[[package]]
name = "cargo-emit"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1582e1c9e755dd6ad6b224dcffb135d199399a4568d454bd89fe515ca8425695"

[[package]]
name = "cc"
version = "1.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1898,16 1753,6 @@ dependencies = [
]

[[package]]
name = "core-foundation"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
dependencies = [
 "core-foundation-sys",
 "libc",
]

[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 1920,7 1765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [
 "bitflags 1.3.2",
 "core-foundation 0.9.4",
 "core-foundation",
 "core-graphics-types",
 "foreign-types",
 "libc",


@@ 1933,115 1778,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
dependencies = [
 "bitflags 1.3.2",
 "core-foundation 0.9.4",
 "core-foundation",
 "libc",
]

[[package]]
name = "coreaudio-rs"
version = "0.11.3"
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
 "bitflags 1.3.2",
 "core-foundation-sys",
 "coreaudio-sys",
 "cfg-if",
]

[[package]]
name = "coreaudio-sys"
version = "0.2.16"
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"

[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
 "bindgen",
 "crossbeam-utils",
]

[[package]]
name = "cosmic-text"
version = "0.13.2"
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e418dd4f5128c3e93eab12246391c54a20c496811131f85754dc8152ee207892"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
 "bitflags 2.9.1",
 "fontdb",
 "log",
 "rangemap",
 "rustc-hash 1.1.0",
 "rustybuzz",
 "self_cell",
 "smol_str",
 "swash",
 "sys-locale",
 "ttf-parser 0.21.1",
 "unicode-bidi",
 "unicode-linebreak",
 "unicode-script",
 "unicode-segmentation",
 "crossbeam-epoch",
 "crossbeam-utils",
]

[[package]]
name = "cpal"
version = "0.15.3"
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779"
dependencies = [
 "alsa",
 "core-foundation-sys",
 "coreaudio-rs",
 "dasp_sample",
 "jni",
 "js-sys",
 "libc",
 "mach2",
 "ndk 0.8.0",
 "ndk-context",
 "oboe",
 "wasm-bindgen",
 "wasm-bindgen-futures",
 "web-sys",
 "windows 0.54.0",
]

[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
 "cfg-if",
]

[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"

[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
 "crossbeam-utils",
]

[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
 "crossbeam-epoch",
 "crossbeam-utils",
]

[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
 "crossbeam-utils",
]


@@ 2073,7 1852,7 @@ version = "3.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
dependencies = [
 "nix 0.30.1",
 "nix",
 "windows-sys 0.59.0",
]



@@ 2084,12 1863,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"

[[package]]
name = "dasp_sample"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"

[[package]]
name = "data-encoding"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2133,17 1906,6 @@ dependencies = [
]

[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "disqualified"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2397,50 2159,12 @@ dependencies = [
]

[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"

[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"

[[package]]
name = "font-types"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7"
dependencies = [
 "bytemuck",
]

[[package]]
name = "fontconfig-parser"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646"
dependencies = [
 "roxmltree",
]

[[package]]
name = "fontdb"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3"
dependencies = [
 "fontconfig-parser",
 "log",
 "memmap2",
 "slotmap",
 "tinyvec",
 "ttf-parser 0.20.0",
]

[[package]]
name = "foreign-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2468,15 2192,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"

[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
 "percent-encoding",
]

[[package]]
name = "futures-channel"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2549,9 2264,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
 "cfg-if",
 "js-sys",
 "libc",
 "r-efi",
 "wasi 0.14.2+wasi-0.2.4",
 "wasm-bindgen",
]

[[package]]


@@ 2565,40 2282,6 @@ dependencies = [
]

[[package]]
name = "gilrs"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb2c998745a3c1ac90f64f4f7b3a54219fd3612d7705e7798212935641ed18f"
dependencies = [
 "fnv",
 "gilrs-core",
 "log",
 "uuid",
 "vec_map",
]

[[package]]
name = "gilrs-core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6d95ae10ce5aa99543a28cf74e41c11f3b9e3c14f0452bbde46024753cd683e"
dependencies = [
 "core-foundation 0.10.0",
 "inotify",
 "io-kit-sys",
 "js-sys",
 "libc",
 "libudev-sys",
 "log",
 "nix 0.29.0",
 "uuid",
 "vec_map",
 "wasm-bindgen",
 "web-sys",
 "windows 0.58.0",
]

[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2617,7 2300,7 @@ checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
dependencies = [
 "bytemuck",
 "libm",
 "rand",
 "rand 0.8.5",
 "serde",
]



@@ 2712,7 2395,7 @@ dependencies = [
 "log",
 "presser",
 "thiserror 1.0.69",
 "windows 0.58.0",
 "windows",
]

[[package]]


@@ 2736,12 2419,6 @@ dependencies = [
]

[[package]]
name = "grid"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36119f3a540b086b4e436bb2b588cf98a68863470e0e880f4d0842f112a3183a"

[[package]]
name = "guillotiere"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2823,122 2500,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"

[[package]]
name = "home"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
 "windows-sys 0.59.0",
]

[[package]]
name = "icu_collections"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
dependencies = [
 "displaydoc",
 "potential_utf",
 "yoke",
 "zerofrom",
 "zerovec",
]

[[package]]
name = "icu_locale_core"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
dependencies = [
 "displaydoc",
 "litemap",
 "tinystr",
 "writeable",
 "zerovec",
]

[[package]]
name = "icu_normalizer"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
dependencies = [
 "displaydoc",
 "icu_collections",
 "icu_normalizer_data",
 "icu_properties",
 "icu_provider",
 "smallvec",
 "zerovec",
]

[[package]]
name = "icu_normalizer_data"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"

[[package]]
name = "icu_properties"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a"
dependencies = [
 "displaydoc",
 "icu_collections",
 "icu_locale_core",
 "icu_properties_data",
 "icu_provider",
 "potential_utf",
 "zerotrie",
 "zerovec",
]

[[package]]
name = "icu_properties_data"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04"

[[package]]
name = "icu_provider"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
dependencies = [
 "displaydoc",
 "icu_locale_core",
 "stable_deref_trait",
 "tinystr",
 "writeable",
 "yoke",
 "zerofrom",
 "zerotrie",
 "zerovec",
]

[[package]]
name = "idna"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
dependencies = [
 "idna_adapter",
 "smallvec",
 "utf8_iter",
]

[[package]]
name = "idna_adapter"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
dependencies = [
 "icu_normalizer",
 "icu_properties",
]

[[package]]
name = "image"
version = "0.25.6"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3004,26 2565,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"

[[package]]
name = "inotify"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
 "bitflags 2.9.1",
 "inotify-sys",
 "libc",
]

[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
 "libc",
]

[[package]]
name = "interpolate_name"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3035,16 2576,6 @@ dependencies = [
]

[[package]]
name = "io-kit-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b"
dependencies = [
 "core-foundation-sys",
 "mach2",
]

[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3164,17 2695,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"

[[package]]
name = "lewton"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
dependencies = [
 "byteorder",
 "ogg",
 "tinyvec",
]

[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3218,28 2738,12 @@ dependencies = [
]

[[package]]
name = "libudev-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
dependencies = [
 "libc",
 "pkg-config",
]

[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"

[[package]]
name = "litemap"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"

[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3271,15 2775,6 @@ dependencies = [
]

[[package]]
name = "mach2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
dependencies = [
 "libc",
]

[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3436,20 2931,6 @@ dependencies = [

[[package]]
name = "ndk"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
dependencies = [
 "bitflags 2.9.1",
 "jni-sys",
 "log",
 "ndk-sys 0.5.0+25.2.9519653",
 "num_enum",
 "thiserror 1.0.69",
]

[[package]]
name = "ndk"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"


@@ 3495,18 2976,6 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"

[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
 "bitflags 2.9.1",
 "cfg-if",
 "cfg_aliases",
 "libc",
]

[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"


@@ 3546,15 3015,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"

[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
 "winapi",
]

[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3925,29 3385,6 @@ dependencies = [
]

[[package]]
name = "oboe"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
dependencies = [
 "jni",
 "ndk 0.8.0",
 "ndk-context",
 "num-derive",
 "num-traits",
 "oboe-sys",
]

[[package]]
name = "oboe-sys"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d"
dependencies = [
 "cc",
]

[[package]]
name = "offset-allocator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3958,15 3395,6 @@ dependencies = [
]

[[package]]
name = "ogg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
dependencies = [
 "byteorder",
]

[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4002,7 3430,7 @@ version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4"
dependencies = [
 "ttf-parser 0.25.1",
 "ttf-parser",
]

[[package]]


@@ 4051,34 3479,6 @@ dependencies = [
 "num-derive",
 "num-traits",
 "ordered-float",
 "rayon",
 "rstar",
 "rustc-hash 2.1.1",
 "simba",
 "slab",
 "smallvec",
 "spade",
 "thiserror 1.0.69",
]

[[package]]
name = "parry3d-f64"
version = "0.17.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4484c8ad93ff03c0e57aa1a4f3ff5406ab6301a1eb838ef6dea90e94f00a6c7"
dependencies = [
 "approx",
 "arrayvec",
 "bitflags 2.9.1",
 "downcast-rs 1.2.1",
 "either",
 "ena",
 "log",
 "nalgebra",
 "num-derive",
 "num-traits",
 "ordered-float",
 "rayon",
 "rstar",
 "rustc-hash 2.1.1",
 "simba",


@@ 4101,18 3501,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"

[[package]]
name = "petgraph"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
dependencies = [
 "fixedbitset",
 "indexmap",
 "serde",
 "serde_derive",
]

[[package]]
name = "pin-project"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4199,15 3587,6 @@ dependencies = [
]

[[package]]
name = "potential_utf"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
dependencies = [
 "zerovec",
]

[[package]]
name = "pp-rs"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4352,8 3731,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
 "libc",
 "rand_chacha",
 "rand_core",
 "rand_chacha 0.3.1",
 "rand_core 0.6.4",
]

[[package]]
name = "rand"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
 "rand_chacha 0.9.0",
 "rand_core 0.9.3",
]

[[package]]


@@ 4363,7 3752,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
 "ppv-lite86",
 "rand_core",
 "rand_core 0.6.4",
]

[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
 "ppv-lite86",
 "rand_core 0.9.3",
]

[[package]]


@@ 4372,7 3771,16 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
 "getrandom 0.2.16",
 "getrandom 0.2.16",
]

[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
 "getrandom 0.3.3",
]

[[package]]


@@ 4382,7 3790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
dependencies = [
 "num-traits",
 "rand",
 "rand 0.8.5",
]

[[package]]


@@ 4392,12 3800,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"

[[package]]
name = "rangemap"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"

[[package]]
name = "rav1e"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4423,8 3825,8 @@ dependencies = [
 "once_cell",
 "paste",
 "profiling",
 "rand",
 "rand_chacha",
 "rand 0.8.5",
 "rand_chacha 0.3.1",
 "simd_helpers",
 "system-deps",
 "thiserror 1.0.69",


@@ 4480,16 3882,6 @@ dependencies = [
]

[[package]]
name = "read-fonts"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ce8e2ca6b24313587a03ca61bb74c384e2a815bd90cf2866cfc9f5fb7a11fa0"
dependencies = [
 "bytemuck",
 "font-types",
]

[[package]]
name = "rectangle-pack"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4576,16 3968,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"

[[package]]
name = "rodio"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1"
dependencies = [
 "cpal",
 "lewton",
]

[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4598,12 3980,6 @@ dependencies = [
]

[[package]]
name = "roxmltree"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"

[[package]]
name = "rstar"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4646,23 4022,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"

[[package]]
name = "rustybuzz"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
dependencies = [
 "bitflags 2.9.1",
 "bytemuck",
 "libm",
 "smallvec",
 "ttf-parser 0.21.1",
 "unicode-bidi-mirroring",
 "unicode-ccc",
 "unicode-properties",
 "unicode-script",
]

[[package]]
name = "ruzstd"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4721,12 4080,6 @@ dependencies = [
]

[[package]]
name = "self_cell"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"

[[package]]
name = "send_wrapper"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4817,16 4170,6 @@ dependencies = [
]

[[package]]
name = "skrifa"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe6666ab11018ab91ff7b03f1a3b9fdbecfb610848436fefa5ce50343d3d913"
dependencies = [
 "bytemuck",
 "read-fonts",
]

[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4967,17 4310,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb"

[[package]]
name = "swash"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dce3f0af95643c855cdc449fbaa17d8c2cd08e0b00a49a6babcbe6e71667f3d"
dependencies = [
 "skrifa",
 "yazi",
 "zeno",
]

[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 4989,39 4321,6 @@ dependencies = [
]

[[package]]
name = "synstructure"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "sys-locale"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4"
dependencies = [
 "libc",
]

[[package]]
name = "sysinfo"
version = "0.34.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4b93974b3d3aeaa036504b8eefd4c039dced109171c1ae973f1dc63b2c7e4b2"
dependencies = [
 "libc",
 "memchr",
 "ntapi",
 "objc2-core-foundation",
 "windows 0.57.0",
]

[[package]]
name = "system-deps"
version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5035,18 4334,6 @@ dependencies = [
]

[[package]]
name = "taffy"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab4f4d046dd956a47a7e1a2947083d7ac3e6aa3cfaaead36173ceaa5ab11878c"
dependencies = [
 "arrayvec",
 "grid",
 "serde",
 "slotmap",
]

[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5148,16 4435,6 @@ dependencies = [
]

[[package]]
name = "tinystr"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
dependencies = [
 "displaydoc",
 "zerovec",
]

[[package]]
name = "tinyvec"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5295,18 4572,6 @@ dependencies = [

[[package]]
name = "ttf-parser"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"

[[package]]
name = "ttf-parser"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"

[[package]]
name = "ttf-parser"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"


@@ 5330,48 4595,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"

[[package]]
name = "unicode-bidi"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"

[[package]]
name = "unicode-bidi-mirroring"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86"

[[package]]
name = "unicode-ccc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"

[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"

[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"

[[package]]
name = "unicode-properties"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"

[[package]]
name = "unicode-script"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"

[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5390,23 4619,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"

[[package]]
name = "url"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
dependencies = [
 "form_urlencoded",
 "idna",
 "percent-encoding",
]

[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"

[[package]]
name = "uuid"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5447,12 4659,6 @@ dependencies = [
]

[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"

[[package]]
name = "version-compare"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5690,23 4896,6 @@ dependencies = [
]

[[package]]
name = "webbrowser"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5df295f8451142f1856b1bd86a606dfe9587d439bc036e319c827700dbd555e"
dependencies = [
 "core-foundation 0.10.0",
 "home",
 "jni",
 "log",
 "ndk-context",
 "objc2 0.6.1",
 "objc2-foundation 0.3.1",
 "url",
 "web-sys",
]

[[package]]
name = "weezl"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 5805,8 4994,8 @@ dependencies = [
 "wasm-bindgen",
 "web-sys",
 "wgpu-types",
 "windows 0.58.0",
 "windows-core 0.58.0",
 "windows",
 "windows-core",
]

[[package]]


@@ 5865,53 5054,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

[[package]]
name = "windows"
version = "0.54.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
dependencies = [
 "windows-core 0.54.0",
 "windows-targets 0.52.6",
]

[[package]]
name = "windows"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [
 "windows-core 0.57.0",
 "windows-targets 0.52.6",
]

[[package]]
name = "windows"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
 "windows-core 0.58.0",
 "windows-targets 0.52.6",
]

[[package]]
name = "windows-core"
version = "0.54.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"
dependencies = [
 "windows-result 0.1.2",
 "windows-targets 0.52.6",
]

[[package]]
name = "windows-core"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [
 "windows-implement 0.57.0",
 "windows-interface 0.57.0",
 "windows-result 0.1.2",
 "windows-core",
 "windows-targets 0.52.6",
]



@@ 5921,26 5068,15 @@ version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
 "windows-implement 0.58.0",
 "windows-interface 0.58.0",
 "windows-result 0.2.0",
 "windows-implement",
 "windows-interface",
 "windows-result",
 "windows-strings",
 "windows-targets 0.52.6",
]

[[package]]
name = "windows-implement"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"


@@ 5952,17 5088,6 @@ dependencies = [

[[package]]
name = "windows-interface"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"


@@ 5974,15 5099,6 @@ dependencies = [

[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
 "windows-targets 0.52.6",
]

[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"


@@ 5996,7 5112,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
 "windows-result 0.2.0",
 "windows-result",
 "windows-targets 0.52.6",
]



@@ 6284,14 5400,14 @@ dependencies = [
 "calloop",
 "cfg_aliases",
 "concurrent-queue",
 "core-foundation 0.9.4",
 "core-foundation",
 "core-graphics",
 "cursor-icon",
 "dpi",
 "js-sys",
 "libc",
 "memmap2",
 "ndk 0.9.0",
 "ndk",
 "objc2 0.5.2",
 "objc2-app-kit 0.2.2",
 "objc2-foundation 0.2.2",


@@ 6340,10 5456,13 @@ dependencies = [
]

[[package]]
name = "writeable"
version = "0.6.1"
name = "wyrand"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
checksum = "15e0359b0b8d9cdef235a1fd4a8c5d02e4c9204e9fac861c14c229a8e803d1a6"
dependencies = [
 "rand_core 0.9.3",
]

[[package]]
name = "x11-dl"


@@ 6409,42 5528,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda"

[[package]]
name = "yazi"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"

[[package]]
name = "yoke"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
dependencies = [
 "serde",
 "stable_deref_trait",
 "yoke-derive",
 "zerofrom",
]

[[package]]
name = "yoke-derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "synstructure",
]

[[package]]
name = "zeno"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"

[[package]]
name = "zerocopy"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 6465,60 5548,6 @@ dependencies = [
]

[[package]]
name = "zerofrom"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
dependencies = [
 "zerofrom-derive",
]

[[package]]
name = "zerofrom-derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "synstructure",
]

[[package]]
name = "zerotrie"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
dependencies = [
 "displaydoc",
 "yoke",
 "zerofrom",
]

[[package]]
name = "zerovec"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
dependencies = [
 "yoke",
 "zerofrom",
 "zerovec-derive",
]

[[package]]
name = "zerovec-derive"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +14 -10
@@ 1,7 1,14 @@
[package]
name = "bevy-dice"
version = "0.1.0"
[workspace]
resolver = "3"
members = ["crates/*"]

[workspace.package]
authors = ["Jonni Liljamo <jonni@liljamo.com>"]
edition = "2024"
homepage = "https://liljamo.dev/bevy-dice"
license = "MIT"
publish = false
repository = "https://git.src.quest/~liljamo/bevy_dice"

[profile.dev]
opt-level = 1


@@ 9,10 16,7 @@ opt-level = 1
[profile.dev.package."*"]
opt-level = 3

[dependencies]
avian3d = { version = "0.3", features = ["debug-plugin"] }
bevy = { version = "0.16", features = ["wayland"] }
bevy_egui = "0.34"

[dev-dependencies]
bevy-inspector-egui = "0.31"
[profile.release]
opt-level = 'z'
lto = true
codegen-units = 1

A LICENSE => LICENSE +7 -0
@@ 0,0 1,7 @@
Copyright 2025 Jonni Liljamo <jonni@liljamo.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

A README.md => README.md +4 -0
@@ 0,0 1,4 @@
# bevy_dice

## Assets used
* https://opengameart.org/content/low-poly-3d-dice

A assets/export/D6.glb => assets/export/D6.glb +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Percent_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d10_Percent_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d12_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d12_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d20_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d20_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d4_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d4_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d6_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d6_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/GIMP Project Files/d8_Numbers.xcf => assets/ext/Dice/Dice UV Maps/GIMP Project Files/d8_Numbers.xcf +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Percent_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d10_Percent_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d12_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d12_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d20_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d20_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d4_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d4_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d6_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d6_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d8_Numbers.png => assets/ext/Dice/Dice UV Maps/UV Maps Numbered/d8_Numbers.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d10.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d10.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d12.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d12.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d20.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d20.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d4.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d4.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d6.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d6.png +0 -0
A assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d8.png => assets/ext/Dice/Dice UV Maps/UV Maps non numbered/d8.png +0 -0
A assets/ext/Dice/Dice.blend => assets/ext/Dice/Dice.blend +0 -0
A assets/ext/Dice/Dice_Textured.blend => assets/ext/Dice/Dice_Textured.blend +0 -0
A assets/ext/Dice/Dice_Textured.blend1 => assets/ext/Dice/Dice_Textured.blend1 +0 -0
A assets/ext/Dice/Dice_Textured.glb => assets/ext/Dice/Dice_Textured.glb +0 -0
A assets/ext/dice.zip => assets/ext/dice.zip +0 -0
A assets/raw/D6.blend => assets/raw/D6.blend +0 -0
A assets/raw/D6.blend1 => assets/raw/D6.blend1 +0 -0
A crates/bevy_dice/Cargo.toml => crates/bevy_dice/Cargo.toml +32 -0
@@ 0,0 1,32 @@
[package]
name = "bevy_dice"
version = "0.1.0"
edition.workspace = true
homepage.workspace = true
license.workspace = true
publish.workspace = true
repository.workspace = true

[features]
default = []
debug = ["bevy/bevy_gizmos"]
wasm = ["bevy_rand/wasm_js"]

[dependencies]
avian3d = { version = "0.3", default-features = false, features = [
  "3d",
  "f32",
  "default-collider",
  "parry-f32",
  "collider-from-mesh",
] }
bevy = { version = "0.16", default-features = false, features = [
  "bevy_asset",
  "bevy_gltf",
  "std",
] }
bevy_rand = { version = "0.11", default-features = false, features = [
  "wyrand",
] }
lazy_static = "1"
rand = "0.9"

A crates/bevy_dice/src/die.rs => crates/bevy_dice/src/die.rs +65 -0
@@ 0,0 1,65 @@
/*
 * Copyright (C) 2025 Jonni Liljamo <jonni@liljamo.com>
 *
 * This file is licensed under MIT, see LICENSE for more information.
 */

use avian3d::prelude::*;
use bevy::prelude::*;

#[derive(Component, Reflect)]
pub struct Die {
    pub rolling: bool,
}

impl Default for Die {
    fn default() -> Self {
        Self { rolling: true }
    }
}

#[derive(Event)]
pub struct DieStopped(Entity);

pub fn die_wait_for_stop(mut commands: Commands, q_dice: Query<(Entity, &Die, &AngularVelocity)>) {
    for (die_entity, die, angular_velocity) in q_dice {
        if die.rolling {
            let angular_velocity_abs = angular_velocity.abs();
            if angular_velocity_abs.x < 0.01
                && angular_velocity_abs.y < 0.01
                && angular_velocity_abs.z < 0.01
            {
                commands.trigger(DieStopped(die_entity));
            }
        }
    }
}

pub fn die_stopped(
    trigger: Trigger<DieStopped>,
    mut q_dice: Query<&mut Die>,
    q_children: Query<&Children>,
    q_faces: Query<&crate::Face>,
    q_global_transforms: Query<&GlobalTransform>,
) {
    if let Ok(mut die) = q_dice.get_mut(trigger.0) {
        die.rolling = false;

        let mut highest = f32::NEG_INFINITY;
        let mut value = 0;

        for face_entity in q_children.iter_descendants(trigger.0) {
            if let Ok(face) = q_faces.get(face_entity) {
                if let Ok(global_transform) = q_global_transforms.get(face_entity) {
                    let y = global_transform.translation().y;
                    if y > highest {
                        highest = y;
                        value = face.value;
                    }
                }
            }
        }

        info!("Rolled {}", value);
    }
}

A crates/bevy_dice/src/face.rs => crates/bevy_dice/src/face.rs +172 -0
@@ 0,0 1,172 @@
/*
 * Copyright (C) 2025 Jonni Liljamo <jonni@liljamo.com>
 *
 * This file is licensed under MIT, see LICENSE for more information.
 */

#[cfg(feature = "debug")]
use bevy::color::palettes::css::*;
use bevy::prelude::*;
use lazy_static::lazy_static;

/// Debug gizmo colours.
#[cfg(feature = "debug")]
const DEBUG_GIZMO_COLOURS: [Srgba; 20] = [
    AQUA,
    BISQUE,
    BLUE,
    BLUE_VIOLET,
    BROWN,
    CHARTREUSE,
    CORAL,
    CRIMSON,
    FUCHSIA,
    GOLDENROD,
    GREEN,
    HOT_PINK,
    INDIGO,
    KHAKI,
    LAVENDER,
    MAGENTA,
    OLIVE,
    ORANGE,
    SALMON,
    THISTLE,
];

/// Component for entities representing a face of a die.
#[derive(Component, Reflect, Clone)]
pub struct Face {
    /// The value of the face.
    pub value: u8,
}

impl Face {
    pub fn new(value: u8) -> Self {
        Self { value }
    }
}

#[cfg(feature = "debug")]
pub fn draw_face_gizmos(
    q_dice: Query<Entity, With<crate::Die>>,
    q_children: Query<&Children>,
    q_faces: Query<&Face>,
    q_global_transforms: Query<&GlobalTransform>,
    mut gizmos: Gizmos,
) {
    for die_entity in &q_dice {
        let mut face_i = 0;
        for face_entity in q_children.iter_descendants(die_entity) {
            if q_faces.get(face_entity).is_ok() {
                if let Ok(global_transform) = q_global_transforms.get(face_entity) {
                    gizmos.sphere(
                        global_transform.to_isometry(),
                        0.25,
                        DEBUG_GIZMO_COLOURS[face_i],
                    );
                    face_i += 1;
                }
            }
        }
    }
}

macro_rules! face_config {
    ($v:expr, $x:expr, $y:expr, $z:expr) => {
        (
            Face::new($v),
            Transform {
                translation: Vec3::new($x, $y, $z),
                ..Default::default()
            },
        )
    };
}

lazy_static! {
    pub static ref D4_FACE_CONFIGS: [(Face, Transform); 4] = [
        face_config!(1, 0.0, 0.6, 0.0),
        face_config!(2, -0.3, -0.2, -0.6),
        face_config!(3, 0.7, -0.2, 0.0),
        face_config!(4, -0.3, -0.2, 0.6),
    ];
    pub static ref D6_FACE_CONFIGS: [(Face, Transform); 6] = [
        face_config!(1, 0.0, 0.0, 0.5),
        face_config!(2, 0.0, 0.5, 0.0),
        face_config!(3, 0.5, 0.0, 0.0),
        face_config!(4, -0.5, 0.0, 0.0),
        face_config!(5, 0.0, -0.5, 0.0),
        face_config!(6, 0.0, 0.0, -0.5),
    ];
    pub static ref D8_FACE_CONFIGS: [(Face, Transform); 8] = [
        face_config!(1, 0.5, 0.5, 0.5),
        face_config!(2, -0.5, -0.5, -0.5),
        face_config!(3, 0.5, -0.5, -0.5),
        face_config!(4, -0.5, 0.5, 0.5),
        face_config!(5, -0.5, 0.5, -0.5),
        face_config!(6, 0.5, -0.5, 0.5),
        face_config!(7, -0.5, -0.5, 0.5),
        face_config!(8, 0.5, 0.5, -0.5),
    ];
    pub static ref D10_FACE_CONFIGS: [(Face, Transform); 10] = [
        face_config!(1, 0.2, 0.3, -0.6),
        face_config!(2, 0.5, -0.3, 0.4),
        face_config!(3, -0.5, 0.3, 0.4),
        face_config!(4, -0.2, -0.3, -0.6),
        face_config!(5, 0.2, 0.3, 0.6),
        face_config!(6, 0.5, -0.3, -0.4),
        face_config!(7, -0.5, 0.3, -0.4),
        face_config!(8, -0.2, -0.3, 0.6),
        face_config!(9, 0.7, 0.3, 0.0),
        face_config!(10, -0.7, -0.3, 0.0),
    ];
    pub static ref D10P_FACE_CONFIGS: [(Face, Transform); 10] = [
        face_config!(10, 0.2, 0.3, -0.6),
        face_config!(20, 0.5, -0.3, 0.4),
        face_config!(30, -0.5, 0.3, 0.4),
        face_config!(40, -0.2, -0.3, -0.6),
        face_config!(50, 0.2, 0.3, 0.6),
        face_config!(60, 0.5, -0.3, -0.4),
        face_config!(70, -0.5, 0.3, -0.4),
        face_config!(80, -0.2, -0.3, 0.6),
        face_config!(90, 0.7, 0.3, 0.0),
        face_config!(100, -0.7, -0.3, 0.0),
    ];
    pub static ref D12_FACE_CONFIGS: [(Face, Transform); 12] = [
        face_config!(1, -0.5, -0.7, 0.0),
        face_config!(2, 0.5, -0.7, 0.0),
        face_config!(3, 0.0, -0.5, 0.7),
        face_config!(4, 0.0, -0.5, -0.7),
        face_config!(5, -0.7, 0.0, 0.4),
        face_config!(6, -0.7, 0.0, -0.4),
        face_config!(7, 0.7, 0.0, 0.4),
        face_config!(8, 0.7, 0.0, -0.4),
        face_config!(9, 0.0, 0.5, 0.7),
        face_config!(10, 0.0, 0.5, -0.7),
        face_config!(11, -0.5, 0.7, 0.0),
        face_config!(12, 0.5, 0.7, 0.0),
    ];
    pub static ref D20_FACE_CONFIGS: [(Face, Transform); 20] = [
        face_config!(1, 0.7, 0.3, 0.0),
        face_config!(2, -0.45, -0.45, 0.45),
        face_config!(3, 0.0, 0.7, -0.3),
        face_config!(4, 0.0, -0.7, -0.3),
        face_config!(5, 0.45, -0.45, 0.45),
        face_config!(6, -0.3, 0.0, -0.7),
        face_config!(7, 0.45, 0.45, 0.45),
        face_config!(8, -0.7, 0.3, 0.0),
        face_config!(9, 0.3, 0.0, -0.7),
        face_config!(10, -0.45, 0.45, 0.45),
        face_config!(11, 0.45, -0.45, -0.45),
        face_config!(12, -0.3, 0.0, 0.7),
        face_config!(13, 0.7, -0.3, 0.0),
        face_config!(14, -0.45, -0.45, -0.45),
        face_config!(15, 0.3, 0.0, 0.7),
        face_config!(16, -0.45, 0.45, -0.45),
        face_config!(17, 0.0, 0.7, 0.3),
        face_config!(18, 0.0, -0.7, 0.3),
        face_config!(19, 0.45, 0.45, -0.45),
        face_config!(20, -0.7, -0.3, 0.0),
    ];
}

A crates/bevy_dice/src/lib.rs => crates/bevy_dice/src/lib.rs +174 -0
@@ 0,0 1,174 @@
/*
 * Copyright (C) 2025 Jonni Liljamo <jonni@liljamo.com>
 *
 * This file is licensed under MIT, see LICENSE for more information.
 */

use std::collections::HashMap;

use avian3d::prelude::*;
use bevy::{gltf::GltfMesh, prelude::*};
use bevy_rand::{global::GlobalEntropy, plugin::EntropyPlugin, prelude::WyRand};
use rand::prelude::Rng;

mod die;
pub use die::Die;
mod face;
pub(crate) use face::Face;

pub struct DicePlugin;

impl Plugin for DicePlugin {
    fn build(&self, app: &mut App) {
        app.register_type::<DicePluginConfig>()
            .register_type::<DieVariant>()
            .register_type::<Die>()
            .register_type::<Face>()
            .add_plugins(EntropyPlugin::<WyRand>::new())
            .add_observer(throw_die)
            .add_observer(die::die_stopped)
            .add_systems(
                Update,
                (
                    die::die_wait_for_stop,
                    #[cfg(feature = "debug")]
                    face::draw_face_gizmos,
                ),
            );
    }
}

#[derive(Resource, Reflect)]
pub struct DicePluginConfig {
    /// Gltf handle to get the meshes from.
    pub gltf_handle: Handle<Gltf>,
    /// Mapping of variants to Gltf mesh names.
    pub variant_mesh_names: HashMap<DieVariant, String>,
    /// Mesh rotation overrides, used to correct the mesh rotation relative to
    /// the face positions.
    pub override_mesh_rotations: HashMap<DieVariant, Vec3>,
    /// Face position overrides, used to completely remap what value is in what
    /// face position.
    ///
    /// Can also be used to just override the values of faces.
    pub override_face_positions: HashMap<DieVariant, HashMap<u8, u8>>,
}

#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DieVariant {
    D4,
    D6,
    D8,
    D10,
    D10P,
    D12,
    D20,
}

impl DieVariant {
    pub const VALUES: [Self; 7] = [
        Self::D4,
        Self::D6,
        Self::D8,
        Self::D10,
        Self::D10P,
        Self::D12,
        Self::D20,
    ];

    fn faces(&self) -> Vec<(Face, Transform)> {
        match self {
            Self::D4 => face::D4_FACE_CONFIGS.to_vec(),
            Self::D6 => face::D6_FACE_CONFIGS.to_vec(),
            Self::D8 => face::D8_FACE_CONFIGS.to_vec(),
            Self::D10 => face::D10_FACE_CONFIGS.to_vec(),
            Self::D10P => face::D10P_FACE_CONFIGS.to_vec(),
            Self::D12 => face::D12_FACE_CONFIGS.to_vec(),
            Self::D20 => face::D20_FACE_CONFIGS.to_vec(),
        }
    }
}

#[derive(Event)]
pub struct ThrowDie {
    /// Die variant.
    pub variant: DieVariant,
    /// Initial angular velocity, random if not set.
    pub angular_velocity: Option<Vec3>,
    /// Initial rotation, random if not set.
    pub rotation: Option<Quat>,
}

fn throw_die(
    trigger: Trigger<ThrowDie>,
    mut commands: Commands,
    mut rng: GlobalEntropy<WyRand>,
    r_gltfs: Res<Assets<Gltf>>,
    r_gltf_meshes: Res<Assets<GltfMesh>>,
    r_meshes: Res<Assets<Mesh>>,
    r_config: Res<DicePluginConfig>,
) {
    let gltf = r_gltfs.get(&r_config.gltf_handle).unwrap();
    let gltf_mesh = r_gltf_meshes
        .get(&gltf.named_meshes[&*r_config.variant_mesh_names[&trigger.variant]])
        .unwrap();
    let mesh = r_meshes.get(&gltf_mesh.primitives[0].mesh).unwrap();

    let angular_velocity = match trigger.angular_velocity {
        Some(v) => AngularVelocity(v),
        None => AngularVelocity(Vec3 {
            x: rng.random_range(0u32..=10u32) as f32,
            y: rng.random_range(0u32..=10u32) as f32,
            z: rng.random_range(0u32..=10u32) as f32,
        }),
    };

    let mesh_rotation = match r_config.override_mesh_rotations.get(&trigger.variant) {
        Some(rotation) => Quat::from_euler(
            EulerRot::XYZ,
            rotation.x.to_radians(),
            rotation.y.to_radians(),
            rotation.z.to_radians(),
        ),
        None => Quat::default(),
    };

    let mut die = commands.spawn((
        Visibility::Inherited,
        // Place the mesh in a child to allow correcting the rotation.
        children![(
            Mesh3d(gltf_mesh.primitives[0].mesh.clone()),
            MeshMaterial3d(gltf_mesh.primitives[0].material.clone().unwrap()),
            Transform {
                rotation: mesh_rotation,
                ..Default::default()
            },
        )],
        Transform {
            translation: Vec3::new(0.0, 4.0, 0.0),
            //rotation: Quat::from_rng(rng.as_mut()),
            ..Default::default()
        },
        RigidBody::Dynamic,
        Collider::convex_hull_from_mesh(mesh).unwrap(),
        angular_velocity,
        Die::default(),
    ));

    die.with_children(|parent| {
        if let Some(overrides) = r_config.override_face_positions.get(&trigger.variant) {
            let defaults = trigger.variant.faces();
            for default in defaults {
                if let Some(new_value) = overrides.get(&default.0.value) {
                    parent.spawn((Face::new(*new_value), default.1));
                } else {
                    parent.spawn(default.clone());
                }
            }
        } else {
            for face in trigger.variant.faces() {
                parent.spawn(face);
            }
        }
    });
}

A crates/bevy_dice_demo/Cargo.toml => crates/bevy_dice_demo/Cargo.toml +32 -0
@@ 0,0 1,32 @@
[package]
name = "bevy_dice_demo"
version = "0.1.0"
edition.workspace = true

[features]
default = ["debug", "wayland"]
debug = ["bevy_dice/debug", "avian3d/debug-plugin", "dep:bevy-inspector-egui"]
wasm = ["bevy/webgl2", "bevy_dice/wasm", "dep:console_error_panic_hook"]
wayland = ["bevy/wayland"]

[dependencies]
bevy_dice = { path = "../bevy_dice" }

avian3d = { version = "0.3", default-features = false }
bevy = { version = "0.16", default-features = false, features = [
  "async_executor",
  "bevy_render",
  "bevy_state",
  "bevy_window",
  "bevy_winit",
  "multi_threaded",
  "png",
  "tonemapping_luts",
] }
bevy_embedded_assets = { version = "0.13", default-features = false }
bevy_egui = { version = "0.34", default-features = false, features = [
  "render",
  "default_fonts",
] }
bevy-inspector-egui = { version = "0.31", optional = true }
console_error_panic_hook = { version = "0.1", optional = true }

A crates/bevy_dice_demo/src/main.rs => crates/bevy_dice_demo/src/main.rs +225 -0
@@ 0,0 1,225 @@
/*
 * Copyright (C) 2025 Jonni Liljamo <jonni@liljamo.com>
 *
 * This file is licensed under MIT, see LICENSE for more information.
 */

use std::{collections::HashMap, f32::consts::PI};

use avian3d::prelude::*;
use bevy::{
    asset::LoadState,
    core_pipeline::bloom::Bloom,
    pbr::{Atmosphere, light_consts::lux::RAW_SUNLIGHT},
    prelude::*,
    render::camera::Exposure,
};
use bevy_dice::{DicePlugin, DicePluginConfig, Die, DieVariant, ThrowDie};
use bevy_egui::{EguiContextPass, EguiContexts, EguiPlugin, egui};
use bevy_embedded_assets::EmbeddedAssetPlugin;
#[cfg(feature = "debug")]
use bevy_inspector_egui::quick::WorldInspectorPlugin;
#[cfg(feature = "wasm")]
extern crate console_error_panic_hook;

fn main() {
    #[cfg(feature = "wasm")]
    std::panic::set_hook(Box::new(console_error_panic_hook::hook));

    let mut app = App::new();
    app.add_plugins(EmbeddedAssetPlugin::default());

    app.add_plugins(DefaultPlugins.set(WindowPlugin {
        primary_window: Some(Window {
            #[cfg(feature = "wasm")]
            canvas: Some("#bevy-dice-demo".into()),
            #[cfg(feature = "wasm")]
            fit_canvas_to_parent: true,
            ..Default::default()
        }),
        ..Default::default()
    }));

    app.add_plugins((
        PhysicsPlugins::default(),
        #[cfg(feature = "debug")]
        PhysicsDebugPlugin::default(),
    ));

    app.add_plugins((
        EguiPlugin {
            enable_multipass_for_primary_context: true,
        },
        #[cfg(feature = "debug")]
        WorldInspectorPlugin::default(),
    ));

    app.add_plugins(DicePlugin);

    app.init_resource::<ExampleAssets>();
    app.init_state::<ExampleState>()
        .add_systems(Startup, load_assets)
        .add_systems(Update, wait_for_assets_to_load)
        .add_systems(OnEnter(ExampleState::Running), setup);

    app.init_resource::<UIState>()
        .add_systems(EguiContextPass, ui);

    app.add_systems(Update, rotate_sun);

    app.add_observer(despawn_dice);

    app.run();
}

#[derive(States, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
enum ExampleState {
    #[default]
    LoadingAssets,
    Running,
}

fn load_assets(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.insert_resource(ExampleAssets {
        dice: asset_server.load("embedded://ext/Dice/Dice_Textured.glb"),
    });
}

fn wait_for_assets_to_load(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    r_assets: Res<ExampleAssets>,
) {
    if let Some(LoadState::Loaded) = asset_server.get_load_state(&r_assets.dice) {
        commands.set_state(ExampleState::Running)
    }
}

fn setup(
    mut commands: Commands,
    mut r_meshes: ResMut<Assets<Mesh>>,
    mut r_materials: ResMut<Assets<StandardMaterial>>,
    r_assets: Res<ExampleAssets>,
) {
    commands.spawn((
        RigidBody::Static,
        Collider::cylinder(4.0, 0.1),
        Mesh3d(r_meshes.add(Cylinder::new(4.0, 0.1))),
        MeshMaterial3d(r_materials.add(Color::WHITE)),
    ));

    commands.spawn((
        DirectionalLight {
            shadows_enabled: true,
            illuminance: RAW_SUNLIGHT,
            ..default()
        },
        Transform::from_xyz(1.0, 3.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));

    commands.spawn((
        Camera3d::default(),
        Camera {
            hdr: true,
            ..Default::default()
        },
        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Dir3::Y),
        Atmosphere::EARTH,
        Exposure::SUNLIGHT,
        Bloom::NATURAL,
    ));

    commands.insert_resource(DicePluginConfig {
        gltf_handle: r_assets.dice.clone(),
        variant_mesh_names: HashMap::from([
            (DieVariant::D4, "d4".into()),
            (DieVariant::D6, "d6".into()),
            (DieVariant::D8, "d8".into()),
            (DieVariant::D10, "d10".into()),
            (DieVariant::D10P, "d10_Percent".into()),
            (DieVariant::D12, "d12".into()),
            (DieVariant::D20, "d20".into()),
        ]),
        override_mesh_rotations: HashMap::from([(DieVariant::D6, Vec3::new(90.0, 90.0, 0.0))]),
        override_face_positions: HashMap::from([(
            DieVariant::D10P,
            HashMap::from([
                (10, 30),
                (20, 40),
                (30, 10),
                (40, 20),
                (50, 70),
                (60, 80),
                (70, 50),
                (80, 60),
                (90, 90),
                (100, 100),
            ]),
        )]),
    });
}

#[derive(Resource, Default)]
struct ExampleAssets {
    dice: Handle<Gltf>,
}

#[derive(Resource)]
struct UIState {
    selected_variant: DieVariant,
}

impl Default for UIState {
    fn default() -> Self {
        Self {
            selected_variant: DieVariant::D6,
        }
    }
}

fn ui(mut commands: Commands, mut contexts: EguiContexts, mut r_ui_state: ResMut<UIState>) {
    egui::Window::new("Demo").show(contexts.ctx_mut(), |ui| {
        egui::ComboBox::from_label("")
            .selected_text(format!("{:?}", r_ui_state.selected_variant))
            .show_ui(ui, |ui| {
                for variant in DieVariant::VALUES {
                    ui.selectable_value(
                        &mut r_ui_state.selected_variant,
                        variant,
                        format!("{:?}", variant),
                    );
                }
            });

        if ui.button("Throw").clicked() {
            commands.trigger(ThrowDie {
                variant: r_ui_state.selected_variant,
                angular_velocity: None,
                rotation: None,
            });
        }

        if ui.button("Despawn Dice").clicked() {
            commands.trigger(DespawnDice);
        }
    });
}

#[derive(Event)]
struct DespawnDice;

fn despawn_dice(
    _trigger: Trigger<DespawnDice>,
    mut commands: Commands,
    q_dice: Query<Entity, With<Die>>,
) {
    for die_entity in q_dice {
        commands.entity(die_entity).despawn();
    }
}

fn rotate_sun(mut q_suns: Query<&mut Transform, With<DirectionalLight>>, r_time: Res<Time>) {
    q_suns
        .iter_mut()
        .for_each(|mut transform| transform.rotate_y(-r_time.delta_secs() * PI / 10.0));
}

D examples/simple.rs => examples/simple.rs +0 -61
@@ 1,61 0,0 @@
use avian3d::prelude::*;
use bevy::prelude::*;
use bevy_egui::EguiPlugin;
use bevy_inspector_egui::quick::WorldInspectorPlugin;

fn main() {
    let mut app = App::new();
    app.add_plugins(DefaultPlugins);

    app.add_plugins((PhysicsPlugins::default(), PhysicsDebugPlugin::default()));

    app.add_plugins((
        EguiPlugin {
            enable_multipass_for_primary_context: true,
        },
        WorldInspectorPlugin::default(),
    ));

    app.add_systems(Startup, setup);

    app.run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // Static physics object with a collision shape
    commands.spawn((
        RigidBody::Static,
        Collider::cylinder(4.0, 0.1),
        Mesh3d(meshes.add(Cylinder::new(4.0, 0.1))),
        MeshMaterial3d(materials.add(Color::WHITE)),
    ));

    // Dynamic physics object with a collision shape and initial angular velocity
    commands.spawn((
        RigidBody::Dynamic,
        Collider::cuboid(1.0, 1.0, 1.0),
        AngularVelocity(Vec3::new(2.5, 3.5, 1.5)),
        Mesh3d(meshes.add(Cuboid::from_length(1.0))),
        MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
        Transform::from_xyz(0.0, 4.0, 0.0),
    ));

    // Light
    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));

    // Camera
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Dir3::Y),
    ));
}

M flake.nix => flake.nix +6 -0
@@ 71,6 71,12 @@
              clang
              pkg-config

              # wasm build
              wasm-bindgen-cli

              # wasm-opt
              binaryen

              # tools
              just
            ]

M justfile => justfile +10 -2
@@ 1,5 1,13 @@
_default:
    just --list

example EXAMPLE="simple":
    cargo run --example {{EXAMPLE}}
demo ARGS="":
    cargo run --bin bevy_dice_demo {{ARGS}}

build-demo-wasm:
    cargo build --release --target wasm32-unknown-unknown --bin bevy_dice_demo --no-default-features --features wasm
    wasm-bindgen --no-typescript --target web \
        --out-dir ./out-demo-wasm/ \
        --out-name "bevy_dice_demo" \
        ./target/wasm32-unknown-unknown/release/bevy_dice_demo.wasm
    wasm-opt -Oz -o out-demo-wasm/bevy_dice_demo_bg.wasm out-demo-wasm/bevy_dice_demo_bg.wasm

M rust-toolchain.toml => rust-toolchain.toml +1 -0
@@ 1,2 1,3 @@
[toolchain]
channel = "1.87"
targets = ["wasm32-unknown-unknown"]

D src/lib.rs => src/lib.rs +0 -14
@@ 1,14 0,0 @@
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}