diff options
| author | LLLL Colonq <llll@colonq> | 2026-04-26 22:56:52 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2026-04-26 22:59:25 -0400 |
| commit | d943ba194b3cfab18354e96f7be2c1e434d6c073 (patch) | |
| tree | 786b7c92f3d9abc6a147a59e440982306fc77f55 | |
| parent | 4a22d2573cd4014c3cc0ed784dd2e9d6bed7fb67 (diff) | |
Update
37 files changed, 1675 insertions, 584 deletions
@@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.12", "once_cell", "version_check", "zerocopy", @@ -47,15 +47,6 @@ dependencies = [ ] [[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - -[[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -161,12 +152,6 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" - -[[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -176,23 +161,6 @@ dependencies = [ ] [[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "arrayref" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -223,29 +191,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "av1-grain" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" -dependencies = [ - "arrayvec", -] - -[[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -292,7 +237,7 @@ dependencies = [ "bitflags 2.8.0", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools", "proc-macro2", "quote", "regex", @@ -324,12 +269,27 @@ name = "bitflags" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] [[package]] -name = "bitstream-io" -version = "2.6.0" +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] [[package]] name = "block-sys" @@ -351,12 +311,6 @@ dependencies = [ ] [[package]] -name = "built" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" - -[[package]] name = "bumpalo" version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -367,20 +321,6 @@ name = "bytemuck" version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "byteorder" @@ -409,7 +349,7 @@ dependencies = [ "bitflags 2.8.0", "log", "polling", - "rustix", + "rustix 0.38.44", "slab", "thiserror 1.0.69", ] @@ -421,7 +361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" dependencies = [ "calloop", - "rustix", + "rustix 0.38.44", "wayland-backend", "wayland-client", ] @@ -453,16 +393,6 @@ dependencies = [ ] [[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - -[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -564,6 +494,12 @@ dependencies = [ ] [[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -588,7 +524,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-graphics-types", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -624,29 +560,6 @@ dependencies = [ ] [[package]] -name = "cosmic-text" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da46a9d5a8905cc538a4a5bceb6a4510de7a51049c5588c0114efce102bcbbe8" -dependencies = [ - "bitflags 2.8.0", - "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", -] - -[[package]] name = "cpal" version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -670,6 +583,24 @@ dependencies = [ ] [[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] name = "crc32fast" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -741,6 +672,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + +[[package]] name = "cursor-icon" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -756,6 +706,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] name = "device_query" version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -770,6 +726,27 @@ dependencies = [ ] [[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "const-oid", + "crypto-common 0.2.1", +] + +[[package]] name = "directories" version = "6.0.0" source = "git+https://github.com/lcolonq/directories-rs#164536daab2c07265167715934081cb1942387b0" @@ -786,7 +763,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -852,6 +829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" dependencies = [ "enum-map-derive", + "serde", ] [[package]] @@ -889,26 +867,6 @@ dependencies = [ ] [[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -956,6 +914,12 @@ dependencies = [ ] [[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] name = "fdeflate" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -981,25 +945,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] -name = "font-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fontdb" -version = "0.16.2" +name = "foreign-types" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "log", - "memmap2", - "slotmap", - "tinyvec", - "ttf-parser 0.20.0", + "foreign-types-shared 0.1.1", ] [[package]] @@ -1009,7 +960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -1025,6 +976,12 @@ dependencies = [ [[package]] name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "foreign-types-shared" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" @@ -1039,6 +996,16 @@ dependencies = [ ] [[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] name = "gethostname" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1050,9 +1017,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -1095,7 +1062,7 @@ dependencies = [ [[package]] name = "glfw" version = "0.59.0" -source = "git+https://github.com/lcolonq/glfw-rs#1ce13a2bcf3ef3bf6184bcb4c2a90d9034956841" +source = "git+https://github.com/lcolonq/glfw-rs#e7904991ea1ef6d34501d9d31c2d6f27b3ca957e" dependencies = [ "bitflags 1.3.2", "objc2 0.5.2", @@ -1130,7 +1097,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "gltf-json", - "image", + "image 0.25.10", "lazy_static", "serde_json", "urlencoding", @@ -1206,9 +1173,25 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "humantime" @@ -1217,6 +1200,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + +[[package]] name = "icrate" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1368,44 +1360,38 @@ dependencies = [ [[package]] name = "image" -version = "0.25.5" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", - "byteorder-lite", + "byteorder", "color_quant", "exr", "gif", - "image-webp", + "jpeg-decoder", "num-traits", - "png", + "png 0.17.16", "qoi", - "ravif", - "rayon", - "rgb", "tiff", - "zune-core", - "zune-jpeg", ] [[package]] -name = "image-webp" -version = "0.2.4" +name = "image" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ + "bytemuck", "byteorder-lite", - "quick-error", + "moxcms", + "num-traits", + "png 0.18.1", + "zune-core", + "zune-jpeg", ] [[package]] -name = "imgref" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" - -[[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1428,17 +1414,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" [[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1446,15 +1421,6 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" @@ -1589,16 +1555,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] -name = "libfuzzer-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] name = "libloading" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1632,6 +1588,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] name = "litemap" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1644,15 +1606,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - -[[package]] name = "mach2" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1682,16 +1635,6 @@ dependencies = [ ] [[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - -[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1729,6 +1672,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] name = "mutate_once" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1763,6 +1716,23 @@ dependencies = [ ] [[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] name = "ndk" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1793,12 +1763,6 @@ dependencies = [ ] [[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] name = "newton_client" version = "0.1.0" dependencies = [ @@ -1806,6 +1770,7 @@ dependencies = [ "bitflags 2.8.0", "clap", "env_logger", + "getrandom 0.2.12", "glam", "glow", "lazy_static", @@ -1846,18 +1811,22 @@ dependencies = [ "clap", "cpal", "device_query", + "enum-map", "env_logger", "glam", + "glfw", "glow", - "image", + "image 0.24.9", "lazy_static", "lexpr", + "libc", "log", "newton_shader", - "png", + "png 0.17.16", "polling", "rand", "redis", + "sha2", "strum", "teleia", "termion", @@ -1886,6 +1855,21 @@ dependencies = [ ] [[package]] +name = "newton_video_player" +version = "0.1.0" +dependencies = [ + "bitflags 2.8.0", + "env_logger", + "glam", + "glow", + "lazy_static", + "log", + "rand", + "teleia", + "uuid", +] + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1896,12 +1880,6 @@ dependencies = [ ] [[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] name = "num-bigint" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2056,6 +2034,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2085,7 +2107,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]] @@ -2152,18 +2174,30 @@ dependencies = [ ] [[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.8.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] name = "polling" -version = "3.7.4" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", + "rustix 1.0.8", + "windows-sys 0.61.2", ] [[package]] @@ -2213,6 +2247,12 @@ dependencies = [ ] [[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] name = "qoi" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2222,12 +2262,6 @@ dependencies = [ ] [[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] name = "quick-xml" version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2272,16 +2306,10 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.12", ] [[package]] -name = "rangemap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbbbbea733ec66275512d0b9694f34102e7d5406fdbe2ad8d21b28dce92887c" - -[[package]] name = "rapier3d" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2306,56 +2334,6 @@ dependencies = [ ] [[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.12.1", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "system-deps", - "thiserror 1.0.69", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2388,16 +2366,6 @@ dependencies = [ ] [[package]] -name = "read-fonts" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] name = "readkey" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2455,7 +2423,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.12", "libredox", "thiserror 2.0.11", ] @@ -2490,12 +2458,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] -name = "rgb" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" - -[[package]] name = "ringbuf" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2542,34 +2504,30 @@ dependencies = [ "bitflags 2.8.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] [[package]] -name = "rustversion" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" - -[[package]] -name = "rustybuzz" -version = "0.14.1" +name = "rustix" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.8.0", - "bytemuck", - "libm", - "smallvec", - "ttf-parser 0.21.1", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", ] [[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2594,6 +2552,15 @@ dependencies = [ ] [[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2613,10 +2580,27 @@ dependencies = [ ] [[package]] -name = "self_cell" -version = "1.2.1" +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.8.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] name = "send_wrapper" @@ -2626,18 +2610,28 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -2657,12 +2651,14 @@ dependencies = [ ] [[package]] -name = "serde_spanned" -version = "0.6.9" +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "serde", + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", ] [[package]] @@ -2672,6 +2668,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.2", +] + +[[package]] name = "sharded-slab" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2706,15 +2713,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - -[[package]] name = "simple-eyre" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2725,16 +2723,6 @@ dependencies = [ ] [[package]] -name = "skrifa" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c31071dedf532758ecf3fed987cdb4bd9509f900e026ab684b4ecb81ea49841" -dependencies = [ - "bytemuck", - "read-fonts", -] - -[[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2771,7 +2759,7 @@ dependencies = [ "libc", "log", "memmap2", - "rustix", + "rustix 0.38.44", "thiserror 1.0.69", "wayland-backend", "wayland-client", @@ -2855,17 +2843,6 @@ dependencies = [ ] [[package]] -name = "swash" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47846491253e976bdd07d0f9cc24b7daf24720d11309302ccbbc6e6b6e53550a" -dependencies = [ - "skrifa", - "yazi", - "zeno", -] - -[[package]] name = "symphonia" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2983,34 +2960,6 @@ dependencies = [ ] [[package]] -name = "sys-locale" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" -dependencies = [ - "libc", -] - -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] name = "teleia" version = "0.1.0" dependencies = [ @@ -3022,16 +2971,15 @@ dependencies = [ "bytes", "console_error_panic_hook", "console_log", - "cosmic-text", "directories", "enum-map", "env_logger", - "getrandom 0.2.15", + "getrandom 0.2.12", "glam", "glfw", "glow", "gltf", - "image", + "image 0.25.10", "js-sys", "kira", "log", @@ -3046,6 +2994,7 @@ dependencies = [ "strum", "tobj", "tracing-wasm", + "tungstenite", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3053,6 +3002,19 @@ dependencies = [ ] [[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.1", + "once_cell", + "rustix 1.0.8", + "windows-sys 0.61.2", +] + +[[package]] name = "termion" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3161,21 +3123,6 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] name = "tobj" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3185,25 +3132,10 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -3212,8 +3144,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] @@ -3282,21 +3212,28 @@ 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" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] -name = "ttf-parser" -version = "0.25.1" +name = "tungstenite" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand", + "sha1", + "thiserror 1.0.69", + "utf-8", +] [[package]] name = "typenum" @@ -3305,48 +3242,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.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" - -[[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" @@ -3376,6 +3277,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] name = "utf16_iter" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3405,21 +3312,10 @@ dependencies = [ ] [[package]] -name = "v_frame" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - -[[package]] -name = "version-compare" -version = "0.2.0" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" @@ -3537,7 +3433,7 @@ checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 0.38.44", "scoped-tls", "smallvec", "wayland-sys", @@ -3550,7 +3446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" dependencies = [ "bitflags 2.8.0", - "rustix", + "rustix 0.38.44", "wayland-backend", "wayland-scanner", ] @@ -3572,7 +3468,7 @@ version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" dependencies = [ - "rustix", + "rustix 0.38.44", "wayland-client", "xcursor", ] @@ -3649,7 +3545,7 @@ dependencies = [ "jpeg-decoder", "jpeg-encoder", "kamadak-exif", - "png", + "png 0.17.16", "thiserror 1.0.69", ] @@ -3750,6 +3646,12 @@ dependencies = [ ] [[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] name = "windows-result" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3795,6 +3697,15 @@ dependencies = [ ] [[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] name = "windows-targets" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4001,7 +3912,7 @@ dependencies = [ "percent-encoding", "raw-window-handle", "redox_syscall 0.3.5", - "rustix", + "rustix 0.38.44", "sctk-adwaita", "serde", "smithay-client-toolkit", @@ -4083,7 +3994,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix", + "rustix 0.38.44", "x11rb-protocol", ] @@ -4119,12 +4030,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] -name = "yazi" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" - -[[package]] name = "yoke" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4149,12 +4054,6 @@ dependencies = [ ] [[package]] -name = "zeno" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" - -[[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4220,9 +4119,9 @@ dependencies = [ [[package]] name = "zune-core" -version = "0.4.12" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-inflate" @@ -4235,9 +4134,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ "zune-core", ] diff --git a/Makefile b/Makefile deleted file mode 100644 index 3cddfcd..0000000 --- a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -CARGO_OPTS = --config 'patch."https://github.com/lcolonq/teleia".teleia.path="../teleia/crates/teleia"' - -.PHONY: build - -build: - @mkdir -p .tmp/ - @cp Cargo.lock .tmp/Cargo.lock - @cargo build $(CARGO_OPTS) - @cp .tmp/Cargo.lock Cargo.lock diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index 8c98cd4..3f197e9 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -31,4 +31,4 @@ png = { workspace = true } cpal = { workspace = true } redis = { workspace = true } web-image-meta = { workspace = true } -uuid = { workspace = true }
\ No newline at end of file +uuid = { workspace = true } diff --git a/crates/renderer/src/assets.rs b/crates/renderer/src/assets.rs index bfcaa0d..4eb681a 100644 --- a/crates/renderer/src/assets.rs +++ b/crates/renderer/src/assets.rs @@ -3,6 +3,8 @@ use teleia::*; pub struct Assets { pub font: font::Bitmap, pub shader_flat: shader::Shader, + pub shader_flat_noflip: shader::Shader, + pub shader_acs: shader::Shader, pub shader_scene: shader::Shader, pub shader_color: shader::Shader, pub shader_tcg: shader::Shader, @@ -13,17 +15,28 @@ pub struct Assets { pub texture_mod: texture::Texture, pub texture_operatop: texture::Texture, pub texture_operabottom: texture::Texture, + pub texture_clippyborder: texture::Texture, } impl Assets { pub fn new(ctx: &context::Context) -> Self { Self { - font: font::Bitmap::new(ctx), + font: font::Bitmap::default(ctx), shader_flat: shader::Shader::new( ctx, include_str!("assets/shaders/flat/vert.glsl"), include_str!("assets/shaders/flat/frag.glsl"), ), + shader_flat_noflip: shader::Shader::new( + ctx, + include_str!("assets/shaders/flat_noflip/vert.glsl"), + include_str!("assets/shaders/flat_noflip/frag.glsl"), + ), + shader_acs: shader::Shader::new( + ctx, + include_str!("assets/shaders/acs/vert.glsl"), + include_str!("assets/shaders/acs/frag.glsl"), + ), shader_scene: shader::Shader::new( ctx, include_str!("assets/shaders/scene/vert.glsl"), @@ -58,6 +71,7 @@ impl Assets { texture_mod: texture::Texture::new(ctx, include_bytes!("assets/textures/mod.png")), texture_operatop: texture::Texture::new(ctx, include_bytes!("assets/textures/operatop.png")), texture_operabottom: texture::Texture::new(ctx, include_bytes!("assets/textures/operabottom.png")), + texture_clippyborder: texture::Texture::new(ctx, include_bytes!("assets/textures/clippyborder.png")), } } } diff --git a/crates/renderer/src/assets/acs/bonzi.acs b/crates/renderer/src/assets/acs/bonzi.acs Binary files differnew file mode 100644 index 0000000..b463dc8 --- /dev/null +++ b/crates/renderer/src/assets/acs/bonzi.acs diff --git a/crates/renderer/src/assets/acs/clippy.acs b/crates/renderer/src/assets/acs/clippy.acs Binary files differnew file mode 100644 index 0000000..0dbc388 --- /dev/null +++ b/crates/renderer/src/assets/acs/clippy.acs diff --git a/crates/renderer/src/assets/acs/pikachu.acs b/crates/renderer/src/assets/acs/pikachu.acs Binary files differnew file mode 100644 index 0000000..4e7615d --- /dev/null +++ b/crates/renderer/src/assets/acs/pikachu.acs diff --git a/crates/renderer/src/assets/shaders/acs/frag.glsl b/crates/renderer/src/assets/shaders/acs/frag.glsl new file mode 100644 index 0000000..8fba8bf --- /dev/null +++ b/crates/renderer/src/assets/shaders/acs/frag.glsl @@ -0,0 +1,8 @@ +uniform sampler2D texture_data; + +void main() +{ + vec2 tcfull = vec2(vertex_texcoord.x, vertex_texcoord.y); + vec4 texel = texture(texture_data, tcfull); + frag_color = texel; +} diff --git a/crates/renderer/src/assets/shaders/acs/vert.glsl b/crates/renderer/src/assets/shaders/acs/vert.glsl new file mode 100644 index 0000000..e324f7e --- /dev/null +++ b/crates/renderer/src/assets/shaders/acs/vert.glsl @@ -0,0 +1,4 @@ +void main() +{ + default_main(); +}
\ No newline at end of file diff --git a/crates/renderer/src/assets/shaders/flat_noflip/frag.glsl b/crates/renderer/src/assets/shaders/flat_noflip/frag.glsl new file mode 100644 index 0000000..e20995c --- /dev/null +++ b/crates/renderer/src/assets/shaders/flat_noflip/frag.glsl @@ -0,0 +1,7 @@ +uniform sampler2D texture_data; + +void main() +{ + vec4 texel = texture(texture_data, vertex_texcoord); + frag_color = texel; +} diff --git a/crates/renderer/src/assets/shaders/flat_noflip/vert.glsl b/crates/renderer/src/assets/shaders/flat_noflip/vert.glsl new file mode 100644 index 0000000..e324f7e --- /dev/null +++ b/crates/renderer/src/assets/shaders/flat_noflip/vert.glsl @@ -0,0 +1,4 @@ +void main() +{ + default_main(); +}
\ No newline at end of file diff --git a/crates/renderer/src/assets/textures/clippyborder.png b/crates/renderer/src/assets/textures/clippyborder.png Binary files differnew file mode 100644 index 0000000..3bb3089 --- /dev/null +++ b/crates/renderer/src/assets/textures/clippyborder.png diff --git a/crates/renderer/src/assets/textures/combo/a.webp b/crates/renderer/src/assets/textures/combo/a.webp Binary files differnew file mode 100644 index 0000000..15d4042 --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/a.webp diff --git a/crates/renderer/src/assets/textures/combo/b.webp b/crates/renderer/src/assets/textures/combo/b.webp Binary files differnew file mode 100644 index 0000000..3eec6b1 --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/b.webp diff --git a/crates/renderer/src/assets/textures/combo/c.webp b/crates/renderer/src/assets/textures/combo/c.webp Binary files differnew file mode 100644 index 0000000..1babbdf --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/c.webp diff --git a/crates/renderer/src/assets/textures/combo/d.webp b/crates/renderer/src/assets/textures/combo/d.webp Binary files differnew file mode 100644 index 0000000..1d08e9c --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/d.webp diff --git a/crates/renderer/src/assets/textures/combo/s.webp b/crates/renderer/src/assets/textures/combo/s.webp Binary files differnew file mode 100644 index 0000000..faec75a --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/s.webp diff --git a/crates/renderer/src/assets/textures/combo/ss.webp b/crates/renderer/src/assets/textures/combo/ss.webp Binary files differnew file mode 100644 index 0000000..62fec55 --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/ss.webp diff --git a/crates/renderer/src/assets/textures/combo/sss.webp b/crates/renderer/src/assets/textures/combo/sss.webp Binary files differnew file mode 100644 index 0000000..f1ecb80 --- /dev/null +++ b/crates/renderer/src/assets/textures/combo/sss.webp diff --git a/crates/renderer/src/ffi/egl.rs b/crates/renderer/src/ffi/egl.rs new file mode 100644 index 0000000..33a39d4 --- /dev/null +++ b/crates/renderer/src/ffi/egl.rs @@ -0,0 +1,41 @@ +// from <EGL/egl.h> +pub const EGL_NONE: EGLenum = 0x3038; +pub const EGL_WIDTH: EGLenum = 0x3057; +pub const EGL_HEIGHT: EGLenum = 0x3056; + +// from <EGL/eglext.h> +pub const EGL_LINUX_DMA_BUF_EXT: EGLenum = 0x3270; +pub const EGL_LINUX_DRM_FOURCC_EXT: EGLenum = 0x3271; +pub const EGL_DMA_BUF_PLANE0_FD_EXT: EGLenum = 0x3272; +pub const EGL_DMA_BUF_PLANE0_OFFSET_EXT: EGLenum = 0x3273; +pub const EGL_DMA_BUF_PLANE0_PITCH_EXT: EGLenum = 0x3274; + +#[repr(C)] +pub struct EGLDisplayTarget(()); +pub type EGLDisplay = *mut EGLDisplayTarget; + +#[repr(C)] +pub struct EGLContextTarget(()); +pub type EGLContext = *mut EGLContextTarget; + +#[repr(C)] +pub struct EGLClientBufferTarget(()); +pub type EGLClientBuffer = *mut EGLClientBufferTarget; + +#[repr(C)] +pub struct EGLImageTarget(()); +pub type EGLImage = *mut EGLImageTarget; + +pub type EGLenum = core::ffi::c_uint; + +pub type EGLAttrib = libc::intptr_t; + +#[link(name = "EGL")] +extern "C" { + pub fn eglCreateImage(d: EGLDisplay, c: EGLContext, t: EGLenum, buf: EGLClientBuffer, attribs: *const EGLAttrib) -> EGLImage; +} + +#[link(name = "GL")] +extern "C" { + pub fn glEGLImageTargetTexture2DOES(t: u32, img: EGLImage); +} diff --git a/crates/renderer/src/ffi/glfw.rs b/crates/renderer/src/ffi/glfw.rs new file mode 100644 index 0000000..1b79089 --- /dev/null +++ b/crates/renderer/src/ffi/glfw.rs @@ -0,0 +1,7 @@ +use super::egl::*; + +#[link(name = "glfw")] +extern "C" { + pub fn glfwGetEGLDisplay() -> EGLDisplay; + pub fn glfwGetEGLContext(w: *mut glfw::ffi::GLFWwindow) -> EGLContext; +} diff --git a/crates/renderer/src/ffi/mod.rs b/crates/renderer/src/ffi/mod.rs new file mode 100644 index 0000000..a98fd71 --- /dev/null +++ b/crates/renderer/src/ffi/mod.rs @@ -0,0 +1,2 @@ +pub mod egl; +pub mod glfw; diff --git a/crates/renderer/src/main.rs b/crates/renderer/src/main.rs index ae8cc03..b71a836 100644 --- a/crates/renderer/src/main.rs +++ b/crates/renderer/src/main.rs @@ -1,3 +1,6 @@ +#![feature(unix_socket_ancillary_data)] +#![feature(str_from_utf16_endian)] +#![feature(try_blocks)] #![allow(dead_code, unused_variables)] mod assets; mod terminal; @@ -5,9 +8,12 @@ mod background; mod toggle; mod overlay; mod input; +mod ffi; +mod texture_server; use teleia::*; -use clap::{command, Command}; +use clap::{command, Command, Arg}; +use std::io::Write as _; pub fn main() -> Erm<()> { let matches = command!() @@ -22,6 +28,16 @@ pub fn main() -> Erm<()> { Command::new("model-terminal") .about("Run the LCOLONQ model renderer in a terminal") ) + .subcommand( + Command::new("validate-card") + .arg(Arg::new("path")) + .about("Validate the TCG card at the given path.") + ) + .subcommand( + Command::new("repair-card") + .arg(Arg::new("path")) + .about("Repair the TCG card at the given path.") + ) .get_matches(); match matches.subcommand() { Some(("overlay", _cm)) => { @@ -29,8 +45,10 @@ pub fn main() -> Erm<()> { overlay::Overlays::new(ctx, vec![ Box::new(overlay::automata::Overlay::new(ctx)), Box::new(overlay::shader::Overlay::new(ctx)), - Box::new(overlay::drawing::Overlay::new(ctx)), Box::new(overlay::tcg::Overlay::new(ctx)), + Box::new(overlay::clippy::Overlay::new(ctx)), + Box::new(overlay::combo::Overlay::new(ctx)), + Box::new(overlay::drawing::Overlay::new(ctx)), // Box::new(overlay::model::Overlay::new(ctx)), // Box::new(overlay::loopback::Overlay::new(ctx)), ]) @@ -39,6 +57,27 @@ pub fn main() -> Erm<()> { Some(("model-terminal", _cm)) => { teleia::run("LCOLONQ", 1920, 1080, teleia::Options::HIDDEN, overlay::model::Terminal::new)?; }, + Some(("validate-card", cm)) => { + if let Some(path) = cm.get_one::<String>("path") { + if overlay::tcg::validate_card(&std::fs::read(path)?)? { + println!("signatures match!"); + std::process::exit(0); + } else { + println!("signatures do not match"); + std::process::exit(1); + } + } else { + eprintln!("no path specified"); + } + }, + Some(("repair-card", cm)) => { + if let Some(path) = cm.get_one::<String>("path") { + let res = overlay::tcg::repair_card(&std::fs::read(path)?)?; + std::io::stdout().write_all(&res)?; + } else { + eprintln!("no path specified"); + } + }, _ => unreachable!("no subcommand"), } Ok(()) diff --git a/crates/renderer/src/overlay.rs b/crates/renderer/src/overlay.rs index 049d788..5abeb04 100644 --- a/crates/renderer/src/overlay.rs +++ b/crates/renderer/src/overlay.rs @@ -4,13 +4,17 @@ pub mod drawing; pub mod automata; pub mod tcg; pub mod loopback; +pub mod clippy; +pub mod combo; +use redis::Commands; use teleia::*; use std::f32::consts::PI; use byteorder::{LE, ReadBytesExt}; +use sha2::Digest; -use crate::{assets, fig, toggle, input, background}; +use crate::{assets, background, input, net::fig, texture_server, toggle}; pub struct Chat { author: String, @@ -49,6 +53,7 @@ pub struct State { model: scene::Scene, model_neck_base: glam::Mat4, fig_binary: fig::BinaryClient, + texture_server: texture_server::Server, tracking: Tracking, info: Info, chat: Chat, @@ -87,7 +92,12 @@ impl State { b"overlay shader chat", b"overlay automata spawn", b"overlay tcg generate", + b"overlay clippy animate", + b"overlay clippy border on", + b"overlay clippy border off", + b"overlay combo message", ]).expect("failed to connect to bus"), + texture_server: texture_server::Server::new(ctx), tracking: Tracking { eyes: (1.0, 1.0), mouth: 0.0, @@ -121,6 +131,7 @@ impl State { if let Some(n) = self.model.nodes_by_name.get("J_Bip_C_Neck").and_then(|i| self.model.nodes.get_mut(*i)) { n.transform = self.model_neck_base * glam::Mat4::from_quat(self.tracking.neck); } + self.texture_server.update(ctx); Ok(()) } } @@ -256,6 +267,14 @@ impl teleia::state::Game for Overlays { for ov in self.overlays.iter_mut() { ov.render(ctx, st, &mut self.state)?; } + // st.bind_2d(ctx, &self.state.assets.shader_flat); + // self.state.assets.shader_flat.set_f32(ctx, "transparency", 0.0); + // self.state.assets.shader_flat.set_position_2d(ctx, st, + // &glam::Vec2::new(0.0, 0.0), + // &glam::Vec2::new(200.0, 200.0), + // ); + // self.state.texture_server.tex.bind(ctx); + // st.mesh_square.render(ctx); Ok(()) } } diff --git a/crates/renderer/src/overlay/automata.rs b/crates/renderer/src/overlay/automata.rs index 224a783..f48ed9d 100644 --- a/crates/renderer/src/overlay/automata.rs +++ b/crates/renderer/src/overlay/automata.rs @@ -249,13 +249,13 @@ impl overlay::Overlay for Overlay { } fn handle_binary( &mut self, ctx: &context::Context, st: &mut state::State, _ost: &mut overlay::State, - msg: &fig::BinaryMessage, + msg: &net::fig::BinaryMessage, ) -> Erm<()> { if msg.event == b"overlay automata spawn" { let res: Erm<()> = (|| { let mut reader = std::io::Cursor::new(&msg.data); - let rle = fig::read_length_prefixed_utf8(&mut reader)?; - let _user = fig::read_length_prefixed_utf8(&mut reader)?; + let rle = net::fig::read_length_prefixed_utf8(&mut reader)?; + let _user = net::fig::read_length_prefixed_utf8(&mut reader)?; let col = reader.read_u32::<LE>()?; log::info!("col: {}", col); let r = (col >> 16 & 0xff) as u8; diff --git a/crates/renderer/src/overlay/clippy.rs b/crates/renderer/src/overlay/clippy.rs new file mode 100644 index 0000000..e1ddb0e --- /dev/null +++ b/crates/renderer/src/overlay/clippy.rs @@ -0,0 +1,605 @@ +use teleia::*; + +use crate::overlay; + +use rand::Rng; +use std::{collections::HashMap, io::{Seek, SeekFrom}}; +use byteorder::{LE, ReadBytesExt}; + +struct Bitstream { + bytes: Vec<u8>, + idx: usize, + bidx: usize, +} +impl Bitstream { + pub fn new(bytes: Vec<u8>) -> Self { Self { bytes, idx: 0, bidx: 0 } } + fn pop_bit(&mut self) -> Option<bool> { + let w = self.bytes.get(self.idx)?; + let ret = (w >> self.bidx) & 0b1; + self.bidx += 1; + if self.bidx > 7 { self.bidx = 0; self.idx += 1; } + Some(ret == 1) + } + fn pop_bits(&mut self, count: usize) -> Option<u32> { + let mut ret = 0; + for shift in 0..count { + ret |= (self.pop_bit()? as u32) << shift; + } + Some(ret) + } + fn pop_byte(&mut self) -> Option<u8> { Some(self.pop_bits(8)? as u8) } +} + +fn decompress(bytes: Vec<u8>) -> Option<Vec<u8>> { + let mut ret = Vec::new(); + let mut bits = Bitstream::new(bytes); + if bits.pop_byte()? != 0 { + panic!("no leading 0 byte"); + } + while let Some(bty) = bits.pop_bit() { match bty { + false => ret.push(bits.pop_byte()?), + true => { + let mut bytes_to_read = 2; + let mut off_sequential_ones = 0; + for _ in 0..3 { + if bits.pop_bit()? { off_sequential_ones += 1; } + else { break; } + } + let (bitcount, addend) = match off_sequential_ones { + 0 => (6, 1), + 1 => (9, 65), + 2 => (12, 577), + 3 => (20, 4673), + _ => unreachable!("bad sequential bits"), + }; + let mut num = bits.pop_bits(bitcount)?; + if bitcount == 20 { + if num == 0x000FFFFF { break; } + else { bytes_to_read += 1; } + } + num += addend; + let idx = ret.len() - num as usize; + let mut sequential_ones = 0; + for i in 0..12 { + if i == 11 { + if bits.pop_bit()? { panic!("malformed data! expected 0-bit terminator!"); } + break; + } else { + if bits.pop_bit()? { sequential_ones += 1; } else { break; } + } + } + bytes_to_read += (1 << sequential_ones) - 1; + bytes_to_read += bits.pop_bits(sequential_ones)? as usize; + for i in 0..bytes_to_read { + ret.push(ret[idx + i]); + } + }, + }} + Some(ret) +} + +fn parse_string<R>(r: &mut R) -> Erm<String> where R: ReadBytesExt + Seek { + let len = r.read_u32::<LE>()?; // account for null terminator + if len == 0 { return Ok(String::new()) } + let mut bs = vec![0; (len * 2 + 2) as usize]; + r.read_exact(&mut bs)?; + Ok(String::from_utf16le(&bs[0..bs.len() - 2])?) +} + +type RGB = [u8; 3]; +fn parse_rgb<R>(r: &mut R) -> Erm<RGB> where R: ReadBytesExt + Seek { + let cb = r.read_u8()?; + let cg = r.read_u8()?; + let cr = r.read_u8()?; + let _ = r.read_u8()?; + Ok([cr, cg, cb]) +} + +#[derive(Debug)] +struct Locator { + offset: u32, + size: u32, +} +impl Locator { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + offset: r.read_u32::<LE>()?, + size: r.read_u32::<LE>()?, + }) + } + fn seek<R>(&self, r: &mut R) -> Erm<()> where R: Seek { + r.seek(SeekFrom::Start(self.offset as _))?; + Ok(()) + } +} + +#[derive(Debug)] +struct GUID(u32, u16, u16, [u8; 8]); +impl GUID { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self( + r.read_u32::<LE>()?, + r.read_u16::<LE>()?, + r.read_u16::<LE>()?, + [ r.read_u8()?, r.read_u8()?, r.read_u8()?, r.read_u8()?, + r.read_u8()?, r.read_u8()?, r.read_u8()?, r.read_u8()? ] + )) + } +} + +#[derive(Debug)] +struct VoiceInfoExtra { + lang_id: u16, + dialect: String, + gender: u16, + age: u16, + style: String, +} +impl VoiceInfoExtra { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + lang_id: r.read_u16::<LE>()?, + dialect: parse_string(r)?, + gender: r.read_u16::<LE>()?, + age: r.read_u16::<LE>()?, + style: parse_string(r)?, + }) + } +} +#[derive(Debug)] +struct VoiceInfo { + engine_id: GUID, + mode_id: GUID, + speed: u32, + pitch: u16, + extra: Option<VoiceInfoExtra>, +} +impl VoiceInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + let engine_id = GUID::parse(r)?; + let mode_id = GUID::parse(r)?; + let speed = r.read_u32::<LE>()?; + let pitch = r.read_u16::<LE>()?; + let is_extra = r.read_u8()? == 1; + let extra = if is_extra { Some(VoiceInfoExtra::parse(r)?) } else { None }; + Ok(Self { + engine_id, mode_id, + speed, pitch, + extra + }) + } +} + +#[derive(Debug)] +struct BalloonInfo { + lines: u8, + chars_per_line: u8, + foreground: RGB, + background: RGB, + border: RGB, + font_name: String, + font_height: i32, + font_weight: i32, + font_italic: bool, + font_underline: bool, +} +impl BalloonInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + lines: r.read_u8()?, + chars_per_line: r.read_u8()?, + foreground: parse_rgb(r)?, + background: parse_rgb(r)?, + border: parse_rgb(r)?, + font_name: parse_string(r)?, + font_height: r.read_i32::<LE>()?, + font_weight: r.read_i32::<LE>()?, + font_italic: r.read_u8()? == 1, + font_underline: r.read_u8()? == 1, + }) + } +} + +#[derive(Debug)] +struct CharacterInfo { + minor_version: u16, + major_version: u16, + localized_info: Locator, + id: GUID, + width: u16, + height: u16, + transparent_index: u8, + flags: u32, + animation_major_version: u16, + animation_minor_version: u16, + voice_info: Option<VoiceInfo>, + balloon_info: Option<BalloonInfo>, + palette: Vec<RGB>, +} +impl CharacterInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + let minor_version = r.read_u16::<LE>()?; + let major_version = r.read_u16::<LE>()?; + let localized_info = Locator::parse(r)?; + let id = GUID::parse(r)?; + let width = r.read_u16::<LE>()?; + let height = r.read_u16::<LE>()?; + let transparent_index = r.read_u8()?; + let flags = r.read_u32::<LE>()?; + let animation_major_version = r.read_u16::<LE>()?; + let animation_minor_version = r.read_u16::<LE>()?; + let voice_info = if flags >> 4 & 1 == 1 { None } else { Some(VoiceInfo::parse(r)?) }; + let balloon_info = if flags >> 8 & 1 == 1 { None } else { Some(BalloonInfo::parse(r)?) }; + let palette = { + let len = r.read_u32::<LE>()?; + (0..len).map(|_| parse_rgb(r)).collect::<Erm<Vec<RGB>>>()? + }; + Ok(Self { + minor_version, major_version, + localized_info, id, + width, height, + transparent_index, + flags, + animation_major_version, animation_minor_version, + voice_info, + balloon_info, + palette, + }) + } +} + +#[derive(Debug)] +struct FrameImage { + index: u32, + x_off: i16, + y_off: i16, +} +impl FrameImage { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + index: r.read_u32::<LE>()?, + x_off: r.read_i16::<LE>()?, + y_off: r.read_i16::<LE>()?, + }) + } + fn parse_list<R>(r: &mut R) -> Erm<Vec<Self>> where R: ReadBytesExt + Seek { + let len = r.read_u16::<LE>()?; + (0..len).map(|_| Self::parse(r)).collect() + } +} + +#[derive(Debug)] +struct BranchInfo { + index: u16, + probability: u16, +} +impl BranchInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + index: r.read_u16::<LE>()?, + probability: r.read_u16::<LE>()?, + }) + } + fn parse_list<R>(r: &mut R) -> Erm<Vec<Self>> where R: ReadBytesExt + Seek { + let len = r.read_u8()?; + (0..len).map(|_| Self::parse(r)).collect() + } +} + +#[derive(Debug)] +enum OverlayType { + MouthClosed, + MouthWideOpen1, + MouthWideOpen2, + MouthWideOpen3, + MouthWideOpen4, + MouthMedium, + MouthNarrow, +} +#[derive(Debug)] +struct OverlayInfo { + ty: OverlayType, + replace_top_image: bool, + index: u16, + x_off: i16, + y_off: i16, + width: u16, + height: u16, + data: Option<Vec<u8>>, +} +impl OverlayInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + let ty = match r.read_u8()? { + 0 => OverlayType::MouthClosed, + 1 => OverlayType::MouthWideOpen1, + 2 => OverlayType::MouthWideOpen2, + 3 => OverlayType::MouthWideOpen3, + 4 => OverlayType::MouthWideOpen4, + 5 => OverlayType::MouthMedium, + 6 => OverlayType::MouthNarrow, + _ => { return utils::erm_msg("invalid overlay type"); } + }; + let replace_top_image = r.read_u8()? == 1; + let index = r.read_u16::<LE>()?; + let _ = r.read_u8()?; + let has_data = r.read_u8()? == 1; + let x_off = r.read_i16::<LE>()?; + let y_off = r.read_i16::<LE>()?; + let width = r.read_u16::<LE>()?; + let height = r.read_u16::<LE>()?; + let data = if has_data { + let len = r.read_u32::<LE>()?; + let mut buf = vec![0; len as usize]; + r.read_exact(&mut buf)?; + Some(buf) + } else { None }; + Ok(Self { + ty, + replace_top_image, + index, + x_off, y_off, + width, height, + data, + }) + } + fn parse_list<R>(r: &mut R) -> Erm<Vec<Self>> where R: ReadBytesExt + Seek { + let len = r.read_u8()?; + (0..len).map(|_| Self::parse(r)).collect() + } +} + +#[derive(Debug)] +struct FrameInfo { + images: Vec<FrameImage>, + audio_index: u16, + duration: u16, + exit_frame: i16, + branches: Vec<BranchInfo>, + mouth_overlays: Vec<OverlayInfo>, +} +impl FrameInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + Ok(Self { + images: FrameImage::parse_list(r)?, + audio_index: r.read_u16::<LE>()?, + duration: r.read_u16::<LE>()?, + exit_frame: r.read_i16::<LE>()?, + branches: BranchInfo::parse_list(r)?, + mouth_overlays: OverlayInfo::parse_list(r)?, + }) + } + fn parse_list<R>(r: &mut R) -> Erm<Vec<Self>> where R: ReadBytesExt + Seek { + let len = r.read_u16::<LE>()?; + (0..len).map(|_| Self::parse(r)).collect() + } +} + +#[derive(Debug)] +enum AnimationTransition {Return, ExitBranch, None} +#[derive(Debug)] +struct AnimationInfo { + name: String, + transition: AnimationTransition, + return_name: String, + frames: Vec<FrameInfo> +} +impl AnimationInfo { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + let _name = parse_string(r)?; + let loc = Locator::parse(r)?; + let pos = r.stream_position()?; + loc.seek(r)?; + let name = parse_string(r)?; + let transition = match r.read_u8()? { + 0 => AnimationTransition::Return, + 1 => AnimationTransition::ExitBranch, + 2 => AnimationTransition::None, + _ => { return utils::erm_msg("invalid animation transition type"); } + }; + let return_name = parse_string(r)?; + let frames = FrameInfo::parse_list(r)?; + r.seek(SeekFrom::Start(pos))?; + Ok(Self { + name, transition, return_name, frames + }) + } + fn parse_map<R>(r: &mut R) -> Erm<HashMap<String, Self>> where R: ReadBytesExt + Seek { + let mut ret = HashMap::new(); + let len = r.read_u32::<LE>()?; + for _ in 0..len { + let v = Self::parse(r)?; + ret.insert(v.name.clone(), v); + } + Ok(ret) + } +} + +struct ImageInfo { + width: u16, + height: u16, + image: Vec<u8>, +} +impl std::fmt::Debug for ImageInfo { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fmt.write_fmt(format_args!("<image w: {}, h: {}>", self.width, self.height))?; + Ok(()) + } +} +impl ImageInfo { + fn size() -> u32 { 3 } + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + let loc = Locator::parse(r)?; + let _ = r.read_u32::<LE>()?; + let pos = r.stream_position()?; + loc.seek(r)?; + let _ = r.read_u8()?; + let width = r.read_u16::<LE>()?; + let height = r.read_u16::<LE>()?; + let compressed = r.read_u8()? == 1; + let img_len = r.read_u32::<LE>()?; + let mut img_bytes = vec![0; img_len as usize]; + r.read_exact(&mut img_bytes)?; + r.seek(SeekFrom::Start(pos))?; + Ok(Self { + width, height, + image: if compressed { + decompress(img_bytes).ok_or_else( + || utils::Error { msg: "failed to decompress".to_owned()} + )? + } else { img_bytes } + }) + } + fn parse_list<R>(r: &mut R) -> Erm<Vec<Self>> where R: ReadBytesExt + Seek { + let len = r.read_u32::<LE>()?; + (0..len).map(|_| Self::parse(r)).collect() + } +} + +#[derive(Debug)] +struct ACS { + character_info: CharacterInfo, + animation_info: HashMap<String, AnimationInfo>, + image_info: Vec<ImageInfo>, + audio_info: Locator, +} +impl ACS { + fn parse<R>(r: &mut R) -> Erm<Self> where R: ReadBytesExt + Seek { + if r.read_u32::<LE>()? != 0xabcdabc3 { + return utils::erm_msg("invalid magic bytes"); + } + let character_info_loc = Locator::parse(r)?; + let animation_info_loc = Locator::parse(r)?; + let image_info_loc = Locator::parse(r)?; + let audio_info = Locator::parse(r)?; + Ok(Self { + character_info: { character_info_loc.seek(r)?; CharacterInfo::parse(r)? }, + animation_info: { animation_info_loc.seek(r)?; AnimationInfo::parse_map(r)? }, + image_info: { image_info_loc.seek(r)?; ImageInfo::parse_list(r)? }, + audio_info, + }) + } +} + +pub struct Overlay { + tex: texture::Texture, + acs: ACS, + anim: Option<String>, + anim_idx: usize, + border: bool, +} +impl Overlay { + pub fn new(ctx: &context::Context) -> Self { + let tex = texture::Texture::new_empty(ctx); + let bytes = include_bytes!("../assets/acs/clippy.acs"); + let mut r = std::io::Cursor::new(bytes); + let acs = ACS::parse(&mut r).unwrap(); + log::info!("{:#?}", acs.animation_info.keys().collect::<Vec<&String>>()); + Self { + tex, + acs, + anim: Some("EMPTYTRASH".to_owned()), + anim_idx: 0, + border: false, + } + } + pub fn reset_animation(&mut self) { + self.anim = None; + self.anim_idx = 0; + } + pub fn play_animation(&mut self, anim: &str) { + self.anim = Some(anim.to_owned()); + self.anim_idx = 0; + } + pub fn play_idle_animation(&mut self) { + let idle = [ + "IDLEEYEBROWRAISE", + "IDLE1_1", + "IDLESIDETOSIDE", + "IDLEFINGERTAP", + "IDLEHEADSCRATCH", + ]; + let idx = rand::thread_rng().gen_range(0..idle.len()); + self.play_animation(idle[idx]); + } +} +impl overlay::Overlay for Overlay { + fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { + match &*msg.event { + b"overlay clippy animate" => { + let res: Erm<()> = try { + let mut reader = std::io::Cursor::new(&msg.data); + let anim = net::fig::read_length_prefixed_utf8(&mut reader)?; + self.play_animation(&anim); + () + }; + if let Err(e) = res { log::warn!("malformed clippy update: {}", e); } + }, + b"overlay clippy border on" => self.border = true, + b"overlay clippy border off" => self.border = false, + _ => {}, + } + Ok(()) + } + fn update(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { + let anim = self.anim.as_deref().unwrap_or("RESTPOSE"); + if let Some(ainfo) = &self.acs.animation_info.get(anim) { + let frames = &ainfo.frames; + let f = &frames[self.anim_idx]; + if f.images.len() > 0 { + let idx = f.images[0].index as usize; + let colors: Vec<u8> = self.acs.image_info[idx].image.iter().flat_map(|idx| { + if *idx == self.acs.character_info.transparent_index { + [0, 0, 0, 0] + } else { + let c = self.acs.character_info.palette[*idx as usize]; + [c[0], c[1], c[2], 255] + } + }).collect(); + self.tex.upload_rgba8(ctx, + self.acs.image_info[idx].width as _, + self.acs.image_info[idx].height as _, + &colors + ); + } + if st.tick % 6 == 0 { + if self.anim_idx < frames.len() - 1 { + self.anim_idx += 1; + } else { + self.reset_animation(); + } + } + } else { + self.reset_animation(); + } + if self.anim.is_none() { + if rand::thread_rng().gen_ratio(1, 10 * 60) { + self.play_idle_animation(); + } + } + Ok(()) + } + fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { + st.bind_2d(ctx, &ost.assets.shader_acs); + let w = 3.0 * self.acs.character_info.width as f32; + let h = 3.0 * self.acs.character_info.height as f32; + ost.assets.shader_acs.set_position_2d_helper(ctx, st, + &(st.render_dims - glam::Vec2::new(w, h)), + &glam::Vec2::new(w, h), + // &glam::Quat::from_rotation_z(st.tick as f32 / 100.0), + &glam::Quat::IDENTITY, + ); + self.tex.bind(ctx); + st.mesh_square.render(ctx); + if self.border { + st.bind_2d(ctx, &ost.assets.shader_flat); + ost.assets.shader_flat.set_position_2d_helper(ctx, st, + &glam::Vec2::new(1590.0, 541.0), + &glam::Vec2::new(295.0, 238.0), + &glam::Quat::IDENTITY, + ); + ost.assets.texture_clippyborder.bind(ctx); + st.mesh_square.render(ctx); + } + Ok(()) + } +} diff --git a/crates/renderer/src/overlay/combo.rs b/crates/renderer/src/overlay/combo.rs new file mode 100644 index 0000000..f200e22 --- /dev/null +++ b/crates/renderer/src/overlay/combo.rs @@ -0,0 +1,216 @@ +use std::collections::HashMap; + +use rand::Rng; +use teleia::*; + +use crate::overlay; + +use enum_map::{enum_map, Enum, EnumMap}; +use strum::{EnumIter, IntoEnumIterator}; + +const MAX_SCORE: f32 = 12800.0; + +const WIDTH: i64 = 250; +const HEIGHT: i64 = 400; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Enum, EnumIter)] +enum Rank {SSS, SS, S, A, B, C, D, None} +impl Rank { + fn threshold(self) -> f32 { + match self { + Self::SSS => 2800.0, + Self::SS => 2100.0, + Self::S => 1500.0, + Self::A => 1000.0, + Self::B => 600.0, + Self::C => 300.0, + Self::D => 100.0, + Self::None => 0.0, + } + } + fn multiplier(self) -> f32 { + match self { + Self::SSS => 16.0, + Self::SS => 6.0, + Self::S => 5.0, + Self::A => 4.0, + Self::B => 3.0, + Self::C => 2.0, + Self::D => 1.5, + Self::None => 1.0, + } + } +} + +pub struct Overlay { + font: font::Bitmap, + fb: framebuffer::Framebuffer, + rank_textures: EnumMap<Rank, texture::Texture>, + shake: u64, + score: f32, + tags: HashMap<String, u64>, +} +impl Overlay { + pub fn new(ctx: &context::Context) -> Self { + let fb = framebuffer::Framebuffer::new(ctx, &glam::Vec2::new(WIDTH as f32, HEIGHT as f32), &glam::Vec2::new(0.0, 0.0)); + Self { + fb, + font: font::Bitmap::from_image(ctx, 6, 12, 96, 72, include_bytes!("../assets/fonts/terminus.png")), + rank_textures: enum_map! { + Rank::SSS => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/sss.webp")), + Rank::SS => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/ss.webp")), + Rank::S => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/s.webp")), + Rank::A => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/a.webp")), + Rank::B => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/b.webp")), + Rank::C => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/c.webp")), + Rank::D => texture::Texture::new(ctx, include_bytes!("../assets/textures/combo/d.webp")), + Rank::None => texture::Texture::new(ctx, include_bytes!("../assets/textures/test.png")), + }, + shake: 0, + score: 0.0, + tags: HashMap::new(), + } + } + fn rank(&self) -> (Rank, f32) { + let mut prev = MAX_SCORE; + for r in Rank::iter() { + let thresh = r.threshold(); + if self.score > thresh { + return (r, (self.score - thresh) / (prev - thresh)); + } + prev = thresh; + } + return (Rank::None, 0.0); + } + fn tag_multiplier(&self) -> f32 { + return 1.0 + self.tags.len() as f32; + } + fn shake_offset(&self, r: Rank) -> f32 { + rand::thread_rng().gen_range(0..10) as f32 / 100.0 * r.multiplier() + } +} +impl overlay::Overlay for Overlay { + fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { + match &*msg.event { + b"overlay combo message" => { + let (oldrank, _) = self.rank(); + self.score += 267.0 * self.tag_multiplier(); + let (newrank, _) = self.rank(); + if oldrank != newrank { + self.shake = 20; + } + if let Ok(ts) = String::from_utf8(msg.data.clone()) { + for t in ts.split(",") { + if t.len() > 0 { + self.tags.entry(t.to_owned()).and_modify(|x| *x += 1).or_insert(1); + } + } + } + }, + _ => {}, + } + Ok(()) + } + fn update(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { + let (rank, _) = self.rank(); + self.score -= 2.0 * rank.multiplier(); + if self.score < 0.0 { + self.score = 0.0; + self.tags.clear(); + } + if self.score > MAX_SCORE { self.score = MAX_SCORE; } + if self.shake > 0 { self.shake -= 1; } + Ok(()) + } + fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { + let (rank, meter) = self.rank(); + if rank == Rank::None { return Ok(()); } + + st.bind_framebuffer(ctx, &self.fb); + ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.8)); + ctx.clear(); + + // rank name + st.bind_2d(ctx, &ost.assets.shader_flat); + ost.assets.shader_flat.set_position_2d( + ctx, st, + &glam::Vec2::new(-4.0, 4.0), + &glam::Vec2::new(WIDTH as f32, WIDTH as f32 / 3.0), + ); + self.rank_textures[rank].bind(ctx); + st.mesh_square.render(ctx); + + // meter + st.bind_2d(ctx, &ost.assets.shader_color); + ost.assets.shader_color.set_position_2d( + ctx, st, + &glam::Vec2::new(0.0, 100.0), + &glam::Vec2::new(WIDTH as f32, 16.0), + ); + ost.assets.shader_color.set_vec4(ctx, "color", &glam::Vec4::new(0.0, 0.0, 0.0, 1.0)); + st.mesh_square.render(ctx); + ost.assets.shader_color.set_position_2d( + ctx, st, + &glam::Vec2::new(0.0, 100.0), + &glam::Vec2::new(WIDTH as f32 * meter, 16.0), + ); + ost.assets.shader_color.set_vec4(ctx, "color", &glam::Vec4::new(1.0, 1.0, 1.0, 1.0)); + st.mesh_square.render(ctx); + + // tags + let mut tagy = 124.0; + for (t, count) in self.tags.iter() { + self.font.render_text_parameterized( + ctx, st, + &glam::Vec2::new(4.0, tagy), + &format!("+ {t} (x{count})"), + font::BitmapParams { + color: &[glam::Vec3::new(1.0, 1.0, 1.0)], + scale: glam::Vec2::new(2.0, 2.0), + }, + ); + tagy += 24.0; + } + + // multiplier + self.font.render_text_parameterized( + ctx, st, + &glam::Vec2::new(4.0, HEIGHT as f32 - 50.0), + &format!("MULT:"), + font::BitmapParams { + color: &[glam::Vec3::new(1.0, 1.0, 1.0)], + scale: glam::Vec2::new(4.0, 4.0), + }, + ); + self.font.render_text_parameterized( + ctx, st, + &glam::Vec2::new(128.0, HEIGHT as f32 - 50.0), + &format!("{}x", self.tag_multiplier()), + font::BitmapParams { + color: &[glam::Vec3::new(1.0, 0.7, 0.0)], + scale: glam::Vec2::new(4.0, 4.0), + }, + ); + + // actually draw box to screen + st.bind_render_framebuffer(ctx); + ctx.clear_depth(); + st.bind_3d(ctx, &ost.assets.shader_flat_noflip); + let shake_offset = if self.shake > 0 { + glam::Vec3::new(self.shake_offset(rank), 0.0, self.shake_offset(rank)) + } else { + glam::Vec3::ZERO + }; + ost.assets.shader_flat_noflip.set_position_3d( + ctx, st, + &glam::Mat4::from_scale_rotation_translation( + glam::Vec3::new(WIDTH as f32 / HEIGHT as f32, 1.0, 1.0), + glam::Quat::from_rotation_y(std::f32::consts::PI + 0.7), + glam::Vec3::new(-5.5, 1.0, -8.0) + shake_offset, + ), + ); + self.fb.bind_texture(ctx); + st.mesh_square.render(ctx); + Ok(()) + } +} diff --git a/crates/renderer/src/overlay/model.rs b/crates/renderer/src/overlay/model.rs index d74870e..9c4b51b 100644 --- a/crates/renderer/src/overlay/model.rs +++ b/crates/renderer/src/overlay/model.rs @@ -81,7 +81,7 @@ impl Overlay { } impl overlay::Overlay for Overlay { - fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &fig::BinaryMessage) -> Erm<()> { + fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { if msg.event == b"overlay avatar text" { match str::from_utf8(&msg.data) { Ok(s) => self.terminal.fill_string(s), diff --git a/crates/renderer/src/overlay/shader.rs b/crates/renderer/src/overlay/shader.rs index 2bed8d6..b30242f 100644 --- a/crates/renderer/src/overlay/shader.rs +++ b/crates/renderer/src/overlay/shader.rs @@ -2,8 +2,11 @@ use teleia::*; use crate::{overlay, toggle}; +use glow::HasContext; + pub struct Overlay { visualizer: newton_shader::Visualizer, + fb: framebuffer::Framebuffer, } impl Overlay { @@ -11,6 +14,7 @@ impl Overlay { let visualizer = newton_shader::Visualizer::new(); Self { visualizer, + fb: framebuffer::Framebuffer::new(ctx, &glam::Vec2::new(640.0, 360.0), &glam::Vec2::ZERO), } } } @@ -21,12 +25,12 @@ impl overlay::Overlay for Overlay { self.visualizer.shader = None; Ok(()) } - fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &fig::BinaryMessage) -> Erm<()> { + fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { if msg.event == b"overlay shader" { let res: Erm<()> = (|| { let mut reader = std::io::Cursor::new(&msg.data); - let author = fig::read_length_prefixed_utf8(&mut reader)?; - let shader = fig::read_length_prefixed_utf8(&mut reader)?; + let author = net::fig::read_length_prefixed_utf8(&mut reader)?; + let shader = net::fig::read_length_prefixed_utf8(&mut reader)?; self.visualizer.author = author.to_string(); if let Err(e) = self.visualizer.set(ctx, st, &shader) { log::warn!("error compiling shader: {}", e); @@ -40,6 +44,11 @@ impl overlay::Overlay for Overlay { } fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { if let Some(s) = &self.visualizer.shader { + self.fb.bind(ctx); + unsafe { + ctx.gl.disable(glow::BLEND); + } + ctx.clear(); s.bind(ctx); s.set_f32( ctx, "opacity", @@ -51,17 +60,30 @@ impl overlay::Overlay for Overlay { 0.5 } ); - s.set_vec2(ctx, "resolution", &glam::Vec2::new(ctx.render_width, ctx.render_height)); + s.set_vec2(ctx, "resolution", &st.render_dims); let elapsed = (st.tick - self.visualizer.tickset) as f32 / 60.0; s.set_f32(ctx, "time", elapsed); s.set_f32(ctx, "chat_time", ost.chat.time - self.visualizer.timeset as f32); - ctx.render_no_geometry(); s.set_f32(ctx, "tracking_mouth", ost.tracking.mouth); s.set_vec2(ctx, "tracking_eyes", &glam::Vec2::new(ost.tracking.eyes.0, ost.tracking.eyes.1)); s.set_mat4(ctx, "tracking_neck", &glam::Mat4::from_quat(ost.tracking.neck)); s.set_vec2(ctx, "emacs_cursor", &glam::Vec2::new(ost.info.emacs_cursor.0, ost.info.emacs_cursor.1)); s.set_vec2(ctx, "mouse_cursor", &glam::Vec2::new(ost.info.mouse_cursor.0, ost.info.mouse_cursor.1)); s.set_i32(ctx, "heartrate", ost.info.emacs_heartrate); + ctx.render_no_geometry(); + unsafe { + ctx.gl.enable(glow::BLEND); + } + + st.render_framebuffer.bind(ctx); + st.bind_2d(ctx, &ost.assets.shader_flat_noflip); + self.fb.bind_texture(ctx); + ost.assets.shader_flat_noflip.set_position_2d( + ctx, st, + &glam::Vec2::new(0.0, 0.0), + &glam::Vec2::new(1920.0, 1080.0) + ); + st.mesh_square.render(ctx); } if let Some(t@toggle::Toggle { val: true, .. }) = ost.toggles.get(ctx, st, "adblock") { st.bind_2d(ctx, &ost.assets.shader_flat); diff --git a/crates/renderer/src/overlay/tcg.rs b/crates/renderer/src/overlay/tcg.rs index 7361e86..ece01e8 100644 --- a/crates/renderer/src/overlay/tcg.rs +++ b/crates/renderer/src/overlay/tcg.rs @@ -1,6 +1,8 @@ +use sha2::Digest; use teleia::*; -use std::{cell::RefCell, io::Write, rc::Rc}; +use std::{cell::RefCell, rc::Rc}; +use std::fmt::Write as _; use redis::Commands; use image::EncodableLayout; @@ -129,7 +131,7 @@ impl RenderedCardSlot { struct ImageWrite { buf: Rc<RefCell<Vec<u8>>>, } -impl Write for ImageWrite { +impl std::io::Write for ImageWrite { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { self.buf.borrow_mut().write(buf) } @@ -138,6 +140,7 @@ impl Write for ImageWrite { struct ImageEncoder { frames: u32, frames_left: u32, + frame_hashes: Vec<u8>, buf: Rc<RefCell<Vec<u8>>>, writer: png::Writer<ImageWrite>, } @@ -164,12 +167,14 @@ impl ImageEncoder { Some(Self { frames, frames_left: frames, + frame_hashes: Vec::new(), buf, writer, }) } fn write_frame(&mut self, pixels: &[u8]) { if self.frames_left > 0 { + self.frame_hashes.extend_from_slice(sha2::Sha256::digest(pixels).as_slice()); let _ = self.writer.write_image_data(&pixels); self.frames_left -= 1; } @@ -177,10 +182,10 @@ impl ImageEncoder { fn is_finished(&self) -> bool { self.frames_left == 0 } - fn finish(self) -> Option<Vec<u8>> { + fn finish(self) -> Option<(Vec<u8>, Vec<u8>)> { if self.is_finished() { self.writer.finish().expect("failed to finish"); - Some(self.buf.replace(Vec::new())) + Some((self.buf.replace(Vec::new()), self.frame_hashes)) } else { None } } } @@ -283,15 +288,24 @@ impl Marquee { } } fn upload_card(ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, - c: &Card, buf: &[u8] + c: &Card, buf: &[u8], hashes: &[u8], ) -> Erm<()> { - let with_meta = web_image_meta::png::add_text_chunk( - buf, "lcolonqtcg", &c.encoded, + let mut signed = Vec::from(c.encoded.as_bytes()); + signed.extend(hashes); + let signature = sign(&mut ost.redis_conn, &signed)?; + let mut res = "+SIGNED+".to_owned(); + for s in signature { + write!(res, "{:02x}", s)?; + } + res.push_str("+"); + res.push_str(&c.encoded); + let with_signature = web_image_meta::png::add_text_chunk( + buf, "lcolonqtcg", &res, )?; let uuid = uuid::Uuid::new_v4(); - let _: () = ost.redis_conn.hset("tcg:cards", uuid.to_string(), &with_meta)?; + let () = ost.redis_conn.hset("tcg:cards", uuid.to_string(), &with_signature)?; let inventory_key = format!("tcg-inventory:{}", c.owner_id); - let _: () = ost.redis_conn.lpush(inventory_key, uuid.to_string())?; + let () = ost.redis_conn.lpush(inventory_key, uuid.to_string())?; Ok(()) } pub fn render(&mut self, @@ -299,9 +313,9 @@ impl Marquee { renderer: &CardRenderer, ) { for s in self.slots.iter_mut() { - if let Some(b) = s.encoder.take_if(|e| e.is_finished()).and_then(|enc| enc.finish()) { + if let Some((b, h)) = s.encoder.take_if(|e| e.is_finished()).and_then(|enc| enc.finish()) { if let Some(c) = &s.card.card { - let _ = Self::upload_card(ctx, st, ost, &c, &b).expect("failed to upload"); + let _ = Self::upload_card(ctx, st, ost, &c, &b, &h).expect("failed to upload"); } } } @@ -554,7 +568,7 @@ impl overlay::Overlay for Overlay { fn reset(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { Ok(()) } - fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &fig::BinaryMessage) -> Erm<()> { + fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { match &*msg.event { b"overlay tcg generate" => { let res: Erm<()> = (|| { @@ -621,3 +635,87 @@ impl overlay::Overlay for Overlay { Ok(()) } } + +pub fn sign(conn: &mut redis::Connection, data: &[u8]) -> Erm<Vec<u8>> { + let mut secret: Vec<u8> = conn.get("tcg:secret")?; + secret.extend_from_slice(data); + Ok(Vec::from(sha2::Sha256::digest(&secret).as_slice())) +} + +pub fn validate_card(png: &[u8]) -> Erm<bool> { + let decoder = png::Decoder::new(png); + let mut reader = decoder.read_info()?; + let mut buf = vec![0; reader.output_buffer_size()]; + let mut frame_hashes = Vec::new(); + while let Ok(f) = reader.next_frame(&mut buf) { + frame_hashes.extend_from_slice(sha2::Sha256::digest(&buf).as_slice()); + } + reader.finish()?; + for tc in reader.info().uncompressed_latin1_text.iter() { + if tc.keyword == "lcolonqtcg" { + eprintln!("{}", tc.text); + let (sig, meta) = if let Some(suffix) = tc.text.strip_prefix("+SIGNED+") { + suffix.split_once("+").unwrap_or(("", suffix)) + } else { + ("", &*tc.text) + }; + let mut to_sign = Vec::from(meta); + to_sign.extend_from_slice(&frame_hashes); + eprintln!("to_sign: {:?}", to_sign); + let signed = { + let redis = redis::Client::open("redis://shiro").unwrap(); + let mut redis_conn = redis.get_connection().unwrap(); + sign(&mut redis_conn, &to_sign)? + }; + let mut computed_sig = String::new(); + for s in signed { + write!(computed_sig, "{:02x}", s)?; + } + eprintln!("attached signature: {}", sig); + eprintln!("computed signature: {}", computed_sig); + return Ok(sig == computed_sig); + } + } + Ok(false) +} + +pub fn repair_card(png: &[u8]) -> Erm<Vec<u8>> { + let decoder = png::Decoder::new(png); + let mut reader = decoder.read_info()?; + let mut buf = vec![0; reader.output_buffer_size()]; + let mut frame_hashes = Vec::new(); + while let Ok(f) = reader.next_frame(&mut buf) { + frame_hashes.extend_from_slice(sha2::Sha256::digest(&buf).as_slice()); + } + reader.finish()?; + for tc in reader.info().uncompressed_latin1_text.iter() { + if tc.keyword == "lcolonqtcg" { + let (sig, meta) = if let Some(suffix) = tc.text.strip_prefix("+SIGNED+") { + suffix.split_once("+").unwrap_or(("", suffix)) + } else { + ("", &*tc.text) + }; + let mut to_sign = Vec::from(meta); + to_sign.extend_from_slice(&frame_hashes); + eprintln!("to_sign: {:?}", to_sign); + let signed = { + let redis = redis::Client::open("redis://shiro").unwrap(); + let mut redis_conn = redis.get_connection().unwrap(); + sign(&mut redis_conn, &to_sign)? + }; + let mut computed_sig = String::new(); + for s in signed { + write!(computed_sig, "{:02x}", s)?; + } + if sig != computed_sig { + eprintln!("repairing, new signature: {}", computed_sig); + eprintln!("old signature: {}", sig); + let clean = web_image_meta::png::clean_chunks(png)?; + return Ok(web_image_meta::png::add_text_chunk( + &clean, "lcolonqtcg", &format!("+SIGNED+{}+{}", computed_sig, meta), + )?); + } + } + } + Ok(Vec::from(png)) +} diff --git a/crates/renderer/src/texture_server.rs b/crates/renderer/src/texture_server.rs new file mode 100644 index 0000000..5afad70 --- /dev/null +++ b/crates/renderer/src/texture_server.rs @@ -0,0 +1,80 @@ +use teleia::*; + +use std::io::Write; +use std::os::fd::FromRawFd; +use std::os::unix::net::{AncillaryData, SocketAncillary}; +use std::sync::mpsc::{Receiver, channel}; +use std::{os::unix::net::UnixDatagram, thread::{spawn, JoinHandle}}; + +use glow::HasContext; +use crate::ffi::egl; +use crate::ffi::glfw; + +const KEY: usize = 42; +const SOCK_PATH: &'static str = "/tmp/newton.sock"; + + +pub struct Server { + pub tex: texture::Texture, + thread: JoinHandle<()>, + receiver: Receiver<i32>, +} +impl Server { + pub fn new(ctx: &context::Context) -> Self { + std::fs::remove_file(SOCK_PATH).expect("failed to remove socket"); + let sock = UnixDatagram::bind(SOCK_PATH).expect("failed to bind texture server socket"); + + let (sender, receiver) = channel::<i32>(); + let thread = spawn(move || { + let mut ancillary_buf = [0; 128]; + let mut ancillary = SocketAncillary::new(&mut ancillary_buf); + loop { + match sock.recv_vectored_with_ancillary(&mut [], &mut ancillary) { + Ok(_) => { + for ar in ancillary.messages() { + match ar { + Ok(AncillaryData::ScmRights(mut sr)) => { + if let Some(fd) = sr.next() { + if let Err(e) = sender.send(fd) { + log::warn!("error on channel: {:?}", e); + } + } + }, + Ok(_) => log::info!("message is not SCM_RIGHTS"), + Err(e) => log::warn!("failed to read ancillary message: {:?}", e), + } + } + }, + Err(e) => log::warn!("texture server failed to receive: {}", e), + } + } + }); + Self { + tex: texture::Texture::new_empty(ctx), + thread, + receiver, + } + } + pub fn update(&self, ctx: &context::Context) { + if let Ok(fd) = self.receiver.try_recv() { + log::info!("received file descriptor: {}", fd); + unsafe { + let window = ctx.window.borrow_mut().0.ptr; + let d = glfw::glfwGetEGLDisplay(); + let c = glfw::glfwGetEGLContext(window); + let img = egl::eglCreateImage(d, c, egl::EGL_LINUX_DMA_BUF_EXT, std::ptr::null_mut(), [ + egl::EGL_WIDTH as _, 16, + egl::EGL_HEIGHT as _, 16, + egl::EGL_LINUX_DRM_FOURCC_EXT as _, 875708993, + egl::EGL_DMA_BUF_PLANE0_FD_EXT as _, fd as _, + egl::EGL_DMA_BUF_PLANE0_OFFSET_EXT as _, 0, + egl::EGL_DMA_BUF_PLANE0_PITCH_EXT as _, 128, + egl::EGL_NONE as _, + ].as_ptr()); + self.tex.bind(ctx); + egl::glEGLImageTargetTexture2DOES(glow::TEXTURE_2D, img); + log::info!("set up texture"); + } + } + } +} diff --git a/crates/renderer/src/toggle.rs b/crates/renderer/src/toggle.rs index 8468fc4..7add3ca 100644 --- a/crates/renderer/src/toggle.rs +++ b/crates/renderer/src/toggle.rs @@ -27,7 +27,7 @@ impl Toggles { } pub fn handle(&mut self, ctx: &context::Context, st: &state::State, - msg: fig::BinaryMessage + msg: net::fig::BinaryMessage ) { let nm = if let Ok(s) = str::from_utf8(&msg.data) { s } else { log::warn!("failed to decode toggle name"); @@ -38,7 +38,7 @@ impl Toggles { } pub fn handle_set(&mut self, ctx: &context::Context, st: &state::State, - msg: fig::BinaryMessage, val: bool + msg: net::fig::BinaryMessage, val: bool ) { let nm = if let Ok(s) = str::from_utf8(&msg.data) { s } else { log::warn!("failed to decode toggle name"); diff --git a/crates/video_player/Cargo.toml b/crates/video_player/Cargo.toml new file mode 100644 index 0000000..df0e2bc --- /dev/null +++ b/crates/video_player/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "newton_video_player" +version.workspace = true +edition.workspace = true +authors.workspace = true + +[[bin]] +name = "newton_video_player" +path = "src/main.rs" + +[dependencies] +teleia = {workspace = true} +glam = "*" # linear algebra +glow = "*" # gl bindings +bitflags = "*" # C-style bitwise flags +rand = { version = "=0.8.5", features = ["small_rng"] } # rng +log = "*" # logging +env_logger = "*" # native logging +lazy_static = "*" # global constants +uuid = {version = "*", features = ["v4"]} # generate uuids
\ No newline at end of file diff --git a/crates/video_player/src/main.rs b/crates/video_player/src/main.rs new file mode 100644 index 0000000..e9fc5e1 --- /dev/null +++ b/crates/video_player/src/main.rs @@ -0,0 +1,13 @@ +#![feature(unix_socket_ancillary_data)] +use std::os::unix::net::{SocketAncillary, UnixDatagram}; + +fn main() { + let sock = UnixDatagram::unbound().expect("failed to create socket"); + sock.connect("/tmp/newton.sock").expect("failed to connect"); + let mut ancillary_buffer = [0; 128]; + let mut ancillary = SocketAncillary::new(&mut ancillary_buffer); + ancillary.add_fds(&[1]); + sock.send_vectored_with_ancillary(&mut [], &mut ancillary).expect("failed to send"); + println!("hi"); + loop {} +} @@ -67,11 +67,11 @@ ] }, "locked": { - "lastModified": 1753584741, - "narHash": "sha256-i147iFSy4K4PJvID+zoszLbRi2o+YV8AyG4TUiDQ3+I=", + "lastModified": 1766717007, + "narHash": "sha256-ZjLiHCHgoH2maP5ZAKn0anrHymbjGOS5/PZqfJUK8Ik=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "69dfe029679e73b8d159011c9547f6148a85ca6b", + "rev": "a18efe8a9112175e43397cf870fb6bc1ca480548", "type": "github" }, "original": { @@ -123,11 +123,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1755248408, - "narHash": "sha256-fSdigxPV4/fASh0e32GGso1TuQVBbv9m7oNmLdWeUOQ=", + "lastModified": 1766795639, + "narHash": "sha256-dujt59KKcTW7h+VqjG9+I962Qh1rvRKr4jzKfIgAjBA=", "owner": "lcolonq", "repo": "teleia", - "rev": "d8b65583864e57c6702283ee19d18c2421bbc8fb", + "rev": "ff3317bee0584b89758bbda6712396d35ba82153", "type": "github" }, "original": { @@ -46,6 +46,7 @@ }; devShells.${system}.default = inputs.teleia.shell.overrideAttrs (final: prev: { buildInputs = prev.buildInputs ++ [ + pkgs.glfw ]; }); }; @@ -1,8 +1,9 @@ #!/bin/sh set -xu -pactl load-module module-null-sink sink_name=lcolonq-hls -./target/debug/newton_renderer overlay & -sleep 3 -pw-link lcolonq-hls:monitor_FL alsa_capture.newton_renderer:input_FL -pw-link lcolonq-hls:monitor_FR alsa_capture.newton_renderer:input_FR +# pactl load-module module-null-sink sink_name=lcolonq-hls +# ./target/debug/newton_renderer overlay & +# sleep 3 +# pw-link lcolonq-hls:monitor_FL alsa_capture.newton_renderer:input_FL +# pw-link lcolonq-hls:monitor_FR alsa_capture.newton_renderer:input_FR +cargo run -p newton_renderer overlay wait |
