lazer pointer wao

feat: it works tada

ptr.pet aad23617 5ba89399

verified
+10
.cargo/config.toml
···
+
[alias]
+
run-wasm = ["run", "--release", "--package", "run-wasm", "--"]
+
+
[target.x86_64-pc-windows-msvc]
+
linker = "rust-lld.exe"
+
rustdocflags = ["-Clinker=rust-lld.exe"]
+
rustflags = ["-Ctarget-cpu=haswell"]
+
+
# [target.wasm32-unknown-unknown]
+
# rustflags = ["-Ctarget-feature=+atomics,+bulk-memory,+mutable-globals"]
+2
.gitignore
···
/target
+
/server-build
+
/client-build
+899 -571
Cargo.lock
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
-
"gimli",
+
"gimli 0.31.1",
]
[[package]]
···
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
-
"getrandom",
+
"const-random",
+
"getrandom 0.3.3",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
-
name = "allocator-api2"
-
version = "0.2.21"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
-
-
[[package]]
name = "android-activity"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"log",
"ndk",
"ndk-context",
-
"ndk-sys 0.6.0+11769913",
+
"ndk-sys",
"num_enum",
-
"thiserror",
+
"thiserror 1.0.69",
]
[[package]]
···
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
[[package]]
-
name = "android_system_properties"
-
version = "0.1.5"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-
dependencies = [
-
"libc",
-
]
-
-
[[package]]
name = "annoyance"
version = "0.1.0"
dependencies = [
"ahash",
-
"pixels",
+
"anyhow",
+
"bincode",
+
"console_error_panic_hook",
+
"fastrand",
+
"futures-util",
"quanta",
+
"softbuffer",
"tiny-skia",
"tokio",
-
"winapi",
+
"tokio-tungstenite-wasm",
+
"tokio-websockets",
+
"wasm-bindgen-futures",
"winit",
]
[[package]]
+
name = "anyhow"
+
version = "1.0.99"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
+
+
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[package]]
-
name = "ash"
-
version = "0.37.3+1.3.251"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"
-
dependencies = [
-
"libloading 0.7.4",
-
]
-
-
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
-
name = "bit-set"
-
version = "0.5.3"
+
name = "base64"
+
version = "0.22.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+
[[package]]
+
name = "bincode"
+
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+
checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
dependencies = [
-
"bit-vec",
+
"bincode_derive",
+
"serde",
+
"unty",
]
[[package]]
-
name = "bit-vec"
-
version = "0.6.3"
+
name = "bincode_derive"
+
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+
dependencies = [
+
"virtue",
+
]
[[package]]
name = "bitflags"
···
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
[[package]]
-
name = "block"
-
version = "0.1.6"
+
name = "block-buffer"
+
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+
dependencies = [
+
"generic-array",
+
]
[[package]]
name = "block2"
···
version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
+
dependencies = [
+
"bytemuck_derive",
+
]
+
+
[[package]]
+
name = "bytemuck_derive"
+
version = "1.10.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
[[package]]
name = "bytes"
···
"polling",
"rustix 0.38.44",
"slab",
-
"thiserror",
+
"thiserror 1.0.69",
]
[[package]]
···
]
[[package]]
+
name = "cargo-run-wasm"
+
version = "0.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "fa9c33bbfab116bda01ec67729b988895b34167a1e9cf034343099092421ed43"
+
dependencies = [
+
"devserver_lib",
+
"pico-args",
+
"serde_json",
+
"wasm-bindgen-cli-support",
+
]
+
+
[[package]]
name = "cc"
version = "1.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
name = "cfg_aliases"
-
version = "0.1.1"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
-
-
[[package]]
-
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
-
name = "codespan-reporting"
-
version = "0.11.1"
+
name = "combine"
+
version = "4.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
dependencies = [
-
"termcolor",
-
"unicode-width",
+
"bytes",
+
"memchr",
]
[[package]]
-
name = "com"
-
version = "0.6.0"
+
name = "concurrent-queue"
+
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6"
+
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
-
"com_macros",
+
"crossbeam-utils",
]
[[package]]
-
name = "com_macros"
-
version = "0.6.0"
+
name = "console_error_panic_hook"
+
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5"
+
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
-
"com_macros_support",
-
"proc-macro2",
-
"syn 1.0.109",
+
"cfg-if",
+
"wasm-bindgen",
]
[[package]]
-
name = "com_macros_support"
-
version = "0.6.0"
+
name = "const-random"
+
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c"
+
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
dependencies = [
-
"proc-macro2",
-
"quote",
-
"syn 1.0.109",
+
"const-random-macro",
]
[[package]]
-
name = "combine"
-
version = "4.6.7"
+
name = "const-random-macro"
+
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
-
"bytes",
-
"memchr",
+
"getrandom 0.2.16",
+
"once_cell",
+
"tiny-keccak",
]
[[package]]
-
name = "concurrent-queue"
-
version = "2.5.0"
+
name = "core-foundation"
+
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
-
"crossbeam-utils",
+
"core-foundation-sys",
+
"libc",
]
[[package]]
name = "core-foundation"
-
version = "0.9.4"
+
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
dependencies = [
"core-foundation-sys",
"libc",
···
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [
"bitflags 1.3.2",
-
"core-foundation",
-
"core-graphics-types",
+
"core-foundation 0.9.4",
+
"core-graphics-types 0.1.3",
+
"foreign-types",
+
"libc",
+
]
+
+
[[package]]
+
name = "core-graphics"
+
version = "0.24.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
+
dependencies = [
+
"bitflags 2.9.3",
+
"core-foundation 0.10.1",
+
"core-graphics-types 0.2.0",
"foreign-types",
"libc",
]
···
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
dependencies = [
"bitflags 1.3.2",
-
"core-foundation",
+
"core-foundation 0.9.4",
"libc",
]
[[package]]
+
name = "core-graphics-types"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
+
dependencies = [
+
"bitflags 2.9.3",
+
"core-foundation 0.10.1",
+
"libc",
+
]
+
+
[[package]]
+
name = "cpufeatures"
+
version = "0.2.17"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+
dependencies = [
+
"libc",
+
]
+
+
[[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"
+
dependencies = [
+
"crossbeam-utils",
+
]
+
+
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
+
name = "crunchy"
+
version = "0.2.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
+
+
[[package]]
+
name = "crypto-common"
+
version = "0.1.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+
dependencies = [
+
"generic-array",
+
"typenum",
+
]
+
+
[[package]]
+
name = "ctor-lite"
+
version = "0.1.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b"
+
+
[[package]]
name = "cursor-icon"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
[[package]]
-
name = "d3d12"
-
version = "0.19.0"
+
name = "data-encoding"
+
version = "2.9.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
+
+
[[package]]
+
name = "devserver_lib"
+
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307"
+
checksum = "edf215dbb8cb1409cca7645aaed35f9e39fb0a21855bba1ac48bc0334903bf66"
+
+
[[package]]
+
name = "digest"
+
version = "0.10.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
-
"bitflags 2.9.3",
-
"libloading 0.8.8",
-
"winapi",
+
"block-buffer",
+
"crypto-common",
]
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [
-
"libloading 0.8.8",
+
"libloading",
]
[[package]]
···
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
+
name = "drm"
+
version = "0.12.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1"
+
dependencies = [
+
"bitflags 2.9.3",
+
"bytemuck",
+
"drm-ffi",
+
"drm-fourcc",
+
"rustix 0.38.44",
+
]
+
+
[[package]]
+
name = "drm-ffi"
+
version = "0.8.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53"
+
dependencies = [
+
"drm-sys",
+
"rustix 0.38.44",
+
]
+
+
[[package]]
+
name = "drm-fourcc"
+
version = "2.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4"
+
+
[[package]]
+
name = "drm-sys"
+
version = "0.7.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986"
+
dependencies = [
+
"libc",
+
"linux-raw-sys 0.6.5",
+
]
+
+
[[package]]
+
name = "either"
+
version = "1.15.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "fallible-iterator"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+
[[package]]
+
name = "fastrand"
+
version = "2.3.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
dependencies = [
+
"getrandom 0.2.16",
+
]
+
+
[[package]]
+
name = "fnv"
+
version = "1.0.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+
[[package]]
name = "foreign-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
]
[[package]]
···
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
-
name = "gethostname"
-
version = "0.4.3"
+
name = "futures-channel"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
+
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
-
"libc",
-
"windows-targets 0.48.5",
+
"futures-core",
]
[[package]]
-
name = "getrandom"
-
version = "0.3.3"
+
name = "futures-core"
+
version = "0.3.31"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+
+
[[package]]
+
name = "futures-sink"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
-
dependencies = [
-
"cfg-if",
-
"libc",
-
"r-efi",
-
"wasi 0.14.2+wasi-0.2.4",
-
]
+
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
-
name = "gimli"
-
version = "0.31.1"
+
name = "futures-task"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
-
name = "gl_generator"
-
version = "0.14.0"
+
name = "futures-util"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
+
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
-
"khronos_api",
-
"log",
-
"xml-rs",
+
"futures-core",
+
"futures-sink",
+
"futures-task",
+
"pin-project-lite",
+
"pin-utils",
+
"slab",
]
[[package]]
-
name = "glow"
-
version = "0.13.1"
+
name = "generic-array"
+
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1"
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
-
"js-sys",
-
"slotmap",
-
"wasm-bindgen",
-
"web-sys",
+
"typenum",
+
"version_check",
]
[[package]]
-
name = "glutin_wgl_sys"
-
version = "0.5.0"
+
name = "gethostname"
+
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
+
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
dependencies = [
-
"gl_generator",
+
"libc",
+
"windows-targets 0.48.5",
]
[[package]]
-
name = "gpu-alloc"
-
version = "0.6.0"
+
name = "getrandom"
+
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
+
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
-
"bitflags 2.9.3",
-
"gpu-alloc-types",
+
"cfg-if",
+
"js-sys",
+
"libc",
+
"wasi 0.11.1+wasi-snapshot-preview1",
+
"wasm-bindgen",
]
[[package]]
-
name = "gpu-alloc-types"
-
version = "0.3.0"
+
name = "getrandom"
+
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
+
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
-
"bitflags 2.9.3",
+
"cfg-if",
+
"libc",
+
"r-efi",
+
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
-
name = "gpu-allocator"
-
version = "0.25.0"
+
name = "gimli"
+
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884"
+
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
-
"log",
-
"presser",
-
"thiserror",
-
"winapi",
-
"windows",
+
"fallible-iterator",
+
"indexmap 1.9.3",
+
"stable_deref_trait",
]
[[package]]
-
name = "gpu-descriptor"
-
version = "0.2.4"
+
name = "gimli"
+
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
-
dependencies = [
-
"bitflags 2.9.3",
-
"gpu-descriptor-types",
-
"hashbrown 0.14.5",
-
]
+
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
-
name = "gpu-descriptor-types"
-
version = "0.1.2"
+
name = "hashbrown"
+
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c"
-
dependencies = [
-
"bitflags 2.9.3",
-
]
+
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
···
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
-
"allocator-api2",
+
"serde",
]
[[package]]
···
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
[[package]]
-
name = "hassle-rs"
-
version = "0.11.0"
+
name = "heck"
+
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890"
-
dependencies = [
-
"bitflags 2.9.3",
-
"com",
-
"libc",
-
"libloading 0.8.8",
-
"thiserror",
-
"widestring",
-
"winapi",
-
]
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
···
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
-
name = "hexf-parse"
-
version = "0.2.1"
+
name = "http"
+
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
+
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
+
dependencies = [
+
"bytes",
+
"fnv",
+
"itoa",
+
]
+
+
[[package]]
+
name = "httparse"
+
version = "1.10.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+
[[package]]
+
name = "id-arena"
+
version = "2.2.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
+
dependencies = [
+
"rayon",
+
]
+
+
[[package]]
+
name = "indexmap"
+
version = "1.9.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+
dependencies = [
+
"autocfg",
+
"hashbrown 0.12.3",
+
]
[[package]]
name = "indexmap"
···
dependencies = [
"equivalent",
"hashbrown 0.15.5",
+
"serde",
]
[[package]]
···
"cfg-if",
"libc",
]
+
+
[[package]]
+
name = "itoa"
+
version = "1.0.15"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jni"
···
"combine",
"jni-sys",
"log",
-
"thiserror",
+
"thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
-
"getrandom",
+
"getrandom 0.3.3",
"libc",
]
···
]
[[package]]
-
name = "khronos-egl"
-
version = "6.0.0"
+
name = "leb128"
+
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
-
dependencies = [
-
"libc",
-
"libloading 0.8.8",
-
"pkg-config",
-
]
-
-
[[package]]
-
name = "khronos_api"
-
version = "3.1.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
+
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
-
-
[[package]]
-
name = "libloading"
-
version = "0.7.4"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
-
dependencies = [
-
"cfg-if",
-
"winapi",
-
]
[[package]]
name = "libloading"
···
[[package]]
name = "linux-raw-sys"
-
version = "0.9.4"
+
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
[[package]]
-
name = "lock_api"
-
version = "0.4.13"
+
name = "linux-raw-sys"
+
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
-
dependencies = [
-
"autocfg",
-
"scopeguard",
-
]
+
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "log"
···
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
-
name = "malloc_buf"
-
version = "0.0.6"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-
dependencies = [
-
"libc",
-
]
-
-
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
-
name = "metal"
-
version = "0.27.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
-
dependencies = [
-
"bitflags 2.9.3",
-
"block",
-
"core-graphics-types",
-
"foreign-types",
-
"log",
-
"objc",
-
"paste",
-
]
-
-
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
-
name = "naga"
-
version = "0.19.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843"
-
dependencies = [
-
"bit-set",
-
"bitflags 2.9.3",
-
"codespan-reporting",
-
"hexf-parse",
-
"indexmap",
-
"log",
-
"num-traits",
-
"rustc-hash",
-
"spirv",
-
"termcolor",
-
"thiserror",
-
"unicode-xid",
-
]
-
-
[[package]]
name = "ndk"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"bitflags 2.9.3",
"jni-sys",
"log",
-
"ndk-sys 0.6.0+11769913",
+
"ndk-sys",
"num_enum",
"raw-window-handle",
-
"thiserror",
+
"thiserror 1.0.69",
]
[[package]]
···
[[package]]
name = "ndk-sys"
-
version = "0.5.0+25.2.9519653"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
-
dependencies = [
-
"jni-sys",
-
]
-
-
[[package]]
-
name = "ndk-sys"
version = "0.6.0+11769913"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
···
]
[[package]]
-
name = "num-traits"
-
version = "0.2.19"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-
dependencies = [
-
"autocfg",
-
]
-
-
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"proc-macro-crate",
"proc-macro2",
"quote",
-
"syn 2.0.106",
-
]
-
-
[[package]]
-
name = "objc"
-
version = "0.2.7"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
-
dependencies = [
-
"malloc_buf",
-
"objc_exception",
+
"syn",
]
[[package]]
···
[[package]]
-
name = "objc_exception"
-
version = "0.1.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
-
dependencies = [
-
"cc",
-
]
-
-
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
-
name = "parking_lot"
-
version = "0.12.4"
+
name = "percent-encoding"
+
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
-
dependencies = [
-
"lock_api",
-
"parking_lot_core",
-
]
+
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
-
name = "parking_lot_core"
-
version = "0.9.11"
+
name = "pico-args"
+
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
-
dependencies = [
-
"cfg-if",
-
"libc",
-
"redox_syscall 0.5.17",
-
"smallvec",
-
"windows-targets 0.52.6",
-
]
-
-
[[package]]
-
name = "paste"
-
version = "1.0.15"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-
[[package]]
-
name = "percent-encoding"
-
version = "2.3.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "pin-project"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
[[package]]
···
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
-
name = "pixels"
-
version = "0.15.0"
+
name = "pin-utils"
+
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "518d43cd70c5381d4c7bd4bf47ee344beee99b58b0587adcb198cc713ff0dfb5"
-
dependencies = [
-
"bytemuck",
-
"pollster",
-
"raw-window-handle",
-
"thiserror",
-
"ultraviolet",
-
"wgpu",
-
]
+
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
···
[[package]]
-
name = "pollster"
-
version = "0.3.0"
+
name = "ppv-lite86"
+
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
-
-
[[package]]
-
name = "presser"
-
version = "0.3.1"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
+
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+
dependencies = [
+
"zerocopy",
+
]
[[package]]
name = "proc-macro-crate"
···
dependencies = [
"unicode-ident",
-
-
[[package]]
-
name = "profiling"
-
version = "1.0.17"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
[[package]]
name = "quanta"
···
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
-
name = "range-alloc"
-
version = "0.1.4"
+
name = "rand"
+
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
+
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+
dependencies = [
+
"rand_chacha",
+
"rand_core",
+
]
+
+
[[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",
+
]
+
+
[[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]]
name = "raw-cpuid"
···
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
+
name = "rayon"
+
version = "1.11.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
+
dependencies = [
+
"either",
+
"rayon-core",
+
]
+
+
[[package]]
+
name = "rayon-core"
+
version = "1.13.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
+
dependencies = [
+
"crossbeam-deque",
+
"crossbeam-utils",
+
]
+
+
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
-
name = "renderdoc-sys"
-
version = "1.1.0"
+
name = "ring"
+
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
+
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
+
dependencies = [
+
"cc",
+
"cfg-if",
+
"getrandom 0.2.16",
+
"libc",
+
"untrusted",
+
"windows-sys 0.52.0",
+
]
+
+
[[package]]
+
name = "run-wasm"
+
version = "0.1.0"
+
dependencies = [
+
"cargo-run-wasm",
+
]
[[package]]
name = "rustc-demangle"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
-
-
[[package]]
-
name = "rustc-hash"
-
version = "1.1.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
···
[[package]]
+
name = "rustls"
+
version = "0.23.31"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
+
dependencies = [
+
"once_cell",
+
"rustls-pki-types",
+
"rustls-webpki",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "rustls-pki-types"
+
version = "1.12.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
+
dependencies = [
+
"zeroize",
+
]
+
+
[[package]]
+
name = "rustls-webpki"
+
version = "0.103.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
+
dependencies = [
+
"ring",
+
"rustls-pki-types",
+
"untrusted",
+
]
+
+
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
-
name = "safe_arch"
-
version = "0.7.4"
+
name = "ryu"
+
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
-
dependencies = [
-
"bytemuck",
-
]
+
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "same-file"
···
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
-
name = "scopeguard"
-
version = "1.2.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-
[[package]]
name = "sctk-adwaita"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "semver"
+
version = "1.0.26"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
+
+
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
+
]
+
+
[[package]]
+
name = "serde_json"
+
version = "1.0.143"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
+
dependencies = [
+
"itoa",
+
"memchr",
+
"ryu",
+
"serde",
[[package]]
+
name = "sha1"
+
version = "0.10.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+
dependencies = [
+
"cfg-if",
+
"cpufeatures",
+
"digest",
+
]
+
+
[[package]]
+
name = "sha1_smol"
+
version = "1.0.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
+
+
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
-
name = "signal-hook-registry"
-
version = "1.4.6"
+
name = "simdutf8"
+
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
-
dependencies = [
-
"libc",
-
]
+
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "slab"
···
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]]
-
name = "slotmap"
-
version = "1.0.7"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
-
dependencies = [
-
"version_check",
-
]
-
-
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"log",
"memmap2",
"rustix 0.38.44",
-
"thiserror",
+
"thiserror 1.0.69",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
···
[[package]]
-
name = "spirv"
-
version = "0.3.0+sdk-1.3.268.0"
+
name = "softbuffer"
+
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
+
checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08"
dependencies = [
-
"bitflags 2.9.3",
+
"as-raw-xcb-connection",
+
"bytemuck",
+
"cfg_aliases",
+
"core-graphics 0.24.0",
+
"drm",
+
"fastrand",
+
"foreign-types",
+
"js-sys",
+
"log",
+
"memmap2",
+
"objc2",
+
"objc2-foundation",
+
"objc2-quartz-core",
+
"raw-window-handle",
+
"redox_syscall 0.5.17",
+
"rustix 0.38.44",
+
"tiny-xlib",
+
"wasm-bindgen",
+
"wayland-backend",
+
"wayland-client",
+
"wayland-sys",
+
"web-sys",
+
"windows-sys 0.59.0",
+
"x11rb",
[[package]]
-
name = "static_assertions"
-
version = "1.1.0"
+
name = "stable_deref_trait"
+
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strict-num"
···
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
-
name = "syn"
-
version = "1.0.109"
+
name = "subtle"
+
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-
dependencies = [
-
"proc-macro2",
-
"quote",
-
"unicode-ident",
-
]
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
···
[[package]]
-
name = "termcolor"
-
version = "1.4.1"
+
name = "tempfile"
+
version = "3.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+
checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
dependencies = [
-
"winapi-util",
+
"fastrand",
+
"getrandom 0.3.3",
+
"once_cell",
+
"rustix 1.0.8",
+
"windows-sys 0.60.2",
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
-
"thiserror-impl",
+
"thiserror-impl 1.0.69",
+
]
+
+
[[package]]
+
name = "thiserror"
+
version = "2.0.16"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
+
dependencies = [
+
"thiserror-impl 2.0.16",
[[package]]
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
+
]
+
+
[[package]]
+
name = "thiserror-impl"
+
version = "2.0.16"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
+
+
[[package]]
+
name = "tiny-keccak"
+
version = "2.0.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+
dependencies = [
+
"crunchy",
[[package]]
···
[[package]]
+
name = "tiny-xlib"
+
version = "0.2.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0324504befd01cab6e0c994f34b2ffa257849ee019d3fb3b64fb2c858887d89e"
+
dependencies = [
+
"as-raw-xcb-connection",
+
"ctor-lite",
+
"libloading",
+
"pkg-config",
+
"tracing",
+
]
+
+
[[package]]
name = "tokio"
version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"io-uring",
"libc",
"mio",
-
"parking_lot",
"pin-project-lite",
-
"signal-hook-registry",
"slab",
"socket2",
"tokio-macros",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
+
]
+
+
[[package]]
+
name = "tokio-rustls"
+
version = "0.26.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
+
dependencies = [
+
"rustls",
+
"tokio",
+
]
+
+
[[package]]
+
name = "tokio-tungstenite"
+
version = "0.26.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
+
dependencies = [
+
"futures-util",
+
"log",
+
"rustls",
+
"rustls-pki-types",
+
"tokio",
+
"tokio-rustls",
+
"tungstenite",
+
"webpki-roots 0.26.11",
+
]
+
+
[[package]]
+
name = "tokio-tungstenite-wasm"
+
version = "0.6.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "02567f5f341725fb3e452c1f55dd4e5b0f2a685355c3b10babf0fe8e137d176e"
+
dependencies = [
+
"bytes",
+
"futures-channel",
+
"futures-util",
+
"http",
+
"httparse",
+
"js-sys",
+
"rustls",
+
"thiserror 2.0.16",
+
"tokio",
+
"tokio-tungstenite",
+
"wasm-bindgen",
+
"web-sys",
+
]
+
+
[[package]]
+
name = "tokio-util"
+
version = "0.7.16"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
+
dependencies = [
+
"bytes",
+
"futures-core",
+
"futures-sink",
+
"pin-project-lite",
+
"tokio",
+
]
+
+
[[package]]
+
name = "tokio-websockets"
+
version = "0.12.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5190767f03b86528ab9f4f6a9158072a6d0ef240d9a9591772eb411f315920f4"
+
dependencies = [
+
"base64",
+
"bytes",
+
"futures-core",
+
"futures-sink",
+
"http",
+
"httparse",
+
"sha1_smol",
+
"simdutf8",
+
"tokio",
+
"tokio-util",
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
-
"indexmap",
+
"indexmap 2.11.0",
"toml_datetime",
"winnow",
···
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
-
name = "ultraviolet"
-
version = "0.9.2"
+
name = "tungstenite"
+
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6a28554d13eb5daba527cc1b91b6c341372a0ae45ed277ffb2c6fbc04f319d7e"
+
checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
dependencies = [
-
"wide",
+
"bytes",
+
"data-encoding",
+
"http",
+
"httparse",
+
"log",
+
"rand",
+
"rustls",
+
"rustls-pki-types",
+
"sha1",
+
"thiserror 2.0.16",
+
"utf-8",
[[package]]
+
name = "typenum"
+
version = "1.18.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
+
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
-
name = "unicode-width"
-
version = "0.1.14"
+
name = "untrusted"
+
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
-
name = "unicode-xid"
-
version = "0.2.6"
+
name = "unty"
+
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
+
[[package]]
+
name = "utf-8"
+
version = "0.7.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "version_check"
···
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
+
name = "virtue"
+
version = "0.0.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
+
+
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "walrus"
+
version = "0.23.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6481311b98508f4bc2d0abbfa5d42172e7a54b4b24d8f15e28b0dc650be0c59f"
+
dependencies = [
+
"anyhow",
+
"gimli 0.26.2",
+
"id-arena",
+
"leb128",
+
"log",
+
"rayon",
+
"walrus-macro",
+
"wasm-encoder",
+
"wasmparser",
+
]
+
+
[[package]]
+
name = "walrus-macro"
+
version = "0.22.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "439ad39ff894c43c9649fa724cdde9a6fc50b855d517ef071a93e5df82fe51d3"
+
dependencies = [
+
"heck",
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
+
+
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"log",
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
"wasm-bindgen-shared",
[[package]]
+
name = "wasm-bindgen-cli-support"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "21e1a4a49abe9cd6f762fc65fac2ef5732afeeb66be369d2f71a85b165a533cf"
+
dependencies = [
+
"anyhow",
+
"base64",
+
"log",
+
"rustc-demangle",
+
"serde",
+
"serde_json",
+
"tempfile",
+
"walrus",
+
"wasm-bindgen-externref-xform",
+
"wasm-bindgen-multi-value-xform",
+
"wasm-bindgen-shared",
+
"wasm-bindgen-threads-xform",
+
"wasm-bindgen-wasm-conventions",
+
"wasm-bindgen-wasm-interpreter",
+
]
+
+
[[package]]
+
name = "wasm-bindgen-externref-xform"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "940542c5cdbe96c35f98b5da5c65fb9d18df55a0cb1d81fc5ca4acc4fda4d61c"
+
dependencies = [
+
"anyhow",
+
"walrus",
+
"wasm-bindgen-wasm-conventions",
+
]
+
+
[[package]]
name = "wasm-bindgen-futures"
-
version = "0.4.45"
+
version = "0.4.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b"
+
checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
dependencies = [
"cfg-if",
"js-sys",
+
"once_cell",
"wasm-bindgen",
"web-sys",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
[[package]]
+
name = "wasm-bindgen-multi-value-xform"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "64b5ad2e97adde0c3e4369c38e0dbaee329ad8f6cc2ee8e01d1d0b13bd8b14cf"
+
dependencies = [
+
"anyhow",
+
"walrus",
+
"wasm-bindgen-wasm-conventions",
+
]
+
+
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "wasm-bindgen-threads-xform"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1cbdf2d55a50f7edc9dd9aecae7a3a40e9736fda851bd8816f98a86167c8c277"
+
dependencies = [
+
"anyhow",
+
"walrus",
+
"wasm-bindgen-wasm-conventions",
+
]
+
+
[[package]]
+
name = "wasm-bindgen-wasm-conventions"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b1c24fcaa34d2d84407122cfb1d3f37c3586756cf462be18e049b49245a16c08"
+
dependencies = [
+
"anyhow",
+
"leb128",
+
"log",
+
"walrus",
+
"wasmparser",
+
]
+
+
[[package]]
+
name = "wasm-bindgen-wasm-interpreter"
+
version = "0.2.100"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "33f24921401faadd6944206f9d6837d07bbb5ff766ed51ad34528089f66550e0"
+
dependencies = [
+
"anyhow",
+
"log",
+
"walrus",
+
"wasm-bindgen-wasm-conventions",
+
]
+
+
[[package]]
+
name = "wasm-encoder"
+
version = "0.214.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ff694f02a8d7a50b6922b197ae03883fbf18cdb2ae9fbee7b6148456f5f44041"
+
dependencies = [
+
"leb128",
+
]
+
+
[[package]]
+
name = "wasmparser"
+
version = "0.214.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6"
+
dependencies = [
+
"ahash",
+
"bitflags 2.9.3",
+
"hashbrown 0.14.5",
+
"indexmap 2.11.0",
+
"semver",
+
"serde",
+
]
+
+
[[package]]
name = "wayland-backend"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
name = "web-sys"
-
version = "0.3.72"
+
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
+
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
dependencies = [
"js-sys",
"wasm-bindgen",
···
[[package]]
-
name = "wgpu"
-
version = "0.19.4"
+
name = "webpki-roots"
+
version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01"
+
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
-
"arrayvec",
-
"cfg-if",
-
"cfg_aliases 0.1.1",
-
"js-sys",
-
"log",
-
"naga",
-
"parking_lot",
-
"profiling",
-
"raw-window-handle",
-
"smallvec",
-
"static_assertions",
-
"wasm-bindgen",
-
"wasm-bindgen-futures",
-
"web-sys",
-
"wgpu-core",
-
"wgpu-hal",
-
"wgpu-types",
+
"webpki-roots 1.0.2",
[[package]]
-
name = "wgpu-core"
-
version = "0.19.4"
+
name = "webpki-roots"
+
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a"
+
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
dependencies = [
-
"arrayvec",
-
"bit-vec",
-
"bitflags 2.9.3",
-
"cfg_aliases 0.1.1",
-
"codespan-reporting",
-
"indexmap",
-
"log",
-
"naga",
-
"once_cell",
-
"parking_lot",
-
"profiling",
-
"raw-window-handle",
-
"rustc-hash",
-
"smallvec",
-
"thiserror",
-
"web-sys",
-
"wgpu-hal",
-
"wgpu-types",
+
"rustls-pki-types",
[[package]]
-
name = "wgpu-hal"
-
version = "0.19.5"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bfabcfc55fd86611a855816326b2d54c3b2fd7972c27ce414291562650552703"
-
dependencies = [
-
"android_system_properties",
-
"arrayvec",
-
"ash",
-
"bit-set",
-
"bitflags 2.9.3",
-
"block",
-
"cfg_aliases 0.1.1",
-
"core-graphics-types",
-
"d3d12",
-
"glow",
-
"glutin_wgl_sys",
-
"gpu-alloc",
-
"gpu-allocator",
-
"gpu-descriptor",
-
"hassle-rs",
-
"js-sys",
-
"khronos-egl",
-
"libc",
-
"libloading 0.8.8",
-
"log",
-
"metal",
-
"naga",
-
"ndk-sys 0.5.0+25.2.9519653",
-
"objc",
-
"once_cell",
-
"parking_lot",
-
"profiling",
-
"range-alloc",
-
"raw-window-handle",
-
"renderdoc-sys",
-
"rustc-hash",
-
"smallvec",
-
"thiserror",
-
"wasm-bindgen",
-
"web-sys",
-
"wgpu-types",
-
"winapi",
-
]
-
-
[[package]]
-
name = "wgpu-types"
-
version = "0.19.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805"
-
dependencies = [
-
"bitflags 2.9.3",
-
"js-sys",
-
"web-sys",
-
]
-
-
[[package]]
-
name = "wide"
-
version = "0.7.33"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
-
dependencies = [
-
"bytemuck",
-
"safe_arch",
-
]
-
-
[[package]]
-
name = "widestring"
-
version = "1.2.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
-
-
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-
[[package]]
-
name = "windows"
-
version = "0.52.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
-
dependencies = [
-
"windows-core",
-
"windows-targets 0.52.6",
-
]
-
-
[[package]]
-
name = "windows-core"
-
version = "0.52.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-
dependencies = [
-
"windows-targets 0.52.6",
-
]
[[package]]
name = "windows-link"
···
"block2",
"bytemuck",
"calloop",
-
"cfg_aliases 0.2.1",
+
"cfg_aliases",
"concurrent-queue",
-
"core-foundation",
-
"core-graphics",
+
"core-foundation 0.9.4",
+
"core-graphics 0.23.2",
"cursor-icon",
"dpi",
"js-sys",
···
"as-raw-xcb-connection",
"gethostname",
"libc",
-
"libloading 0.8.8",
+
"libloading",
"once_cell",
"rustix 0.38.44",
"x11rb-protocol",
···
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
[[package]]
-
name = "xml-rs"
-
version = "0.8.27"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
-
-
[[package]]
name = "zerocopy"
version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn 2.0.106",
+
"syn",
+
+
[[package]]
+
name = "zeroize"
+
version = "1.8.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+35 -6
Cargo.toml
···
version = "0.1.0"
edition = "2024"
+
[workspace]
+
members = ["run-wasm"]
+
+
[features]
+
default = []
+
server = [
+
"tokio/net",
+
"futures-util/std",
+
"dep:tokio-websockets",
+
]
+
client = [
+
"dep:tokio-tungstenite-wasm",
+
]
+
[dependencies]
+
anyhow = "1"
winit = "0.30"
-
pixels = "0.15"
-
tokio = { version = "1", features = ["full"] }
-
ahash = "0.8.12"
+
softbuffer = "0.4"
+
ahash = { version = "0.8", default-features = false, features = ["compile-time-rng"] }
tiny-skia = { version = "0.11", default-features = false, features = ["simd", "std"] }
-
quanta = "0.12.6"
+
quanta = "0.12"
+
bincode = "2.0.1"
+
fastrand = "2"
+
futures-util = { version = "0.3.31", default-features = false, features = ["sink"] }
+
tokio = { version = "1", default-features = false, features = ["rt", "sync", "macros"] }
+
tokio-websockets = { optional = true, version = "0.12", default-features = false, features = ["nightly", "server", "sha1_smol"] }
+
tokio-tungstenite-wasm = { optional = true, version = "0.6", default-features = false, features = ["rustls-tls-webpki-roots"] }
-
[target.'cfg(windows)'.dependencies]
-
winapi = "0.3"
+
[target.'cfg(target_arch = "wasm32")'.dependencies]
+
fastrand = { version = "2", features = ["js"] }
+
console_error_panic_hook = "0.1"
+
wasm-bindgen-futures = "0.4"
+
+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "sync"] }
+
ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] }
+
+
[profile.release]
+
debug = true
+7
build.nu
···
+
def main [feat: string, --run (-r)] {
+
let dir = pwd | path join $"($feat)-build"
+
cargo b --release --features $feat --artifact-dir $dir -Z unstable-options
+
if $run {
+
exec ($dir | path join "annoyance.exe")
+
}
+
}
+11
run-wasm/Cargo.toml
···
+
[package]
+
name = "run-wasm"
+
version = "0.1.0"
+
edition = "2024"
+
+
[[bin]]
+
name = "run-wasm"
+
path = "main.rs"
+
+
[dependencies]
+
cargo-run-wasm = "0.4.0"
+14
run-wasm/main.rs
···
+
fn main() {
+
cargo_run_wasm::run_wasm_cli_with_css(
+
"* {
+
margin:0;
+
padding:0;
+
overflow:hidden;
+
}
+
+
canvas {
+
width:100vw!important;
+
height:100vh!important;
+
}",
+
);
+
}
+3 -2
rust-toolchain.toml
···
[toolchain]
-
channel = "stable"
-
components = ["rust-src", "rust-analyzer"]
+
channel = "nightly-2025-08-27"
+
targets = ["x86_64-pc-windows-msvc", "wasm32-unknown-unknown"]
+
components = ["rust-src", "rust-analyzer", "llvm-tools"]
+315 -184
src/main.rs
···
-
use pixels::Pixels;
+
#![feature(if_let_guard)]
+
use quanta::{Clock, Instant};
use std::collections::HashMap;
+
use std::ops::DerefMut;
use std::sync::Arc;
use std::time::Duration;
use tiny_skia::{Color, *};
-
use tokio::sync::mpsc;
-
use winit::dpi::PhysicalSize;
-
use winit::platform::windows::WindowAttributesExtWindows;
+
use tokio::sync::{OnceCell, mpsc};
use winit::{
application::ApplicationHandler,
event::{ElementState, MouseButton, WindowEvent},
event_loop::{ActiveEventLoop, ControlFlow, EventLoop},
-
window::{Window, WindowAttributes, WindowId, WindowLevel},
+
window::{Window, WindowAttributes, WindowId},
};
-
const BASE_MAX_AGE: Duration = Duration::from_millis(500); // Base lifetime for newest points
-
const MIN_AGE: Duration = Duration::from_millis(50); // Minimum lifetime for oldest points
-
const MAX_POINTS_PER_LINE: usize = 1000; // Maximum points to keep per line
-
const FAST_DECAY_THRESHOLD: usize = 50; // Points beyond this count start decaying faster
+
use crate::renderer::{Renderer, skia_rgba_to_bgra_u32};
+
use crate::ws::LaserMessage;
-
#[derive(Debug, Clone)]
-
pub struct LaserMessage {
-
pub x: f32,
-
pub y: f32,
-
pub color: [u8; 3],
-
pub id: u32,
-
}
+
mod renderer;
+
mod utils;
+
mod ws;
+
+
type BoxedError = Box<dyn std::error::Error + 'static>;
+
type AppResult<T> = Result<T, BoxedError>;
+
+
const BASE_MAX_AGE: Duration = Duration::from_millis(200);
+
const MIN_AGE: Duration = Duration::from_millis(50);
+
const FAST_DECAY_THRESHOLD: usize = 30;
+
#[cfg(target_arch = "wasm32")]
+
const TARGET_FPS: u32 = 120;
+
#[cfg(not(target_arch = "wasm32"))]
+
const TARGET_FPS: u32 = 60;
+
const FRAME_TIME_MS: u64 = 1000 / TARGET_FPS as u64; // ~16.67ms
#[derive(Clone)]
struct LaserPoint {
x: f32,
y: f32,
-
color: [u8; 3], // RGB
+
color: [u8; 3],
created_at: Instant,
}
impl LaserPoint {
fn new(msg: LaserMessage, now: Instant) -> Self {
Self {
-
x: msg.x,
-
y: msg.y,
-
color: msg.color,
+
x: msg.x as f32,
+
y: msg.y as f32,
+
color: utils::id_to_color(msg.id),
created_at: now,
}
}
}
+
pub type WindowHandle = Arc<OnceCell<Arc<Window>>>;
+
+
pub struct Graphics {
+
window: Arc<Window>,
+
renderer: Renderer,
+
pixmap: Pixmap,
+
}
+
+
impl Graphics {
+
fn resize(&mut self, width: u32, height: u32) -> AppResult<()> {
+
self.renderer.resize(width, height)?;
+
self.pixmap = Pixmap::new(width, height).unwrap();
+
Ok(())
+
}
+
}
+
pub struct LaserOverlay {
-
window: Option<Arc<Window>>,
-
pixels: Option<Pixels<'static>>,
-
laser_points: HashMap<u32, Vec<LaserPoint>, ahash::RandomState>,
-
rx: mpsc::Receiver<LaserMessage>,
-
tx: mpsc::Sender<LaserMessage>,
-
width: u32,
-
height: u32,
+
gfx: Option<Graphics>,
+
window: WindowHandle,
+
laser_points: HashMap<(u64, u8), Vec<LaserPoint>, ahash::RandomState>,
+
in_chan: (mpsc::Sender<LaserMessage>, mpsc::Receiver<LaserMessage>),
+
out_tx: mpsc::Sender<LaserMessage>,
last_render: Instant,
+
last_cleanup: Instant,
clock: Clock,
-
// Mouse state
+
client_id: u64,
mouse_pressed: bool,
mouse_pos: (f32, f32),
-
current_line_id: u32,
-
next_line_id: u32,
+
current_line_id: u8,
+
next_line_id: u8,
+
needs_redraw: bool,
+
has_any_points: bool,
}
impl LaserOverlay {
-
pub fn new() -> (Self, mpsc::Sender<LaserMessage>) {
-
let (tx, rx) = mpsc::channel(512);
+
pub fn new() -> (
+
mpsc::Sender<LaserMessage>,
+
mpsc::Receiver<LaserMessage>,
+
Self,
+
) {
+
let in_chan = mpsc::channel(1024);
+
let (out_tx, out_rx) = mpsc::channel(512);
+
let clock = Clock::new();
+
let now = clock.now();
+
let this = Self {
-
window: None,
-
pixels: None,
+
gfx: None,
+
window: WindowHandle::default(),
laser_points: Default::default(),
-
rx,
-
tx: tx.clone(),
-
width: 1920,
-
height: 1080,
-
last_render: clock.now(),
+
in_chan,
+
out_tx,
+
last_render: now,
+
last_cleanup: now,
clock,
+
client_id: fastrand::u64(..),
mouse_pressed: false,
mouse_pos: (0.0, 0.0),
current_line_id: 0,
next_line_id: 1,
+
needs_redraw: false,
+
has_any_points: false,
};
-
(this, tx)
+
(this.in_chan.0.clone(), out_rx, this)
}
-
pub fn init_graphics(&mut self, window: Arc<Window>) {
-
let window_size = window.inner_size();
-
self.width = window_size.width;
-
self.height = window_size.height;
+
pub fn window_handle(&self) -> WindowHandle {
+
self.window.clone()
+
}
-
let surface = pixels::SurfaceTexture::new(self.width, self.height, window.clone());
-
let pixels = pixels::PixelsBuilder::new(self.width, self.height, surface)
-
.build()
-
.unwrap();
+
pub fn init_graphics(&mut self, window: Arc<Window>) -> AppResult<()> {
+
#[cfg(target_arch = "wasm32")]
+
let size = {
+
use winit::platform::web::WindowExtWebSys;
+
let canvas = window.canvas().unwrap();
+
let (w, h) = (canvas.client_width(), canvas.client_height());
+
canvas.set_width(w.try_into().unwrap());
+
canvas.set_height(h.try_into().unwrap());
+
winit::dpi::PhysicalSize::new(w as u32, h as u32)
+
};
+
#[cfg(not(target_arch = "wasm32"))]
+
let size = window.inner_size();
-
self.pixels = Some(pixels);
-
self.window = Some(window);
+
let _ = self.window.set(window.clone());
+
self.gfx = Some(Graphics {
+
renderer: Renderer::new(window.clone(), size.width, size.height)?,
+
pixmap: Pixmap::new(size.width, size.height).unwrap(),
+
window,
+
});
+
+
self.needs_redraw = true;
+
+
Ok(())
}
fn handle_mouse_press(&mut self, position: (f32, f32)) {
self.mouse_pressed = true;
self.mouse_pos = position;
self.current_line_id = self.next_line_id;
-
self.next_line_id += 1;
+
self.next_line_id = self.next_line_id.wrapping_add(1);
+
self.needs_redraw = true;
-
// Send initial point
-
let _ = self.tx.try_send(LaserMessage {
-
x: position.0,
-
y: position.1,
-
color: [255, 0, 0], // Red laser
-
id: self.current_line_id,
-
});
+
let msg = LaserMessage {
+
x: position.0 as u32,
+
y: position.1 as u32,
+
id: self.client_id,
+
line_id: self.current_line_id,
+
};
+
let _ = self.in_chan.0.try_send(msg);
+
let _ = self.out_tx.try_send(msg);
}
fn handle_mouse_move(&mut self, position: (f32, f32)) {
if self.mouse_pressed {
-
// Only add point if mouse moved enough to avoid too many points
let dx = position.0 - self.mouse_pos.0;
let dy = position.1 - self.mouse_pos.1;
let distance = (dx * dx + dy * dy).sqrt();
if distance > 3.0 {
-
// Minimum distance threshold
self.mouse_pos = position;
-
let _ = self.tx.try_send(LaserMessage {
-
x: position.0,
-
y: position.1,
-
color: [255, 0, 0], // Red laser
-
id: self.current_line_id,
-
});
+
self.needs_redraw = true;
+
let msg = LaserMessage {
+
x: position.0 as u32,
+
y: position.1 as u32,
+
id: self.client_id,
+
line_id: self.current_line_id,
+
};
+
let _ = self.in_chan.0.try_send(msg);
+
let _ = self.out_tx.try_send(msg);
}
}
}
···
fn calculate_point_max_age(point_index: usize, total_points: usize) -> Duration {
if total_points <= FAST_DECAY_THRESHOLD {
-
// If we have few points, use base aging for all
return BASE_MAX_AGE;
}
-
// Points are ordered oldest first (index 0) to newest last
-
// Older points (lower indices) should have shorter lifespans
-
if point_index < FAST_DECAY_THRESHOLD {
-
// These are the "far away" points that should decay faster
-
// Create a gradient from MIN_AGE (oldest) to BASE_MAX_AGE (at threshold)
let progress = point_index as f32 / FAST_DECAY_THRESHOLD as f32;
let age_range = BASE_MAX_AGE.as_millis() - MIN_AGE.as_millis();
let calculated_age = MIN_AGE.as_millis() + (age_range as f32 * progress) as u128;
Duration::from_millis(calculated_age as u64)
} else {
-
// Recent points get full lifespan
BASE_MAX_AGE
}
}
+
#[inline(always)]
fn ingest_points(&mut self) {
-
let now = self.clock.now();
+
let mut has_any_points = false;
-
// Clean up old points with variable aging
-
for (_, points) in self.laser_points.iter_mut() {
-
let original_len = points.len();
+
let should_cleanup = self.last_cleanup.elapsed().as_millis() >= FRAME_TIME_MS as u128;
-
// Create a new vector with points that should be kept
-
let mut new_points = Vec::with_capacity(points.len());
-
for (index, point) in points.iter().enumerate() {
-
let max_age = Self::calculate_point_max_age(index, original_len);
-
if now.duration_since(point.created_at) < max_age {
-
new_points.push(point.clone());
+
if should_cleanup {
+
self.last_cleanup = self.clock.now();
+
+
for (_, points) in self.laser_points.iter_mut() {
+
let points_len = points.len();
+
if points_len == 0 {
+
continue;
}
-
}
-
*points = new_points;
-
// Also enforce maximum point limit by removing oldest points
-
if points.len() > MAX_POINTS_PER_LINE {
-
let excess = points.len() - MAX_POINTS_PER_LINE;
-
points.drain(0..excess);
+
let mut new_points = Vec::with_capacity(points_len);
+
for (index, point) in points.iter().enumerate() {
+
let max_age = Self::calculate_point_max_age(index, points_len);
+
if point.created_at.elapsed() < max_age {
+
new_points.push(point.clone());
+
}
+
}
+
+
if new_points.len() != points_len {
+
self.needs_redraw = true;
+
}
+
*points = new_points;
+
+
if !points.is_empty() {
+
has_any_points = true;
+
}
}
+
} else {
+
has_any_points = self.laser_points.values().any(|points| !points.is_empty());
}
-
// Remove empty lines
-
self.laser_points.retain(|_, points| !points.is_empty());
-
-
// Add new points
-
while let Ok(msg) = self.rx.try_recv() {
+
while let Ok(msg) = self.in_chan.1.try_recv() {
self.laser_points
-
.entry(msg.id)
+
.entry((msg.id, msg.line_id))
.or_default()
.push(LaserPoint::new(msg, self.clock.now()));
+
has_any_points = true;
}
+
+
self.has_any_points = has_any_points;
}
-
fn draw_tapering_laser_line(pixmap: &mut PixmapMut, points: &[LaserPoint], now: Instant) {
+
#[inline(always)]
+
fn draw_tapering_laser_line(mut pixmap: PixmapMut, points: &[LaserPoint], now: Instant) {
if points.len() < 2 {
return;
}
-
Self::draw_with_multiple_strokes(pixmap, points, now);
-
}
-
-
fn draw_with_multiple_strokes(pixmap: &mut PixmapMut, points: &[LaserPoint], now: Instant) {
let max_width = 8.0;
let min_width = 0.5;
+
let points_len = points.len();
-
// Use chunks to create line segments from consecutive points
-
for (i, chunk) in points.windows(2).enumerate() {
-
let current = &chunk[0];
-
let next = &chunk[1];
+
let data = points
+
.windows(2)
+
.enumerate()
+
.map(|(i, chunk)| {
+
let current = &chunk[0];
+
let next = &chunk[1];
-
// Calculate thickness based on position in line
-
// i=0 (oldest) should be thinnest, i=len-1 (newest) should be thickest
-
let progress = i as f32 / (points.len() - 2) as f32; // -2 because windows(2) has len-1 elements
-
let width = min_width + (max_width - min_width) * progress;
+
let progress = i as f32 / (points_len - 2) as f32;
+
let width = min_width + (max_width - min_width) * progress;
-
// Calculate alpha based on age and position for smoother fading
-
let point_index = i;
-
let max_age = Self::calculate_point_max_age(point_index, points.len());
-
let age = now.duration_since(current.created_at);
-
let age_progress = age.as_millis() as f32 / max_age.as_millis() as f32;
-
let alpha = (255.0 * (1.0 - age_progress.clamp(0.0, 1.0))) as u8;
+
let point_index = i;
+
let max_age = Self::calculate_point_max_age(point_index, points_len);
+
let age = now.duration_since(current.created_at);
+
let age_progress = age.as_millis() as f32 / max_age.as_millis() as f32;
+
let alpha = (255.0 * (1.0 - age_progress.clamp(0.0, 1.0))) as u8;
+
+
let mut pb = PathBuilder::new();
+
pb.move_to(current.x, current.y);
+
pb.line_to(next.x, next.y);
+
+
(pb.finish(), width, next.color, alpha)
+
})
+
.collect::<Vec<_>>();
-
// Create path for this single segment
-
let mut pb = PathBuilder::new();
-
pb.move_to(current.x, current.y);
-
pb.line_to(next.x, next.y);
+
// draw glow first so we can draw the actual line on top
+
// otherwise the glow would cover the line
+
for (path, width, color, alpha) in data.iter().filter(|p| p.1 > 2.0) {
+
let Some(path) = path else {
+
continue;
+
};
-
if let Some(path) = pb.finish() {
-
// Main stroke with calculated alpha
-
let mut paint = Paint::default();
-
paint.set_color_rgba8(
-
next.color[0],
-
next.color[1],
-
next.color[2],
-
alpha.max(10), // Ensure minimum visibility
-
);
-
paint.anti_alias = true;
+
let mut glow_paint = Paint::default();
+
glow_paint.set_color_rgba8(color[0], color[1], color[2], alpha / 5);
+
glow_paint.anti_alias = true;
+
// replace the existing alpha
+
glow_paint.blend_mode = BlendMode::Source;
-
let mut stroke = Stroke::default();
-
stroke.width = width;
-
stroke.line_cap = LineCap::Round;
-
stroke.line_join = LineJoin::Round;
+
let mut glow_stroke = Stroke::default();
+
glow_stroke.width = width * 1.8;
+
glow_stroke.line_cap = LineCap::Round;
+
glow_stroke.line_join = LineJoin::Round;
-
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
-
}
+
pixmap.stroke_path(
+
&path,
+
&glow_paint,
+
&glow_stroke,
+
Transform::identity(),
+
None,
+
);
}
-
}
-
pub fn render(&mut self) {
-
let Some(pixels) = self.pixels.as_mut() else {
-
return;
-
};
+
for (path, width, color, alpha) in data {
+
let Some(path) = path else {
+
continue;
+
};
-
let frame = pixels.frame_mut();
+
let mut paint = Paint::default();
+
paint.set_color_rgba8(color[0], color[1], color[2], alpha.max(10));
+
paint.anti_alias = true;
+
// replace the existing alpha (so it doesn't blend with existing pixels, looks bad)
+
paint.blend_mode = BlendMode::Source;
-
// Create tiny-skia pixmap from the frame buffer
-
if let Some(mut pixmap) = PixmapMut::from_bytes(frame, self.width, self.height) {
-
// Clear to transparent
-
pixmap.fill(Color::TRANSPARENT);
+
let mut stroke = Stroke::default();
+
stroke.width = width;
+
stroke.line_cap = LineCap::Round;
+
stroke.line_join = LineJoin::Round;
-
// Draw all laser lines
-
for points in self.laser_points.values() {
-
Self::draw_tapering_laser_line(&mut pixmap, points, self.clock.now());
-
}
+
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
}
+
}
-
if let Some(window) = self.window.as_ref() {
-
window.pre_present_notify();
+
#[inline(always)]
+
pub fn render(&mut self) -> AppResult<()> {
+
let Some(gfx) = self.gfx.as_mut() else {
+
return Ok(());
+
};
+
+
let mut frame = gfx.renderer.frame_mut()?;
+
+
gfx.pixmap.fill(Color::TRANSPARENT);
+
for points in self.laser_points.values() {
+
Self::draw_tapering_laser_line(gfx.pixmap.as_mut(), points, self.clock.now());
}
+
skia_rgba_to_bgra_u32(gfx.pixmap.data(), frame.deref_mut());
-
// Render to screen
-
if let Err(err) = pixels.render() {
-
eprintln!("Render error: {err}");
-
}
+
gfx.window.pre_present_notify();
+
gfx.renderer.present()?;
self.last_render = self.clock.now();
+
self.needs_redraw = false;
+
+
Ok(())
+
}
+
+
#[inline(always)]
+
pub fn should_render(&self) -> bool {
+
self.has_any_points || self.needs_redraw
}
}
impl ApplicationHandler for LaserOverlay {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
-
let window_attributes = WindowAttributes::default()
-
.with_title("Laser Overlay")
-
.with_transparent(true)
-
.with_decorations(true)
-
.with_skip_taskbar(false)
-
.with_window_level(WindowLevel::AlwaysOnTop)
-
.with_inner_size(PhysicalSize::new(800, 600));
+
let attrs = WindowAttributes::default()
+
.with_title("laser overlay")
+
.with_transparent(true);
-
let window = event_loop.create_window(window_attributes).unwrap();
-
let _ = window.set_cursor_hittest(true);
+
#[cfg(feature = "server")]
+
let attrs = attrs
+
.with_fullscreen(Some(winit::window::Fullscreen::Borderless(None)))
+
.with_window_level(winit::window::WindowLevel::AlwaysOnTop)
+
.with_decorations(false);
-
self.init_graphics(window.into());
+
#[cfg(target_arch = "wasm32")]
+
let attrs = winit::platform::web::WindowAttributesExtWebSys::with_append(attrs, true);
+
+
let window = event_loop.create_window(attrs).unwrap();
+
#[cfg(feature = "server")]
+
let _ = window.set_cursor_hittest(false);
+
+
self.init_graphics(window.into()).unwrap();
+
+
event_loop.set_control_flow(ControlFlow::wait_duration(Duration::from_millis(
+
FRAME_TIME_MS,
+
)));
}
fn window_event(
···
WindowEvent::CursorMoved { position, .. } => {
let pos = (position.x as f32, position.y as f32);
self.handle_mouse_move(pos);
-
// Always update mouse position for when clicking starts
if !self.mouse_pressed {
self.mouse_pos = pos;
}
}
-
WindowEvent::RedrawRequested if self.last_render.elapsed().as_millis() >= 16 => {
+
WindowEvent::Resized(size) if let Some(gfx) = self.gfx.as_mut() => {
+
gfx.resize(size.width, size.height).unwrap();
+
}
+
WindowEvent::RedrawRequested => {
self.ingest_points();
-
self.render();
+
self.render().unwrap();
}
_ => {}
}
+
}
-
// Request redraw if mouse is pressed (for continuous drawing)
-
if self.mouse_pressed {
-
if let Some(window) = self.window.as_ref() {
-
window.request_redraw();
+
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
+
if self.should_render() {
+
if let Some(gfx) = self.gfx.as_ref() {
+
if self.last_render.elapsed().as_millis() >= FRAME_TIME_MS as u128 {
+
gfx.window.request_redraw();
+
}
}
+
event_loop.set_control_flow(ControlFlow::wait_duration(Duration::from_millis(
+
FRAME_TIME_MS,
+
)));
+
} else {
+
event_loop.set_control_flow(ControlFlow::Wait);
}
+
}
+
}
-
match event_loop.control_flow() {
-
ControlFlow::WaitUntil(instant) if instant.elapsed().as_millis() >= 16 => {
-
event_loop.set_control_flow(ControlFlow::wait_duration(Duration::from_millis(16)));
-
}
-
_ => {}
-
}
+
#[allow(unused_mut)]
+
fn run_app(event_loop: EventLoop<()>, mut app: LaserOverlay) -> AppResult<()> {
+
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
+
event_loop.run_app(&mut app)?;
+
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
+
{
+
console_error_panic_hook::set_once();
+
winit::platform::web::EventLoopExtWebSys::spawn_app(event_loop, app);
}
+
Ok(())
}
-
// Example usage
-
pub async fn run_laser_overlay() -> Result<(), Box<dyn std::error::Error>> {
+
fn run() -> AppResult<()> {
let event_loop = EventLoop::new()?;
-
event_loop.set_control_flow(ControlFlow::wait_duration(Duration::from_millis(16)));
+
let (_tx, _rx, app) = LaserOverlay::new();
-
let (mut app, _tx) = LaserOverlay::new();
+
#[cfg(any(feature = "server", feature = "client"))]
+
let window = app.window_handle();
-
event_loop.run_app(&mut app)?;
+
#[cfg(feature = "server")]
+
tokio::spawn({
+
let window = window.clone();
+
let tx = _tx.clone();
+
async move { ws::server::listen(3111, window, tx).await.unwrap() }
+
});
+
#[cfg(feature = "client")]
+
{
+
let client_id = app.client_id;
+
let fut = async move {
+
ws::client::connect("ws://localhost:3111", window, _rx, _tx, client_id)
+
.await
+
.unwrap()
+
};
+
#[cfg(not(target_arch = "wasm32"))]
+
tokio::spawn(fut);
+
#[cfg(target_arch = "wasm32")]
+
wasm_bindgen_futures::spawn_local(fut);
+
}
+
+
run_app(event_loop, app)?;
+
Ok(())
}
+
#[cfg(not(target_arch = "wasm32"))]
#[tokio::main]
-
async fn main() -> Result<(), Box<dyn std::error::Error>> {
-
run_laser_overlay().await
+
async fn main() -> AppResult<()> {
+
run()
+
}
+
+
#[cfg(target_arch = "wasm32")]
+
fn main() -> AppResult<()> {
+
run()
}
+48
src/renderer.rs
···
+
use super::*;
+
use softbuffer::{Buffer, Context, Surface};
+
+
type W = Arc<Window>;
+
+
pub struct Renderer {
+
_ctx: Context<W>,
+
surface: Surface<W, W>,
+
}
+
+
impl Renderer {
+
pub fn new(window: Arc<Window>, width: u32, height: u32) -> AppResult<Self> {
+
let ctx = Context::new(window.clone())?;
+
let surface = Surface::new(&ctx, window)?;
+
let mut this = Self { _ctx: ctx, surface };
+
this.resize(width, height)?;
+
Ok(this)
+
}
+
+
#[inline(always)]
+
pub fn resize(&mut self, width: u32, height: u32) -> AppResult<()> {
+
// println!("resizing to {}x{}", width, height);
+
Ok(self.surface.resize(width.try_into()?, height.try_into()?)?)
+
}
+
+
#[inline(always)]
+
pub fn present(&mut self) -> AppResult<()> {
+
Ok(self.surface.buffer_mut()?.present()?)
+
}
+
+
#[inline(always)]
+
pub fn frame_mut(&mut self) -> AppResult<Buffer<'_, W, W>> {
+
Ok(self.surface.buffer_mut()?)
+
}
+
}
+
+
/// convert tiny-skia RGBA8888 buffer (premultiplied) to BGRA8888 u32 for softbuffer.
+
#[inline(always)]
+
pub fn skia_rgba_to_bgra_u32(rgba: &[u8], out_bgra: &mut [u32]) {
+
debug_assert_eq!(rgba.len() / 4, out_bgra.len());
+
for (dst, src) in out_bgra.iter_mut().zip(rgba.chunks_exact(4)) {
+
let r = src[0] as u32;
+
let g = src[1] as u32;
+
let b = src[2] as u32;
+
let a = src[3] as u32;
+
*dst = (a << 24) | (r << 16) | (g << 8) | (b << 0); // RGBA -> ARGB little-endian == BGRA bytes
+
}
+
}
+42
src/utils.rs
···
+
// id to rgb color
+
pub fn id_to_color(id: u64) -> [u8; 3] {
+
let mut hash = id;
+
+
hash ^= hash >> 16;
+
hash = hash.wrapping_mul(0x85ebca6b);
+
hash ^= hash >> 13;
+
hash = hash.wrapping_mul(0xb00b1355);
+
hash ^= hash >> 16;
+
+
let hue = (hash % 360) as f32;
+
let saturation = 0.7 + ((hash >> 8) % 30) as f32 / 100.0; // 0.7-1.0 for vibrant colors
+
let value = 0.6 + ((hash >> 16) % 40) as f32 / 100.0; // 0.6-1.0 to avoid dark colors
+
+
hsv_to_rgb(hue, saturation, value)
+
}
+
+
fn hsv_to_rgb(h: f32, s: f32, v: f32) -> [u8; 3] {
+
let c = v * s;
+
let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs());
+
let m = v - c;
+
+
let (r_prime, g_prime, b_prime) = if h < 60.0 {
+
(c, x, 0.0)
+
} else if h < 120.0 {
+
(x, c, 0.0)
+
} else if h < 180.0 {
+
(0.0, c, x)
+
} else if h < 240.0 {
+
(0.0, x, c)
+
} else if h < 300.0 {
+
(x, 0.0, c)
+
} else {
+
(c, 0.0, x)
+
};
+
+
[
+
((r_prime + m) * 255.0) as u8,
+
((g_prime + m) * 255.0) as u8,
+
((b_prime + m) * 255.0) as u8,
+
]
+
}
+174
src/ws.rs
···
+
use bincode::{Decode, Encode};
+
+
#[cfg(any(feature = "client", feature = "server"))]
+
const BINCODE_CFG: bincode::config::Configuration = bincode::config::standard();
+
+
#[derive(Debug, Clone, Copy, Encode, Decode)]
+
pub struct LaserMessage {
+
pub x: u32,
+
pub y: u32,
+
pub id: u64,
+
pub line_id: u8,
+
}
+
+
#[cfg(feature = "client")]
+
pub mod client {
+
use futures_util::{SinkExt, StreamExt};
+
use tokio::sync::mpsc;
+
use tokio_tungstenite_wasm::Message;
+
+
use crate::{
+
AppResult, WindowHandle,
+
ws::{BINCODE_CFG, LaserMessage},
+
};
+
+
pub async fn connect(
+
server_url: &str,
+
window: WindowHandle,
+
mut overlay_rx: mpsc::Receiver<LaserMessage>,
+
overlay_tx: mpsc::Sender<LaserMessage>,
+
id: u64,
+
) -> AppResult<()> {
+
let (mut tx, mut rx) = tokio_tungstenite_wasm::connect(server_url).await?.split();
+
let send_task = async move {
+
while let Some(msg) = overlay_rx.recv().await {
+
let Ok(encoded) = bincode::encode_to_vec(&msg, BINCODE_CFG) else {
+
continue;
+
};
+
let _ = tx.send(Message::Binary(encoded.into())).await;
+
}
+
};
+
let receive_task = async move {
+
while let Some(ev) = rx.next().await {
+
match ev {
+
Ok(Message::Binary(payload)) => {
+
let Ok((decoded, _)): Result<(LaserMessage, _), _> =
+
bincode::decode_from_slice(&payload, BINCODE_CFG)
+
else {
+
continue;
+
};
+
// don't send messages from the client we are on
+
if decoded.id == id {
+
continue;
+
}
+
let _ = overlay_tx.send(decoded).await;
+
if let Some(window) = window.get() {
+
window.request_redraw();
+
}
+
}
+
Ok(Message::Close(_)) => {
+
eprintln!("server closed connection");
+
break;
+
}
+
Err(err) => {
+
eprintln!("error receiving message: {}", err);
+
}
+
_ => {}
+
}
+
}
+
};
+
let _ = futures_util::future::join(send_task, receive_task).await;
+
Ok(())
+
}
+
}
+
+
#[cfg(feature = "server")]
+
pub mod server {
+
use std::net::SocketAddr;
+
+
use futures_util::{SinkExt, StreamExt};
+
use tokio::{
+
net::{TcpListener, TcpStream},
+
sync::{broadcast, mpsc},
+
};
+
use tokio_websockets::Message;
+
+
use crate::{
+
AppResult, WindowHandle,
+
ws::{BINCODE_CFG, LaserMessage},
+
};
+
+
pub async fn listen(
+
port: u16,
+
window: WindowHandle,
+
overlay_tx: mpsc::Sender<LaserMessage>,
+
) -> AppResult<impl Future> {
+
let addr = SocketAddr::from(([0, 0, 0, 0], port));
+
let listener = TcpListener::bind(&addr).await?;
+
println!("listening on {}", addr);
+
+
let (tx, mut rx) = broadcast::channel(1024);
+
+
let server_task = tokio::spawn(async move {
+
loop {
+
let conn = match listener.accept().await {
+
Ok((conn, addr)) => {
+
println!("accepted connection from {}", addr);
+
conn
+
}
+
Err(err) => {
+
eprintln!("error accepting connection: {}", err);
+
continue;
+
}
+
};
+
tokio::spawn(handle_server_conn(conn, tx.clone(), tx.subscribe()));
+
}
+
});
+
let overlay_task = tokio::spawn(async move {
+
while let Ok((_, msg)) = rx.recv().await {
+
let _ = overlay_tx.send(msg).await;
+
if let Some(window) = window.get() {
+
window.request_redraw();
+
}
+
}
+
});
+
+
Ok(futures_util::future::join(server_task, overlay_task))
+
}
+
+
async fn handle_server_conn(
+
conn: TcpStream,
+
msg_tx: broadcast::Sender<(u64, LaserMessage)>,
+
mut msg_rx: broadcast::Receiver<(u64, LaserMessage)>,
+
) -> impl Future {
+
let (_, server) = tokio_websockets::ServerBuilder::new()
+
.accept(conn)
+
.await
+
.unwrap();
+
let (mut tx, mut rx) = server.split();
+
+
let id = fastrand::u64(..);
+
+
let send_task = tokio::spawn(async move {
+
while let Some(msg) = rx.next().await {
+
match msg {
+
Ok(msg) => {
+
let payload = msg.into_payload();
+
let Ok((decoded, _)) = bincode::decode_from_slice(&payload, BINCODE_CFG)
+
else {
+
continue;
+
};
+
let _ = msg_tx.send((id, decoded));
+
}
+
Err(err) => {
+
eprintln!("error receiving message: {}", err);
+
}
+
}
+
}
+
});
+
let receive_task = tokio::spawn(async move {
+
while let Ok((msg_id, msg)) = msg_rx.recv().await {
+
// skip if message is from self
+
if msg_id == id {
+
continue;
+
}
+
let Ok(encoded) = bincode::encode_to_vec(&msg, BINCODE_CFG) else {
+
continue;
+
};
+
let _ = tx.send(Message::binary(encoded)).await;
+
}
+
});
+
+
futures_util::future::join(send_task, receive_task)
+
}
+
}