From bbb5c0920cccf47fa0608d4150987b7d3ef5b9ad Mon Sep 17 00:00:00 2001 From: Ilya Epifanov Date: Sat, 24 Feb 2024 00:30:56 +0100 Subject: [PATCH 01/11] WIP --- Cargo.lock | 2317 +++++++++++------- Cargo.toml | 2 + nih_plug_derive/Cargo.toml | 2 +- nih_plug_egui/Cargo.toml | 2 +- nih_plug_iced/Cargo.toml | 52 +- nih_plug_iced/src/assets.rs | 72 +- nih_plug_iced/src/editor.rs | 24 +- nih_plug_iced/src/lib.rs | 38 +- nih_plug_iced/src/widgets.rs | 6 +- nih_plug_iced/src/widgets/generic_ui.rs | 90 +- nih_plug_iced/src/widgets/param_slider.rs | 516 ++-- nih_plug_iced/src/widgets/peak_meter.rs | 34 +- nih_plug_iced/src/widgets/util.rs | 2 +- nih_plug_iced/src/wrapper.rs | 89 +- nih_plug_vizia/Cargo.toml | 2 +- plugins/examples/gain_gui_iced/src/editor.rs | 7 +- 16 files changed, 1979 insertions(+), 1276 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 818c2c9f..75387576 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,7 +68,7 @@ checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31" dependencies = [ "accesskit", "accesskit_consumer", - "arrayvec 0.7.4", + "arrayvec", "once_cell", "paste", "windows 0.48.0", @@ -104,9 +104,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" dependencies = [ "cfg-if", "once_cell", @@ -129,6 +129,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "alsa" version = "0.7.1" @@ -192,9 +198,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -206,9 +212,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -240,9 +246,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.77" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "anymap" @@ -250,15 +256,6 @@ version = "1.0.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" -[[package]] -name = "approx" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" -dependencies = [ - "num-traits", -] - [[package]] name = "approx" version = "0.5.1" @@ -269,10 +266,10 @@ dependencies = [ ] [[package]] -name = "arrayvec" -version = "0.5.2" +name = "arrayref" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -280,6 +277,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "assert_no_alloc" version = "1.1.2" @@ -312,13 +318,13 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 4.0.1", - "event-listener-strategy", + "event-listener 5.1.0", + "event-listener-strategy 0.5.0", "futures-core", "pin-project-lite", ] @@ -329,11 +335,11 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock 3.2.0", + "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "slab", ] @@ -349,21 +355,6 @@ dependencies = [ "futures-lite 1.13.0", ] -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.1.1", - "async-executor", - "async-io 2.2.2", - "async-lock 3.2.0", - "blocking", - "futures-lite 2.1.0", - "once_cell", -] - [[package]] name = "async-io" version = "1.13.0" @@ -386,18 +377,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" +checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" dependencies = [ - "async-lock 3.2.0", + "async-lock 3.3.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "parking", - "polling 3.3.1", - "rustix 0.38.28", + "polling 3.5.0", + "rustix 0.38.31", "slab", "tracing", "windows-sys 0.52.0", @@ -414,26 +405,15 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 4.0.1", - "event-listener-strategy", + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", "pin-project-lite", ] -[[package]] -name = "async-net" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" -dependencies = [ - "async-io 1.13.0", - "blocking", - "futures-lite 1.13.0", -] - [[package]] name = "async-process" version = "1.8.1" @@ -447,7 +427,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.28", + "rustix 0.38.31", "windows-sys 0.48.0", ] @@ -459,7 +439,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -468,60 +448,33 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.2.2", + "async-io 2.3.1", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.28", + "rustix 0.38.31", "signal-hook-registry", "slab", "windows-sys 0.48.0", ] -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite 1.13.0", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-task" -version = "4.6.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.75" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -601,62 +554,89 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "baseview" version = "0.1.0" -source = "git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25#1d9806d5bd92275d0d8142d9c9c90198757b9b25" +source = "git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4#2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" dependencies = [ "cocoa", "core-foundation", "keyboard-types", "nix 0.22.3", "objc", - "raw-window-handle 0.4.3", + "raw-window-handle", "uuid", "winapi", "x11", - "xcb 0.9.0", + "xcb", "xcb-util", ] [[package]] name = "baseview" version = "0.1.0" -source = "git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4#2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" +source = "git+https://github.com/RustAudio/baseview.git?rev=fdb43ea#fdb43eac115470408c5a90f04766bcc346e27ef3" dependencies = [ "cocoa", "core-foundation", "keyboard-types", "nix 0.22.3", "objc", - "raw-window-handle 0.5.2", + "raw-window-handle", "uuid", "winapi", "x11", - "xcb 0.9.0", + "xcb", "xcb-util", ] [[package]] name = "bindgen" -version = "0.69.1" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cexpr", "clang-sys", + "itertools", "lazy_static", "lazycell", - "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.43", + "syn 2.0.50", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", ] +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -665,9 +645,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block" @@ -709,12 +689,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.1.1", - "async-lock 3.2.0", + "async-channel 2.2.0", + "async-lock 3.3.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "piper", "tracing", ] @@ -728,15 +708,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" dependencies = [ "bytemuck_derive", ] @@ -749,7 +729,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -779,11 +759,10 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" dependencies = [ - "jobserver", "libc", ] @@ -823,42 +802,36 @@ dependencies = [ "libc", ] -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.3", ] [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", - "libloading 0.7.4", + "libloading 0.8.1", ] [[package]] name = "clap" -version = "4.4.12" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -871,9 +844,9 @@ source = "git+https://github.com/robbert-vdh/clap-sys.git?branch=feature/cstr-ma [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", @@ -884,21 +857,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "clipboard-win" @@ -910,15 +883,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "cocoa" version = "0.24.1" @@ -949,6 +913,16 @@ dependencies = [ "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -961,6 +935,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "com-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" + [[package]] name = "combine" version = "4.6.6" @@ -996,20 +976,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "copypasta" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4423d79fed83ebd9ab81ec21fa97144300a961782158287dc9bf7eddac37ff0b" -dependencies = [ - "clipboard-win", - "objc", - "objc-foundation", - "objc_id", - "smithay-clipboard", - "x11-clipboard 0.5.3", -] - [[package]] name = "copypasta" version = "0.8.2" @@ -1020,20 +986,21 @@ dependencies = [ "objc", "objc-foundation", "objc_id", + "smithay-clipboard", "x11-clipboard 0.7.1", ] [[package]] name = "copypasta" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d35364349bf9e9e1c3a035ddcb00d188d23a3c40c50244c03c27a99fc6a65ae" +checksum = "deb85422867ca93da58b7f95fb5c0c10f6183ed6e1ef8841568968a896d3a858" dependencies = [ "clipboard-win", "objc", "objc-foundation", "objc_id", - "x11-clipboard 0.8.1", + "x11-clipboard 0.9.1", ] [[package]] @@ -1076,18 +1043,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-text" -version = "19.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" -dependencies = [ - "core-foundation", - "core-graphics", - "foreign-types", - "libc", -] - [[package]] name = "coreaudio-rs" version = "0.11.3" @@ -1101,9 +1056,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3120ebb80a9de008e638ad833d4127d50ea3d3a960ea23ea69bc66d9358a028" +checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" dependencies = [ "bindgen", ] @@ -1138,7 +1093,27 @@ dependencies = [ "libm", "log", "rangemap", - "rustybuzz", + "rustybuzz 0.7.0", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cosmic-text" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b68966c2543609f8d92f9d33ac3b719b2a67529b0c6c0b3e025637b477eef9" +dependencies = [ + "aliasable", + "fontdb", + "libm", + "log", + "rangemap", + "rustybuzz 0.8.0", "swash", "sys-locale", "unicode-bidi", @@ -1174,18 +1149,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -1200,11 +1175,10 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb9105919ca8e40d437fc9cbb8f1975d916f1bd28afe795a48aae32a2cc8920" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "cfg-if", "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", @@ -1214,54 +1188,46 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.17" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc6598521bb5a83d491e8c1fe51db7296019d2ca3cb93cc6c2a20369a4d78a2" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossover" @@ -1271,6 +1237,12 @@ dependencies = [ "realfft", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1305,14 +1277,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] -name = "cty" -version = "0.2.2" +name = "d3d12" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" +dependencies = [ + "bitflags 1.3.2", + "libloading 0.7.4", + "winapi", +] [[package]] name = "dasp_sample" @@ -1320,6 +1297,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data-url" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5" + [[package]] name = "deranged" version = "0.3.11" @@ -1376,27 +1359,6 @@ dependencies = [ "triple_buffer", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dispatch" version = "0.2.0" @@ -1411,7 +1373,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -1444,18 +1406,6 @@ dependencies = [ "dtoa", ] -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi", - "wio", -] - [[package]] name = "ecolor" version = "0.26.2" @@ -1482,12 +1432,12 @@ version = "0.2.0" source = "git+https://github.com/BillyDM/egui-baseview.git?rev=1fe7e1d0081ab29474b0a5cdc567f60a3219b20d#1fe7e1d0081ab29474b0a5cdc567f60a3219b20d" dependencies = [ "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4)", - "copypasta 0.10.0", + "copypasta 0.10.1", "egui", "egui_glow", "keyboard-types", "log", - "raw-window-handle 0.5.2", + "raw-window-handle", ] [[package]] @@ -1507,9 +1457,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "emath" @@ -1522,9 +1472,9 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" +checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" dependencies = [ "enumflags2_derive", "serde", @@ -1532,13 +1482,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" +checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -1573,6 +1523,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "etagere" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306960881d6c46bd0dd6b7f07442a441418c08d0d3e63d8d080b0f64c6343e4e" +dependencies = [ + "euclid", + "svg_fmt", +] + [[package]] name = "euclid" version = "0.22.9" @@ -1601,9 +1561,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.1" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f2cdcf274580f2d63697192d744727b3198894b1bf02923643bf59e2c26712" +checksum = "b7ad6fd685ce13acd6d9541a30f6db6567a7a24c9ffd4ba2955d29e3f22c8b27" dependencies = [ "concurrent-queue", "parking", @@ -1616,20 +1587,42 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.1", + "event-listener 4.0.3", "pin-project-lite", ] [[package]] -name = "expat-sys" -version = "2.1.6" +name = "event-listener-strategy" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" dependencies = [ - "cmake", - "pkg-config", + "event-listener 5.1.0", + "pin-project-lite", +] + +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "1.9.0" @@ -1647,9 +1640,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -1660,15 +1653,15 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3a2d0ff0df09856a5c1c89cc83863a1f0f994c55452186621bb57a01f270b3" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "fnv", "generational-arena", "glow 0.12.3", "image", "imgref", - "lru", + "lru 0.10.1", "rgb", - "rustybuzz", + "rustybuzz 0.7.0", "unicode-bidi", "unicode-segmentation", "wasm-bindgen", @@ -1686,19 +1679,16 @@ dependencies = [ ] [[package]] -name = "float-ord" -version = "0.2.0" +name = "float-cmp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" [[package]] name = "float_next_after" -version = "0.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632" -dependencies = [ - "num-traits", -] +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" [[package]] name = "fluent-bundle" @@ -1735,34 +1725,33 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "font-kit" -version = "0.10.1" +name = "font-types" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd7f3ea17572640b606b35df42cfb6ecdf003704b062580e59918692190b73d" + +[[package]] +name = "fontconfig-parser" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" +checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" dependencies = [ - "bitflags 1.3.2", - "byteorder", - "core-foundation", - "core-graphics", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype", - "lazy_static", - "libc", - "log", - "pathfinder_geometry", - "pathfinder_simd", - "servo-fontconfig", - "walkdir", - "winapi", + "roxmltree 0.19.0", ] [[package]] @@ -1771,6 +1760,7 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e" dependencies = [ + "fontconfig-parser", "log", "memmap2 0.6.2", "slotmap", @@ -1793,27 +1783,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "freetype" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" -dependencies = [ - "freetype-sys", - "libc", -] - -[[package]] -name = "freetype-sys" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", -] - [[package]] name = "futures" version = "0.3.30" @@ -1880,9 +1849,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -1899,7 +1868,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -2007,12 +1976,12 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ "libc", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -2028,15 +1997,35 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.28.1" @@ -2056,12 +2045,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.10.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579160312273c954cc51bd440f059dde741029ac8daf8c84fece76cb77f62c15" -dependencies = [ - "version_check", -] +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" [[package]] name = "glob" @@ -2069,30 +2055,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "glow" version = "0.12.3" @@ -2117,18 +2079,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "glow_glyph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4e62c64947b9a24fe20e2bba9ad819ecb506ef5c8df7ffc4737464c6df9510" -dependencies = [ - "bytemuck", - "glow 0.11.2", - "glyph_brush", - "log", -] - [[package]] name = "glutin" version = "0.30.10" @@ -2146,7 +2096,7 @@ dependencies = [ "libloading 0.7.4", "objc2", "once_cell", - "raw-window-handle 0.5.2", + "raw-window-handle", "windows-sys 0.45.0", "x11-dl", ] @@ -2159,7 +2109,7 @@ checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" dependencies = [ "cfg_aliases", "glutin", - "raw-window-handle 0.5.2", + "raw-window-handle", "winit", ] @@ -2193,59 +2143,130 @@ dependencies = [ ] [[package]] -name = "glyph_brush" -version = "0.7.8" +name = "glyphon" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3676f482c536a985fca36ce320a5e5b8fafd7b260806742af1963b71c5dc38c" +checksum = "5e87caa7459145f5e5f167bf34db4532901404c679e62339fb712a0e3ccf722a" dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "ordered-float", - "rustc-hash", - "twox-hash", + "cosmic-text 0.9.0", + "etagere", + "lru 0.11.1", + "wgpu", ] [[package]] -name = "glyph_brush_draw_cache" -version = "0.1.5" +name = "goblin" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" +checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", + "log", + "plain", + "scroll", ] [[package]] -name = "glyph_brush_layout" -version = "0.2.3" +name = "gpu-alloc" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" +checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" dependencies = [ - "ab_glyph", - "approx 0.5.1", - "xi-unicode", + "bitflags 1.3.2", + "gpu-alloc-types", ] [[package]] -name = "goblin" -version = "0.6.1" +name = "gpu-alloc-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" +checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "gpu-allocator" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" dependencies = [ + "backtrace", "log", - "plain", - "scroll", + "thiserror", + "winapi", + "windows 0.44.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" +dependencies = [ + "bitflags 2.4.2", + "gpu-descriptor-types", + "hashbrown 0.14.3", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" +dependencies = [ + "bitflags 2.4.2", +] + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "half" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +dependencies = [ + "cfg-if", + "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hassle-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" +dependencies = [ + "bitflags 1.3.2", + "com-rs", + "libc", + "libloading 0.7.4", + "thiserror", + "widestring", + "winapi", +] [[package]] name = "heck" @@ -2264,9 +2285,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hex" @@ -2274,11 +2295,17 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2300,123 +2327,208 @@ dependencies = [ [[package]] name = "iced_baseview" version = "0.0.3" -source = "git+https://github.com/robbert-vdh/iced_baseview.git?branch=feature/update-baseview#df3a852a15cf0e9fcc8d2b32f5718e56780beaf3" +source = "git+https://github.com/BillyDM/iced_baseview.git?rev=4feacc03bc1135023f73167093aea953a858a7c2#4feacc03bc1135023f73167093aea953a858a7c2" dependencies = [ - "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25)", - "copypasta 0.7.1", - "iced_core", - "iced_futures", - "iced_glow", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=fdb43ea)", + "cfg-if", + "copypasta 0.8.2", "iced_graphics", - "iced_native", + "iced_renderer", + "iced_runtime", + "iced_style", + "iced_widget", "keyboard-types", - "raw-window-handle 0.4.3", + "log", + "raw-window-handle", + "thiserror", ] [[package]] name = "iced_core" -version = "0.4.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d0bc4fbf018576d08d93f838e6058cc6f10bbc05e04ae249a2a44dffb4ebc8" dependencies = [ "bitflags 1.3.2", + "instant", + "log", "palette", - "wasm-timer", + "thiserror", + "twox-hash", ] [[package]] name = "iced_futures" -version = "0.3.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dab0054a9c7a1cbce227a8cd9ee4a094497b3d06094551ac6c1488d563802e" dependencies = [ - "async-std", "futures", + "iced_core", "log", - "smol", - "tokio", "wasm-bindgen-futures", "wasm-timer", ] [[package]] -name = "iced_glow" -version = "0.2.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_graphics" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ff14447a221e9e9205a13d84d7bbdf0636a3b1daa02cfca690ed09689c4d2b" dependencies = [ + "bitflags 1.3.2", "bytemuck", - "euclid", - "glow 0.11.2", - "glow_glyph", - "glyph_brush", - "iced_graphics", - "iced_native", + "glam", + "half", + "iced_core", + "image", + "kamadak-exif", "log", + "lyon_path", + "raw-window-handle", + "thiserror", ] [[package]] -name = "iced_graphics" -version = "0.2.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_renderer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1033385b0db0099a0d13178c9ff93c1ce11e7d0177522acf578bf79febdb2af8" dependencies = [ - "bytemuck", - "font-kit", - "glam", - "iced_native", - "iced_style", - "lyon", - "qrcode", - "raw-window-handle 0.4.3", + "iced_graphics", + "iced_tiny_skia", + "iced_wgpu", + "log", + "raw-window-handle", "thiserror", ] [[package]] -name = "iced_native" -version = "0.4.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_runtime" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c6c89853e1250c6fac82c5015fa2144517be9b33d4b8e456f10e198b23e28bd" dependencies = [ "iced_core", "iced_futures", - "iced_style", - "num-traits", - "twox-hash", - "unicode-segmentation", + "thiserror", ] [[package]] name = "iced_style" -version = "0.3.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85c47d9d13e2281f75ddf98c865daf2101632bd2b855c401dd0b1c8b81a31a0" dependencies = [ "iced_core", + "once_cell", + "palette", +] + +[[package]] +name = "iced_tiny_skia" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7715f6222c9470bbbd75a39f70478fa0d1bdfb81a377a34fd1b090ffccc480b" +dependencies = [ + "bytemuck", + "cosmic-text 0.9.0", + "iced_graphics", + "kurbo", + "log", + "raw-window-handle", + "resvg", + "rustc-hash", + "softbuffer", + "tiny-skia", + "twox-hash", +] + +[[package]] +name = "iced_wgpu" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f7c5de46b997ed7b18e05ec67059dcdf3beeac51e917c21071b021bb848b9" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "futures", + "glam", + "glyphon", + "guillotiere", + "iced_graphics", + "log", + "lyon", + "once_cell", + "raw-window-handle", + "resvg", + "rustc-hash", + "twox-hash", + "wgpu", +] + +[[package]] +name = "iced_widget" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177219ae51c3ba08f228ab932354b360cc669e94aec50c01e7c9b675f074c7c" +dependencies = [ + "iced_renderer", + "iced_runtime", + "iced_style", + "num-traits", + "thiserror", + "unicode-segmentation", ] [[package]] name = "image" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", - "num-rational", + "exr", + "gif 0.13.1", + "jpeg-decoder", "num-traits", "png", + "qoi", + "tiff", ] +[[package]] +name = "imagesize" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" + [[package]] name = "imgref" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90d944e334f00f4449c9640b440a171f816be0152305c12ef90424fc35fd035c" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -2456,11 +2568,20 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.6", "libc", "windows-sys 0.48.0", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -2529,23 +2650,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] -name = "jobserver" -version = "0.1.27" +name = "jpeg-decoder" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" dependencies = [ - "libc", + "rayon", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kamadak-exif" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077" +dependencies = [ + "mutate_once", +] + [[package]] name = "keyboard-types" version = "0.6.2" @@ -2555,6 +2685,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "khronos-egl" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +dependencies = [ + "libc", + "libloading 0.7.4", + "pkg-config", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -2562,12 +2703,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] -name = "kv-log-macro" -version = "1.0.7" +name = "kurbo" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" dependencies = [ - "log", + "arrayvec", ] [[package]] @@ -2588,11 +2729,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -2620,34 +2767,17 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall 0.4.1", -] - [[package]] name = "libredox" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2656,9 +2786,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2675,9 +2805,6 @@ name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] [[package]] name = "loudness_war_winner" @@ -2692,11 +2819,20 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +[[package]] +name = "lru" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "lyon" -version = "0.17.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb" +checksum = "91e7f9cda98b5430809e63ca5197b06c7d191bf7e26dfc467d5a3f0290e2a74f" dependencies = [ "lyon_algorithms", "lyon_tessellation", @@ -2704,42 +2840,44 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "0.17.7" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a" +checksum = "a3bca95f9a4955b3e4a821fbbcd5edfbd9be2a9a50bb5758173e5358bfb4c623" dependencies = [ "lyon_path", - "sid", + "num-traits", ] [[package]] name = "lyon_geom" -version = "0.17.7" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d89ccbdafd83d259403e22061be27bccc3254bba65cdc5303250c4227c8c8e" +checksum = "edecfb8d234a2b0be031ab02ebcdd9f3b9ee418fb35e265f7a540a48d197bff9" dependencies = [ - "arrayvec 0.5.2", + "arrayvec", "euclid", "num-traits", ] [[package]] name = "lyon_path" -version = "0.17.7" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0" +checksum = "ca507745ba7ccbc76e5c44e7b63b1a29d2b0d6126f375806a5bbaf657c7d6c45" dependencies = [ "lyon_geom", + "num-traits", ] [[package]] name = "lyon_tessellation" -version = "0.17.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760" +checksum = "8c7c67b5bc8123b352b2e7e742b47d1f236a13fe77619433be9568fbd888e9c0" dependencies = [ "float_next_after", "lyon_path", + "num-traits", ] [[package]] @@ -2817,6 +2955,20 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", +] + [[package]] name = "midi-consts" version = "0.1.0" @@ -2854,9 +3006,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -2883,6 +3035,32 @@ dependencies = [ "smallvec", ] +[[package]] +name = "mutate_once" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" + +[[package]] +name = "naga" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbcc2e0513220fd2b598e6068608d4462db20322c0e77e47f6f488dfcfc279cb" +dependencies = [ + "bit-set", + "bitflags 1.3.2", + "codespan-reporting", + "hexf-parse", + "indexmap 1.9.3", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + [[package]] name = "ndk" version = "0.7.0" @@ -2893,7 +3071,7 @@ dependencies = [ "jni-sys", "ndk-sys", "num_enum 0.5.11", - "raw-window-handle 0.5.2", + "raw-window-handle", "thiserror", ] @@ -2932,7 +3110,7 @@ version = "0.0.0" dependencies = [ "anyhow", "anymap", - "approx 0.5.1", + "approx", "assert_no_alloc", "atomic_float", "atomic_refcell", @@ -2955,7 +3133,7 @@ dependencies = [ "nih_plug_derive", "objc", "parking_lot 0.12.1", - "raw-window-handle 0.5.2", + "raw-window-handle", "rtrb", "serde", "serde_json", @@ -2990,7 +3168,7 @@ dependencies = [ "lazy_static", "nih_plug", "parking_lot 0.12.1", - "raw-window-handle 0.5.2", + "raw-window-handle", "serde", ] @@ -2999,12 +3177,13 @@ name = "nih_plug_iced" version = "0.0.0" dependencies = [ "atomic_refcell", - "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25)", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=fdb43ea)", "crossbeam", + "futures-util", "iced_baseview", "nih_plug", "nih_plug_assets", - "raw-window-handle 0.4.3", + "raw-window-handle", "serde", ] @@ -3056,6 +3235,19 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.26.4" @@ -3066,6 +3258,7 @@ dependencies = [ "cfg-if", "libc", "memoffset 0.7.1", + "pin-utils", ] [[package]] @@ -3086,13 +3279,19 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.3.3" @@ -3106,32 +3305,21 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3140,7 +3328,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.6", "libc", ] @@ -3183,14 +3371,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -3202,6 +3390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", + "objc_exception", ] [[package]] @@ -3236,9 +3425,18 @@ dependencies = [ name = "objc2-encode" version = "2.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +dependencies = [ + "objc-sys", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" dependencies = [ - "objc-sys", + "cc", ] [[package]] @@ -3304,16 +3502,7 @@ version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox 0.0.2", -] - -[[package]] -name = "ordered-float" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" -dependencies = [ - "num-traits", + "libredox", ] [[package]] @@ -3337,26 +3526,25 @@ dependencies = [ [[package]] name = "palette" -version = "0.5.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05c0334468e62a4dfbda34b29110aa7d70d58c7fdb2c9857b5874dd9827cc59" +checksum = "3d38e6e5ca1612e2081cc31188f08c3cba630ce4ba44709a153f1a0f38d678f2" dependencies = [ - "approx 0.3.2", - "num-traits", + "approx", + "fast-srgb8", "palette_derive", - "phf 0.8.0", - "phf_codegen", + "phf 0.11.2", ] [[package]] name = "palette_derive" -version = "0.5.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b4b5f600e60dd3a147fb57b4547033d382d1979eb087af310e91cb45a63b1f4" +checksum = "e05d1c929301fee6830dafa764341118829b2535c216b0571e3821ecac5c885b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.50", ] [[package]] @@ -3425,31 +3613,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0444332826c70dc47be74a7c6a5fc44e23a7905ad6858d4162b658320455ef93" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3471,11 +3634,21 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "phf_macros", + "phf_macros 0.10.0", "phf_shared 0.10.0", "proc-macro-hack", ] +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros 0.11.2", + "phf_shared 0.11.2", +] + [[package]] name = "phf_codegen" version = "0.8.0" @@ -3506,6 +3679,16 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + [[package]] name = "phf_macros" version = "0.10.0" @@ -3520,6 +3703,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3538,6 +3734,21 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3563,9 +3774,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plain" @@ -3575,9 +3786,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -3604,14 +3815,14 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.28", + "rustix 0.38.31", "tracing", "windows-sys 0.52.0", ] @@ -3670,13 +3881,19 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" + [[package]] name = "puberty_simulator" version = "0.1.0" @@ -3686,28 +3903,28 @@ dependencies = [ ] [[package]] -name = "qrcode" -version = "0.12.0" +name = "qoi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ - "checked_int_cast", + "bytemuck", ] [[package]] name = "quick-xml" -version = "0.22.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3772,7 +3989,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", ] [[package]] @@ -3803,19 +4020,16 @@ dependencies = [ ] [[package]] -name = "rangemap" -version = "1.4.0" +name = "range-alloc" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" [[package]] -name = "raw-window-handle" -version = "0.4.3" +name = "rangemap" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" -dependencies = [ - "cty", -] +checksum = "795915a3930a5d6bafd9053d37602fea3e61be2e5d4d788983a8ba9654c1c6f2" [[package]] name = "raw-window-handle" @@ -3825,9 +4039,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -3835,14 +4049,29 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] +[[package]] +name = "rctree" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" + +[[package]] +name = "read-fonts" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c044ab88c43e2eae05b34a17fc13598736679fdb03d71b49fcfe114443ec8a86" +dependencies = [ + "font-types", +] + [[package]] name = "realfft" version = "3.3.0" @@ -3879,17 +4108,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom 0.2.11", - "libredox 0.0.1", - "thiserror", -] - [[package]] name = "reflink" version = "0.1.3" @@ -3901,9 +4119,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -3913,9 +4131,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3928,6 +4146,29 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "renderdoc-sys" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" + +[[package]] +name = "resvg" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6554f47c38eca56827eea7f285c2a3018b4e12e0e195cc105833c008be338f1" +dependencies = [ + "gif 0.12.0", + "jpeg-decoder", + "log", + "pico-args", + "png", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", +] + [[package]] name = "rgb" version = "0.8.37" @@ -3937,6 +4178,21 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "roxmltree" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862340e351ce1b271a378ec53f304a5558f7db87f3769dc655a8f6ecbb68b302" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "roxmltree" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" + [[package]] name = "rtrb" version = "0.2.3" @@ -3969,9 +4225,9 @@ dependencies = [ [[package]] name = "rustfft" -version = "6.1.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d4f6cbdb180c9f4b2a26bbf01c4e647f1e1dea22fe8eb9db54198b32f9434" +checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" dependencies = [ "num-complex", "num-integer", @@ -3998,14 +4254,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys 0.4.12", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -4026,11 +4282,28 @@ dependencies = [ "unicode-script", ] +[[package]] +name = "rustybuzz" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82eea22c8f56965eeaf3a209b3d24508256c7b920fb3b6211b8ba0f7c0583250" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.19.2", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-general-category", + "unicode-script", +] + [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "safety_limiter" @@ -4077,7 +4350,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -4113,35 +4386,35 @@ checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -4150,13 +4423,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -4168,27 +4441,6 @@ dependencies = [ "serde", ] -[[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - [[package]] name = "sha1" version = "0.10.6" @@ -4202,18 +4454,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" - -[[package]] -name = "sid" -version = "0.6.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb" -dependencies = [ - "num-traits", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -4230,6 +4473,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + [[package]] name = "sine" version = "0.1.0" @@ -4263,9 +4515,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smithay-client-toolkit" @@ -4280,7 +4532,7 @@ dependencies = [ "memmap2 0.5.10", "nix 0.24.3", "pkg-config", - "wayland-client", + "wayland-client 0.29.5", "wayland-cursor", "wayland-protocols", ] @@ -4292,24 +4544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" dependencies = [ "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "smol" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" -dependencies = [ - "async-channel 1.9.0", - "async-executor", - "async-fs", - "async-io 1.13.0", - "async-lock 2.8.0", - "async-net", - "async-process", - "blocking", - "futures-lite 1.13.0", + "wayland-client 0.29.5", ] [[package]] @@ -4326,10 +4561,38 @@ dependencies = [ name = "soft_vacuum" version = "0.1.0" dependencies = [ - "approx 0.5.1", + "approx", "nih_plug", ] +[[package]] +name = "softbuffer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2b953f6ba7285f0af131eb748aabd8ddaf53e0b81dda3ba5d803b0847d6559f" +dependencies = [ + "bytemuck", + "cfg_aliases", + "cocoa", + "core-graphics", + "fastrand 1.9.0", + "foreign-types", + "log", + "nix 0.26.4", + "objc", + "raw-window-handle", + "redox_syscall 0.3.5", + "thiserror", + "wasm-bindgen", + "wayland-backend", + "wayland-client 0.30.2", + "wayland-sys 0.30.1", + "web-sys", + "windows-sys 0.48.0", + "x11-dl", + "x11rb 0.11.1", +] + [[package]] name = "spectral_compressor" version = "0.4.3" @@ -4344,6 +4607,25 @@ dependencies = [ "triple_buffer", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spirv" +version = "0.2.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +dependencies = [ + "bitflags 1.3.2", + "num-traits", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -4364,18 +4646,44 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + +[[package]] +name = "svg_fmt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" + +[[package]] +name = "svgtypes" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "ed4b0611e7f3277f68c0fa18e385d9e2d26923691379690039548f867cef02a7" +dependencies = [ + "kurbo", + "siphasher", +] [[package]] name = "swash" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7c73c813353c347272919aa1af2885068b05e625e5532b43049e4f641ae77f" +checksum = "d06ff4664af8923625604261c645f5c4cc610cc83c84bec74b50d76237089de7" dependencies = [ + "read-fonts", "yazi", "zeno", ] @@ -4393,9 +4701,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -4420,22 +4728,21 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.4.1", - "rustix 0.38.28", + "rustix 0.38.31", "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -4446,39 +4753,51 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.28", + "rustix 0.38.31", "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + +[[package]] +name = "tiff" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.43", + "flate2", + "jpeg-decoder", + "weezl", ] [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -4494,13 +4813,40 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] +[[package]] +name = "tiny-skia" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db11798945fa5c3e5490c794ccca7c6de86d3afdd54b4eb324109939c6f37bc" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f60aa35c89ac2687ace1a2556eaaea68e8c0d47408a2e3e7f5c98a489e7281c" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinystr" version = "0.7.5" @@ -4525,17 +4871,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "1.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - [[package]] name = "toml" version = "0.7.8" @@ -4563,7 +4898,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "serde", "serde_spanned", "toml_datetime", @@ -4589,7 +4924,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -4603,9 +4938,9 @@ dependencies = [ [[package]] name = "transpose" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6522d49d03727ffb138ae4cbc1283d3774f0d10aa7f9bf52e6784c45daf9b23" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" dependencies = [ "num-integer", "strength_reduce", @@ -4714,15 +5049,15 @@ checksum = "fea2a4c80deb4fb3ca51f66b5e2dd91e3642bbce52234bcf22e41668281208e4" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.43", + "syn 2.0.50", "unic-langid-impl", ] [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-bidi-mirroring" @@ -4756,15 +5091,94 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-script" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc" +checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "usvg" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14d09ddfb0d93bf84824c09336d32e42f80961a9d1680832eb24fdf249ce11e6" +dependencies = [ + "base64", + "log", + "pico-args", + "usvg-parser", + "usvg-text-layout", + "usvg-tree", + "xmlwriter", +] + +[[package]] +name = "usvg-parser" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19bf93d230813599927d88557014e0908ecc3531666d47c634c6838bc8db408" +dependencies = [ + "data-url", + "flate2", + "imagesize", + "kurbo", + "log", + "roxmltree 0.18.1", + "simplecss", + "siphasher", + "svgtypes", + "usvg-tree", +] + +[[package]] +name = "usvg-text-layout" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "035044604e89652c0a2959b8b356946997a52649ba6cade45928c2842376feb4" +dependencies = [ + "fontdb", + "kurbo", + "log", + "rustybuzz 0.7.0", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "usvg-tree", +] + +[[package]] +name = "usvg-tree" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "7939a7e4ed21cadb5d311d6339730681c3e24c3e81d60065be80e485d3fc8b92" +dependencies = [ + "rctree", + "strict-num", + "svgtypes", + "tiny-skia-path", +] [[package]] name = "utf8parse" @@ -4778,15 +5192,9 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", ] -[[package]] -name = "value-bag" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" - [[package]] name = "version_check" version = "0.9.4" @@ -4811,7 +5219,7 @@ dependencies = [ "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4)", "femtovg", "lazy_static", - "raw-window-handle 0.5.2", + "raw-window-handle", "vizia_core", "vizia_id", "vizia_input", @@ -4823,10 +5231,10 @@ version = "0.1.0" source = "git+https://github.com/robbert-vdh/vizia.git?tag=patched-2023-12-30#0a4af1999d24f866d8e274a7810c4b61eea95a91" dependencies = [ "accesskit", - "bitflags 2.4.1", + "bitflags 2.4.2", "chrono", "copypasta 0.8.2", - "cosmic-text", + "cosmic-text 0.8.0", "femtovg", "fluent-bundle", "fluent-langneg", @@ -4887,7 +5295,7 @@ name = "vizia_style" version = "0.1.0" source = "git+https://github.com/robbert-vdh/vizia.git?tag=patched-2023-12-30#0a4af1999d24f866d8e274a7810c4b61eea95a91" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cssparser", "femtovg", "morphorm", @@ -4918,7 +5326,7 @@ dependencies = [ "femtovg", "glutin", "glutin-winit", - "raw-window-handle 0.5.2", + "raw-window-handle", "vizia_core", "vizia_id", "vizia_input", @@ -4996,9 +5404,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -5006,24 +5414,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -5033,9 +5441,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5043,22 +5451,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-timer" @@ -5075,6 +5483,21 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b48e27457e8da3b2260ac60d0a94512f5cba36448679f3747c0865b7893ed8" +dependencies = [ + "cc", + "downcast-rs", + "io-lifetimes", + "nix 0.26.4", + "scoped-tls", + "smallvec", + "wayland-sys 0.30.1", +] + [[package]] name = "wayland-client" version = "0.29.5" @@ -5087,8 +5510,20 @@ dependencies = [ "nix 0.24.3", "scoped-tls", "wayland-commons", - "wayland-scanner", - "wayland-sys", + "wayland-scanner 0.29.5", + "wayland-sys 0.29.5", +] + +[[package]] +name = "wayland-client" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489c9654770f674fc7e266b3c579f4053d7551df0ceb392f153adb1f9ed06ac8" +dependencies = [ + "bitflags 1.3.2", + "nix 0.26.4", + "wayland-backend", + "wayland-scanner 0.30.1", ] [[package]] @@ -5100,7 +5535,7 @@ dependencies = [ "nix 0.24.3", "once_cell", "smallvec", - "wayland-sys", + "wayland-sys 0.29.5", ] [[package]] @@ -5110,7 +5545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" dependencies = [ "nix 0.24.3", - "wayland-client", + "wayland-client 0.29.5", "xcursor", ] @@ -5121,9 +5556,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ "bitflags 1.3.2", - "wayland-client", + "wayland-client 0.29.5", "wayland-commons", - "wayland-scanner", + "wayland-scanner 0.29.5", ] [[package]] @@ -5137,6 +5572,17 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "wayland-scanner" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b873b257fbc32ec909c0eb80dea312076a67014e65e245f5eb69a6b8ab330e" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + [[package]] name = "wayland-sys" version = "0.29.5" @@ -5148,14 +5594,132 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "wayland-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" +dependencies = [ + "dlib", + "lazy_static", + "log", + "pkg-config", +] + [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "wgpu" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "480c965c9306872eb6255fa55e4b4953be55a8b64d57e61d7ff840d3dcc051cd" +dependencies = [ + "arrayvec", + "cfg-if", + "js-sys", + "log", + "naga", + "parking_lot 0.12.1", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.4.2", + "codespan-reporting", + "log", + "naga", + "parking_lot 0.12.1", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "1ecb3258078e936deee14fd4e0febe1cfe9bbb5ffef165cb60218d2ee5eb4448" dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.4.2", + "block", + "core-graphics-types", + "d3d12", + "foreign-types", + "glow 0.12.3", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.1", + "log", + "metal", + "naga", + "objc", + "parking_lot 0.12.1", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash", + "smallvec", + "thiserror", "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a" +dependencies = [ + "bitflags 2.4.2", + "js-sys", + "web-sys", ] [[package]] @@ -5254,7 +5818,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -5318,7 +5882,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -5353,17 +5917,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", ] [[package]] @@ -5380,9 +5944,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" [[package]] name = "windows_aarch64_msvc" @@ -5398,9 +5962,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" [[package]] name = "windows_i686_gnu" @@ -5416,9 +5980,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" [[package]] name = "windows_i686_msvc" @@ -5434,9 +5998,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" [[package]] name = "windows_x86_64_gnu" @@ -5452,9 +6016,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" [[package]] name = "windows_x86_64_gnullvm" @@ -5470,9 +6034,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" [[package]] name = "windows_x86_64_msvc" @@ -5488,9 +6052,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" [[package]] name = "winit" @@ -5513,10 +6077,10 @@ dependencies = [ "once_cell", "orbclient", "percent-encoding", - "raw-window-handle 0.5.2", + "raw-window-handle", "redox_syscall 0.3.5", "wasm-bindgen", - "wayland-scanner", + "wayland-scanner 0.29.5", "web-sys", "windows-sys 0.45.0", "x11-dl", @@ -5524,22 +6088,13 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.31" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - [[package]] name = "x11" version = "2.21.0" @@ -5550,15 +6105,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11-clipboard" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" -dependencies = [ - "xcb 0.10.1", -] - [[package]] name = "x11-clipboard" version = "0.7.1" @@ -5570,11 +6116,12 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41aca1115b1f195f21c541c5efb423470848d48143127d0f07f8b90c27440df" +checksum = "613c2be3e772af2bbb57c5a94413675f5ec668bac00a71ada2ced28c420ef087" dependencies = [ - "x11rb 0.12.0", + "libc", + "x11rb 0.13.0", ] [[package]] @@ -5603,15 +6150,29 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.12.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617" dependencies = [ - "gethostname 0.3.0", - "nix 0.26.4", + "gethostname 0.2.3", + "libc", + "libloading 0.7.4", + "nix 0.25.1", + "once_cell", "winapi", "winapi-wsapoll", - "x11rb-protocol 0.12.0", + "x11rb-protocol 0.11.1", +] + +[[package]] +name = "x11rb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +dependencies = [ + "gethostname 0.4.3", + "rustix 0.38.31", + "x11rb-protocol 0.13.0", ] [[package]] @@ -5625,33 +6186,28 @@ dependencies = [ [[package]] name = "x11rb-protocol" -version = "0.12.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56" dependencies = [ - "nix 0.26.4", + "nix 0.25.1", ] [[package]] -name = "xcb" -version = "0.9.0" +name = "x11rb-protocol" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62056f63138b39116f82a540c983cc11f1c90cd70b3d492a70c25eaa50bd22a6" -dependencies = [ - "libc", - "log", - "x11", -] +checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" [[package]] name = "xcb" -version = "0.10.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" +checksum = "62056f63138b39116f82a540c983cc11f1c90cd70b3d492a70c25eaa50bd22a6" dependencies = [ "libc", "log", - "quick-xml", + "x11", ] [[package]] @@ -5661,7 +6217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43893e47f27bf7d81d489feef3a0e34a457e90bc314b7e74ad9bb3980e4c1c48" dependencies = [ "libc", - "xcb 0.9.0", + "xcb", ] [[package]] @@ -5672,26 +6228,32 @@ checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" [[package]] name = "xdg-home" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ - "nix 0.26.4", + "libc", "winapi", ] -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - [[package]] name = "xml-rs" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "xtask" version = "0.1.0" @@ -5707,9 +6269,9 @@ checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" [[package]] name = "zbus" -version = "3.14.1" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +checksum = "5acecd3f8422f198b1a2f954bcc812fe89f3fa4281646f3da1da7925db80085d" dependencies = [ "async-broadcast", "async-executor", @@ -5748,9 +6310,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.14.1" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +checksum = "2207eb71efebda17221a579ca78b45c4c5f116f074eb745c3a172e688ccf89f5" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5794,7 +6356,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.50", ] [[package]] @@ -5826,11 +6388,20 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + [[package]] name = "zvariant" -version = "3.15.0" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +checksum = "c5b4fcf3660d30fc33ae5cd97e2017b23a96e85afd7a1dd014534cd0bf34ba67" dependencies = [ "byteorder", "enumflags2", @@ -5842,9 +6413,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "3.15.0" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +checksum = "0277758a8a0afc0e573e80ed5bfd9d9c2b48bd3108ffe09384f9f738c83f4a55" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5855,9 +6426,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 3181b255..bf634b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ description = "A simple but modern API-agnostic audio plugin framework" repository = "https://github.com/robbert-vdh/nih-plug" [workspace] +resolver = "2" + members = [ "nih_plug_derive", "nih_plug_egui", diff --git a/nih_plug_derive/Cargo.toml b/nih_plug_derive/Cargo.toml index 746c6b65..85c26f81 100644 --- a/nih_plug_derive/Cargo.toml +++ b/nih_plug_derive/Cargo.toml @@ -14,4 +14,4 @@ quote = "1.0" proc-macro2 = "1.0" [dev-dependencies] -nih_plug = { path = ".." } +nih_plug = { path = "..", default-features = false } diff --git a/nih_plug_egui/Cargo.toml b/nih_plug_egui/Cargo.toml index af51dd9c..b279c623 100644 --- a/nih_plug_egui/Cargo.toml +++ b/nih_plug_egui/Cargo.toml @@ -16,7 +16,7 @@ default_fonts = ["egui-baseview/default_fonts"] rayon = ["egui-baseview/rayon"] [dependencies] -nih_plug = { path = ".." } +nih_plug = { path = "..", default-features = false } raw-window-handle = "0.5" baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" } crossbeam = "0.8" diff --git a/nih_plug_iced/Cargo.toml b/nih_plug_iced/Cargo.toml index ae34e11d..dec22de8 100644 --- a/nih_plug_iced/Cargo.toml +++ b/nih_plug_iced/Cargo.toml @@ -8,7 +8,7 @@ license = "ISC" description = "An adapter to use iced GUIs with NIH-plug" [features] -default = ["opengl"] +default = [] # NOTE: wgpu support has been removed from the iced-baseview fork out because # this old iced version uses a wgpu version that doesn't pin the web-sys @@ -20,53 +20,33 @@ default = ["opengl"] # wgpu = ["iced_baseview/wgpu", "baseview/opengl"] # Use OpenGL instead of wgpu for the rendering. This should increase platform # compatibility at the cost of some iced features not being available. -opengl = ["iced_baseview/glow"] +# opengl = ["iced_baseview/glow"] # Enables a debug view in native platforms (press F12) debug = ["iced_baseview/debug"] -# # Enables the `Image` widget, only supported by the wgpu backend -# wgpu_image = ["iced_baseview/wgpu_image"] -# # Enables the `Svg` widget, only supported by the wgpu backend -# wgpu_svg = ["iced_baseview/wgpu_svg"] - -# # Enables the `Canvas` widget for the wgpu backend -# wgpu_canvas = ["iced_baseview/wgpu_canvas"] -# Enables the `Canvas` widget for the OpenGL backend -opengl_canvas = ["iced_baseview/glow_canvas"] - -# # Enables the `QRCode` widget for the wgpu backend -# wgpu_qr_code = ["iced_baseview/wgpu_qr_code"] -# Enables the `QRCode` widget for the OpenGL backend -opengl_qr_code = ["iced_baseview/glow_qr_code"] - -# # Enables using system fonts for the wgpu backend -# wgpu_default_system_font = ["iced_baseview/wgpu_default_system_font"] -# Enables using system fonts for the OpenGL backend -opengl_default_system_font = ["iced_baseview/glow_default_system_font"] - -# Enables advanced color conversion via `palette` -palette = ["iced_baseview/palette"] - -# Enables `tokio` as the `executor::Default` on native platforms -tokio = ["iced_baseview/tokio"] -# Enables `async-std` as the `executor::Default` on native platforms -async-std = ["iced_baseview/async-std"] -# Enables `smol` as the `executor::Default` on native platforms -smol = ["iced_baseview/smol"] +wgpu = ["iced_baseview/wgpu"] +# Enables the `Image` widget, only supported by the wgpu backend +image = ["iced_baseview/image"] +# Enables the `Svg` widget, only supported by the wgpu backend +svg = ["iced_baseview/svg"] +# Enables the `Canvas` widget for the wgpu backend +canvas = ["iced_baseview/canvas"] [dependencies] -nih_plug = { path = ".." } +nih_plug = { path = "..", default-features = false } nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" } # The currently targeted version of baseview uses a different version of # `raw_window_handle` than NIH-plug, so we need to manually convert between them -raw-window-handle = "0.4" +raw-window-handle = "0.5" atomic_refcell = "0.1" -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "1d9806d5bd92275d0d8142d9c9c90198757b9b25" } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "fdb43ea" } crossbeam = "0.8" -# This targets iced 0.4 -iced_baseview = { git = "https://github.com/robbert-vdh/iced_baseview.git", branch = "feature/update-baseview", default_features = false } +# This targets iced 0.10 +iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "4feacc03bc1135023f73167093aea953a858a7c2", default_features = false } +futures-util = "0.3" + # To make the state persistable serde = { version = "1.0", features = ["derive"] } diff --git a/nih_plug_iced/src/assets.rs b/nih_plug_iced/src/assets.rs index 9a6db717..befe1582 100644 --- a/nih_plug_iced/src/assets.rs +++ b/nih_plug_iced/src/assets.rs @@ -1,46 +1,38 @@ //! Binary assets for use with `nih_plug_iced`. -use crate::Font; +use std::borrow::Cow; +use crate::core::Font; + +use iced_baseview::runtime::{font, Command}; // This module provides a re-export and simple font wrappers around the re-exported fonts. pub use nih_plug_assets::*; -pub const NOTO_SANS_REGULAR: Font = Font::External { - name: "Noto Sans Regular", - bytes: fonts::NOTO_SANS_REGULAR, -}; - -pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::External { - name: "Noto Sans Regular Italic", - bytes: fonts::NOTO_SANS_REGULAR_ITALIC, -}; - -pub const NOTO_SANS_THIN: Font = Font::External { - name: "Noto Sans Thin", - bytes: fonts::NOTO_SANS_THIN, -}; - -pub const NOTO_SANS_THIN_ITALIC: Font = Font::External { - name: "Noto Sans Thin Italic", - bytes: fonts::NOTO_SANS_THIN_ITALIC, -}; - -pub const NOTO_SANS_LIGHT: Font = Font::External { - name: "Noto Sans Light", - bytes: fonts::NOTO_SANS_LIGHT, -}; - -pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::External { - name: "Noto Sans Light Italic", - bytes: fonts::NOTO_SANS_LIGHT_ITALIC, -}; - -pub const NOTO_SANS_BOLD: Font = Font::External { - name: "Noto Sans Bold", - bytes: fonts::NOTO_SANS_BOLD, -}; - -pub const NOTO_SANS_BOLD_ITALIC: Font = Font::External { - name: "Noto Sans Bold Italic", - bytes: fonts::NOTO_SANS_BOLD_ITALIC, -}; +pub const NOTO_SANS_REGULAR: Font = Font::with_name("Noto Sans Regular"); +pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::with_name("Noto Sans Regular Italic"); +pub const NOTO_SANS_THIN: Font = Font::with_name("Noto Sans Thin"); +pub const NOTO_SANS_THIN_ITALIC: Font = Font::with_name("Noto Sans Thin Italic"); +pub const NOTO_SANS_LIGHT: Font = Font::with_name("Noto Sans Light"); +pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::with_name("Noto Sans Light Italic"); +pub const NOTO_SANS_BOLD: Font = Font::with_name("Noto Sans Bold"); +pub const NOTO_SANS_BOLD_ITALIC: Font = Font::with_name("Noto Sans Bold Italic"); + +/// Useful for initializing the Settings, like this: +/// ```rust +/// Settings { +/// ... +/// fonts: noto_sans_fonts_data().into_iter().collect(), +/// } +/// ``` +pub const fn noto_sans_fonts_data() -> [Cow<'static, [u8]>; 8] { + [ + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD_ITALIC), + ] +} diff --git a/nih_plug_iced/src/editor.rs b/nih_plug_iced/src/editor.rs index d2984d27..f073083a 100644 --- a/nih_plug_iced/src/editor.rs +++ b/nih_plug_iced/src/editor.rs @@ -1,20 +1,23 @@ //! And [`Editor`] implementation for iced. -use baseview::{WindowOpenOptions, WindowScalePolicy}; +use ::baseview::{WindowOpenOptions, WindowScalePolicy}; use crossbeam::atomic::AtomicCell; use crossbeam::channel; -pub use iced_baseview::*; +use iced_baseview::settings::IcedBaseviewSettings; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use std::sync::atomic::Ordering; +use std::{borrow::Cow, sync::atomic::Ordering}; use std::sync::Arc; use crate::{wrapper, IcedEditor, IcedState, ParameterUpdate}; +pub use iced_baseview::*; + /// An [`Editor`] implementation that renders an iced [`Application`]. pub(crate) struct IcedEditorWrapper { pub(crate) iced_state: Arc, pub(crate) initialization_flags: E::InitializationFlags, + pub(crate) fonts: Vec>, /// The scaling factor reported by the host, if any. On macOS this will never be set and we /// should use the system scaling factor instead. @@ -33,17 +36,17 @@ unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { fn raw_window_handle(&self) -> RawWindowHandle { match self.0 { ParentWindowHandle::X11Window(window) => { - let mut handle = raw_window_handle::XcbHandle::empty(); + let mut handle = raw_window_handle::XcbWindowHandle::empty(); handle.window = window; RawWindowHandle::Xcb(handle) } ParentWindowHandle::AppKitNsView(ns_view) => { - let mut handle = raw_window_handle::AppKitHandle::empty(); + let mut handle = raw_window_handle::AppKitWindowHandle::empty(); handle.ns_view = ns_view; RawWindowHandle::AppKit(handle) } ParentWindowHandle::Win32Hwnd(hwnd) => { - let mut handle = raw_window_handle::Win32Handle::empty(); + let mut handle = raw_window_handle::Win32WindowHandle::empty(); handle.hwnd = hwnd; RawWindowHandle::Win32(handle) } @@ -62,7 +65,7 @@ impl Editor for IcedEditorWrapper { // TODO: iced_baseview does not have gracefuly error handling for context creation failures. // This will panic if the context could not be created. - let window = IcedWindow::>::open_parented( + let window = iced_baseview::open_parented::, _>( &ParentWindowHandleAdapter(parent), Settings { window: WindowOpenOptions { @@ -96,8 +99,8 @@ impl Editor for IcedEditorWrapper { // FIXME: Rust analyzer always thinks baseview/opengl is enabled even if we // don't explicitly enable it, so you'd get a compile error if this line // is missing - #[cfg(not(feature = "opengl"))] - gl_config: None, + // #[cfg(not(feature = "opengl"))] + // gl_config: None, }, iced_baseview: IcedBaseviewSettings { ignore_non_modifier_keys: false, @@ -109,6 +112,7 @@ impl Editor for IcedEditorWrapper { self.parameter_updates_receiver.clone(), self.initialization_flags.clone(), ), + fonts: self.fonts.clone(), }, ); @@ -154,7 +158,7 @@ impl Editor for IcedEditorWrapper { /// The window handle used for [`IcedEditorWrapper`]. struct IcedEditorHandle { iced_state: Arc, - window: iced_baseview::WindowHandle, + window: iced_baseview::window::WindowHandle, } /// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around diff --git a/nih_plug_iced/src/lib.rs b/nih_plug_iced/src/lib.rs index a8ae536b..54590d2c 100644 --- a/nih_plug_iced/src/lib.rs +++ b/nih_plug_iced/src/lib.rs @@ -89,12 +89,20 @@ //! } //! ``` -use baseview::WindowScalePolicy; +use ::baseview::WindowScalePolicy; use crossbeam::atomic::AtomicCell; use crossbeam::channel; +use iced_baseview::core::{Color, Element, Font}; +use iced_baseview::futures::{Executor, Subscription}; +use iced_baseview::graphics::Antialiasing; +use iced_baseview::runtime::Command; +use iced_baseview::style::application::StyleSheet; +use iced_baseview::widget::renderer::Settings as RendererSettings; +use iced_baseview::window::WindowSubs; use nih_plug::params::persist::PersistentField; use nih_plug::prelude::{Editor, GuiContext}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; // This doesn't need to be re-export but otherwise the compiler complains about // `hidden_glob_reexports` pub use std::fmt::Debug; @@ -126,6 +134,7 @@ mod wrapper; pub fn create_iced_editor( iced_state: Arc, initialization_flags: E::InitializationFlags, + fonts: Vec>, ) -> Option> { // We need some way to communicate parameter changes to the `IcedEditor` since parameter updates // come from outside of the editor's reactive model. This contains only capacity to store only @@ -147,6 +156,7 @@ pub fn create_iced_editor( parameter_updates_sender, parameter_updates_receiver: Arc::new(parameter_updates_receiver), + fonts, })) } @@ -162,6 +172,8 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { type Message: 'static + Clone + Debug + Send; /// See [`Application::Flags`]. type InitializationFlags: 'static + Clone + Send + Sync; + /// See [`Application::Theme`] + type Theme: Default + StyleSheet; /// See [`Application::new`]. This also receivs the GUI context in addition to the flags. fn new( @@ -179,7 +191,6 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { /// [`handle_param_message()`][Self::handle_param_message()] to handle the parameter update. fn update( &mut self, - window: &mut WindowQueue, message: Self::Message, ) -> Command; @@ -192,13 +203,21 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { } /// See [`Application::view`]. - fn view(&mut self) -> Element<'_, Self::Message>; + fn view(&self) -> Element<'_, Self::Message, Renderer>; /// See [`Application::background_color`]. fn background_color(&self) -> Color { Color::WHITE } + fn theme(&self) -> Self::Theme { + Self::Theme::default() + } + + fn title(&self) -> String { + "nih_plug plugin".to_owned() + } + /// See [`Application::scale_policy`]. /// /// TODO: Is this needed? Editors shouldn't change the scale policy. @@ -207,16 +226,13 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { } /// See [`Application::renderer_settings`]. - fn renderer_settings() -> iced_baseview::backend::settings::Settings { - iced_baseview::backend::settings::Settings { + fn renderer_settings() -> RendererSettings { + RendererSettings { // Enable some anti-aliasing by default. Since GUIs are likely very simple and most of // the work will be on the CPU anyways this should not affect performance much. - antialiasing: Some(iced_baseview::backend::settings::Antialiasing::MSAAx4), - // Use Noto Sans as the default font as that renders a bit more cleanly than the default - // Lato font. This crate also contains other weights and versions of this font you can - // use for individual widgets. - default_font: Some(crate::assets::fonts::NOTO_SANS_REGULAR), - ..iced_baseview::backend::settings::Settings::default() + antialiasing: Some(Antialiasing::MSAAx4), + default_font: Font::DEFAULT, + ..RendererSettings::default() } } diff --git a/nih_plug_iced/src/widgets.rs b/nih_plug_iced/src/widgets.rs index fa52f029..28856fc0 100644 --- a/nih_plug_iced/src/widgets.rs +++ b/nih_plug_iced/src/widgets.rs @@ -7,12 +7,12 @@ use nih_plug::prelude::ParamPtr; -pub mod generic_ui; -pub mod param_slider; +// pub mod generic_ui; +// pub mod param_slider; pub mod peak_meter; pub mod util; -pub use param_slider::ParamSlider; +// pub use param_slider::ParamSlider; pub use peak_meter::PeakMeter; /// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with diff --git a/nih_plug_iced/src/widgets/generic_ui.rs b/nih_plug_iced/src/widgets/generic_ui.rs index 8e975a67..d12281f3 100644 --- a/nih_plug_iced/src/widgets/generic_ui.rs +++ b/nih_plug_iced/src/widgets/generic_ui.rs @@ -2,6 +2,9 @@ //! list of sliders and labels. use atomic_refcell::AtomicRefCell; +use baseview::{Event, Point}; +use iced_baseview::Renderer; +use crate::{widget::{self, scrollable::Alignment, Row, Scrollable, Space, Text}}; use std::borrow::Borrow; use std::collections::HashMap; use std::marker::PhantomData; @@ -10,12 +13,7 @@ use std::sync::Arc; use nih_plug::prelude::{Param, ParamFlags, ParamPtr, Params}; use super::{ParamMessage, ParamSlider}; -use crate::backend::Renderer; -use crate::text::Renderer as TextRenderer; -use crate::{ - alignment, event, layout, renderer, widget, Alignment, Clipboard, Element, Event, Layout, - Length, Point, Rectangle, Row, Scrollable, Shell, Space, Text, Widget, -}; +use crate::core::{alignment, event, layout, renderer, Clipboard, Element, Layout, Length, Rectangle, Shell, Widget}; /// A widget that can be used to create a generic UI with. This is used in conjuction with empty /// structs to emulate existential types. @@ -27,7 +25,7 @@ pub trait ParamWidget { fn into_widget_element<'a, P: Param>( param: &'a P, state: &'a mut Self::State, - ) -> Element<'a, ParamMessage>; + ) -> Element<'a, ParamMessage, Renderer>; /// The same as [`into_widget_element()`][Self::into_widget_element()], but for a `ParamPtr`. /// @@ -37,7 +35,7 @@ pub trait ParamWidget { unsafe fn into_widget_element_raw<'a>( param: &ParamPtr, state: &'a mut Self::State, - ) -> Element<'a, ParamMessage> { + ) -> Element<'a, ParamMessage, Renderer> { match param { ParamPtr::FloatParam(p) => Self::into_widget_element(&**p, state), ParamPtr::IntParam(p) => Self::into_widget_element(&**p, state), @@ -133,16 +131,15 @@ where /// Create a temporary [`Scrollable`]. This needs to be created on demand because it needs to /// mutably borrow the `Scrollable`'s widget state. - fn with_scrollable_widget( + fn with_scrollable_widget( &'a self, scrollable_state: &'a mut widget::scrollable::State, widget_state: &'a mut HashMap, - renderer: R, + renderer: &Renderer, f: F, ) -> T where - F: FnOnce(Scrollable<'a, ParamMessage>, R) -> T, - R: Borrow, + F: FnOnce(Scrollable<'a, ParamMessage>, &Renderer) -> T { let text_size = renderer.borrow().default_size(); let spacing = (text_size as f32 * 0.2).round() as u16; @@ -233,10 +230,12 @@ where fn draw( &self, + state: &iced_baseview::core::widget::Tree, renderer: &mut Renderer, + theme: &::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: iced_baseview::core::mouse::Cursor, viewport: &Rectangle, ) { let mut scrollable_state = self.state.scrollable_state.borrow_mut(); @@ -246,19 +245,21 @@ where &mut widget_state, renderer, |scrollable, renderer| { - scrollable.draw(renderer, style, layout, cursor_position, viewport) + scrollable.draw(todo!(), renderer, style, todo!(), layout, cursor_position, viewport) }, ) } fn on_event( &mut self, - event: Event, - layout: Layout<'_>, - cursor_position: Point, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, ParamMessage>, + _state: &mut iced_baseview::core::widget::Tree, + _event: event::Event, + _layout: Layout<'_>, + _cursor: iced_baseview::core::mouse::Cursor, + _renderer: &Renderer, + _clipboard: &mut dyn Clipboard, + _shell: &mut Shell<'_, ParamMessage>, + _viewport: &Rectangle, ) -> event::Status { let mut scrollable_state = self.state.scrollable_state.borrow_mut(); let mut widget_state = self.state.widget_state.borrow_mut(); @@ -267,10 +268,51 @@ where &mut widget_state, renderer, |mut scrollable, _| { - scrollable.on_event(event, layout, cursor_position, renderer, clipboard, shell) + scrollable.on_event(todo!(), event, layout, cursor_position, renderer, clipboard, shell, todo!()) }, ) } + + // fn draw( + // &self, + // renderer: &mut Renderer, + // style: &mut renderer::Style, + // layout: Layout<'_>, + // cursor_position: Point, + // viewport: &Rectangle, + // ) { + // let mut scrollable_state = self.state.scrollable_state.borrow_mut(); + // let mut widget_state = self.state.widget_state.borrow_mut(); + // self.with_scrollable_widget( + // &mut scrollable_state, + // &mut widget_state, + // renderer, + // |scrollable, renderer| { + // scrollable.draw(todo!(), renderer, style, todo!(), layout, cursor_position, viewport) + // }, + // ) + // } + + // fn on_event( + // &mut self, + // event: Event, + // layout: Layout<'_>, + // cursor_position: Point, + // renderer: &Renderer, + // clipboard: &mut dyn Clipboard, + // shell: &mut Shell<'_, ParamMessage>, + // ) -> event::Status { + // let mut scrollable_state = self.state.scrollable_state.borrow_mut(); + // let mut widget_state = self.state.widget_state.borrow_mut(); + // self.with_scrollable_widget( + // &mut scrollable_state, + // &mut widget_state, + // renderer, + // |mut scrollable, _| { + // scrollable.on_event(todo!(), event, layout, cursor_position, renderer, clipboard, shell, todo!()) + // }, + // ) + // } } impl ParamWidget for GenericSlider { @@ -279,7 +321,7 @@ impl ParamWidget for GenericSlider { fn into_widget_element<'a, P: Param>( param: &'a P, state: &'a mut Self::State, - ) -> Element<'a, ParamMessage> { + ) -> Element<'a, ParamMessage, Renderer> { ParamSlider::new(state, param).into() } } @@ -289,7 +331,7 @@ impl<'a, W: ParamWidget> GenericUi<'a, W> { /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message> + pub fn map(self, f: F) -> Element<'a, Message, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, @@ -298,7 +340,7 @@ impl<'a, W: ParamWidget> GenericUi<'a, W> { } } -impl<'a, W> From> for Element<'a, ParamMessage> +impl<'a, W> From> for Element<'a, ParamMessage, Renderer> where W: ParamWidget, { diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index fb941562..939c5272 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,16 +1,18 @@ //! A slider that integrates with NIH-plug's [`Param`] types. -use atomic_refcell::AtomicRefCell; +use iced_baseview::widget::text_input; +use iced_baseview::widget::text_input::Id; +use iced_baseview::widget::TextInput; use nih_plug::prelude::Param; use std::borrow::Borrow; -use crate::backend::widget; -use crate::backend::Renderer; -use crate::renderer::Renderer as GraphicsRenderer; -use crate::text::Renderer as TextRenderer; -use crate::{ +use iced_baseview::Renderer; +use crate::core::widget; +use crate::core::renderer::Renderer as GraphicsRenderer; +use crate::core::text::Renderer as TextRenderer; +use crate::core::{ alignment, event, keyboard, layout, mouse, renderer, text, touch, Background, Clipboard, Color, - Element, Event, Font, Layout, Length, Point, Rectangle, Shell, Size, TextInput, Vector, Widget, + Element, Event, Font, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, }; use super::util; @@ -34,12 +36,12 @@ pub struct ParamSlider<'a, P: Param> { height: Length, width: Length, - text_size: Option, + text_size: Option, font: Font, } /// State for a [`ParamSlider`]. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct State { keyboard_modifiers: keyboard::Modifiers, /// Will be set to `true` if we're dragging the parameter. Resetting the parameter or entering a @@ -51,11 +53,22 @@ pub struct State { /// Track clicks for double clicks. last_click: Option, - /// State for the text input overlay that will be shown when this widget is alt+clicked. - text_input_state: AtomicRefCell, + // /// State for the text input overlay that will be shown when this widget is alt+clicked. + // text_input_state: AtomicRefCell, /// The text that's currently in the text input. If this is set to `None`, then the text input /// is not visible. text_input_value: Option, + + text_input_id: Id, +} + +impl Default for State { + fn default() -> Self { + Self { + text_input_id: Id::unique(), + ..Default::default() + } + } } /// An internal message for intercep- I mean handling output from the embedded [`TextInpu`] widget. @@ -70,29 +83,40 @@ enum TextInputMessage { /// The default text input style with the border removed. struct TextInputStyle; -impl widget::text_input::StyleSheet for TextInputStyle { - fn active(&self) -> widget::text_input::Style { - widget::text_input::Style { +impl crate::widget::text_input::StyleSheet for TextInputStyle { + type Style = (); + + fn disabled_color(&self, style: &Self::Style) -> Color { + todo!() + } + + fn disabled(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { + todo!() + } + + fn active(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { + iced_baseview::widget::text_input::Appearance { background: Background::Color(Color::TRANSPARENT), - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + icon_color: Color::TRANSPARENT, } } - fn focused(&self) -> widget::text_input::Style { - self.active() + fn focused(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { + self.active(style) } - fn placeholder_color(&self) -> Color { + fn placeholder_color(&self, style: &Self::Style) -> Color { Color::from_rgb(0.7, 0.7, 0.7) } - fn value_color(&self) -> Color { + fn value_color(&self, style: &Self::Style) -> Color { Color::from_rgb(0.3, 0.3, 0.3) } - fn selection_color(&self) -> Color { + fn selection_color(&self, style: &Self::Style) -> Color { Color::from_rgb(0.8, 0.8, 1.0) } } @@ -105,8 +129,8 @@ impl<'a, P: Param> ParamSlider<'a, P> { param, - width: Length::Units(180), - height: Length::Units(30), + width: Length::Fixed(180.0), + height: Length::Fixed(30.0), text_size: None, font: ::Font::default(), } @@ -125,7 +149,7 @@ impl<'a, P: Param> ParamSlider<'a, P> { } /// Sets the text size of the [`ParamSlider`]. - pub fn text_size(mut self, size: u16) -> Self { + pub fn text_size(mut self, size: f32) -> Self { self.text_size = Some(size); self } @@ -143,25 +167,24 @@ impl<'a, P: Param> ParamSlider<'a, P> { F: FnOnce(TextInput<'_, TextInputMessage>, Layout, R) -> T, R: Borrow, { - let mut text_input_state = self.state.text_input_state.borrow_mut(); - text_input_state.focus(); + // let mut text_input_state = self.state.text_input_state.borrow_mut(); + // text_input_state.focus(); let text_size = self .text_size .unwrap_or_else(|| renderer.borrow().default_size()); let text_width = renderer .borrow() - .measure_width(current_value, text_size, self.font); + .measure_width(current_value, text_size, self.font, Default::default()); let text_input = TextInput::new( - &mut text_input_state, "", current_value, - TextInputMessage::Value, ) + .id(self.state.text_input_id) .font(self.font) .size(text_size) - .width(Length::Units(text_width.ceil() as u16)) - .style(TextInputStyle) + .width(Length::Fixed(text_width)) + // .style(TextInputStyle) .on_submit(TextInputMessage::Submit); // Make sure to not draw over the borders, and center the text @@ -220,14 +243,148 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { layout::Node::new(size) } + fn draw( + &self, + _state: &widget::Tree, + renderer: &mut Renderer, + _theme: &::Theme, + style: &renderer::Style, + layout: Layout<'_>, + cursor: mouse::Cursor, + _viewport: &Rectangle, + ) { + let bounds = layout.bounds(); + // I'm sure there's some philosophical meaning behind this + let bounds_without_borders = Rectangle { + x: bounds.x + BORDER_WIDTH, + y: bounds.y + BORDER_WIDTH, + width: bounds.width - (BORDER_WIDTH * 2.0), + height: bounds.height - (BORDER_WIDTH * 2.0), + }; + let is_mouse_over = if let Some(cursor_position) = cursor.position() { + bounds.contains(cursor_position) + } else { + false + }; + + // The bar itself, show a different background color when the value is being edited or when + // the mouse is hovering over it to indicate that it's interactive + let background_color = + if is_mouse_over || self.state.drag_active || self.state.text_input_value.is_some() { + Color::new(0.5, 0.5, 0.5, 0.1) + } else { + Color::TRANSPARENT + }; + + renderer.fill_quad( + renderer::Quad { + bounds, + border_color: Color::BLACK, + border_width: BORDER_WIDTH, + border_radius: 0.0.into(), + }, + background_color, + ); + + // Only draw the text input widget when it gets focussed. Otherwise, overlay the label with + // the slider. + if let Some(current_value) = &self.state.text_input_value { + self.with_text_input( + layout, + renderer, + current_value, + |text_input, layout, renderer| { + text_input.draw( + todo!(), + renderer, + todo!(), + layout, + cursor, + None + ) + }, + ) + } else { + // We'll visualize the difference between the current value and the default value if the + // default value lies somewhere in the middle and the parameter is continuous. Otherwise + // this appraoch looks a bit jarring. + let current_value = self.param.modulated_normalized_value(); + let default_value = self.param.default_normalized_value(); + let fill_start_x = util::remap_rect_x_t( + &bounds_without_borders, + if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { + default_value + } else { + 0.0 + }, + ); + let fill_end_x = util::remap_rect_x_t(&bounds_without_borders, current_value); + + let fill_color = Color::from_rgb8(196, 196, 196); + let fill_rect = Rectangle { + x: fill_start_x.min(fill_end_x), + width: (fill_end_x - fill_start_x).abs(), + ..bounds_without_borders + }; + renderer.fill_quad( + renderer::Quad { + bounds: fill_rect, + border_color: Color::TRANSPARENT, + border_width: 0.0, + border_radius: 0.0.into(), + }, + fill_color, + ); + + // To make it more readable (and because it looks cool), the parts that overlap with the + // fill rect will be rendered in white while the rest will be rendered in black. + let display_value = self.param.to_string(); + let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()) as f32; + let text_bounds = Rectangle { + x: bounds.center_x(), + y: bounds.center_y(), + ..bounds + }; + renderer.fill_text(text::Text { + content: &display_value, + font: self.font, + size: text_size, + bounds: text_bounds, + color: style.text_color, + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + }); + + // This will clip to the filled area + renderer.with_layer(fill_rect, |renderer| { + let filled_text_color = Color::from_rgb8(80, 80, 80); + renderer.fill_text(text::Text { + content: &display_value, + font: self.font, + size: text_size, + bounds: text_bounds, + color: filled_text_color, + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + }); + }); + } + } + fn on_event( &mut self, + state: &mut widget::Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, ParamMessage>, + _viewport: &Rectangle, ) -> event::Status { // The pressence of a value in `self.state.text_input_value` indicates that the field should // be focussed. The field handles defocussing by itself @@ -245,19 +402,21 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { current_value, |mut text_input, layout, renderer| { text_input.on_event( + todo!(), event, layout, - cursor_position, + cursor, renderer, clipboard, &mut text_input_shell, + todo!(), ) }, ); // Pressing escape will unfocus the text field, so we should propagate that change in // our own model - if self.state.text_input_state.borrow().is_focused() { + if state.text_input_state.borrow().is_focused() { for message in messages { match message { TextInputMessage::Value(s) => self.state.text_input_value = Some(s), @@ -302,48 +461,51 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if bounds.contains(cursor_position) { - let click = mouse::Click::new(cursor_position, self.state.last_click); - self.state.last_click = Some(click); - if self.state.keyboard_modifiers.alt() { - // Alt+click should not start a drag, instead it should show the text entry - // widget - self.state.drag_active = false; - - // Changing the parameter happens in the TextInput event handler above - let mut text_input_state = self.state.text_input_state.borrow_mut(); - self.state.text_input_value = Some(self.param.to_string()); - text_input_state.move_cursor_to_end(); - text_input_state.select_all(); - } else if self.state.keyboard_modifiers.command() - || matches!(click.kind(), mouse::click::Kind::Double) - { - // Likewise resetting a parameter should not let you immediately drag it to a new value - self.state.drag_active = false; - - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.set_normalized_value(shell, self.param.default_normalized_value()); - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - } else if self.state.keyboard_modifiers.shift() { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - // When holding down shift while clicking on a parameter we want to - // granuarly edit the parameter without jumping to a new value - self.state.granular_drag_start_x_value = - Some((cursor_position.x, self.param.modulated_normalized_value())); - } else { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - self.state.granular_drag_start_x_value = None; + if let Some(cursor_position) = cursor.position() { + if bounds.contains(cursor_position) { + let click = mouse::Click::new(cursor_position, self.state.last_click); + self.state.last_click = Some(click); + if self.state.keyboard_modifiers.alt() { + // Alt+click should not start a drag, instead it should show the text entry + // widget + self.state.drag_active = false; + + // Changing the parameter happens in the TextInput event handler above + self.state.text_input_value = Some(self.param.to_string()); + + // TODO!!!! send these commands somehow + text_input::move_cursor_to_end(self.state.text_input_id); + text_input::select_all(self.state.text_input_id); + } else if self.state.keyboard_modifiers.command() + || matches!(click.kind(), mouse::click::Kind::Double) + { + // Likewise resetting a parameter should not let you immediately drag it to a new value + self.state.drag_active = false; + + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.set_normalized_value(shell, self.param.default_normalized_value()); + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + } else if self.state.keyboard_modifiers.shift() { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.state.drag_active = true; + + // When holding down shift while clicking on a parameter we want to + // granuarly edit the parameter without jumping to a new value + self.state.granular_drag_start_x_value = + Some((cursor_position.x, self.param.modulated_normalized_value())); + } else { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.state.drag_active = true; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + self.state.granular_drag_start_x_value = None; + } + + return event::Status::Captured; } - - return event::Status::Captured; } } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) @@ -362,29 +524,31 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { if self.state.drag_active { // If shift is being held then the drag should be more granular instead of // absolute - if self.state.keyboard_modifiers.shift() { - let (drag_start_x, drag_start_value) = *self - .state - .granular_drag_start_x_value - .get_or_insert_with(|| { - (cursor_position.x, self.param.modulated_normalized_value()) - }); - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate( - &bounds, - util::remap_rect_x_t(&bounds, drag_start_value) - + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, - ), - ); - } else { - self.state.granular_drag_start_x_value = None; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); + if let Some(cursor_position) = cursor.position() { + if self.state.keyboard_modifiers.shift() { + let (drag_start_x, drag_start_value) = *self + .state + .granular_drag_start_x_value + .get_or_insert_with(|| { + (cursor_position.x, self.param.modulated_normalized_value()) + }); + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate( + &bounds, + util::remap_rect_x_t(&bounds, drag_start_value) + + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, + ), + ); + } else { + self.state.granular_drag_start_x_value = None; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } } return event::Status::Captured; @@ -401,10 +565,12 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { { self.state.granular_drag_start_x_value = None; - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); + if let Some(cursor_position) = cursor.position() { + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } } return event::Status::Captured; @@ -415,137 +581,35 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { event::Status::Ignored } + fn mouse_interaction( &self, - layout: Layout<'_>, - cursor_position: Point, + _state: &widget::Tree, + _layout: Layout<'_>, + _cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); - - if is_mouse_over { - mouse::Interaction::Pointer - } else { - mouse::Interaction::default() - } + mouse::Interaction::Idle } - fn draw( - &self, - renderer: &mut Renderer, - style: &renderer::Style, - layout: Layout<'_>, - cursor_position: Point, - _viewport: &Rectangle, - ) { - let bounds = layout.bounds(); - // I'm sure there's some philosophical meaning behind this - let bounds_without_borders = Rectangle { - x: bounds.x + BORDER_WIDTH, - y: bounds.y + BORDER_WIDTH, - width: bounds.width - (BORDER_WIDTH * 2.0), - height: bounds.height - (BORDER_WIDTH * 2.0), - }; - let is_mouse_over = bounds.contains(cursor_position); - - // The bar itself, show a different background color when the value is being edited or when - // the mouse is hovering over it to indicate that it's interactive - let background_color = - if is_mouse_over || self.state.drag_active || self.state.text_input_value.is_some() { - Color::new(0.5, 0.5, 0.5, 0.1) - } else { - Color::TRANSPARENT - }; - - renderer.fill_quad( - renderer::Quad { - bounds, - border_color: Color::BLACK, - border_width: BORDER_WIDTH, - border_radius: 0.0, - }, - background_color, - ); - - // Only draw the text input widget when it gets focussed. Otherwise, overlay the label with - // the slider. - if let Some(current_value) = &self.state.text_input_value { - self.with_text_input( - layout, - renderer, - current_value, - |text_input, layout, renderer| { - text_input.draw(renderer, layout, cursor_position, None) - }, - ) - } else { - // We'll visualize the difference between the current value and the default value if the - // default value lies somewhere in the middle and the parameter is continuous. Otherwise - // this appraoch looks a bit jarring. - let current_value = self.param.modulated_normalized_value(); - let default_value = self.param.default_normalized_value(); - let fill_start_x = util::remap_rect_x_t( - &bounds_without_borders, - if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { - default_value - } else { - 0.0 - }, - ); - let fill_end_x = util::remap_rect_x_t(&bounds_without_borders, current_value); - - let fill_color = Color::from_rgb8(196, 196, 196); - let fill_rect = Rectangle { - x: fill_start_x.min(fill_end_x), - width: (fill_end_x - fill_start_x).abs(), - ..bounds_without_borders - }; - renderer.fill_quad( - renderer::Quad { - bounds: fill_rect, - border_color: Color::TRANSPARENT, - border_width: 0.0, - border_radius: 0.0, - }, - fill_color, - ); - - // To make it more readable (and because it looks cool), the parts that overlap with the - // fill rect will be rendered in white while the rest will be rendered in black. - let display_value = self.param.to_string(); - let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()) as f32; - let text_bounds = Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..bounds - }; - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, - size: text_size, - bounds: text_bounds, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - }); + // fn mouse_interaction( + // &self, + // layout: Layout<'_>, + // cursor_position: Point, + // _viewport: &Rectangle, + // _renderer: &Renderer, + // ) -> mouse::Interaction { + // let bounds = layout.bounds(); + // let is_mouse_over = bounds.contains(cursor_position); + + // if is_mouse_over { + // mouse::Interaction::Pointer + // } else { + // mouse::Interaction::default() + // } + // } - // This will clip to the filled area - renderer.with_layer(fill_rect, |renderer| { - let filled_text_color = Color::from_rgb8(80, 80, 80); - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, - size: text_size, - bounds: text_bounds, - color: filled_text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - }); - }); - } - } } impl<'a, P: Param> ParamSlider<'a, P> { @@ -553,7 +617,7 @@ impl<'a, P: Param> ParamSlider<'a, P> { /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message> + pub fn map(self, f: F) -> Element<'a, Message, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, @@ -562,7 +626,7 @@ impl<'a, P: Param> ParamSlider<'a, P> { } } -impl<'a, P: Param> From> for Element<'a, ParamMessage> { +impl<'a, P: Param> From> for Element<'a, ParamMessage, Renderer> { fn from(widget: ParamSlider<'a, P>) -> Self { Element::new(widget) } diff --git a/nih_plug_iced/src/widgets/peak_meter.rs b/nih_plug_iced/src/widgets/peak_meter.rs index 688d67d7..c0435e52 100644 --- a/nih_plug_iced/src/widgets/peak_meter.rs +++ b/nih_plug_iced/src/widgets/peak_meter.rs @@ -5,11 +5,11 @@ use std::marker::PhantomData; use std::time::Duration; use std::time::Instant; -use crate::backend::Renderer; -use crate::renderer::Renderer as GraphicsRenderer; -use crate::text::Renderer as TextRenderer; -use crate::{ - alignment, layout, renderer, text, Background, Color, Element, Font, Layout, Length, Point, +use iced_baseview::Renderer; +use crate::core::renderer::Renderer as GraphicsRenderer; +use crate::core::text::Renderer as TextRenderer; +use crate::core::{ + alignment, layout, renderer, text, Background, Color, Element, Font, Layout, Length, Rectangle, Size, Widget, }; @@ -61,8 +61,8 @@ impl<'a, Message> PeakMeter<'a, Message> { hold_time: None, - width: Length::Units(180), - height: Length::Units(30), + width: Length::Fixed(180.0), + height: Length::Fixed(30.0), text_size: None, font: ::Font::default(), @@ -122,10 +122,12 @@ where fn draw( &self, + _state: &iced_baseview::core::widget::Tree, renderer: &mut Renderer, + _theme: &::Theme, style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: iced_baseview::core::mouse::Cursor, _viewport: &Rectangle, ) { let bounds = layout.bounds(); @@ -181,7 +183,7 @@ where renderer.fill_quad( renderer::Quad { bounds: tick_bounds, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -211,7 +213,7 @@ where width: TICK_WIDTH, height: bar_bounds.height - (BORDER_WIDTH * 2.0), }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -223,7 +225,7 @@ where renderer.fill_quad( renderer::Quad { bounds: bar_bounds, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: BORDER_WIDTH, border_color: Color::BLACK, }, @@ -242,7 +244,7 @@ where width: TICK_WIDTH, height: ticks_bounds.height * 0.3, }, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -266,12 +268,14 @@ where color: style.text_color, horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), }); } // Every proper graph needs a unit label let zero_db_x_coordinate = db_to_x_coord(0.0); - let zero_db_text_width = renderer.measure_width("0", text_size, self.font); + let zero_db_text_width = renderer.measure_width("0", text_size.into(), self.font, Default::default()); renderer.fill_text(text::Text { // The spacing looks a bit off if we start with a space here so we'll add a little // offset to the x-coordinate instead @@ -286,11 +290,13 @@ where color: style.text_color, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), }); } } -impl<'a, Message> From> for Element<'a, Message> +impl<'a, Message> From> for Element<'a, Message, Renderer> where Message: 'a + Clone, { diff --git a/nih_plug_iced/src/widgets/util.rs b/nih_plug_iced/src/widgets/util.rs index e755635b..cd61033e 100644 --- a/nih_plug_iced/src/widgets/util.rs +++ b/nih_plug_iced/src/widgets/util.rs @@ -1,6 +1,6 @@ //! Utilities for creating these widgets. -use crate::Rectangle; +use crate::core::Rectangle; /// Remap a `[0, 1]` value to an x-coordinate within this rectangle. The value will be clamped to /// `[0, 1]` if it isn't already in that range. diff --git a/nih_plug_iced/src/wrapper.rs b/nih_plug_iced/src/wrapper.rs index c149489e..0d5c1bbc 100644 --- a/nih_plug_iced/src/wrapper.rs +++ b/nih_plug_iced/src/wrapper.rs @@ -2,14 +2,12 @@ //! `nih_plug_iced`. use crossbeam::channel; +use futures_util::FutureExt; +use iced_baseview::{baseview::WindowScalePolicy, core::Element, futures::{subscription, Subscription}, runtime::Command, widget::renderer::Settings, window::WindowSubs, Renderer}; use nih_plug::prelude::GuiContext; use std::sync::Arc; -use crate::futures::FutureExt; -use crate::{ - futures, subscription, Application, Color, Command, Element, IcedEditor, ParameterUpdate, - Subscription, WindowQueue, WindowScalePolicy, WindowSubs, -}; +use crate::{IcedEditor, ParameterUpdate}; /// Wraps an `iced_baseview` [`Application`] around [`IcedEditor`]. Needed to allow editors to /// always receive a copy of the GUI context. @@ -30,6 +28,16 @@ pub enum Message { ParameterUpdate, } +impl Message { + fn into_editor_message(self) -> Option { + if let Message::EditorMessage(message) = self { + Some(message) + } else { + None + } + } +} + impl std::fmt::Debug for Message { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -48,7 +56,7 @@ impl Clone for Message { } } -impl Application for IcedEditorWrapperApplication { +impl iced_baseview::Application for IcedEditorWrapperApplication { type Executor = E::Executor; type Message = Message; type Flags = ( @@ -56,6 +64,7 @@ impl Application for IcedEditorWrapperApplication { Arc>, E::InitializationFlags, ); + type Theme = E::Theme; fn new( (context, parameter_updates_receiver, flags): Self::Flags, @@ -74,13 +83,12 @@ impl Application for IcedEditorWrapperApplication { #[inline] fn update( &mut self, - window: &mut WindowQueue, message: Self::Message, ) -> Command { match message { Message::EditorMessage(message) => self .editor - .update(window, message) + .update(message) .map(Message::EditorMessage), // This message only exists to force a redraw Message::ParameterUpdate => Command::none(), @@ -93,15 +101,21 @@ impl Application for IcedEditorWrapperApplication { window_subs: &mut WindowSubs, ) -> Subscription { // Since we're wrapping around `E::Message`, we need to do this transformation ourselves - let mut editor_window_subs = WindowSubs { - on_frame: match &window_subs.on_frame { - Some(Message::EditorMessage(message)) => Some(message.clone()), - _ => None, - }, - on_window_will_close: match &window_subs.on_window_will_close { - Some(Message::EditorMessage(message)) => Some(message.clone()), - _ => None, - }, + let on_frame = window_subs.on_frame.clone(); + let on_window_will_close = window_subs.on_window_will_close.clone(); + let mut editor_window_subs: WindowSubs = WindowSubs { + on_frame: Some(Arc::new(move || { + let cb = on_frame.clone(); + cb.and_then(|cb| { + cb().and_then(|m| m.into_editor_message()) + }) + })), + on_window_will_close: Some(Arc::new(move || { + let cb = on_window_will_close.clone(); + cb.and_then(|cb| { + cb().and_then(|m| m.into_editor_message()) + }) + })), }; let subscription = Subscription::batch([ @@ -113,46 +127,55 @@ impl Application for IcedEditorWrapperApplication { "parameter updates", self.parameter_updates_receiver.clone(), |parameter_updates_receiver| match parameter_updates_receiver.try_recv() { - Ok(_) => futures::future::ready(( - Some(Message::ParameterUpdate), + Ok(_) => futures_util::future::ready(( + Message::ParameterUpdate, parameter_updates_receiver, )) .boxed(), - Err(_) => futures::future::pending().boxed(), + Err(_) => futures_util::future::pending().boxed(), }, ), self.editor .subscription(&mut editor_window_subs) - .map(Message::EditorMessage), + .map(|m| Message::EditorMessage(m)), ]); - if let Some(message) = editor_window_subs.on_frame { - window_subs.on_frame = Some(Message::EditorMessage(message)); + if let Some(message) = editor_window_subs.on_frame.as_ref() { + let message = Arc::clone(message); + window_subs.on_frame = Some(Arc::new(move || { + message().map(Message::EditorMessage) + })); } - if let Some(message) = editor_window_subs.on_window_will_close { - window_subs.on_window_will_close = Some(Message::EditorMessage(message)); + if let Some(message) = editor_window_subs.on_window_will_close.as_ref() { + let message = Arc::clone(message); + window_subs.on_window_will_close = Some(Arc::new(move || { + message().map(Message::EditorMessage) + })); } subscription } #[inline] - fn view(&mut self) -> Element<'_, Self::Message> { + fn view(&self) -> Element<'_, Self::Message, Renderer> { self.editor.view().map(Message::EditorMessage) } - #[inline] - fn background_color(&self) -> Color { - self.editor.background_color() - } - #[inline] fn scale_policy(&self) -> WindowScalePolicy { - self.editor.scale_policy() + WindowScalePolicy::SystemScaleFactor } #[inline] - fn renderer_settings() -> iced_baseview::backend::settings::Settings { + fn renderer_settings() -> Settings { E::renderer_settings() } + + fn title(&self) -> String { + self.editor.title() + } + + fn theme(&self) -> Self::Theme { + self.editor.theme() + } } diff --git a/nih_plug_vizia/Cargo.toml b/nih_plug_vizia/Cargo.toml index aab07115..f210bb1f 100644 --- a/nih_plug_vizia/Cargo.toml +++ b/nih_plug_vizia/Cargo.toml @@ -8,7 +8,7 @@ license = "ISC" description = "An adapter to use VIZIA GUIs with NIH-plug" [dependencies] -nih_plug = { path = ".." } +nih_plug = { path = "..", default-features = false } nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" } baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" } diff --git a/plugins/examples/gain_gui_iced/src/editor.rs b/plugins/examples/gain_gui_iced/src/editor.rs index db2c31b7..7e650b86 100644 --- a/plugins/examples/gain_gui_iced/src/editor.rs +++ b/plugins/examples/gain_gui_iced/src/editor.rs @@ -1,5 +1,7 @@ use atomic_float::AtomicF32; use nih_plug::prelude::{util, Editor, GuiContext}; +use nih_plug_iced::assets::noto_sans_fonts_data; +use nih_plug_iced::style::Theme; use nih_plug_iced::widgets as nih_widgets; use nih_plug_iced::*; use std::sync::Arc; @@ -17,7 +19,7 @@ pub(crate) fn create( peak_meter: Arc, editor_state: Arc, ) -> Option> { - create_iced_editor::(editor_state, (params, peak_meter)) + create_iced_editor::(editor_state, (params, peak_meter), noto_sans_fonts_data().into()) } struct GainEditor { @@ -39,7 +41,8 @@ enum Message { impl IcedEditor for GainEditor { type Executor = executor::Default; type Message = Message; - type InitializationFlags = (Arc, Arc); + type InitializationFlags = (Arc, Arc); + type Theme = Theme; fn new( (params, peak_meter): Self::InitializationFlags, From 11d257bdb307af4df7f25782fce82967ee4bd64a Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Sun, 27 Oct 2024 14:16:31 -0700 Subject: [PATCH 02/11] Migration to iced 0.13 started --- Cargo.lock | 2084 ++++++++++++------ Cargo.toml | 23 +- config.toml | 2 + nih_plug_iced/Cargo.toml | 50 +- nih_plug_iced/README.md | 2 +- nih_plug_iced/src/assets.rs | 72 +- nih_plug_iced/src/editor.rs | 59 +- nih_plug_iced/src/lib.rs | 49 +- nih_plug_iced/src/widgets/generic_ui.rs | 384 ++-- nih_plug_iced/src/widgets/param_slider.rs | 966 +++++--- nih_plug_iced/src/widgets/peak_meter.rs | 231 +- nih_plug_iced/src/widgets/util.rs | 2 +- nih_plug_iced/src/wrapper.rs | 124 +- plugins/examples/gain_gui_iced/Cargo.toml | 9 +- plugins/examples/gain_gui_iced/src/editor.rs | 82 +- plugins/examples/gain_gui_iced/src/lib.rs | 2 +- plugins/examples/gain_gui_iced/src/main.rs | 7 + src/wrapper/standalone/wrapper.rs | 2 +- 18 files changed, 2648 insertions(+), 1502 deletions(-) create mode 100644 config.toml create mode 100644 plugins/examples/gain_gui_iced/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 553996ae..3d27ff6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,7 @@ checksum = "134d0acf6acb667c89d3332999b1a5df4edbc8d6113910f392ebb73f2b03bb56" dependencies = [ "accesskit", "accesskit_consumer", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", ] @@ -68,7 +68,7 @@ checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31" dependencies = [ "accesskit", "accesskit_consumer", - "arrayvec 0.7.6", + "arrayvec", "once_cell", "paste", "windows 0.48.0", @@ -129,6 +129,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "alsa" version = "0.7.1" @@ -262,15 +268,6 @@ version = "1.0.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" -[[package]] -name = "approx" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" -dependencies = [ - "num-traits", -] - [[package]] name = "approx" version = "0.5.1" @@ -281,10 +278,10 @@ dependencies = [ ] [[package]] -name = "arrayvec" -version = "0.5.2" +name = "arrayref" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -298,6 +295,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + [[package]] name = "assert_no_alloc" version = "1.1.2" @@ -365,21 +371,6 @@ dependencies = [ "futures-lite 1.13.0", ] -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io 2.3.4", - "async-lock 3.4.0", - "blocking", - "futures-lite 2.3.0", - "once_cell", -] - [[package]] name = "async-io" version = "1.13.0" @@ -439,17 +430,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-net" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" -dependencies = [ - "async-io 1.13.0", - "blocking", - "futures-lite 1.13.0", -] - [[package]] name = "async-process" version = "1.8.1" @@ -496,33 +476,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "async-std" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io 1.13.0", - "async-lock 2.8.0", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite 1.13.0", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-task" version = "4.7.1" @@ -618,22 +571,10 @@ dependencies = [ ] [[package]] -name = "baseview" -version = "0.1.0" -source = "git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25#1d9806d5bd92275d0d8142d9c9c90198757b9b25" -dependencies = [ - "cocoa", - "core-foundation", - "keyboard-types", - "nix 0.22.3", - "objc", - "raw-window-handle 0.4.3", - "uuid", - "winapi", - "x11", - "xcb 0.9.0", - "xcb-util", -] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "baseview" @@ -641,7 +582,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4#2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -649,7 +590,7 @@ dependencies = [ "uuid", "winapi", "x11", - "xcb 0.9.0", + "xcb", "xcb-util", ] @@ -659,7 +600,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=45465c5f46abed6c6ce370fffde5edc8e4cd5aa3#45465c5f46abed6c6ce370fffde5edc8e4cd5aa3" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -676,7 +617,7 @@ version = "0.1.0" source = "git+https://github.com/RustAudio/baseview.git?rev=579130ecb4f9f315ae52190af42f0ea46aeaa4a2#579130ecb4f9f315ae52190af42f0ea46aeaa4a2" dependencies = [ "cocoa", - "core-foundation", + "core-foundation 0.9.4", "keyboard-types", "nix 0.22.3", "objc", @@ -707,6 +648,21 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -740,7 +696,7 @@ version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", ] [[package]] @@ -750,7 +706,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" dependencies = [ "block-sys", - "objc2-encode", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", ] [[package]] @@ -779,6 +744,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "bytemuck" version = "1.17.0" @@ -817,6 +788,32 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.6.0", + "log", + "polling 3.7.3", + "rustix 0.38.34", + "slab", + "thiserror", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.34", + "wayland-backend", + "wayland-client", +] + [[package]] name = "camino" version = "1.1.9" @@ -894,6 +891,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cgl" version = "0.3.2" @@ -903,12 +906,6 @@ dependencies = [ "libc", ] -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "chrono" version = "0.4.38" @@ -991,12 +988,42 @@ dependencies = [ ] [[package]] -name = "cmake" -version = "0.1.51" +name = "clipboard-win" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ - "cc", + "error-code", +] + +[[package]] +name = "clipboard_macos" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f" +dependencies = [ + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "clipboard_wayland" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003f886bc4e2987729d10c1db3424e7f80809f3fc22dbc16c685738887cb37b8" +dependencies = [ + "smithay-clipboard", +] + +[[package]] +name = "clipboard_x11" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c" +dependencies = [ + "thiserror", + "x11rb 0.13.1", ] [[package]] @@ -1008,9 +1035,9 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", - "core-graphics", - "foreign-types", + "core-foundation 0.9.4", + "core-graphics 0.22.3", + "foreign-types 0.3.2", "libc", "objc", ] @@ -1023,12 +1050,22 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "libc", "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1041,6 +1078,37 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "combine" version = "4.6.7" @@ -1076,27 +1144,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "copypasta" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4423d79fed83ebd9ab81ec21fa97144300a961782158287dc9bf7eddac37ff0b" -dependencies = [ - "clipboard-win", - "objc", - "objc-foundation", - "objc_id", - "smithay-clipboard", - "x11-clipboard 0.5.3", -] - [[package]] name = "copypasta" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "133fc8675ee3a4ec9aa513584deda9aa0faeda3586b87f7f0f2ba082c66fb172" dependencies = [ - "clipboard-win", + "clipboard-win 3.1.1", "objc", "objc-foundation", "objc_id", @@ -1109,7 +1163,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb85422867ca93da58b7f95fb5c0c10f6183ed6e1ef8841568968a896d3a858" dependencies = [ - "clipboard-win", + "clipboard-win 3.1.1", "objc", "objc-foundation", "objc_id", @@ -1126,6 +1180,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1139,9 +1203,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "foreign-types 0.5.0", "libc", ] @@ -1152,19 +1229,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] [[package]] -name = "core-text" -version = "19.2.0" +name = "core-graphics-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "core-foundation", - "core-graphics", - "foreign-types", + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -1194,7 +1270,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "coremidi-sys", ] @@ -1214,13 +1290,36 @@ version = "0.8.0" source = "git+https://github.com/pop-os/cosmic-text?rev=79275d15e857428e9b8874f28413197e878f3788#79275d15e857428e9b8874f28413197e878f3788" dependencies = [ "aliasable", - "fontdb", + "fontdb 0.14.1", "libm", "log", "rangemap", - "rustybuzz", + "rustybuzz 0.7.0", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cosmic-text" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2" +dependencies = [ + "bitflags 2.6.0", + "fontdb 0.16.2", + "log", + "rangemap", + "rayon", + "rustc-hash 1.1.0", + "rustybuzz 0.14.1", + "self_cell 1.0.4", "swash", "sys-locale", + "ttf-parser 0.21.1", "unicode-bidi", "unicode-linebreak", "unicode-script", @@ -1340,6 +1439,12 @@ dependencies = [ "realfft", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1378,10 +1483,27 @@ dependencies = [ ] [[package]] -name = "cty" -version = "0.2.2" +name = "ctor-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" + +[[package]] +name = "cursor-icon" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + +[[package]] +name = "d3d12" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307" +dependencies = [ + "bitflags 2.6.0", + "libloading 0.7.4", + "winapi", +] [[package]] name = "dasp_sample" @@ -1389,6 +1511,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + [[package]] name = "deranged" version = "0.3.11" @@ -1446,29 +1574,8 @@ dependencies = [ ] [[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dispatch" -version = "0.2.0" +name = "dispatch" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" @@ -1498,6 +1605,45 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "drm" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "rustix 0.38.34", +] + +[[package]] +name = "drm-ffi" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" +dependencies = [ + "drm-sys", + "rustix 0.38.34", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986" +dependencies = [ + "libc", + "linux-raw-sys 0.6.5", +] + [[package]] name = "dtoa" version = "1.0.9" @@ -1513,18 +1659,6 @@ dependencies = [ "dtoa", ] -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi", - "wio", -] - [[package]] name = "ecolor" version = "0.27.2" @@ -1642,6 +1776,22 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-code" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + +[[package]] +name = "etagere" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e2f1e3be19fb10f549be8c1bf013e8675b4066c445e36eb76d2ebb2f54ee495" +dependencies = [ + "euclid", + "svg_fmt", +] + [[package]] name = "euclid" version = "0.22.10" @@ -1690,14 +1840,10 @@ dependencies = [ ] [[package]] -name = "expat-sys" -version = "2.1.6" +name = "fast-srgb8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] name = "fastrand" @@ -1735,9 +1881,9 @@ dependencies = [ "glow 0.12.3", "image", "imgref", - "lru", + "lru 0.10.1", "rgb", - "rustybuzz", + "rustybuzz 0.7.0", "unicode-bidi", "unicode-segmentation", "wasm-bindgen", @@ -1755,19 +1901,16 @@ dependencies = [ ] [[package]] -name = "float-ord" -version = "0.2.0" +name = "float-cmp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" [[package]] name = "float_next_after" -version = "0.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632" -dependencies = [ - "num-traits", -] +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" [[package]] name = "fluent-bundle" @@ -1810,37 +1953,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "font-kit" -version = "0.10.1" +name = "font-types" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" +checksum = "8f0189ccb084f77c5523e08288d418cbaa09c451a08515678a0aa265df9a8b60" dependencies = [ - "bitflags 1.3.2", - "byteorder", - "core-foundation", - "core-graphics", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype", - "lazy_static", - "libc", - "log", - "pathfinder_geometry", - "pathfinder_simd", - "servo-fontconfig", - "walkdir", - "winapi", + "bytemuck", ] [[package]] -name = "font-types" -version = "0.6.0" +name = "fontconfig-parser" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0189ccb084f77c5523e08288d418cbaa09c451a08515678a0aa265df9a8b60" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" dependencies = [ - "bytemuck", + "roxmltree", ] [[package]] @@ -1856,41 +1983,75 @@ dependencies = [ "ttf-parser 0.19.2", ] +[[package]] +name = "fontdb" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2 0.9.5", + "slotmap", + "tinyvec", + "ttf-parser 0.20.0", +] + +[[package]] +name = "fontdb" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2 0.9.5", + "slotmap", + "tinyvec", + "ttf-parser 0.21.1", +] + [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "foreign-types" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] [[package]] -name = "freetype" -version = "0.7.0" +name = "foreign-types-macros" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ - "freetype-sys", - "libc", + "proc-macro2", + "quote", + "syn 2.0.75", ] [[package]] -name = "freetype-sys" -version = "0.13.1" +name = "foreign-types-shared" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", -] +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "futures" @@ -2115,6 +2276,16 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.29.0" @@ -2134,12 +2305,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.10.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579160312273c954cc51bd440f059dde741029ac8daf8c84fece76cb77f62c15" -dependencies = [ - "version_check", -] +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" [[package]] name = "glob" @@ -2147,30 +2315,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "glow" version = "0.12.3" @@ -2195,18 +2339,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "glow_glyph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4e62c64947b9a24fe20e2bba9ad819ecb506ef5c8df7ffc4737464c6df9510" -dependencies = [ - "bytemuck", - "glow 0.11.2", - "glyph_brush", - "log", -] - [[package]] name = "glutin" version = "0.30.10" @@ -2214,15 +2346,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc93b03242719b8ad39fb26ed2b01737144ce7bd4bfc7adadcef806596760fe" dependencies = [ "bitflags 1.3.2", - "cfg_aliases", + "cfg_aliases 0.1.1", "cgl", - "core-foundation", + "core-foundation 0.9.4", "dispatch", "glutin_egl_sys", "glutin_glx_sys", - "glutin_wgl_sys", + "glutin_wgl_sys 0.4.0", "libloading 0.7.4", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", "raw-window-handle 0.5.2", "windows-sys 0.45.0", @@ -2235,7 +2367,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" dependencies = [ - "cfg_aliases", + "cfg_aliases 0.1.1", "glutin", "raw-window-handle 0.5.2", "winit", @@ -2271,52 +2403,95 @@ dependencies = [ ] [[package]] -name = "glyph_brush" -version = "0.7.9" +name = "glutin_wgl_sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca26e3a8a43052ca015c0b1ce055035ff5bc47afddff5b01c7141e0c3e3a2a1" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "ordered-float", - "rustc-hash 2.0.0", - "twox-hash", + "gl_generator", ] [[package]] -name = "glyph_brush_draw_cache" -version = "0.1.6" +name = "goblin" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6c910def52365fef3f439a6b50a4d5c11b28eec4cf6c191f6dfea18e88d7f" +checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash 2.0.0", + "log", + "plain", + "scroll", ] [[package]] -name = "glyph_brush_layout" -version = "0.2.4" +name = "gpu-alloc" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1e288bfd2f6c0313f78bf5aa538356ad481a3bb97e9b7f93220ab0066c5992" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "ab_glyph", - "approx 0.5.1", - "xi-unicode", + "bitflags 2.6.0", + "gpu-alloc-types", ] [[package]] -name = "goblin" -version = "0.6.1" +name = "gpu-alloc-types" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" dependencies = [ "log", - "plain", - "scroll", + "presser", + "thiserror", + "winapi", + "windows 0.52.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" +dependencies = [ + "bitflags 2.6.0", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", ] [[package]] @@ -2324,6 +2499,25 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.6.0", + "com", + "libc", + "libloading 0.7.4", + "thiserror", + "widestring", + "winapi", +] [[package]] name = "heck" @@ -2358,6 +2552,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -2383,94 +2583,170 @@ dependencies = [ [[package]] name = "iced_baseview" -version = "0.0.3" -source = "git+https://github.com/robbert-vdh/iced_baseview.git?branch=feature/update-baseview#df3a852a15cf0e9fcc8d2b32f5718e56780beaf3" +version = "0.1.0" +source = "git+https://github.com/BillyDM/iced_baseview.git?rev=a0842a8205c852127981e27de6342cf2e665562f#a0842a8205c852127981e27de6342cf2e665562f" dependencies = [ - "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25)", - "copypasta 0.7.1", - "iced_core", - "iced_futures", - "iced_glow", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=579130ecb4f9f315ae52190af42f0ea46aeaa4a2)", + "cfg-if", "iced_graphics", - "iced_native", + "iced_renderer", + "iced_runtime", + "iced_widget", "keyboard-types", - "raw-window-handle 0.4.3", + "log", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "thiserror", + "window_clipboard", ] [[package]] name = "iced_core" -version = "0.4.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0013a238275494641bf8f1732a23a808196540dc67b22ff97099c044ae4c8a1c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", + "bytes", + "glam", + "log", + "num-traits", + "once_cell", "palette", - "wasm-timer", + "rustc-hash 2.0.0", + "smol_str", + "thiserror", + "web-time", ] [[package]] name = "iced_futures" -version = "0.3.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c04a6745ba2e80f32cf01e034fd00d853aa4f4cd8b91888099cb7aaee0d5d7c" dependencies = [ - "async-std", "futures", + "iced_core", "log", - "smol", - "tokio", + "rustc-hash 2.0.0", "wasm-bindgen-futures", "wasm-timer", ] [[package]] -name = "iced_glow" -version = "0.2.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_glyphon" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c3bb56f1820ca252bc1d0994ece33d233a55657c0c263ea7cb16895adbde82" dependencies = [ - "bytemuck", - "euclid", - "glow 0.11.2", - "glow_glyph", - "glyph_brush", - "iced_graphics", - "iced_native", - "log", + "cosmic-text 0.12.1", + "etagere", + "lru 0.12.5", + "rustc-hash 2.0.0", + "wgpu", ] [[package]] name = "iced_graphics" -version = "0.2.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba25a18cfa6d5cc160aca7e1b34f73ccdff21680fa8702168c09739767b6c66f" dependencies = [ + "bitflags 2.6.0", "bytemuck", - "font-kit", - "glam", - "iced_native", - "iced_style", - "lyon", - "qrcode", - "raw-window-handle 0.4.3", + "cosmic-text 0.12.1", + "half", + "iced_core", + "iced_futures", + "image", + "kamadak-exif", + "log", + "lyon_path", + "once_cell", + "raw-window-handle 0.6.2", + "rustc-hash 2.0.0", "thiserror", + "unicode-segmentation", ] [[package]] -name = "iced_native" -version = "0.4.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_renderer" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73558208059f9e622df2bf434e044ee2f838ce75201a023cf0ca3e1244f46c2a" +dependencies = [ + "iced_graphics", + "iced_tiny_skia", + "iced_wgpu", + "log", + "thiserror", +] + +[[package]] +name = "iced_runtime" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348b5b2c61c934d88ca3b0ed1ed913291e923d086a66fa288ce9669da9ef62b5" dependencies = [ + "bytes", "iced_core", "iced_futures", - "iced_style", - "num-traits", - "twox-hash", - "unicode-segmentation", + "raw-window-handle 0.6.2", + "thiserror", ] [[package]] -name = "iced_style" -version = "0.3.0" -source = "git+https://github.com/iced-rs/iced.git?rev=a53fa91e0ddf374bbeb66d5e831b79127ed47a9d#a53fa91e0ddf374bbeb66d5e831b79127ed47a9d" +name = "iced_tiny_skia" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c625d368284fcc43b0b36b176f76eff1abebe7959dd58bd8ce6897d641962a50" dependencies = [ - "iced_core", + "bytemuck", + "cosmic-text 0.12.1", + "iced_graphics", + "kurbo 0.10.4", + "log", + "resvg", + "rustc-hash 2.0.0", + "softbuffer", + "tiny-skia", +] + +[[package]] +name = "iced_wgpu" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15708887133671d2bcc6c1d01d1f176f43a64d6cdc3b2bf893396c3ee498295f" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "futures", + "glam", + "guillotiere", + "iced_glyphon", + "iced_graphics", + "log", + "lyon", + "once_cell", + "resvg", + "rustc-hash 2.0.0", + "thiserror", + "wgpu", +] + +[[package]] +name = "iced_widget" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81429e1b950b0e4bca65be4c4278fea6678ea782030a411778f26fa9f8983e1d" +dependencies = [ + "iced_renderer", + "iced_runtime", + "num-traits", + "once_cell", + "rustc-hash 2.0.0", + "thiserror", + "unicode-segmentation", ] [[package]] @@ -2486,6 +2762,12 @@ dependencies = [ "png", ] +[[package]] +name = "imagesize" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" + [[package]] name = "imgref" version = "1.10.1" @@ -2623,6 +2905,12 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.70" @@ -2632,6 +2920,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kamadak-exif" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077" +dependencies = [ + "mutate_once", +] + [[package]] name = "keyboard-types" version = "0.6.2" @@ -2641,6 +2938,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.5", + "pkg-config", +] + [[package]] name = "khronos_api" version = "3.1.0" @@ -2648,12 +2956,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] -name = "kv-log-macro" -version = "1.0.7" +name = "kurbo" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +checksum = "1618d4ebd923e97d67e7cd363d80aef35fe961005cbbbb3d2dad8bdd1bc63440" dependencies = [ - "log", + "arrayvec", + "smallvec", +] + +[[package]] +name = "kurbo" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" +dependencies = [ + "arrayvec", + "smallvec", ] [[package]] @@ -2717,22 +3036,6 @@ dependencies = [ "redox_syscall 0.4.1", ] -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2745,6 +3048,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "linux-raw-sys" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" + [[package]] name = "lock_api" version = "0.4.12" @@ -2760,9 +3069,6 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -dependencies = [ - "value-bag", -] [[package]] name = "loudness_war_winner" @@ -2777,11 +3083,17 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" + [[package]] name = "lyon" -version = "0.17.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb" +checksum = "91e7f9cda98b5430809e63ca5197b06c7d191bf7e26dfc467d5a3f0290e2a74f" dependencies = [ "lyon_algorithms", "lyon_tessellation", @@ -2789,42 +3101,44 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "0.17.7" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a" +checksum = "a3bca95f9a4955b3e4a821fbbcd5edfbd9be2a9a50bb5758173e5358bfb4c623" dependencies = [ "lyon_path", - "sid", + "num-traits", ] [[package]] name = "lyon_geom" -version = "0.17.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d89ccbdafd83d259403e22061be27bccc3254bba65cdc5303250c4227c8c8e" +checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" dependencies = [ - "arrayvec 0.5.2", + "arrayvec", "euclid", "num-traits", ] [[package]] name = "lyon_path" -version = "0.17.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0" +checksum = "8e0b8aec2f58586f6eef237985b9a9b7cb3a3aff4417c575075cf95bf925252e" dependencies = [ "lyon_geom", + "num-traits", ] [[package]] name = "lyon_tessellation" -version = "0.17.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760" +checksum = "579d42360a4b09846eff2feef28f538696c7d6c7439bfa65874ff3cbe0951b2c" dependencies = [ "float_next_after", "lyon_path", + "num-traits", ] [[package]] @@ -2859,18 +3173,18 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" dependencies = [ "libc", ] [[package]] name = "memmap2" -version = "0.6.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -2902,6 +3216,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-graphics-types 0.1.3", + "foreign-types 0.5.0", + "log", + "objc", + "paste", +] + [[package]] name = "midi-consts" version = "0.1.0" @@ -2968,6 +3297,32 @@ dependencies = [ "smallvec", ] +[[package]] +name = "mutate_once" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" + +[[package]] +name = "naga" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" +dependencies = [ + "bit-set", + "bitflags 2.6.0", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash 1.1.0", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + [[package]] name = "ndk" version = "0.7.0" @@ -3040,7 +3395,7 @@ version = "0.0.0" dependencies = [ "anyhow", "anymap", - "approx 0.5.1", + "approx", "assert_no_alloc", "atomic_float", "atomic_refcell", @@ -3050,7 +3405,7 @@ dependencies = [ "cfg-if", "clap", "clap-sys", - "core-foundation", + "core-foundation 0.9.4", "cpal", "crossbeam", "jack", @@ -3105,12 +3460,13 @@ name = "nih_plug_iced" version = "0.0.0" dependencies = [ "atomic_refcell", - "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=1d9806d5bd92275d0d8142d9c9c90198757b9b25)", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=579130ecb4f9f315ae52190af42f0ea46aeaa4a2)", "crossbeam", + "futures-util", "iced_baseview", "nih_plug", "nih_plug_assets", - "raw-window-handle 0.4.3", + "raw-window-handle 0.5.2", "serde", ] @@ -3233,6 +3589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3324,6 +3681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", + "objc_exception", ] [[package]] @@ -3344,23 +3702,131 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" [[package]] -name = "objc2" -version = "0.3.0-beta.3.patch-leaks.3" +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.3.0-beta.3.patch-leaks.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" +dependencies = [ + "block2 0.2.0-alpha.6", + "objc-sys 0.2.0-beta.2", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys 0.3.5", + "objc2-encode 4.0.3", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-encode" +version = "2.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +dependencies = [ + "objc-sys 0.2.0-beta.2", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "block2", - "objc-sys", - "objc2-encode", + "bitflags 2.6.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation", + "objc2-metal", ] [[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" +name = "objc_exception" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" dependencies = [ - "objc-sys", + "cc", ] [[package]] @@ -3426,16 +3892,7 @@ version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox 0.0.2", -] - -[[package]] -name = "ordered-float" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" -dependencies = [ - "num-traits", + "libredox", ] [[package]] @@ -3459,26 +3916,26 @@ dependencies = [ [[package]] name = "palette" -version = "0.5.0" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05c0334468e62a4dfbda34b29110aa7d70d58c7fdb2c9857b5874dd9827cc59" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ - "approx 0.3.2", - "num-traits", + "approx", + "fast-srgb8", "palette_derive", - "phf 0.8.0", - "phf_codegen", + "phf 0.11.2", ] [[package]] name = "palette_derive" -version = "0.5.0" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b4b5f600e60dd3a147fb57b4547033d382d1979eb087af310e91cb45a63b1f4" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" dependencies = [ + "by_address", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.75", ] [[package]] @@ -3547,25 +4004,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf07ef4804cfa9aea3b04a7bbdd5a40031dbb6b4f2cbaf2b011666c80c5b4f2" -dependencies = [ - "rustc_version", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3587,11 +4025,21 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "phf_macros", + "phf_macros 0.10.0", "phf_shared 0.10.0", "proc-macro-hack", ] +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros 0.11.2", + "phf_shared 0.11.2", +] + [[package]] name = "phf_codegen" version = "0.8.0" @@ -3622,6 +4070,16 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + [[package]] name = "phf_macros" version = "0.10.0" @@ -3636,13 +4094,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.75", +] + [[package]] name = "phf_shared" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] @@ -3651,9 +4122,24 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher 0.3.11", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -3763,6 +4249,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "primal-check" version = "0.3.4" @@ -3806,6 +4298,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" + [[package]] name = "puberty_simulator" version = "0.1.0" @@ -3814,20 +4312,11 @@ dependencies = [ "realfft", ] -[[package]] -name = "qrcode" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" -dependencies = [ - "checked_int_cast", -] - [[package]] name = "quick-xml" -version = "0.22.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] @@ -3931,6 +4420,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "range-alloc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" + [[package]] name = "rangemap" version = "1.5.1" @@ -3939,18 +4434,15 @@ checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" [[package]] name = "raw-window-handle" -version = "0.4.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" -dependencies = [ - "cty", -] +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "raw-window-handle" -version = "0.5.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "rayon" @@ -4027,17 +4519,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "redox_users" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" -dependencies = [ - "getrandom 0.2.15", - "libredox 0.1.3", - "thiserror", -] - [[package]] name = "reflink" version = "0.1.3" @@ -4076,6 +4557,28 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "resvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" +dependencies = [ + "gif", + "jpeg-decoder", + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", +] + [[package]] name = "rgb" version = "0.8.48" @@ -4085,6 +4588,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rtrb" version = "0.2.3" @@ -4174,12 +4683,29 @@ dependencies = [ "libm", "smallvec", "ttf-parser 0.18.1", - "unicode-bidi-mirroring", - "unicode-ccc", + "unicode-bidi-mirroring 0.1.0", + "unicode-ccc 0.1.2", "unicode-general-category", "unicode-script", ] +[[package]] +name = "rustybuzz" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.21.1", + "unicode-bidi-mirroring 0.2.0", + "unicode-ccc 0.2.0", + "unicode-properties", + "unicode-script", +] + [[package]] name = "ryu" version = "1.0.18" @@ -4326,27 +4852,6 @@ dependencies = [ "serde", ] -[[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - [[package]] name = "sha1" version = "0.10.6" @@ -4364,15 +4869,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "sid" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb" -dependencies = [ - "num-traits", -] - [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -4388,6 +4884,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + [[package]] name = "sine" version = "0.1.0" @@ -4401,6 +4906,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "skrifa" version = "0.20.0" @@ -4437,47 +4948,47 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay-client-toolkit" -version = "0.16.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 1.3.2", - "dlib", - "lazy_static", + "bitflags 2.6.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", "log", - "memmap2 0.5.10", - "nix 0.24.3", - "pkg-config", + "memmap2 0.9.5", + "rustix 0.38.34", + "thiserror", + "wayland-backend", "wayland-client", + "wayland-csd-frame", "wayland-cursor", "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner 0.31.5", + "xkeysym", ] [[package]] name = "smithay-clipboard" -version = "0.6.6" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ + "libc", "smithay-client-toolkit", - "wayland-client", + "wayland-backend", ] [[package]] -name = "smol" -version = "1.3.0" +name = "smol_str" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ - "async-channel 1.9.0", - "async-executor", - "async-fs", - "async-io 1.13.0", - "async-lock 2.8.0", - "async-net", - "async-process", - "blocking", - "futures-lite 1.13.0", + "serde", ] [[package]] @@ -4494,10 +5005,42 @@ dependencies = [ name = "soft_vacuum" version = "0.1.0" dependencies = [ - "approx 0.5.1", + "approx", "nih_plug", ] +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "cfg_aliases 0.2.1", + "core-graphics 0.24.0", + "drm", + "fastrand 2.1.0", + "foreign-types 0.5.0", + "js-sys", + "log", + "memmap2 0.9.5", + "objc2 0.5.2", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle 0.6.2", + "redox_syscall 0.5.3", + "rustix 0.38.34", + "tiny-xlib", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.59.0", + "x11rb 0.13.1", +] + [[package]] name = "spectral_compressor" version = "0.4.3" @@ -4512,6 +5055,15 @@ dependencies = [ "triple_buffer", ] +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -4532,12 +5084,37 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "svg_fmt" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" + +[[package]] +name = "svgtypes" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" +dependencies = [ + "kurbo 0.11.1", + "siphasher 1.0.1", +] + [[package]] name = "swash" version = "0.1.18" @@ -4657,19 +5234,58 @@ dependencies = [ ] [[package]] -name = "time-core" -version = "0.1.2" +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] [[package]] -name = "time-macros" -version = "0.2.18" +name = "tiny-xlib" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "1d52f22673960ad13af14ff4025997312def1223bfa7c8e4949d099e6b3d5d1c" dependencies = [ - "num-conv", - "time-core", + "as-raw-xcb-connection", + "ctor-lite", + "libloading 0.8.5", + "pkg-config", + "tracing", ] [[package]] @@ -4696,16 +5312,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "1.39.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" -dependencies = [ - "backtrace", - "pin-project-lite", -] - [[package]] name = "toml" version = "0.7.8" @@ -4815,20 +5421,21 @@ checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" [[package]] name = "ttf-parser" -version = "0.24.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] -name = "twox-hash" -version = "1.6.3" +name = "ttf-parser" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "rand 0.8.5", - "static_assertions", -] +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "ttf-parser" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "type-map" @@ -4911,12 +5518,24 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" +[[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.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" +[[package]] +name = "unicode-ccc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" + [[package]] name = "unicode-general-category" version = "0.6.0" @@ -4935,6 +5554,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-script" version = "0.5.6" @@ -4947,6 +5572,51 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "usvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb 0.18.0", + "imagesize", + "kurbo 0.11.1", + "log", + "pico-args", + "roxmltree", + "rustybuzz 0.14.1", + "simplecss", + "siphasher 1.0.1", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + [[package]] name = "utf8parse" version = "0.2.2" @@ -4962,12 +5632,6 @@ dependencies = [ "getrandom 0.2.15", ] -[[package]] -name = "value-bag" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" - [[package]] name = "version_check" version = "0.9.5" @@ -5007,7 +5671,7 @@ dependencies = [ "bitflags 2.6.0", "chrono", "copypasta 0.8.2", - "cosmic-text", + "cosmic-text 0.8.0", "femtovg", "fluent-bundle", "fluent-langneg", @@ -5258,54 +5922,76 @@ dependencies = [ ] [[package]] -name = "wayland-client" -version = "0.29.5" +name = "wayland-backend" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ - "bitflags 1.3.2", + "cc", "downcast-rs", - "libc", - "nix 0.24.3", + "rustix 0.38.34", "scoped-tls", - "wayland-commons", - "wayland-scanner", + "smallvec", "wayland-sys", ] [[package]] -name = "wayland-commons" -version = "0.29.5" +name = "wayland-client" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys", + "bitflags 2.6.0", + "rustix 0.38.34", + "wayland-backend", + "wayland-scanner 0.31.5", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.6.0", + "cursor-icon", + "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.29.5" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" dependencies = [ - "nix 0.24.3", + "rustix 0.38.34", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.29.5" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner 0.31.5", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", "wayland-client", - "wayland-commons", - "wayland-scanner", + "wayland-protocols", + "wayland-scanner 0.31.5", ] [[package]] @@ -5319,14 +6005,26 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + [[package]] name = "wayland-sys" -version = "0.29.5" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" dependencies = [ "dlib", - "lazy_static", + "log", + "once_cell", "pkg-config", ] @@ -5340,6 +6038,129 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "wgpu" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases 0.1.1", + "js-sys", + "log", + "naga", + "parking_lot 0.11.2", + "profiling", + "raw-window-handle 0.6.2", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.6.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot 0.11.2", + "profiling", + "raw-window-handle 0.6.2", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfabcfc55fd86611a855816326b2d54c3b2fd7972c27ce414291562650552703" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.6.0", + "block", + "cfg_aliases 0.1.1", + "core-graphics-types 0.1.3", + "d3d12", + "glow 0.13.1", + "glutin_wgl_sys 0.5.0", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.7.4", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot 0.11.2", + "profiling", + "range-alloc", + "raw-window-handle 0.6.2", + "renderdoc-sys", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" +dependencies = [ + "bitflags 2.6.0", + "js-sys", + "web-sys", +] + [[package]] name = "widestring" version = "1.1.0" @@ -5386,6 +6207,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "window_clipboard" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d692d46038c433f9daee7ad8757e002a4248c20b0a3fbc991d99521d3bcb6d" +dependencies = [ + "clipboard-win 5.4.0", + "clipboard_macos", + "clipboard_wayland", + "clipboard_x11", + "raw-window-handle 0.6.2", + "thiserror", +] + [[package]] name = "windows" version = "0.43.0" @@ -5421,6 +6256,16 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.54.0" @@ -5718,23 +6563,23 @@ checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" dependencies = [ "android-activity", "bitflags 1.3.2", - "cfg_aliases", - "core-foundation", - "core-graphics", + "cfg_aliases 0.1.1", + "core-foundation 0.9.4", + "core-graphics 0.22.3", "dispatch", "instant", "libc", "log", "mio", "ndk 0.7.0", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", "orbclient", "percent-encoding", "raw-window-handle 0.5.2", "redox_syscall 0.3.5", "wasm-bindgen", - "wayland-scanner", + "wayland-scanner 0.29.5", "web-sys", "windows-sys 0.45.0", "x11-dl", @@ -5749,15 +6594,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - [[package]] name = "x11" version = "2.21.0" @@ -5768,15 +6604,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11-clipboard" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" -dependencies = [ - "xcb 0.10.1", -] - [[package]] name = "x11-clipboard" version = "0.7.1" @@ -5829,6 +6656,8 @@ dependencies = [ "as-raw-xcb-connection", "gethostname 0.4.3", "libc", + "libloading 0.8.5", + "once_cell", "rustix 0.38.34", "x11rb-protocol 0.13.1", ] @@ -5859,17 +6688,6 @@ dependencies = [ "x11", ] -[[package]] -name = "xcb" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" -dependencies = [ - "libc", - "log", - "quick-xml", -] - [[package]] name = "xcb-util" version = "0.3.0" @@ -5877,7 +6695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43893e47f27bf7d81d489feef3a0e34a457e90bc314b7e74ad9bb3980e4c1c48" dependencies = [ "libc", - "xcb 0.9.0", + "xcb", ] [[package]] @@ -5897,10 +6715,10 @@ dependencies = [ ] [[package]] -name = "xi-unicode" -version = "0.3.0" +name = "xkeysym" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" @@ -5908,6 +6726,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "xtask" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 76929e8e..cb2d5e5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,14 @@ assert_process_allocs = ["dep:assert_no_alloc"] # Enables an export target for standalone binaries through the # `nih_export_standalone()` function. Disabled by default as this requires # building additional dependencies for audio and MIDI handling. -standalone = ["dep:baseview", "dep:clap", "dep:cpal", "dep:jack", "dep:midir", "dep:rtrb"] +standalone = [ + "dep:baseview", + "dep:clap", + "dep:cpal", + "dep:jack", + "dep:midir", + "dep:rtrb", +] # Enables the `nih_export_vst3!()` macro. Enabled by default. This feature # exists mostly for GPL-compliance reasons, since even if you don't use the VST3 # wrapper you might otherwise still include a couple (unused) symbols from the @@ -83,7 +90,7 @@ backtrace = "0.3.65" bitflags = "1.3" cfg-if = "1.0" # This supports CLAP 1.1.8 -clap-sys = { git = "https://github.com/robbert-vdh/clap-sys.git", branch = "feature/cstr-macro" } +clap-sys = { git = "https://github.com/robbert-vdh/clap-sys.git", branch = "feature/cstr-macro" } crossbeam = "0.8" log = { version = "0.4", features = ["std", "release_max_level_info"] } midi-consts = "0.1" @@ -95,14 +102,20 @@ serde_json = "1.0" widestring = "1.0.0-beta.1" # Used for the `assert_process_allocs` feature -assert_no_alloc = { git = "https://github.com/robbert-vdh/rust-assert-no-alloc.git", branch = "feature/nested-permit-forbid", features = ["backtrace", "log"], optional = true } +assert_no_alloc = { git = "https://github.com/robbert-vdh/rust-assert-no-alloc.git", branch = "feature/nested-permit-forbid", features = [ + "backtrace", + "log", +], optional = true } # Used for the `standalone` feature # NOTE: OpenGL support is not needed here, but rust-analyzer gets confused when # some crates do use it and others don't -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "579130ecb4f9f315ae52190af42f0ea46aeaa4a2", features = ["opengl"], optional = true } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "579130ecb4f9f315ae52190af42f0ea46aeaa4a2", default_features = false, optional = true } # All the claps! -clap = { version = "4.1.8", features = ["derive", "wrap_help"], optional = true } +clap = { version = "4.1.8", features = [ + "derive", + "wrap_help", +], optional = true } cpal = { version = "0.15", optional = true } jack = { version = "0.11.4", optional = true } midir = { version = "0.9.1", optional = true } diff --git a/config.toml b/config.toml new file mode 100644 index 00000000..18825b8d --- /dev/null +++ b/config.toml @@ -0,0 +1,2 @@ +[env] +RUST_LOG = "info" diff --git a/nih_plug_iced/Cargo.toml b/nih_plug_iced/Cargo.toml index 7b2c9839..35f55d23 100644 --- a/nih_plug_iced/Cargo.toml +++ b/nih_plug_iced/Cargo.toml @@ -8,7 +8,7 @@ license = "ISC" description = "An adapter to use iced GUIs with NIH-plug" [features] -default = ["opengl"] +default = [] # NOTE: wgpu support has been removed from the iced-baseview fork out because # this old iced version uses a wgpu version that doesn't pin the web-sys @@ -20,40 +20,18 @@ default = ["opengl"] # wgpu = ["iced_baseview/wgpu", "baseview/opengl"] # Use OpenGL instead of wgpu for the rendering. This should increase platform # compatibility at the cost of some iced features not being available. -opengl = ["iced_baseview/glow"] +# opengl = ["iced_baseview/glow"] # Enables a debug view in native platforms (press F12) debug = ["iced_baseview/debug"] -# # Enables the `Image` widget, only supported by the wgpu backend -# wgpu_image = ["iced_baseview/wgpu_image"] -# # Enables the `Svg` widget, only supported by the wgpu backend -# wgpu_svg = ["iced_baseview/wgpu_svg"] - -# # Enables the `Canvas` widget for the wgpu backend -# wgpu_canvas = ["iced_baseview/wgpu_canvas"] -# Enables the `Canvas` widget for the OpenGL backend -opengl_canvas = ["iced_baseview/glow_canvas"] - -# # Enables the `QRCode` widget for the wgpu backend -# wgpu_qr_code = ["iced_baseview/wgpu_qr_code"] -# Enables the `QRCode` widget for the OpenGL backend -opengl_qr_code = ["iced_baseview/glow_qr_code"] - -# # Enables using system fonts for the wgpu backend -# wgpu_default_system_font = ["iced_baseview/wgpu_default_system_font"] -# Enables using system fonts for the OpenGL backend -opengl_default_system_font = ["iced_baseview/glow_default_system_font"] - -# Enables advanced color conversion via `palette` -palette = ["iced_baseview/palette"] - -# Enables `tokio` as the `executor::Default` on native platforms -tokio = ["iced_baseview/tokio"] -# Enables `async-std` as the `executor::Default` on native platforms -async-std = ["iced_baseview/async-std"] -# Enables `smol` as the `executor::Default` on native platforms -smol = ["iced_baseview/smol"] +wgpu = ["iced_baseview/wgpu"] +# Enables the `Image` widget, only supported by the wgpu backend +image = ["iced_baseview/image"] +# Enables the `Svg` widget, only supported by the wgpu backend +svg = ["iced_baseview/svg"] +# Enables the `Canvas` widget for the wgpu backend +canvas = ["iced_baseview/canvas"] [dependencies] nih_plug = { path = "..", default-features = false } @@ -61,12 +39,14 @@ nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" } # The currently targeted version of baseview uses a different version of # `raw_window_handle` than NIH-plug, so we need to manually convert between them -raw-window-handle = "0.4" +raw-window-handle = "0.5" atomic_refcell = "0.1" -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "1d9806d5bd92275d0d8142d9c9c90198757b9b25" } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "579130ecb4f9f315ae52190af42f0ea46aeaa4a2" } crossbeam = "0.8" -# This targets iced 0.4 -iced_baseview = { git = "https://github.com/robbert-vdh/iced_baseview.git", branch = "feature/update-baseview", default-features = false } +# This targets iced 0.10 +iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "a0842a8205c852127981e27de6342cf2e665562f", default_features = false } +futures-util = "0.3" + # To make the state persistable serde = { version = "1.0", features = ["derive"] } diff --git a/nih_plug_iced/README.md b/nih_plug_iced/README.md index 548a9d1a..c048e580 100644 --- a/nih_plug_iced/README.md +++ b/nih_plug_iced/README.md @@ -9,7 +9,7 @@ configurations. To use wgpu instead, include the crate with the following options: ```toml -nih_plug_iced = { git = "https://github.com/robbert-vdh/nih-plug.git", default-features = false, features = ["wgpu"] } +nih_plug_iced = { git = "https://github.com/robbert-vdh/nih-plug.git", default_features = false, features = ["wgpu"] } ``` Iced has many more optional features. Check the `Cargo.toml` file for more diff --git a/nih_plug_iced/src/assets.rs b/nih_plug_iced/src/assets.rs index 9a6db717..254e4963 100644 --- a/nih_plug_iced/src/assets.rs +++ b/nih_plug_iced/src/assets.rs @@ -1,46 +1,38 @@ //! Binary assets for use with `nih_plug_iced`. -use crate::Font; +use std::borrow::Cow; +use crate::core::Font; + +use iced_baseview::runtime::font; // This module provides a re-export and simple font wrappers around the re-exported fonts. pub use nih_plug_assets::*; -pub const NOTO_SANS_REGULAR: Font = Font::External { - name: "Noto Sans Regular", - bytes: fonts::NOTO_SANS_REGULAR, -}; - -pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::External { - name: "Noto Sans Regular Italic", - bytes: fonts::NOTO_SANS_REGULAR_ITALIC, -}; - -pub const NOTO_SANS_THIN: Font = Font::External { - name: "Noto Sans Thin", - bytes: fonts::NOTO_SANS_THIN, -}; - -pub const NOTO_SANS_THIN_ITALIC: Font = Font::External { - name: "Noto Sans Thin Italic", - bytes: fonts::NOTO_SANS_THIN_ITALIC, -}; - -pub const NOTO_SANS_LIGHT: Font = Font::External { - name: "Noto Sans Light", - bytes: fonts::NOTO_SANS_LIGHT, -}; - -pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::External { - name: "Noto Sans Light Italic", - bytes: fonts::NOTO_SANS_LIGHT_ITALIC, -}; - -pub const NOTO_SANS_BOLD: Font = Font::External { - name: "Noto Sans Bold", - bytes: fonts::NOTO_SANS_BOLD, -}; - -pub const NOTO_SANS_BOLD_ITALIC: Font = Font::External { - name: "Noto Sans Bold Italic", - bytes: fonts::NOTO_SANS_BOLD_ITALIC, -}; +pub const NOTO_SANS_REGULAR: Font = Font::with_name("Noto Sans Regular"); +pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::with_name("Noto Sans Regular Italic"); +pub const NOTO_SANS_THIN: Font = Font::with_name("Noto Sans Thin"); +pub const NOTO_SANS_THIN_ITALIC: Font = Font::with_name("Noto Sans Thin Italic"); +pub const NOTO_SANS_LIGHT: Font = Font::with_name("Noto Sans Light"); +pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::with_name("Noto Sans Light Italic"); +pub const NOTO_SANS_BOLD: Font = Font::with_name("Noto Sans Bold"); +pub const NOTO_SANS_BOLD_ITALIC: Font = Font::with_name("Noto Sans Bold Italic"); + +/// Useful for initializing the Settings, like this: +/// ```rust +/// Settings { +/// ... +/// fonts: noto_sans_fonts_data().into_iter().collect(), +/// } +/// ``` +pub const fn noto_sans_fonts_data() -> [Cow<'static, [u8]>; 8] { + [ + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT_ITALIC), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD), + Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD_ITALIC), + ] +} diff --git a/nih_plug_iced/src/editor.rs b/nih_plug_iced/src/editor.rs index d2984d27..92036b1e 100644 --- a/nih_plug_iced/src/editor.rs +++ b/nih_plug_iced/src/editor.rs @@ -1,20 +1,23 @@ //! And [`Editor`] implementation for iced. -use baseview::{WindowOpenOptions, WindowScalePolicy}; +use ::baseview::{WindowOpenOptions, WindowScalePolicy}; use crossbeam::atomic::AtomicCell; use crossbeam::channel; -pub use iced_baseview::*; +use iced_baseview::settings::IcedBaseviewSettings; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use std::sync::atomic::Ordering; use std::sync::Arc; +use std::{borrow::Cow, sync::atomic::Ordering}; use crate::{wrapper, IcedEditor, IcedState, ParameterUpdate}; +pub use iced_baseview::*; + /// An [`Editor`] implementation that renders an iced [`Application`]. pub(crate) struct IcedEditorWrapper { pub(crate) iced_state: Arc, pub(crate) initialization_flags: E::InitializationFlags, + pub(crate) fonts: Vec>, /// The scaling factor reported by the host, if any. On macOS this will never be set and we /// should use the system scaling factor instead. @@ -25,32 +28,6 @@ pub(crate) struct IcedEditorWrapper { pub(crate) parameter_updates_receiver: Arc>, } -/// This version of `baseview` uses a different version of `raw_window_handle than NIH-plug, so we -/// need to adapt it ourselves. -struct ParentWindowHandleAdapter(nih_plug::editor::ParentWindowHandle); - -unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { - fn raw_window_handle(&self) -> RawWindowHandle { - match self.0 { - ParentWindowHandle::X11Window(window) => { - let mut handle = raw_window_handle::XcbHandle::empty(); - handle.window = window; - RawWindowHandle::Xcb(handle) - } - ParentWindowHandle::AppKitNsView(ns_view) => { - let mut handle = raw_window_handle::AppKitHandle::empty(); - handle.ns_view = ns_view; - RawWindowHandle::AppKit(handle) - } - ParentWindowHandle::Win32Hwnd(hwnd) => { - let mut handle = raw_window_handle::Win32Handle::empty(); - handle.hwnd = hwnd; - RawWindowHandle::Win32(handle) - } - } - } -} - impl Editor for IcedEditorWrapper { fn spawn( &self, @@ -62,8 +39,14 @@ impl Editor for IcedEditorWrapper { // TODO: iced_baseview does not have gracefuly error handling for context creation failures. // This will panic if the context could not be created. - let window = IcedWindow::>::open_parented( - &ParentWindowHandleAdapter(parent), + let window = iced_baseview::open_parented::, _>( + &parent, + // We use this wrapper to be able to pass the GUI context to the editor + ( + context, + self.parameter_updates_receiver.clone(), + self.initialization_flags.clone(), + ), Settings { window: WindowOpenOptions { title: String::from("iced window"), @@ -96,19 +79,15 @@ impl Editor for IcedEditorWrapper { // FIXME: Rust analyzer always thinks baseview/opengl is enabled even if we // don't explicitly enable it, so you'd get a compile error if this line // is missing - #[cfg(not(feature = "opengl"))] - gl_config: None, + // #[cfg(not(feature = "opengl"))] + // gl_config: None, }, iced_baseview: IcedBaseviewSettings { ignore_non_modifier_keys: false, always_redraw: true, }, - // We use this wrapper to be able to pass the GUI context to the editor - flags: ( - context, - self.parameter_updates_receiver.clone(), - self.initialization_flags.clone(), - ), + fonts: self.fonts.clone(), + ..Default::default() }, ); @@ -154,7 +133,7 @@ impl Editor for IcedEditorWrapper { /// The window handle used for [`IcedEditorWrapper`]. struct IcedEditorHandle { iced_state: Arc, - window: iced_baseview::WindowHandle, + window: iced_baseview::window::WindowHandle, } /// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around diff --git a/nih_plug_iced/src/lib.rs b/nih_plug_iced/src/lib.rs index a8ae536b..d548c23b 100644 --- a/nih_plug_iced/src/lib.rs +++ b/nih_plug_iced/src/lib.rs @@ -39,7 +39,7 @@ //! fn new( //! params: Self::InitializationFlags, //! context: Arc, -//! ) -> (Self, Command) { +//! ) -> (Self, Task) { //! let editor = FooEditor { //! params, //! context, @@ -47,7 +47,7 @@ //! foo_slider_state: Default::default(), //! }; //! -//! (editor, Command::none()) +//! (editor, Task::none()) //! } //! //! fn context(&self) -> &dyn GuiContext { @@ -56,14 +56,13 @@ //! //! fn update( //! &mut self, -//! _window: &mut WindowQueue, //! message: Self::Message, -//! ) -> Command { +//! ) -> Task { //! match message { //! Message::ParamUpdate(message) => self.handle_param_message(message), //! } //! -//! Command::none() +//! Task::none() //! } //! //! fn view(&mut self) -> Element<'_, Self::Message> { @@ -89,12 +88,14 @@ //! } //! ``` -use baseview::WindowScalePolicy; +use ::baseview::WindowScalePolicy; use crossbeam::atomic::AtomicCell; use crossbeam::channel; +use iced_baseview::futures::Subscription; use nih_plug::params::persist::PersistentField; use nih_plug::prelude::{Editor, GuiContext}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; // This doesn't need to be re-export but otherwise the compiler complains about // `hidden_glob_reexports` pub use std::fmt::Debug; @@ -126,6 +127,7 @@ mod wrapper; pub fn create_iced_editor( iced_state: Arc, initialization_flags: E::InitializationFlags, + fonts: Vec>, ) -> Option> { // We need some way to communicate parameter changes to the `IcedEditor` since parameter updates // come from outside of the editor's reactive model. This contains only capacity to store only @@ -147,6 +149,7 @@ pub fn create_iced_editor( parameter_updates_sender, parameter_updates_receiver: Arc::new(parameter_updates_receiver), + fonts, })) } @@ -162,12 +165,14 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { type Message: 'static + Clone + Debug + Send; /// See [`Application::Flags`]. type InitializationFlags: 'static + Clone + Send + Sync; + /// See [`Application::Theme`] + type Theme: Default + DefaultStyle; /// See [`Application::new`]. This also receivs the GUI context in addition to the flags. fn new( initialization_fags: Self::InitializationFlags, context: Arc, - ) -> (Self, Command); + ) -> (Self, Task); /// Returns a reference to the GUI context. /// [`handle_param_message()`][Self::handle_param_message()] uses this to interact with the @@ -177,11 +182,7 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { /// See [`Application::update`]. When receiving the variant that contains a /// [`widgets::ParamMessage`] you can call /// [`handle_param_message()`][Self::handle_param_message()] to handle the parameter update. - fn update( - &mut self, - window: &mut WindowQueue, - message: Self::Message, - ) -> Command; + fn update(&mut self, message: Self::Message) -> Task; /// See [`Application::subscription`]. fn subscription( @@ -192,13 +193,21 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { } /// See [`Application::view`]. - fn view(&mut self) -> Element<'_, Self::Message>; + fn view(&self) -> Element<'_, Self::Message, Self::Theme, Renderer>; /// See [`Application::background_color`]. fn background_color(&self) -> Color { Color::WHITE } + fn theme(&self) -> Self::Theme { + Self::Theme::default() + } + + fn title(&self) -> String { + "nih_plug plugin".to_owned() + } + /// See [`Application::scale_policy`]. /// /// TODO: Is this needed? Editors shouldn't change the scale policy. @@ -206,20 +215,6 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { WindowScalePolicy::SystemScaleFactor } - /// See [`Application::renderer_settings`]. - fn renderer_settings() -> iced_baseview::backend::settings::Settings { - iced_baseview::backend::settings::Settings { - // Enable some anti-aliasing by default. Since GUIs are likely very simple and most of - // the work will be on the CPU anyways this should not affect performance much. - antialiasing: Some(iced_baseview::backend::settings::Antialiasing::MSAAx4), - // Use Noto Sans as the default font as that renders a bit more cleanly than the default - // Lato font. This crate also contains other weights and versions of this font you can - // use for individual widgets. - default_font: Some(crate::assets::fonts::NOTO_SANS_REGULAR), - ..iced_baseview::backend::settings::Settings::default() - } - } - /// Handle a parameter update using the GUI context. fn handle_param_message(&self, message: ParamMessage) { // We can't use the fancy ParamSetter here because this needs to be type erased diff --git a/nih_plug_iced/src/widgets/generic_ui.rs b/nih_plug_iced/src/widgets/generic_ui.rs index 8e975a67..212ad8cc 100644 --- a/nih_plug_iced/src/widgets/generic_ui.rs +++ b/nih_plug_iced/src/widgets/generic_ui.rs @@ -1,33 +1,30 @@ //! A simple generic UI widget that renders all parameters in a [`Params`] object as a scrollable //! list of sliders and labels. -use atomic_refcell::AtomicRefCell; -use std::borrow::Borrow; -use std::collections::HashMap; +use crate::core::{ + alignment, event, layout, renderer, text, widget::Id, widget::Operation, widget::Tree, + Clipboard, Element, Layout, Length, Rectangle, Shell, Widget, +}; +use crate::widget::{self, row, scrollable, Column, Scrollable}; +use iced_baseview::widget::Space; +use iced_baseview::Size; use std::marker::PhantomData; use std::sync::Arc; use nih_plug::prelude::{Param, ParamFlags, ParamPtr, Params}; use super::{ParamMessage, ParamSlider}; -use crate::backend::Renderer; -use crate::text::Renderer as TextRenderer; -use crate::{ - alignment, event, layout, renderer, widget, Alignment, Clipboard, Element, Event, Layout, - Length, Point, Rectangle, Row, Scrollable, Shell, Space, Text, Widget, -}; /// A widget that can be used to create a generic UI with. This is used in conjuction with empty /// structs to emulate existential types. -pub trait ParamWidget { - /// The type of state stores by this parameter type. - type State: Default; - +pub trait ParamWidget { /// Create an [`Element`] for a widget for the specified parameter. fn into_widget_element<'a, P: Param>( param: &'a P, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage>; + ) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a; /// The same as [`into_widget_element()`][Self::into_widget_element()], but for a `ParamPtr`. /// @@ -35,14 +32,17 @@ pub trait ParamWidget { /// /// Undefined behavior of the `ParamPtr` does not point to a valid parameter. unsafe fn into_widget_element_raw<'a>( - param: &ParamPtr, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage> { + param: &'a ParamPtr, + ) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a, + { match param { - ParamPtr::FloatParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::IntParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::BoolParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::EnumParam(p) => Self::into_widget_element(&**p, state), + ParamPtr::FloatParam(p) => Self::into_widget_element(&**p), + ParamPtr::IntParam(p) => Self::into_widget_element(&**p), + ParamPtr::BoolParam(p) => Self::into_widget_element(&**p), + ParamPtr::EnumParam(p) => Self::into_widget_element(&**p), } } } @@ -55,72 +55,72 @@ pub struct GenericSlider; /// determines what widget to use for this. /// /// TODO: There's no way to configure the individual widgets. -pub struct GenericUi<'a, W: ParamWidget> { - state: &'a mut State, - - params: Arc, +pub struct GenericUi { + // Hacky work around so we can borrow &ParamPtr and ensure references + // stay alive for the lifetime of this object. + params: Vec, + id: Option, width: Length, height: Length, - max_width: u32, - max_height: u32, + max_width: u16, + max_height: u16, + pad_scrollbar: bool, /// We don't emit any messages or store the actual widgets, but iced requires us to define some /// message type anyways. - _phantom: PhantomData, -} - -/// State for a [`GenericUi`]. -#[derive(Debug, Default)] -pub struct State { - /// The internal state for each parameter's widget. - scrollable_state: AtomicRefCell, - /// The internal state for each parameter's widget. - widget_state: AtomicRefCell>, + _phantom: PhantomData<(W, Theme, Renderer)>, } -impl<'a, W> GenericUi<'a, W> -where - W: ParamWidget, -{ +impl GenericUi { /// Creates a new [`GenericUi`] for all provided parameters. - pub fn new(state: &'a mut State, params: Arc) -> Self { + pub fn new(params: Arc) -> Self { + let params = params + .param_map() + .into_iter() + .map(|(_, ptr, _)| ptr) + .collect(); Self { - state, - + id: None, params, width: Length::Fill, height: Length::Fill, - max_width: u32::MAX, - max_height: u32::MAX, + max_width: u16::MAX, + max_height: u16::MAX, pad_scrollbar: false, _phantom: PhantomData, } } + /// Sets the [`Id`] of the [`Container`]. + pub fn id(mut self, id: Id) -> Self { + self.id = Some(id); + self + } + /// Sets the width of the [`GenericUi`]. - pub fn width(mut self, width: Length) -> Self { - self.width = width; + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); self } /// Sets the height of the [`GenericUi`]. - pub fn height(mut self, height: Length) -> Self { - self.height = height; + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); self } /// Sets the maximum width of the [`GenericUi`]. - pub fn max_width(mut self, width: u32) -> Self { + pub fn max_width(mut self, width: u16) -> Self { self.max_width = width; self } /// Sets the maximum height of the [`GenericUi`]. - pub fn max_height(mut self, height: u32) -> Self { + pub fn max_height(mut self, height: u16) -> Self { self.max_height = height; self } @@ -130,166 +130,203 @@ where self.pad_scrollbar = true; self } +} - /// Create a temporary [`Scrollable`]. This needs to be created on demand because it needs to - /// mutably borrow the `Scrollable`'s widget state. - fn with_scrollable_widget( +impl<'a, W, Theme, Renderer> GenericUi +where + W: ParamWidget, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, +{ + fn content( &'a self, - scrollable_state: &'a mut widget::scrollable::State, - widget_state: &'a mut HashMap, - renderer: R, - f: F, - ) -> T - where - F: FnOnce(Scrollable<'a, ParamMessage>, R) -> T, - R: Borrow, - { - let text_size = renderer.borrow().default_size(); - let spacing = (text_size as f32 * 0.2).round() as u16; - let padding = (text_size as f32 * 0.5).round() as u16; - - let mut scrollable = Scrollable::new(scrollable_state) - .width(self.width) - .height(self.height) - .max_width(self.max_width) - .max_height(self.max_height) - .spacing(spacing) - .padding(padding) - .align_items(Alignment::Center); - - // Make sure we already have widget state for each widget - let param_map = self.params.param_map(); - for (_, param_ptr, _) in ¶m_map { - let flags = unsafe { param_ptr.flags() }; - if flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) { - continue; - } - - if !widget_state.contains_key(param_ptr) { - widget_state.insert(*param_ptr, Default::default()); - } - } - - for (_, param_ptr, _) in param_map { - let flags = unsafe { param_ptr.flags() }; - if flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) { - continue; - } - - // SAFETY: We only borrow each item once, and the plugin framework statically asserted - // that parameter indices are unique and this widget state cannot outlive this - // function - let widget_state: &'a mut W::State = - unsafe { &mut *(widget_state.get_mut(¶m_ptr).unwrap() as *mut _) }; - - // Show the label next to the parameter for better use of the space - let mut row = Row::new() - .width(Length::Fill) - .align_items(Alignment::Center) - .spacing(spacing * 2) - .push( - Text::new(unsafe { param_ptr.name() }) - .height(20.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Right) - .vertical_alignment(alignment::Vertical::Center), - ) - .push(unsafe { W::into_widget_element_raw(¶m_ptr, widget_state) }); - if self.pad_scrollbar { - // There's already spacing applied, so this element doesn't actually need to hae any - // size of its own - row = row.push(Space::with_width(Length::Units(0))); - } - - scrollable = scrollable.push(row); - } - - f(scrollable, renderer) + renderer: Option<&Renderer>, + ) -> Scrollable<'a, ParamMessage, Theme, Renderer> { + let (spacing, padding) = match renderer { + Some(renderer) => ( + (renderer.default_size() * 0.2).0.round(), + (renderer.default_size() * 0.5).0.round(), + ), + None => (0.0, 0.0), + }; + + let content = Column::with_children( + self.params + .iter() + .filter(|param| is_hidden(*param)) + .map(|param| { + let row = row![ + widget::text(unsafe { param.name() }) + .height(20) + .width(Length::Fill) + .align_x(alignment::Horizontal::Right) + .align_y(alignment::Vertical::Center), + unsafe { W::into_widget_element_raw(param) } + ] + .width(Length::Fill) + .align_y(alignment::Vertical::Center) + .spacing(spacing * 2.0); + + if self.pad_scrollbar { + row.push(Space::with_width(0)) + } else { + row + } + }) + .map(Element::from), + ) + .align_x(alignment::Horizontal::Center) + .spacing(spacing) + .padding(padding) + .width(self.width) + .height(self.height) + .max_width(self.max_width); + + scrollable(content).spacing(spacing) } } -impl<'a, W> Widget for GenericUi<'a, W> +impl<'a, W, Theme, Renderer> Widget for GenericUi where - W: ParamWidget, + W: ParamWidget, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, { - fn width(&self) -> Length { - self.width + fn size(&self) -> iced_baseview::Size { + Size { + width: self.width, + height: self.height, + } } - fn height(&self) -> Length { - self.height + fn children(&self) -> Vec { + let content = self.content(None); + + vec![Tree::new( + &content as &dyn Widget, + )] } - fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, - renderer, - |scrollable, _| scrollable.layout(renderer, limits), - ) + fn layout( + &self, + tree: &mut Tree, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + self.content(Some(renderer)) + .layout(&mut tree.children[0], renderer, limits) } fn draw( &self, + tree: &iced_baseview::core::widget::Tree, renderer: &mut Renderer, + theme: &Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: iced_baseview::core::mouse::Cursor, viewport: &Rectangle, ) { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, + self.content(Some(renderer)).draw( + &tree.children[0], renderer, - |scrollable, renderer| { - scrollable.draw(renderer, style, layout, cursor_position, viewport) - }, + theme, + style, + layout, + cursor, + viewport, ) } + fn operate( + &self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn Operation, + ) { + operation.container(self.id.as_ref(), layout.bounds(), &mut |operation| { + self.content(Some(renderer)).operate( + tree, + layout.children().next().unwrap(), + renderer, + operation, + ) + }); + } + fn on_event( &mut self, - event: Event, + tree: &mut iced_baseview::core::widget::Tree, + event: event::Event, layout: Layout<'_>, - cursor_position: Point, + cursor: iced_baseview::core::mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, ParamMessage>, + viewport: &Rectangle, ) -> event::Status { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, + self.content(Some(renderer)).on_event( + &mut tree.children[0], + event, + layout.children().next().unwrap(), + cursor, + renderer, + clipboard, + shell, + viewport, + ) + } + + fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor: iced_baseview::core::mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> iced_baseview::core::mouse::Interaction { + self.content(Some(renderer)).mouse_interaction( + &tree.children[0], + layout.children().next().unwrap(), + cursor, + viewport, renderer, - |mut scrollable, _| { - scrollable.on_event(event, layout, cursor_position, renderer, clipboard, shell) - }, ) } } -impl ParamWidget for GenericSlider { - type State = super::param_slider::State; +fn is_hidden(param_ptr: &ParamPtr) -> bool { + let flags = unsafe { param_ptr.flags() }; + flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) +} - fn into_widget_element<'a, P: Param>( - param: &'a P, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage> { - ParamSlider::new(state, param).into() +impl ParamWidget for GenericSlider +where + Theme: super::param_slider::Catalog + widget::text_input::Catalog, + Renderer: text::Renderer, + Renderer::Font: From, +{ + fn into_widget_element<'a, P: Param>(param: &'a P) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a, + { + ParamSlider::new(param).into() } } -impl<'a, W: ParamWidget> GenericUi<'a, W> { +impl<'a, W, Theme, Renderer> GenericUi +where + W: ParamWidget + 'a, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, +{ /// Convert this [`GenericUi`] into an [`Element`] with the correct message. You should have a /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message> + pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, @@ -298,11 +335,14 @@ impl<'a, W: ParamWidget> GenericUi<'a, W> { } } -impl<'a, W> From> for Element<'a, ParamMessage> +impl<'a, W, Theme, Renderer> From> + for Element<'a, ParamMessage, Theme, Renderer> where - W: ParamWidget, + W: ParamWidget + 'a, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, { - fn from(widget: GenericUi<'a, W>) -> Self { + fn from(widget: GenericUi) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index fb941562..0b148996 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,20 +1,21 @@ -//! A slider that integrates with NIH-plug's [`Param`] types. - -use atomic_refcell::AtomicRefCell; +use iced_baseview::theme::palette::Pair; +use iced_baseview::{self as iced, alignment}; use nih_plug::prelude::Param; use std::borrow::Borrow; -use crate::backend::widget; -use crate::backend::Renderer; -use crate::renderer::Renderer as GraphicsRenderer; -use crate::text::Renderer as TextRenderer; -use crate::{ - alignment, event, keyboard, layout, mouse, renderer, text, touch, Background, Clipboard, Color, - Element, Event, Font, Layout, Length, Point, Rectangle, Shell, Size, TextInput, Vector, Widget, +use iced::core::event::{self, Event}; +use iced::core::layout::{self, Limits}; +use iced::core::text::{self, Paragraph, Renderer as TextRenderer, Text}; +use iced::core::widget::operation::{self}; +use iced::core::widget::tree::{self, Tree}; +use iced::core::{ + keyboard, mouse, renderer, touch, Border, Clipboard, Element, Font, Layout, Length, Padding, + Pixels, Rectangle, Shell, Size, Vector, Widget, }; +use iced::widget::text_input; +use iced::widget::text_input::{Id, TextInput}; -use super::util; -use super::ParamMessage; +use super::{util, ParamMessage}; /// When shift+dragging a parameter, one pixel dragged corresponds to this much change in the /// noramlized parameter. @@ -23,24 +24,23 @@ const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1; /// The thickness of this widget's borders. const BORDER_WIDTH: f32 = 1.0; -/// A slider that integrates with NIH-plug's [`Param`] types. -/// -/// TODO: There are currently no styling options at all -/// TODO: Handle scrolling for steps (and shift+scroll for smaller steps?) -pub struct ParamSlider<'a, P: Param> { - state: &'a mut State, - +pub struct ParamSlider<'a, P, Theme = iced::Theme> +where + P: Param, + Theme: Catalog, +{ param: &'a P, - height: Length, width: Length, - text_size: Option, - font: Font, + height: Length, + text_size: Option, + font: Option, + class: Theme::Class<'a>, } /// State for a [`ParamSlider`]. -#[derive(Debug, Default)] -pub struct State { +#[derive(Debug)] +struct State { keyboard_modifiers: keyboard::Modifiers, /// Will be set to `true` if we're dragging the parameter. Resetting the parameter or entering a /// text value should not initiate a drag. @@ -51,14 +51,37 @@ pub struct State { /// Track clicks for double clicks. last_click: Option, - /// State for the text input overlay that will be shown when this widget is alt+clicked. - text_input_state: AtomicRefCell, /// The text that's currently in the text input. If this is set to `None`, then the text input /// is not visible. text_input_value: Option, + text_input_id: Id, +} + +impl Default for State { + fn default() -> Self { + Self { + text_input_id: Id::unique(), + keyboard_modifiers: Default::default(), + drag_active: Default::default(), + granular_drag_start_x_value: Default::default(), + last_click: Default::default(), + text_input_value: Default::default(), + } + } } -/// An internal message for intercep- I mean handling output from the embedded [`TextInpu`] widget. +/// The possible UI status of a [`ParamSlider`]. Enables drawing of different styles for each status. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Status { + /// The [`ParamSlider`] can be interacted with. + Active, + /// The [`ParamSlider`] is being hovered. + Hovered, + /// The [`ParamSlider`] is being dragged. + Dragged, +} + +/// An internal message for intercep- I mean handling output from the embedded [`TextInput`] widget. #[derive(Debug, Clone)] enum TextInputMessage { /// A new value was entered in the text input dialog. @@ -67,48 +90,24 @@ enum TextInputMessage { Submit, } -/// The default text input style with the border removed. -struct TextInputStyle; - -impl widget::text_input::StyleSheet for TextInputStyle { - fn active(&self) -> widget::text_input::Style { - widget::text_input::Style { - background: Background::Color(Color::TRANSPARENT), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } - - fn focused(&self) -> widget::text_input::Style { - self.active() - } - - fn placeholder_color(&self) -> Color { - Color::from_rgb(0.7, 0.7, 0.7) - } - - fn value_color(&self) -> Color { - Color::from_rgb(0.3, 0.3, 0.3) - } - - fn selection_color(&self) -> Color { - Color::from_rgb(0.8, 0.8, 1.0) - } -} +impl<'a, P, Theme> ParamSlider<'a, P, Theme> +where + P: Param, + Theme: Catalog, +{ + pub const DEFAULT_WIDTH: Length = Length::Fixed(180.0); + pub const DEFAULT_HEIGHT: Length = Length::Fixed(30.0); -impl<'a, P: Param> ParamSlider<'a, P> { /// Creates a new [`ParamSlider`] for the given parameter. - pub fn new(state: &'a mut State, param: &'a P) -> Self { + pub fn new(param: &'a P) -> Self { Self { - state, - param, - width: Length::Units(180), - height: Length::Units(30), + width: Self::DEFAULT_WIDTH, + height: Self::DEFAULT_HEIGHT, text_size: None, - font: ::Font::default(), + font: None, + class: Theme::default(), } } @@ -125,145 +124,179 @@ impl<'a, P: Param> ParamSlider<'a, P> { } /// Sets the text size of the [`ParamSlider`]. - pub fn text_size(mut self, size: u16) -> Self { + pub fn text_size(mut self, size: Pixels) -> Self { self.text_size = Some(size); self } /// Sets the font of the [`ParamSlider`]. pub fn font(mut self, font: Font) -> Self { - self.font = font; + self.font = Some(font); self } - /// Create a temporary [`TextInput`] hooked up to [`State::text_input_value`] and outputting - /// [`TextInputMessage`] messages and do something with it. This can be used to - fn with_text_input(&self, layout: Layout, renderer: R, current_value: &str, f: F) -> T + /// Sets the style of the [`ParamSlider`]. + pub fn style(mut self, style: impl Fn(&Theme, Status) -> Style + 'a) -> Self where - F: FnOnce(TextInput<'_, TextInputMessage>, Layout, R) -> T, - R: Borrow, + Theme::Class<'a>: From>, { - let mut text_input_state = self.state.text_input_state.borrow_mut(); - text_input_state.focus(); + self.class = (Box::new(style) as StyleFn<'a, Theme>).into(); + self + } +} - let text_size = self - .text_size - .unwrap_or_else(|| renderer.borrow().default_size()); - let text_width = renderer - .borrow() - .measure_width(current_value, text_size, self.font); - let text_input = TextInput::new( - &mut text_input_state, - "", - current_value, - TextInputMessage::Value, - ) - .font(self.font) - .size(text_size) - .width(Length::Units(text_width.ceil() as u16)) - .style(TextInputStyle) - .on_submit(TextInputMessage::Submit); +impl<'a, P, Theme, Renderer> Widget for ParamSlider<'a, P, Theme> +where + P: Param, + Theme: Catalog + text_input::Catalog, + Renderer: TextRenderer, + Renderer::Font: From, +{ + fn tag(&self) -> tree::Tag { + tree::Tag::of::() + } - // Make sure to not draw over the borders, and center the text - let offset_node = layout::Node::with_children( - Size { - width: text_width, - height: layout.bounds().size().height - (BORDER_WIDTH * 2.0), - }, - vec![layout::Node::new(layout.bounds().size())], - ); - let offset_layout = Layout::with_offset( - Vector { - x: layout.bounds().center_x() - (text_width / 2.0), - y: layout.position().y + BORDER_WIDTH, - }, - &offset_node, - ); + fn state(&self) -> tree::State { + tree::State::new(State::default()) + } - f(text_input, offset_layout, renderer) + fn children(&self) -> Vec { + // One child to store text input state. + vec![Tree::empty()] } - /// Set the normalized value for a parameter if that would change the parameter's plain value - /// (to avoid unnecessary duplicate parameter changes). The begin- and end set parameter - /// messages need to be sent before calling this function. - fn set_normalized_value(&self, shell: &mut Shell<'_, ParamMessage>, normalized_value: f32) { - // This snaps to the nearest plain value if the parameter is stepped in some way. - // TODO: As an optimization, we could add a `const CONTINUOUS: bool` to the parameter to - // avoid this normalized->plain->normalized conversion for parameters that don't need - // it - let plain_value = self.param.preview_plain(normalized_value); - let current_plain_value = self.param.modulated_plain_value(); - if plain_value != current_plain_value { - // For the aforementioned snapping - let normalized_plain_value = self.param.preview_normalized(plain_value); - shell.publish(ParamMessage::SetParameterNormalized( - self.param.as_ptr(), - normalized_plain_value, - )); + fn size(&self) -> Size { + Size { + width: self.width, + height: self.height, } } -} -impl<'a, P: Param> Widget for ParamSlider<'a, P> { - fn width(&self) -> Length { - self.width + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> layout::Node { + layout::atomic(limits, self.width, self.height) } - fn height(&self) -> Length { - self.height - } + fn draw( + &self, + tree: &Tree, + renderer: &mut Renderer, + theme: &Theme, + _style: &renderer::Style, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + ) { + let state = tree.state.downcast_ref::(); + let bounds = layout.bounds(); + + let status = if state.drag_active { + Status::Dragged + } else if cursor.is_over(bounds) { + Status::Hovered + } else { + Status::Active + }; + let style = Catalog::style(theme, &self.class, status); - fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); + renderer.fill_quad( + renderer::Quad { + bounds, + border: style.border, + ..Default::default() + }, + style.background.color, + ); - layout::Node::new(size) + // Shrink bounds to inside of the border + let bounds = bounds.shrink(Padding::new(style.border.width)); + + let Some(current_value) = &state.text_input_value else { + return self.draw_bar(renderer, &style, &bounds, viewport); + }; + + self.with_text_input( + layout, + renderer, + current_value, + state, + |text_input, layout, renderer| { + text_input.draw( + &tree.children[0], + renderer, + theme, + layout, + cursor, + None, + viewport, + ); + }, + ); } fn on_event( &mut self, + tree: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, ParamMessage>, + viewport: &Rectangle, ) -> event::Status { + let state = tree.state.downcast_mut::(); + // The pressence of a value in `self.state.text_input_value` indicates that the field should // be focussed. The field handles defocussing by itself // FIMXE: This is super hacky, I have no idea how you can reuse the text input widget // otherwise. Widgets are not supposed to handle messages from other widgets, but // we'll do so anyways by using a special `TextInputMessage` type and our own // `Shell`. - let text_input_status = if let Some(current_value) = &self.state.text_input_value { + let text_input_status = if let Some(current_value) = &state.text_input_value { let event = event.clone(); let mut messages = Vec::new(); let mut text_input_shell = Shell::new(&mut messages); + let status = self.with_text_input( layout, renderer, current_value, + &state, |mut text_input, layout, renderer| { + if tree.children[0].tag != text_input.tag() { + tree.children[0] = Tree { + tag: text_input.tag(), + state: text_input.state(), + children: text_input.children(), + }; + } + text_input.on_event( + &mut tree.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, &mut text_input_shell, + viewport, ) }, ); + // Check if text input is focused. + let text_input_state = tree.children[0] + .state + .downcast_ref::>(); + // Pressing escape will unfocus the text field, so we should propagate that change in // our own model - if self.state.text_input_state.borrow().is_focused() { + if text_input_state.is_focused() { for message in messages { match message { - TextInputMessage::Value(s) => self.state.text_input_value = Some(s), + TextInputMessage::Value(s) => state.text_input_value = Some(s), TextInputMessage::Submit => { - if let Some(normalized_value) = self - .state + if let Some(normalized_value) = state .text_input_value .as_ref() .and_then(|s| self.param.string_to_normalized_value(s)) @@ -274,12 +307,12 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { } // And defocus the text input widget again - self.state.text_input_value = None; + state.text_input_value = None; } } } } else { - self.state.text_input_value = None; + state.text_input_value = None; } status @@ -290,280 +323,505 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { return event::Status::Captured; } - // Compensate for the border when handling these events - let bounds = layout.bounds(); - let bounds = Rectangle { - x: bounds.x + BORDER_WIDTH, - y: bounds.y + BORDER_WIDTH, - width: bounds.width - (BORDER_WIDTH * 2.0), - height: bounds.height - (BORDER_WIDTH * 2.0), - }; - match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if bounds.contains(cursor_position) { - let click = mouse::Click::new(cursor_position, self.state.last_click); - self.state.last_click = Some(click); - if self.state.keyboard_modifiers.alt() { - // Alt+click should not start a drag, instead it should show the text entry - // widget - self.state.drag_active = false; - - // Changing the parameter happens in the TextInput event handler above - let mut text_input_state = self.state.text_input_state.borrow_mut(); - self.state.text_input_value = Some(self.param.to_string()); - text_input_state.move_cursor_to_end(); - text_input_state.select_all(); - } else if self.state.keyboard_modifiers.command() - || matches!(click.kind(), mouse::click::Kind::Double) - { - // Likewise resetting a parameter should not let you immediately drag it to a new value - self.state.drag_active = false; - - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.set_normalized_value(shell, self.param.default_normalized_value()); - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - } else if self.state.keyboard_modifiers.shift() { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - // When holding down shift while clicking on a parameter we want to - // granuarly edit the parameter without jumping to a new value - self.state.granular_drag_start_x_value = - Some((cursor_position.x, self.param.modulated_normalized_value())); - } else { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - self.state.granular_drag_start_x_value = None; - } - - return event::Status::Captured; - } + self.handle_mouse_down_event(tree, layout, cursor, renderer, shell) } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => { - if self.state.drag_active { - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - - self.state.drag_active = false; - - return event::Status::Captured; - } + self.handle_mouse_up_event(shell, state) } Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { - // Don't do anything when we just reset the parameter because that would be weird - if self.state.drag_active { - // If shift is being held then the drag should be more granular instead of - // absolute - if self.state.keyboard_modifiers.shift() { - let (drag_start_x, drag_start_value) = *self - .state - .granular_drag_start_x_value - .get_or_insert_with(|| { - (cursor_position.x, self.param.modulated_normalized_value()) - }); - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate( - &bounds, - util::remap_rect_x_t(&bounds, drag_start_value) - + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, - ), - ); - } else { - self.state.granular_drag_start_x_value = None; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - } - - return event::Status::Captured; - } + self.handle_mouse_move_event(layout, cursor, shell, state) } Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { - self.state.keyboard_modifiers = modifiers; - - // If this happens while dragging, snap back to reality uh I mean the current screen - // position - if self.state.drag_active - && self.state.granular_drag_start_x_value.is_some() - && !modifiers.shift() - { - self.state.granular_drag_start_x_value = None; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - } - - return event::Status::Captured; + self.handle_keyboard_modifiers_changed(layout, cursor, shell, modifiers, state) } - _ => {} + _ => event::Status::Ignored, } - - event::Status::Ignored } fn mouse_interaction( &self, + _state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - let bounds = layout.bounds(); - let is_mouse_over = bounds.contains(cursor_position); - - if is_mouse_over { + if cursor.is_over(layout.bounds()) { mouse::Interaction::Pointer } else { mouse::Interaction::default() } } +} - fn draw( +// ############################################################################ +// Rendering +// ############################################################################ +impl<'a, P, Theme> ParamSlider<'a, P, Theme> +where + P: Param, + Theme: Catalog + text_input::Catalog, +{ + /// Create a temporary [`TextInput`] hooked up to [`State::text_input_value`] and outputting + /// [`TextInputMessage`] messages and do something with it. This can be used to + fn with_text_input( &self, - renderer: &mut Renderer, - style: &renderer::Style, - layout: Layout<'_>, - cursor_position: Point, - _viewport: &Rectangle, - ) { - let bounds = layout.bounds(); - // I'm sure there's some philosophical meaning behind this - let bounds_without_borders = Rectangle { - x: bounds.x + BORDER_WIDTH, - y: bounds.y + BORDER_WIDTH, - width: bounds.width - (BORDER_WIDTH * 2.0), - height: bounds.height - (BORDER_WIDTH * 2.0), - }; - let is_mouse_over = bounds.contains(cursor_position); + layout: Layout, + renderer: BorrowedRenderer, + current_value: &str, + state: &State, + f: F, + ) -> T + where + F: FnOnce(TextInput<'_, TextInputMessage, Theme, Renderer>, Layout, BorrowedRenderer) -> T, + Renderer: TextRenderer, + Renderer::Font: From, + BorrowedRenderer: Borrow, + { + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.borrow().default_font()); + + let text_size = self + .text_size + .unwrap_or_else(|| renderer.borrow().default_size()); + let text_width = Renderer::Paragraph::with_text(Text { + content: current_value, + bounds: layout.bounds().size(), + size: text_size, + font, + line_height: Default::default(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + shaping: Default::default(), + wrapping: Default::default(), + }) + .min_width(); + + let text_input = text_input("", current_value) + .id(state.text_input_id.clone()) + .font(font) + .size(text_size) + .width(text_width) + .on_input(TextInputMessage::Value) + .on_submit(TextInputMessage::Submit); + + // Make sure to not draw over the borders, and center the text + let offset_node = layout::Node::with_children( + Size { + width: text_width, + height: layout.bounds().size().height - (BORDER_WIDTH * 2.0), + }, + vec![layout::Node::new(layout.bounds().size())], + ); + let offset_layout = Layout::with_offset( + Vector { + x: layout.bounds().center_x() - (text_width / 2.0), + y: layout.position().y + BORDER_WIDTH, + }, + &offset_node, + ); + + f(text_input, offset_layout, renderer) + } - // The bar itself, show a different background color when the value is being edited or when - // the mouse is hovering over it to indicate that it's interactive - let background_color = - if is_mouse_over || self.state.drag_active || self.state.text_input_value.is_some() { - Color::new(0.5, 0.5, 0.5, 0.1) + /// Draw the bar + label for this slider + fn draw_bar( + &self, + renderer: &mut Renderer, + style: &Style, + bounds: &Rectangle, + viewport: &Rectangle, + ) where + Renderer: TextRenderer, + Renderer::Font: From, + { + // We'll visualize the difference between the current value and the default value if the + // default value lies somewhere in the middle and the parameter is continuous. Otherwise + // this appraoch looks a bit jarring. + let current_value = self.param.modulated_normalized_value(); + let default_value = self.param.default_normalized_value(); + + let fill_start_x = util::remap_rect_x_t( + bounds, + if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { + default_value } else { - Color::TRANSPARENT - }; + 0.0 + }, + ); + + let fill_end_x = util::remap_rect_x_t(bounds, current_value); + let fill_rect = Rectangle { + x: fill_start_x.min(fill_end_x), + width: (fill_end_x - fill_start_x).abs(), + ..*bounds + }; renderer.fill_quad( renderer::Quad { - bounds, - border_color: Color::BLACK, - border_width: BORDER_WIDTH, - border_radius: 0.0, + bounds: fill_rect, + ..Default::default() }, - background_color, + style.bar.color, ); - // Only draw the text input widget when it gets focussed. Otherwise, overlay the label with - // the slider. - if let Some(current_value) = &self.state.text_input_value { + // To make it more readable (and because it looks cool), the parts that overlap with the + // fill rect will be rendered in white while the rest will be rendered in black. + let display_value = self.param.to_string(); + + let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.default_font()); + + let text_bounds = Rectangle { + x: bounds.center_x(), + y: bounds.center_y(), + ..*bounds + }; + renderer.fill_text( + text::Text { + content: display_value.clone(), + font: font, + size: text_size, + bounds: text_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + wrapping: Default::default(), + }, + text_bounds.position(), + style.background.text, + *viewport, + ); + + // This will clip to the filled area + renderer.with_layer(fill_rect, |renderer| { + renderer.fill_text( + text::Text { + content: display_value, + font: font, + size: text_size, + bounds: text_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + wrapping: Default::default(), + }, + text_bounds.position(), + style.bar.text, + *viewport, + ); + }); + } +} + +// ############################################################################ +// Event Handling +// ############################################################################ +impl<'a, P, Theme> ParamSlider<'a, P, Theme> +where + P: Param, + Theme: Catalog + text_input::Catalog, +{ + /// Set the normalized value for a parameter if that would change the parameter's plain value + /// (to avoid unnecessary duplicate parameter changes). The begin- and end set parameter + /// messages need to be sent before calling this function. + fn set_normalized_value(&self, shell: &mut Shell<'_, ParamMessage>, normalized_value: f32) { + // This snaps to the nearest plain value if the parameter is stepped in some way. + // TODO: As an optimization, we could add a `const CONTINUOUS: bool` to the parameter to + // avoid this normalized->plain->normalized conversion for parameters that don't need + // it + let plain_value = self.param.preview_plain(normalized_value); + let current_plain_value = self.param.modulated_plain_value(); + if plain_value != current_plain_value { + // For the aforementioned snapping + let normalized_plain_value = self.param.preview_normalized(plain_value); + shell.publish(ParamMessage::SetParameterNormalized( + self.param.as_ptr(), + normalized_plain_value, + )); + } + } + + fn handle_mouse_down_event( + &mut self, + tree: &mut Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, + renderer: &Renderer, + shell: &mut Shell<'_, ParamMessage>, + ) -> event::Status + where + Renderer: TextRenderer, + Renderer::Font: From, + { + let state = tree.state.downcast_mut::(); + let bounds = layout.bounds(); + + let Some(cursor_position) = cursor.position_over(bounds) else { + return event::Status::Ignored; + }; + + let click = mouse::Click::new(cursor_position, mouse::Button::Left, state.last_click); + state.last_click = Some(click); + + if state.keyboard_modifiers.alt() { + // Alt+click should not start a drag, instead it should show the text entry + // widget + state.drag_active = false; + + let text_input_id = state.text_input_id.clone(); + + let current_value = self.param.to_string(); + state.text_input_value = Some(current_value.clone()); + self.with_text_input( layout, renderer, - current_value, + ¤t_value, + state, |text_input, layout, renderer| { - text_input.draw(renderer, layout, cursor_position, None) + if tree.children[0].tag != text_input.tag() { + tree.children[0] = Tree { + tag: text_input.tag(), + state: text_input.state(), + children: text_input.children(), + }; + } + + let mut move_cursor_to_end = + operation::text_input::move_cursor_to_end(text_input_id.clone().into()); + let mut select_all = operation::text_input::select_all(text_input_id.into()); + + text_input.operate( + &mut tree.children[0], + layout, + renderer, + &mut move_cursor_to_end, + ); + text_input.operate(&mut tree.children[0], layout, renderer, &mut select_all); }, - ) + ); + } else if state.keyboard_modifiers.command() + || matches!(click.kind(), mouse::click::Kind::Double) + { + // Likewise resetting a parameter should not let you immediately drag it to a new value + state.drag_active = false; + + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.set_normalized_value(shell, self.param.default_normalized_value()); + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + } else if state.keyboard_modifiers.shift() { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + // When holding down shift while clicking on a parameter we want to + // granuarly edit the parameter without jumping to a new value + state.granular_drag_start_x_value = + Some((cursor_position.x, self.param.modulated_normalized_value())); } else { - // We'll visualize the difference between the current value and the default value if the - // default value lies somewhere in the middle and the parameter is continuous. Otherwise - // this appraoch looks a bit jarring. - let current_value = self.param.modulated_normalized_value(); - let default_value = self.param.default_normalized_value(); - let fill_start_x = util::remap_rect_x_t( - &bounds_without_borders, - if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { - default_value - } else { - 0.0 - }, + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), ); - let fill_end_x = util::remap_rect_x_t(&bounds_without_borders, current_value); + state.granular_drag_start_x_value = None; + } + + event::Status::Captured + } + + fn handle_mouse_up_event( + &mut self, + shell: &mut Shell<'_, ParamMessage>, + state: &mut State, + ) -> event::Status { + if !state.drag_active { + return event::Status::Ignored; + } + + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + state.drag_active = false; + event::Status::Captured + } + + fn handle_mouse_move_event( + &mut self, + layout: Layout<'_>, + cursor: mouse::Cursor, + shell: &mut Shell<'_, ParamMessage>, + state: &mut State, + ) -> event::Status { + // Don't do anything when we just reset the parameter because that would be weird + if !state.drag_active { + return event::Status::Ignored; + } + + let bounds = layout.bounds(); + + // If shift is being held then the drag should be more granular instead of + // absolute + if let Some(cursor_position) = cursor.position() { + if state.keyboard_modifiers.shift() { + let (drag_start_x, drag_start_value) = + *state.granular_drag_start_x_value.get_or_insert_with(|| { + (cursor_position.x, self.param.modulated_normalized_value()) + }); + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate( + &bounds, + util::remap_rect_x_t(&bounds, drag_start_value) + + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, + ), + ); + } else { + state.granular_drag_start_x_value = None; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } + } + + event::Status::Captured + } + + fn handle_keyboard_modifiers_changed( + &mut self, + layout: Layout<'_>, + cursor: mouse::Cursor, + shell: &mut Shell<'_, ParamMessage>, + modifiers: keyboard::Modifiers, + state: &mut State, + ) -> event::Status { + state.keyboard_modifiers = modifiers; + let bounds = layout.bounds(); + + // If this happens while dragging, snap back to reality uh I mean the current screen + // position + if state.drag_active && state.granular_drag_start_x_value.is_some() && !modifiers.shift() { + state.granular_drag_start_x_value = None; + + if let Some(cursor_position) = cursor.position() { + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } + } + + event::Status::Captured + } +} + +// ############################################################################ +// Styling / Appearance +// ############################################################################ - let fill_color = Color::from_rgb8(196, 196, 196); - let fill_rect = Rectangle { - x: fill_start_x.min(fill_end_x), - width: (fill_end_x - fill_start_x).abs(), - ..bounds_without_borders +/// The appearance of a slider. +pub struct Style { + /// The [`Color`] of the slider background. + pub background: Pair, + + /// The [`Color`] of the slider bar. + pub bar: Pair, + /// The border of the slider. + pub border: Border, +} + +/// The theme catalog of a [`ParamSlider`]. +pub trait Catalog: Sized { + /// The item class of the [`Catalog`]. + type Class<'a>; + + /// The default class produced by the [`Catalog`]. + fn default<'a>() -> Self::Class<'a>; + + /// The [`Style`] of a class with the given status. + fn style(&self, class: &Self::Class<'_>, status: Status) -> Style; +} + +/// A styling function for a [`ParamSlider`]. +pub type StyleFn<'a, Theme> = Box Style + 'a>; + +impl Catalog for iced::Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> Self::Class<'a> { + Box::new(|theme: &Self, status: Status| -> Style { + use Status::*; + let palette = theme.extended_palette(); + + let (background, bar) = match status { + Active => (palette.background.base, palette.primary.base), + Hovered => (palette.background.strong, palette.primary.strong), + Dragged => (palette.background.base, palette.primary.base), }; - renderer.fill_quad( - renderer::Quad { - bounds: fill_rect, - border_color: Color::TRANSPARENT, - border_width: 0.0, - border_radius: 0.0, - }, - fill_color, - ); - // To make it more readable (and because it looks cool), the parts that overlap with the - // fill rect will be rendered in white while the rest will be rendered in black. - let display_value = self.param.to_string(); - let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()) as f32; - let text_bounds = Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..bounds + let border = Border { + color: palette.background.base.text, + width: BORDER_WIDTH, + radius: 0.0.into(), }; - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, - size: text_size, - bounds: text_bounds, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - }); - - // This will clip to the filled area - renderer.with_layer(fill_rect, |renderer| { - let filled_text_color = Color::from_rgb8(80, 80, 80); - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, - size: text_size, - bounds: text_bounds, - color: filled_text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - }); - }); - } + + Style { + background, + bar, + border, + } + }) + } + + fn style(&self, class: &Self::Class<'_>, status: Status) -> Style { + class(self, status) } } -impl<'a, P: Param> ParamSlider<'a, P> { +impl<'a, P, Theme> ParamSlider<'a, P, Theme> +where + P: Param + 'a, + Theme: Catalog + text_input::Catalog + 'a, +{ /// Convert this [`ParamSlider`] into an [`Element`] with the correct message. You should have a /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message> + pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, + Renderer: TextRenderer + 'a, + Renderer::Font: From, { Element::from(self).map(f) } } -impl<'a, P: Param> From> for Element<'a, ParamMessage> { - fn from(widget: ParamSlider<'a, P>) -> Self { +impl<'a, P, Theme, Renderer> From> + for Element<'a, ParamMessage, Theme, Renderer> +where + P: Param + 'a, + Theme: Catalog + text_input::Catalog + 'a, + Renderer: TextRenderer + 'a, + Renderer::Font: From, +{ + fn from(widget: ParamSlider<'a, P, Theme>) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/widgets/peak_meter.rs b/nih_plug_iced/src/widgets/peak_meter.rs index 688d67d7..b98226cc 100644 --- a/nih_plug_iced/src/widgets/peak_meter.rs +++ b/nih_plug_iced/src/widgets/peak_meter.rs @@ -1,16 +1,16 @@ //! A super simple peak meter widget. use crossbeam::atomic::AtomicCell; +use iced_baseview as iced; use std::marker::PhantomData; use std::time::Duration; use std::time::Instant; -use crate::backend::Renderer; -use crate::renderer::Renderer as GraphicsRenderer; -use crate::text::Renderer as TextRenderer; -use crate::{ - alignment, layout, renderer, text, Background, Color, Element, Font, Layout, Length, Point, - Rectangle, Size, Widget, +use iced::core::text::{self, Paragraph, Renderer as TextRenderer}; +use iced::core::widget::tree::{self, Tree}; +use iced::core::{ + alignment, layout, mouse, padding, renderer, Background, Border, Color, Element, Font, Layout, + Length, Pixels, Point, Rectangle, Size, Widget, }; /// The thickness of this widget's borders. @@ -22,9 +22,7 @@ const TICK_WIDTH: f32 = 1.0; /// /// TODO: There are currently no styling options at all /// TODO: Vertical peak meter, this is just a proof of concept to fit the gain GUI example. -pub struct PeakMeter<'a, Message> { - state: &'a mut State, - +pub struct PeakMeter { /// The current measured value in decibel. current_value_db: f32, @@ -33,8 +31,8 @@ pub struct PeakMeter<'a, Message> { height: Length, width: Length, - text_size: Option, - font: Font, + text_size: Option, + font: Option, /// We don't emit any messages, but iced requires us to define some message type anyways. _phantom: PhantomData, @@ -42,29 +40,27 @@ pub struct PeakMeter<'a, Message> { /// State for a [`PeakMeter`]. #[derive(Debug, Default)] -pub struct State { +struct State { /// The last peak value in decibel. held_peak_value_db: AtomicCell, /// When the last peak value was hit. last_held_peak_value: AtomicCell>, } -impl<'a, Message> PeakMeter<'a, Message> { +impl PeakMeter { /// Creates a new [`PeakMeter`] using the current measurement in decibel. This measurement can /// already have some form of smoothing applied to it. This peak slider widget can draw the last /// hold value for you. - pub fn new(state: &'a mut State, value_db: f32) -> Self { + pub fn new(value_db: f32) -> Self { Self { - state, - current_value_db: value_db, hold_time: None, - width: Length::Units(180), - height: Length::Units(30), + width: Length::Fixed(180.0), + height: Length::Fixed(30.0), text_size: None, - font: ::Font::default(), + font: None, _phantom: PhantomData, } @@ -77,71 +73,72 @@ impl<'a, Message> PeakMeter<'a, Message> { } /// Sets the width of the [`PeakMeter`]. - pub fn width(mut self, width: Length) -> Self { - self.width = width; + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); self } /// Sets the height of the [`PeakMeter`]. - pub fn height(mut self, height: Length) -> Self { - self.height = height; + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); self } /// Sets the text size of the [`PeakMeter`]'s ticks bar. - pub fn text_size(mut self, size: u16) -> Self { - self.text_size = Some(size); + pub fn text_size(mut self, size: impl Into) -> Self { + self.text_size = Some(size.into()); self } /// Sets the font of the [`PeakMeter`]'s ticks bar. pub fn font(mut self, font: Font) -> Self { - self.font = font; + self.font = Some(font); self } } -impl<'a, Message> Widget for PeakMeter<'a, Message> +impl Widget for PeakMeter where Message: Clone, + Renderer: TextRenderer, + Renderer::Font: From, { - fn width(&self) -> Length { - self.width + fn tag(&self) -> tree::Tag { + tree::Tag::of::() } - fn height(&self) -> Length { - self.height + fn state(&self) -> tree::State { + tree::State::new(State::default()) } - fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); + fn size(&self) -> Size { + (self.width, self.height).into() + } - layout::Node::new(size) + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + layout::atomic(limits, self.width, self.height) } fn draw( &self, + tree: &Tree, renderer: &mut Renderer, + _theme: &Theme, style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, - _viewport: &Rectangle, + _cursor: mouse::Cursor, + viewport: &Rectangle, ) { - let bounds = layout.bounds(); - let bar_bounds = Rectangle { - height: bounds.height / 2.0, - ..bounds - }; - let ticks_bounds = Rectangle { - y: bounds.y + (bounds.height / 2.0), - height: bounds.height / 2.0, - ..bounds - }; + let state = tree.state.downcast_ref::(); - let text_size = self - .text_size - .unwrap_or_else(|| (renderer.default_size() as f32 * 0.7).round() as u16); + let bounds = layout.bounds(); + let bar_bounds = bounds.shrink(padding::bottom(bounds.height / 2.0)); + let ticks_bounds = bounds.shrink(padding::top(bounds.height / 2.0)); // We'll draw a simple horizontal for [-90, 20] dB where we'll treat -80 as -infinity, with // a label containing the tick markers below it. If `.hold_time()` was called then we'll @@ -181,9 +178,12 @@ where renderer.fill_quad( renderer::Quad { bounds: tick_bounds, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(tick_color), ); @@ -192,14 +192,14 @@ where // Draw the hold peak value if the hold time option has been set if let Some(hold_time) = self.hold_time { let now = Instant::now(); - let mut held_peak_value_db = self.state.held_peak_value_db.load(); - let last_peak_value = self.state.last_held_peak_value.load(); + let mut held_peak_value_db = state.held_peak_value_db.load(); + let last_peak_value = state.last_held_peak_value.load(); if self.current_value_db >= held_peak_value_db || last_peak_value.is_none() || now > last_peak_value.unwrap() + hold_time { - self.state.held_peak_value_db.store(self.current_value_db); - self.state.last_held_peak_value.store(Some(now)); + state.held_peak_value_db.store(self.current_value_db); + state.last_held_peak_value.store(Some(now)); held_peak_value_db = self.current_value_db; } @@ -211,9 +211,12 @@ where width: TICK_WIDTH, height: bar_bounds.height - (BORDER_WIDTH * 2.0), }, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::from_rgb(0.3, 0.3, 0.3)), ); @@ -223,13 +226,24 @@ where renderer.fill_quad( renderer::Quad { bounds: bar_bounds, - border_radius: 0.0, - border_width: BORDER_WIDTH, - border_color: Color::BLACK, + border: Border { + color: Color::BLACK, + width: BORDER_WIDTH, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::TRANSPARENT), ); + let text_size = self + .text_size + .unwrap_or_else(|| Pixels((renderer.default_size().0 * 0.7).round())); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.default_font()); + // Beneath the bar we want to draw the names of the ticks for tick_db in text_ticks { let x_coordinate = db_to_x_coord(tick_db as f32); @@ -242,9 +256,12 @@ where width: TICK_WIDTH, height: ticks_bounds.height * 0.3, }, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::from_rgb(0.3, 0.3, 0.3)), ); @@ -254,47 +271,75 @@ where } else { tick_db.to_string() }; - renderer.fill_text(text::Text { - content: &tick_text, - font: self.font, - size: text_size as f32, - bounds: Rectangle { + renderer.fill_text( + text::Text { + content: tick_text, + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), + wrapping: text::Wrapping::None, + }, + Point { x: x_coordinate, y: ticks_bounds.y + (ticks_bounds.height * 0.35), - ..ticks_bounds }, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Top, - }); + style.text_color, + *viewport, + ); } // Every proper graph needs a unit label let zero_db_x_coordinate = db_to_x_coord(0.0); - let zero_db_text_width = renderer.measure_width("0", text_size, self.font); - renderer.fill_text(text::Text { - // The spacing looks a bit off if we start with a space here so we'll add a little - // offset to the x-coordinate instead - content: "dBFS", - font: self.font, - size: text_size as f32, - bounds: Rectangle { - x: zero_db_x_coordinate + (zero_db_text_width / 2.0) + (text_size as f32 * 0.2), + + let zero_db_text_width = Renderer::Paragraph::with_text(text::Text { + content: "0", + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), + wrapping: text::Wrapping::None, + }) + .min_width(); + + renderer.fill_text( + text::Text { + // The spacing looks a bit off if we start with a space here so we'll add a little + // offset to the x-coordinate instead + content: "dBFS".into(), + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), + wrapping: text::Wrapping::None, + }, + Point { + x: zero_db_x_coordinate + (zero_db_text_width / 2.0) + (text_size.0 * 0.2), y: ticks_bounds.y + (ticks_bounds.height * 0.35), - ..ticks_bounds }, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Left, - vertical_alignment: alignment::Vertical::Top, - }); + style.text_color, + *viewport, + ); } } -impl<'a, Message> From> for Element<'a, Message> +impl<'a, Theme, Message, Renderer> From> + for Element<'a, Message, Theme, Renderer> where - Message: 'a + Clone, + Message: Clone + 'a, + Renderer: TextRenderer + 'a, + Renderer::Font: From, { - fn from(widget: PeakMeter<'a, Message>) -> Self { + fn from(widget: PeakMeter) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/widgets/util.rs b/nih_plug_iced/src/widgets/util.rs index e755635b..cd61033e 100644 --- a/nih_plug_iced/src/widgets/util.rs +++ b/nih_plug_iced/src/widgets/util.rs @@ -1,6 +1,6 @@ //! Utilities for creating these widgets. -use crate::Rectangle; +use crate::core::Rectangle; /// Remap a `[0, 1]` value to an x-coordinate within this rectangle. The value will be clamped to /// `[0, 1]` if it isn't already in that range. diff --git a/nih_plug_iced/src/wrapper.rs b/nih_plug_iced/src/wrapper.rs index c149489e..245265c8 100644 --- a/nih_plug_iced/src/wrapper.rs +++ b/nih_plug_iced/src/wrapper.rs @@ -2,14 +2,18 @@ //! `nih_plug_iced`. use crossbeam::channel; +use futures_util::FutureExt; +use iced_baseview::{ + baseview::WindowScalePolicy, + core::Element, + futures::{subscription, Subscription}, + window::WindowSubs, + Renderer, Task, +}; use nih_plug::prelude::GuiContext; use std::sync::Arc; -use crate::futures::FutureExt; -use crate::{ - futures, subscription, Application, Color, Command, Element, IcedEditor, ParameterUpdate, - Subscription, WindowQueue, WindowScalePolicy, WindowSubs, -}; +use crate::{IcedEditor, ParameterUpdate}; /// Wraps an `iced_baseview` [`Application`] around [`IcedEditor`]. Needed to allow editors to /// always receive a copy of the GUI context. @@ -30,6 +34,16 @@ pub enum Message { ParameterUpdate, } +impl Message { + fn into_editor_message(self) -> Option { + if let Message::EditorMessage(message) = self { + Some(message) + } else { + None + } + } +} + impl std::fmt::Debug for Message { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -48,7 +62,7 @@ impl Clone for Message { } } -impl Application for IcedEditorWrapperApplication { +impl iced_baseview::Application for IcedEditorWrapperApplication { type Executor = E::Executor; type Message = Message; type Flags = ( @@ -56,34 +70,30 @@ impl Application for IcedEditorWrapperApplication { Arc>, E::InitializationFlags, ); + type Theme = E::Theme; fn new( (context, parameter_updates_receiver, flags): Self::Flags, - ) -> (Self, Command) { - let (editor, command) = E::new(flags, context); + ) -> (Self, Task) { + let (editor, task) = E::new(flags, context); ( Self { editor, parameter_updates_receiver, }, - command.map(Message::EditorMessage), + task.map(Message::EditorMessage), ) } #[inline] - fn update( - &mut self, - window: &mut WindowQueue, - message: Self::Message, - ) -> Command { + fn update(&mut self, message: Self::Message) -> Task { match message { - Message::EditorMessage(message) => self - .editor - .update(window, message) - .map(Message::EditorMessage), + Message::EditorMessage(message) => { + self.editor.update(message).map(Message::EditorMessage) + } // This message only exists to force a redraw - Message::ParameterUpdate => Command::none(), + Message::ParameterUpdate => Task::none(), } } @@ -93,15 +103,17 @@ impl Application for IcedEditorWrapperApplication { window_subs: &mut WindowSubs, ) -> Subscription { // Since we're wrapping around `E::Message`, we need to do this transformation ourselves - let mut editor_window_subs = WindowSubs { - on_frame: match &window_subs.on_frame { - Some(Message::EditorMessage(message)) => Some(message.clone()), - _ => None, - }, - on_window_will_close: match &window_subs.on_window_will_close { - Some(Message::EditorMessage(message)) => Some(message.clone()), - _ => None, - }, + let on_frame = window_subs.on_frame.clone(); + let on_window_will_close = window_subs.on_window_will_close.clone(); + let mut editor_window_subs: WindowSubs = WindowSubs { + on_frame: Some(Arc::new(move || { + let cb = on_frame.clone(); + cb.and_then(|cb| cb().and_then(|m| m.into_editor_message())) + })), + on_window_will_close: Some(Arc::new(move || { + let cb = on_window_will_close.clone(); + cb.and_then(|cb| cb().and_then(|m| m.into_editor_message())) + })), }; let subscription = Subscription::batch([ @@ -109,50 +121,58 @@ impl Application for IcedEditorWrapperApplication { // into a stream that doesn't require consuming that receiver (which wouldn't work in // this case since the subscriptions function gets called repeatedly). So we'll just use // a crossbeam queue and this unfold instead. - subscription::unfold( + Subscription::run_with_id( "parameter updates", - self.parameter_updates_receiver.clone(), - |parameter_updates_receiver| match parameter_updates_receiver.try_recv() { - Ok(_) => futures::future::ready(( - Some(Message::ParameterUpdate), - parameter_updates_receiver, - )) - .boxed(), - Err(_) => futures::future::pending().boxed(), - }, + futures_util::stream::unfold( + self.parameter_updates_receiver.clone(), + |parameter_updates_receiver| match parameter_updates_receiver.try_recv() { + Ok(_) => futures_util::future::ready(Some(( + Message::ParameterUpdate, + parameter_updates_receiver, + ))) + .boxed(), + Err(channel::TryRecvError::Empty) => { + futures_util::future::pending().boxed() + } + Err(channel::TryRecvError::Disconnected) => { + futures_util::future::ready(None).boxed() + } + }, + ), ), self.editor .subscription(&mut editor_window_subs) - .map(Message::EditorMessage), + .map(|m| Message::EditorMessage(m)), ]); - if let Some(message) = editor_window_subs.on_frame { - window_subs.on_frame = Some(Message::EditorMessage(message)); + if let Some(message) = editor_window_subs.on_frame.as_ref() { + let message = Arc::clone(message); + window_subs.on_frame = Some(Arc::new(move || message().map(Message::EditorMessage))); } - if let Some(message) = editor_window_subs.on_window_will_close { - window_subs.on_window_will_close = Some(Message::EditorMessage(message)); + if let Some(message) = editor_window_subs.on_window_will_close.as_ref() { + let message = Arc::clone(message); + window_subs.on_window_will_close = + Some(Arc::new(move || message().map(Message::EditorMessage))); } subscription } #[inline] - fn view(&mut self) -> Element<'_, Self::Message> { + fn view(&self) -> Element<'_, Self::Message, Self::Theme, Renderer> { self.editor.view().map(Message::EditorMessage) } #[inline] - fn background_color(&self) -> Color { - self.editor.background_color() + fn scale_policy(&self) -> WindowScalePolicy { + WindowScalePolicy::SystemScaleFactor } - #[inline] - fn scale_policy(&self) -> WindowScalePolicy { - self.editor.scale_policy() + fn title(&self) -> String { + self.editor.title() } - #[inline] - fn renderer_settings() -> iced_baseview::backend::settings::Settings { - E::renderer_settings() + fn theme(&self) -> Self::Theme { + self.editor.theme() } } diff --git a/plugins/examples/gain_gui_iced/Cargo.toml b/plugins/examples/gain_gui_iced/Cargo.toml index ea4f8f3b..9c2c28cf 100644 --- a/plugins/examples/gain_gui_iced/Cargo.toml +++ b/plugins/examples/gain_gui_iced/Cargo.toml @@ -8,10 +8,13 @@ license = "ISC" description = "A simple gain plugin with an iced GUI" [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "lib"] [dependencies] -nih_plug = { path = "../../../", features = ["assert_process_allocs"] } -nih_plug_iced = { path = "../../../nih_plug_iced" } +nih_plug = { path = "../../../", features = [ + "assert_process_allocs", + "standalone", +] } +nih_plug_iced = { path = "../../../nih_plug_iced", features = ["wgpu"] } atomic_float = "0.1" diff --git a/plugins/examples/gain_gui_iced/src/editor.rs b/plugins/examples/gain_gui_iced/src/editor.rs index db2c31b7..eb3433a6 100644 --- a/plugins/examples/gain_gui_iced/src/editor.rs +++ b/plugins/examples/gain_gui_iced/src/editor.rs @@ -1,5 +1,7 @@ use atomic_float::AtomicF32; use nih_plug::prelude::{util, Editor, GuiContext}; +use nih_plug_iced::assets::noto_sans_fonts_data; +use nih_plug_iced::widget::{column, text, Column, Space, Text}; use nih_plug_iced::widgets as nih_widgets; use nih_plug_iced::*; use std::sync::Arc; @@ -17,7 +19,11 @@ pub(crate) fn create( peak_meter: Arc, editor_state: Arc, ) -> Option> { - create_iced_editor::(editor_state, (params, peak_meter)) + create_iced_editor::( + editor_state, + (params, peak_meter), + noto_sans_fonts_data().into(), + ) } struct GainEditor { @@ -25,9 +31,6 @@ struct GainEditor { context: Arc, peak_meter: Arc, - - gain_slider_state: nih_widgets::param_slider::State, - peak_meter_state: nih_widgets::peak_meter::State, } #[derive(Debug, Clone, Copy)] @@ -40,72 +43,57 @@ impl IcedEditor for GainEditor { type Executor = executor::Default; type Message = Message; type InitializationFlags = (Arc, Arc); + type Theme = Theme; fn new( (params, peak_meter): Self::InitializationFlags, context: Arc, - ) -> (Self, Command) { + ) -> (Self, Task) { let editor = GainEditor { params, context, peak_meter, - - gain_slider_state: Default::default(), - peak_meter_state: Default::default(), }; - (editor, Command::none()) + (editor, Task::none()) } fn context(&self) -> &dyn GuiContext { self.context.as_ref() } - fn update( - &mut self, - _window: &mut WindowQueue, - message: Self::Message, - ) -> Command { + fn update(&mut self, message: Self::Message) -> Task { match message { Message::ParamUpdate(message) => self.handle_param_message(message), } - Command::none() + Task::none() } - fn view(&mut self) -> Element<'_, Self::Message> { - Column::new() - .align_items(Alignment::Center) - .push( - Text::new("Gain GUI") - .font(assets::NOTO_SANS_LIGHT) - .size(40) - .height(50.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Bottom), - ) - .push( - Text::new("Gain") - .height(20.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center), - ) - .push( - nih_widgets::ParamSlider::new(&mut self.gain_slider_state, &self.params.gain) - .map(Message::ParamUpdate), - ) - .push(Space::with_height(10.into())) - .push( - nih_widgets::PeakMeter::new( - &mut self.peak_meter_state, - util::gain_to_db(self.peak_meter.load(std::sync::atomic::Ordering::Relaxed)), - ) - .hold_time(Duration::from_millis(600)), - ) - .into() + fn view(&self) -> Element<'_, Self::Message> { + let title = text("Gain GUI") + .font(assets::NOTO_SANS_LIGHT) + .size(40) + .height(50) + .width(Length::Fill) + .align_x(alignment::Horizontal::Center) + .align_y(alignment::Vertical::Bottom); + + let text = text("Gain").height(20).width(Length::Fill).center(); + + column![ + title, + text, + nih_widgets::ParamSlider::new(&self.params.gain).map(Message::ParamUpdate), + Space::with_height(10), + nih_widgets::PeakMeter::new(util::gain_to_db( + self.peak_meter.load(std::sync::atomic::Ordering::Relaxed), + )) + .hold_time(Duration::from_millis(600)) + ] + .align_x(alignment::Horizontal::Center) + .into() } fn background_color(&self) -> nih_plug_iced::Color { diff --git a/plugins/examples/gain_gui_iced/src/lib.rs b/plugins/examples/gain_gui_iced/src/lib.rs index 15a30ca5..006c7aca 100644 --- a/plugins/examples/gain_gui_iced/src/lib.rs +++ b/plugins/examples/gain_gui_iced/src/lib.rs @@ -9,7 +9,7 @@ mod editor; const PEAK_METER_DECAY_MS: f64 = 150.0; /// This is mostly identical to the gain example, minus some fluff, and with a GUI. -struct Gain { +pub struct Gain { params: Arc, /// Needed to normalize the peak meter's response based on the sample rate. diff --git a/plugins/examples/gain_gui_iced/src/main.rs b/plugins/examples/gain_gui_iced/src/main.rs new file mode 100644 index 00000000..ceb89dfd --- /dev/null +++ b/plugins/examples/gain_gui_iced/src/main.rs @@ -0,0 +1,7 @@ +use gain_gui_iced::Gain; +use nih_plug::prelude::*; +use nih_plug::wrapper::standalone::nih_export_standalone; + +fn main() { + nih_export_standalone::(); +} diff --git a/src/wrapper/standalone/wrapper.rs b/src/wrapper/standalone/wrapper.rs index 43476cc1..bd4ff58f 100644 --- a/src/wrapper/standalone/wrapper.rs +++ b/src/wrapper/standalone/wrapper.rs @@ -342,7 +342,7 @@ impl> Wrapper { height: height as f64, }, scale: scaling_policy, - gl_config: None, + // gl_config: None, }, move |window| { let parent_handle = match window.raw_window_handle() { From c5eb6956eedc4ac74e564b8ee67a37457e0475ed Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 14:48:22 -0700 Subject: [PATCH 03/11] cleanup --- nih_plug_iced/src/assets.rs | 1 - nih_plug_iced/src/editor.rs | 24 - nih_plug_iced/src/widgets/generic_ui.rs | 11 +- nih_plug_iced/src/widgets/param_slider.rs | 866 +++++++++------------- nih_plug_iced/src/widgets/peak_meter.rs | 11 +- 5 files changed, 360 insertions(+), 553 deletions(-) diff --git a/nih_plug_iced/src/assets.rs b/nih_plug_iced/src/assets.rs index 254e4963..70982bd8 100644 --- a/nih_plug_iced/src/assets.rs +++ b/nih_plug_iced/src/assets.rs @@ -4,7 +4,6 @@ use std::borrow::Cow; use crate::core::Font; -use iced_baseview::runtime::font; // This module provides a re-export and simple font wrappers around the re-exported fonts. pub use nih_plug_assets::*; diff --git a/nih_plug_iced/src/editor.rs b/nih_plug_iced/src/editor.rs index 92036b1e..cc98e04e 100644 --- a/nih_plug_iced/src/editor.rs +++ b/nih_plug_iced/src/editor.rs @@ -57,30 +57,6 @@ impl Editor for IcedEditorWrapper { scale: scaling_factor .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) .unwrap_or(WindowScalePolicy::SystemScaleFactor), - - #[cfg(feature = "opengl")] - gl_config: Some(baseview::gl::GlConfig { - // FIXME: glow_glyph forgot to add an `#extension`, so this won't work under - // OpenGL 3.2 at the moment. With that change applied this should work on - // OpenGL 3.2/macOS. - version: (3, 3), - red_bits: 8, - blue_bits: 8, - green_bits: 8, - alpha_bits: 8, - depth_bits: 24, - stencil_bits: 8, - samples: None, - srgb: true, - double_buffer: true, - vsync: true, - ..Default::default() - }), - // FIXME: Rust analyzer always thinks baseview/opengl is enabled even if we - // don't explicitly enable it, so you'd get a compile error if this line - // is missing - // #[cfg(not(feature = "opengl"))] - // gl_config: None, }, iced_baseview: IcedBaseviewSettings { ignore_non_modifier_keys: false, diff --git a/nih_plug_iced/src/widgets/generic_ui.rs b/nih_plug_iced/src/widgets/generic_ui.rs index 212ad8cc..9a9df38d 100644 --- a/nih_plug_iced/src/widgets/generic_ui.rs +++ b/nih_plug_iced/src/widgets/generic_ui.rs @@ -1,13 +1,12 @@ //! A simple generic UI widget that renders all parameters in a [`Params`] object as a scrollable //! list of sliders and labels. +use crate::core::widget::{Id, Operation, Tree}; use crate::core::{ - alignment, event, layout, renderer, text, widget::Id, widget::Operation, widget::Tree, - Clipboard, Element, Layout, Length, Rectangle, Shell, Widget, + alignment, event, layout, renderer, text, Clipboard, Element, Layout, Length, Rectangle, Shell, + Size, Widget, }; -use crate::widget::{self, row, scrollable, Column, Scrollable}; -use iced_baseview::widget::Space; -use iced_baseview::Size; +use crate::widget::{self, row, scrollable, Column, Scrollable, Space}; use std::marker::PhantomData; use std::sync::Arc; @@ -303,7 +302,7 @@ fn is_hidden(param_ptr: &ParamPtr) -> bool { impl ParamWidget for GenericSlider where - Theme: super::param_slider::Catalog + widget::text_input::Catalog, + Theme: widget::text_input::Catalog, Renderer: text::Renderer, Renderer::Font: From, { diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 0b148996..4a3b4283 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,19 +1,15 @@ -use iced_baseview::theme::palette::Pair; -use iced_baseview::{self as iced, alignment}; +use nih_plug::nih_log; use nih_plug::prelude::Param; use std::borrow::Borrow; -use iced::core::event::{self, Event}; -use iced::core::layout::{self, Limits}; -use iced::core::text::{self, Paragraph, Renderer as TextRenderer, Text}; -use iced::core::widget::operation::{self}; -use iced::core::widget::tree::{self, Tree}; -use iced::core::{ - keyboard, mouse, renderer, touch, Border, Clipboard, Element, Font, Layout, Length, Padding, - Pixels, Rectangle, Shell, Size, Vector, Widget, +use crate::core::text::{Paragraph, Renderer as TextRenderer, Text}; +use crate::core::widget::tree::{self, Tree}; +use crate::core::{ + alignment, event, keyboard, layout, mouse, renderer, text, touch, Border, Clipboard, Color, + Element, Event, Font, Layout, Length, Pixels, Rectangle, Shell, Size, Vector, Widget, }; -use iced::widget::text_input; -use iced::widget::text_input::{Id, TextInput}; +use crate::widget::text_input; +use crate::widget::text_input::{Id, TextInput}; use super::{util, ParamMessage}; @@ -24,10 +20,9 @@ const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1; /// The thickness of this widget's borders. const BORDER_WIDTH: f32 = 1.0; -pub struct ParamSlider<'a, P, Theme = iced::Theme> +pub struct ParamSlider<'a, P> where P: Param, - Theme: Catalog, { param: &'a P, @@ -35,7 +30,6 @@ where height: Length, text_size: Option, font: Option, - class: Theme::Class<'a>, } /// State for a [`ParamSlider`]. @@ -90,10 +84,9 @@ enum TextInputMessage { Submit, } -impl<'a, P, Theme> ParamSlider<'a, P, Theme> +impl<'a, P> ParamSlider<'a, P> where P: Param, - Theme: Catalog, { pub const DEFAULT_WIDTH: Length = Length::Fixed(180.0); pub const DEFAULT_HEIGHT: Length = Length::Fixed(30.0); @@ -107,7 +100,6 @@ where height: Self::DEFAULT_HEIGHT, text_size: None, font: None, - class: Theme::default(), } } @@ -135,22 +127,100 @@ where self } - /// Sets the style of the [`ParamSlider`]. - pub fn style(mut self, style: impl Fn(&Theme, Status) -> Style + 'a) -> Self + /// Create a temporary [`TextInput`] hooked up to [`State::text_input_value`] and outputting + /// [`TextInputMessage`] messages and do something with it. This can be used to + fn with_text_input( + &self, + layout: Layout, + renderer: BorrowedRenderer, + current_value: &str, + state: &State, + f: F, + ) -> T where - Theme::Class<'a>: From>, + F: FnOnce(TextInput<'_, TextInputMessage, Theme, Renderer>, Layout, BorrowedRenderer) -> T, + Theme: text_input::Catalog, + Renderer: TextRenderer, + Renderer::Font: From, + BorrowedRenderer: Borrow, { - self.class = (Box::new(style) as StyleFn<'a, Theme>).into(); - self + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.borrow().default_font()); + + let text_size = self + .text_size + .unwrap_or_else(|| renderer.borrow().default_size()); + let text_width = Renderer::Paragraph::with_text(Text { + content: current_value, + bounds: layout.bounds().size(), + size: text_size, + font, + line_height: Default::default(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + shaping: Default::default(), + wrapping: Default::default(), + }) + .min_width(); + + nih_log!("with_text_input() - {} {}", current_value, text_width); + + let text_input = text_input("", current_value) + .id(state.text_input_id.clone()) + .font(font) + .size(text_size) + .width(text_width) + .on_input(TextInputMessage::Value) + .on_submit(TextInputMessage::Submit); + + // Make sure to not draw over the borders, and center the text + let offset_node = layout::Node::with_children( + Size { + width: text_width, + height: layout.bounds().shrink(BORDER_WIDTH).size().height, + }, + vec![layout::Node::new(layout.bounds().size())], + ); + let offset_layout = Layout::with_offset( + Vector { + x: layout.bounds().center_x() - (text_width / 2.0), + y: layout.position().y + BORDER_WIDTH, + }, + &offset_node, + ); + + f(text_input, offset_layout, renderer) + } + + /// Set the normalized value for a parameter if that would change the parameter's plain value + /// (to avoid unnecessary duplicate parameter changes). The begin- and end set parameter + /// messages need to be sent before calling this function. + fn set_normalized_value(&self, shell: &mut Shell<'_, ParamMessage>, normalized_value: f32) { + // This snaps to the nearest plain value if the parameter is stepped in some way. + // TODO: As an optimization, we could add a `const CONTINUOUS: bool` to the parameter to + // avoid this normalized->plain->normalized conversion for parameters that don't need + // it + let plain_value = self.param.preview_plain(normalized_value); + let current_plain_value = self.param.modulated_plain_value(); + if plain_value != current_plain_value { + // For the aforementioned snapping + let normalized_plain_value = self.param.preview_normalized(plain_value); + shell.publish(ParamMessage::SetParameterNormalized( + self.param.as_ptr(), + normalized_plain_value, + )); + } } } -impl<'a, P, Theme, Renderer> Widget for ParamSlider<'a, P, Theme> +impl<'a, P, Theme, Renderer> Widget for ParamSlider<'a, P> where P: Param, - Theme: Catalog + text_input::Catalog, + Theme: text_input::Catalog, Renderer: TextRenderer, - Renderer::Font: From, + Renderer::Font: From, { fn tag(&self) -> tree::Tag { tree::Tag::of::() @@ -161,8 +231,14 @@ where } fn children(&self) -> Vec { + let input = text_input::("", ""); + // One child to store text input state. - vec![Tree::empty()] + vec![Tree { + tag: input.tag(), + state: input.state(), + children: input.children(), + }] } fn size(&self) -> Size { @@ -172,7 +248,12 @@ where } } - fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> layout::Node { + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { layout::atomic(limits, self.width, self.height) } @@ -181,7 +262,7 @@ where tree: &Tree, renderer: &mut Renderer, theme: &Theme, - _style: &renderer::Style, + style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, viewport: &Rectangle, @@ -189,54 +270,139 @@ where let state = tree.state.downcast_ref::(); let bounds = layout.bounds(); - let status = if state.drag_active { - Status::Dragged - } else if cursor.is_over(bounds) { - Status::Hovered - } else { - Status::Active - }; - let style = Catalog::style(theme, &self.class, status); + let background_color = + if cursor.is_over(bounds) || state.drag_active || state.text_input_value.is_some() { + Color::new(0.5, 0.5, 0.5, 0.1) + } else { + Color::TRANSPARENT + }; renderer.fill_quad( renderer::Quad { bounds, - border: style.border, + border: Border { + color: Color::BLACK, + width: BORDER_WIDTH, + radius: 0.0.into(), + }, ..Default::default() }, - style.background.color, + background_color, ); // Shrink bounds to inside of the border - let bounds = bounds.shrink(Padding::new(style.border.width)); + let bounds = bounds.shrink(BORDER_WIDTH); - let Some(current_value) = &state.text_input_value else { - return self.draw_bar(renderer, &style, &bounds, viewport); - }; + if let Some(current_value) = &state.text_input_value { + self.with_text_input( + layout, + renderer, + current_value, + state, + |text_input, layout, renderer| { + text_input.draw( + &tree.children[0], + renderer, + theme, + layout, + cursor, + None, + viewport, + ); + }, + ); + } else { + // We'll visualize the difference between the current value and the default value if the + // default value lies somewhere in the middle and the parameter is continuous. Otherwise + // this appraoch looks a bit jarring. + let current_value = self.param.modulated_normalized_value(); + let default_value = self.param.default_normalized_value(); + + let fill_start_x = util::remap_rect_x_t( + &bounds, + if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { + default_value + } else { + 0.0 + }, + ); + + let fill_end_x = util::remap_rect_x_t(&bounds, current_value); + + let fill_color = Color::from_rgb8(196, 196, 196); + let fill_rect = Rectangle { + x: fill_start_x.min(fill_end_x), + width: (fill_end_x - fill_start_x).abs(), + ..bounds + }; - self.with_text_input( - layout, - renderer, - current_value, - state, - |text_input, layout, renderer| { - text_input.draw( - &tree.children[0], - renderer, - theme, - layout, - cursor, - None, - viewport, + renderer.fill_quad( + renderer::Quad { + bounds: fill_rect, + ..Default::default() + }, + fill_color, + ); + + // To make it more readable (and because it looks cool), the parts that overlap with the + // fill rect will be rendered in white while the rest will be rendered in black. + let display_value = self.param.to_string(); + + let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.default_font()); + + let text_bounds = Rectangle { + x: bounds.center_x(), + y: bounds.center_y(), + ..bounds + }; + renderer.fill_text( + text::Text { + content: display_value.clone(), + font: font, + size: text_size, + bounds: text_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + wrapping: Default::default(), + }, + text_bounds.position(), + style.text_color, + *viewport, + ); + + // This will clip to the filled area + renderer.with_layer(fill_rect, |renderer| { + let filled_text_color = Color::from_rgb8(80, 80, 80); + renderer.fill_text( + text::Text { + content: display_value, + font: font, + size: text_size, + bounds: text_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + wrapping: Default::default(), + }, + text_bounds.position(), + filled_text_color, + *viewport, ); - }, - ); + }); + } } fn on_event( &mut self, tree: &mut Tree, - event: Event, + event: event::Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, @@ -262,15 +428,7 @@ where renderer, current_value, &state, - |mut text_input, layout, renderer| { - if tree.children[0].tag != text_input.tag() { - tree.children[0] = Tree { - tag: text_input.tag(), - state: text_input.state(), - children: text_input.children(), - }; - } - + |mut text_input: TextInput, layout, renderer| { text_input.on_event( &mut tree.children[0], event, @@ -326,18 +484,129 @@ where match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - self.handle_mouse_down_event(tree, layout, cursor, renderer, shell) + let bounds = layout.bounds(); + + let Some(cursor_position) = cursor.position_over(bounds) else { + return event::Status::Ignored; + }; + + let click = + mouse::Click::new(cursor_position, mouse::Button::Left, state.last_click); + state.last_click = Some(click); + + if state.keyboard_modifiers.alt() { + // Alt+click should not start a drag, instead it should show the text entry + // widget + state.drag_active = false; + + let current_value = self.param.to_string(); + state.text_input_value = Some(current_value.clone()); + + let text_input_state = tree.children[0] + .state + .downcast_mut::>(); + text_input_state.select_all(); + text_input_state.move_cursor_to_end(); + text_input_state.focus(); + } else if state.keyboard_modifiers.command() + || matches!(click.kind(), mouse::click::Kind::Double) + { + // Likewise resetting a parameter should not let you immediately drag it to a new value + state.drag_active = false; + + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.set_normalized_value(shell, self.param.default_normalized_value()); + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + } else if state.keyboard_modifiers.shift() { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + // When holding down shift while clicking on a parameter we want to + // granuarly edit the parameter without jumping to a new value + state.granular_drag_start_x_value = + Some((cursor_position.x, self.param.modulated_normalized_value())); + } else { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + state.granular_drag_start_x_value = None; + } + + event::Status::Captured } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => { - self.handle_mouse_up_event(shell, state) + if !state.drag_active { + return event::Status::Ignored; + } + + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + state.drag_active = false; + event::Status::Captured } Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { - self.handle_mouse_move_event(layout, cursor, shell, state) + // Don't do anything when we just reset the parameter because that would be weird + if !state.drag_active { + return event::Status::Ignored; + } + + let bounds = layout.bounds(); + + // If shift is being held then the drag should be more granular instead of + // absolute + if let Some(cursor_position) = cursor.position() { + if state.keyboard_modifiers.shift() { + let (drag_start_x, drag_start_value) = + *state.granular_drag_start_x_value.get_or_insert_with(|| { + (cursor_position.x, self.param.modulated_normalized_value()) + }); + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate( + &bounds, + util::remap_rect_x_t(&bounds, drag_start_value) + + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, + ), + ); + } else { + state.granular_drag_start_x_value = None; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } + } + + event::Status::Captured } Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { - self.handle_keyboard_modifiers_changed(layout, cursor, shell, modifiers, state) + state.keyboard_modifiers = modifiers; + let bounds = layout.bounds(); + + // If this happens while dragging, snap back to reality uh I mean the current screen + // position + if state.drag_active + && state.granular_drag_start_x_value.is_some() + && !modifiers.shift() + { + state.granular_drag_start_x_value = None; + + if let Some(cursor_position) = cursor.position() { + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } + } + + event::Status::Captured } _ => event::Status::Ignored, } @@ -359,469 +628,34 @@ where } } -// ############################################################################ -// Rendering -// ############################################################################ -impl<'a, P, Theme> ParamSlider<'a, P, Theme> -where - P: Param, - Theme: Catalog + text_input::Catalog, -{ - /// Create a temporary [`TextInput`] hooked up to [`State::text_input_value`] and outputting - /// [`TextInputMessage`] messages and do something with it. This can be used to - fn with_text_input( - &self, - layout: Layout, - renderer: BorrowedRenderer, - current_value: &str, - state: &State, - f: F, - ) -> T - where - F: FnOnce(TextInput<'_, TextInputMessage, Theme, Renderer>, Layout, BorrowedRenderer) -> T, - Renderer: TextRenderer, - Renderer::Font: From, - BorrowedRenderer: Borrow, - { - let font = self - .font - .map(Renderer::Font::from) - .unwrap_or_else(|| renderer.borrow().default_font()); - - let text_size = self - .text_size - .unwrap_or_else(|| renderer.borrow().default_size()); - let text_width = Renderer::Paragraph::with_text(Text { - content: current_value, - bounds: layout.bounds().size(), - size: text_size, - font, - line_height: Default::default(), - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - shaping: Default::default(), - wrapping: Default::default(), - }) - .min_width(); - - let text_input = text_input("", current_value) - .id(state.text_input_id.clone()) - .font(font) - .size(text_size) - .width(text_width) - .on_input(TextInputMessage::Value) - .on_submit(TextInputMessage::Submit); - - // Make sure to not draw over the borders, and center the text - let offset_node = layout::Node::with_children( - Size { - width: text_width, - height: layout.bounds().size().height - (BORDER_WIDTH * 2.0), - }, - vec![layout::Node::new(layout.bounds().size())], - ); - let offset_layout = Layout::with_offset( - Vector { - x: layout.bounds().center_x() - (text_width / 2.0), - y: layout.position().y + BORDER_WIDTH, - }, - &offset_node, - ); - - f(text_input, offset_layout, renderer) - } - - /// Draw the bar + label for this slider - fn draw_bar( - &self, - renderer: &mut Renderer, - style: &Style, - bounds: &Rectangle, - viewport: &Rectangle, - ) where - Renderer: TextRenderer, - Renderer::Font: From, - { - // We'll visualize the difference between the current value and the default value if the - // default value lies somewhere in the middle and the parameter is continuous. Otherwise - // this appraoch looks a bit jarring. - let current_value = self.param.modulated_normalized_value(); - let default_value = self.param.default_normalized_value(); - - let fill_start_x = util::remap_rect_x_t( - bounds, - if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { - default_value - } else { - 0.0 - }, - ); - - let fill_end_x = util::remap_rect_x_t(bounds, current_value); - let fill_rect = Rectangle { - x: fill_start_x.min(fill_end_x), - width: (fill_end_x - fill_start_x).abs(), - ..*bounds - }; - - renderer.fill_quad( - renderer::Quad { - bounds: fill_rect, - ..Default::default() - }, - style.bar.color, - ); - - // To make it more readable (and because it looks cool), the parts that overlap with the - // fill rect will be rendered in white while the rest will be rendered in black. - let display_value = self.param.to_string(); - - let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()); - let font = self - .font - .map(Renderer::Font::from) - .unwrap_or_else(|| renderer.default_font()); - - let text_bounds = Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..*bounds - }; - renderer.fill_text( - text::Text { - content: display_value.clone(), - font: font, - size: text_size, - bounds: text_bounds.size(), - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - line_height: text::LineHeight::Relative(1.0), - shaping: Default::default(), - wrapping: Default::default(), - }, - text_bounds.position(), - style.background.text, - *viewport, - ); - - // This will clip to the filled area - renderer.with_layer(fill_rect, |renderer| { - renderer.fill_text( - text::Text { - content: display_value, - font: font, - size: text_size, - bounds: text_bounds.size(), - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - line_height: text::LineHeight::Relative(1.0), - shaping: Default::default(), - wrapping: Default::default(), - }, - text_bounds.position(), - style.bar.text, - *viewport, - ); - }); - } -} - -// ############################################################################ -// Event Handling -// ############################################################################ -impl<'a, P, Theme> ParamSlider<'a, P, Theme> -where - P: Param, - Theme: Catalog + text_input::Catalog, -{ - /// Set the normalized value for a parameter if that would change the parameter's plain value - /// (to avoid unnecessary duplicate parameter changes). The begin- and end set parameter - /// messages need to be sent before calling this function. - fn set_normalized_value(&self, shell: &mut Shell<'_, ParamMessage>, normalized_value: f32) { - // This snaps to the nearest plain value if the parameter is stepped in some way. - // TODO: As an optimization, we could add a `const CONTINUOUS: bool` to the parameter to - // avoid this normalized->plain->normalized conversion for parameters that don't need - // it - let plain_value = self.param.preview_plain(normalized_value); - let current_plain_value = self.param.modulated_plain_value(); - if plain_value != current_plain_value { - // For the aforementioned snapping - let normalized_plain_value = self.param.preview_normalized(plain_value); - shell.publish(ParamMessage::SetParameterNormalized( - self.param.as_ptr(), - normalized_plain_value, - )); - } - } - - fn handle_mouse_down_event( - &mut self, - tree: &mut Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - shell: &mut Shell<'_, ParamMessage>, - ) -> event::Status - where - Renderer: TextRenderer, - Renderer::Font: From, - { - let state = tree.state.downcast_mut::(); - let bounds = layout.bounds(); - - let Some(cursor_position) = cursor.position_over(bounds) else { - return event::Status::Ignored; - }; - - let click = mouse::Click::new(cursor_position, mouse::Button::Left, state.last_click); - state.last_click = Some(click); - - if state.keyboard_modifiers.alt() { - // Alt+click should not start a drag, instead it should show the text entry - // widget - state.drag_active = false; - - let text_input_id = state.text_input_id.clone(); - - let current_value = self.param.to_string(); - state.text_input_value = Some(current_value.clone()); - - self.with_text_input( - layout, - renderer, - ¤t_value, - state, - |text_input, layout, renderer| { - if tree.children[0].tag != text_input.tag() { - tree.children[0] = Tree { - tag: text_input.tag(), - state: text_input.state(), - children: text_input.children(), - }; - } - - let mut move_cursor_to_end = - operation::text_input::move_cursor_to_end(text_input_id.clone().into()); - let mut select_all = operation::text_input::select_all(text_input_id.into()); - - text_input.operate( - &mut tree.children[0], - layout, - renderer, - &mut move_cursor_to_end, - ); - text_input.operate(&mut tree.children[0], layout, renderer, &mut select_all); - }, - ); - } else if state.keyboard_modifiers.command() - || matches!(click.kind(), mouse::click::Kind::Double) - { - // Likewise resetting a parameter should not let you immediately drag it to a new value - state.drag_active = false; - - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.set_normalized_value(shell, self.param.default_normalized_value()); - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - } else if state.keyboard_modifiers.shift() { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - state.drag_active = true; - - // When holding down shift while clicking on a parameter we want to - // granuarly edit the parameter without jumping to a new value - state.granular_drag_start_x_value = - Some((cursor_position.x, self.param.modulated_normalized_value())); - } else { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - state.drag_active = true; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - state.granular_drag_start_x_value = None; - } - - event::Status::Captured - } - - fn handle_mouse_up_event( - &mut self, - shell: &mut Shell<'_, ParamMessage>, - state: &mut State, - ) -> event::Status { - if !state.drag_active { - return event::Status::Ignored; - } - - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - state.drag_active = false; - event::Status::Captured - } - - fn handle_mouse_move_event( - &mut self, - layout: Layout<'_>, - cursor: mouse::Cursor, - shell: &mut Shell<'_, ParamMessage>, - state: &mut State, - ) -> event::Status { - // Don't do anything when we just reset the parameter because that would be weird - if !state.drag_active { - return event::Status::Ignored; - } - - let bounds = layout.bounds(); - - // If shift is being held then the drag should be more granular instead of - // absolute - if let Some(cursor_position) = cursor.position() { - if state.keyboard_modifiers.shift() { - let (drag_start_x, drag_start_value) = - *state.granular_drag_start_x_value.get_or_insert_with(|| { - (cursor_position.x, self.param.modulated_normalized_value()) - }); - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate( - &bounds, - util::remap_rect_x_t(&bounds, drag_start_value) - + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, - ), - ); - } else { - state.granular_drag_start_x_value = None; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - } - } - - event::Status::Captured - } - - fn handle_keyboard_modifiers_changed( - &mut self, - layout: Layout<'_>, - cursor: mouse::Cursor, - shell: &mut Shell<'_, ParamMessage>, - modifiers: keyboard::Modifiers, - state: &mut State, - ) -> event::Status { - state.keyboard_modifiers = modifiers; - let bounds = layout.bounds(); - - // If this happens while dragging, snap back to reality uh I mean the current screen - // position - if state.drag_active && state.granular_drag_start_x_value.is_some() && !modifiers.shift() { - state.granular_drag_start_x_value = None; - - if let Some(cursor_position) = cursor.position() { - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - } - } - - event::Status::Captured - } -} - -// ############################################################################ -// Styling / Appearance -// ############################################################################ - -/// The appearance of a slider. -pub struct Style { - /// The [`Color`] of the slider background. - pub background: Pair, - - /// The [`Color`] of the slider bar. - pub bar: Pair, - /// The border of the slider. - pub border: Border, -} - -/// The theme catalog of a [`ParamSlider`]. -pub trait Catalog: Sized { - /// The item class of the [`Catalog`]. - type Class<'a>; - - /// The default class produced by the [`Catalog`]. - fn default<'a>() -> Self::Class<'a>; - - /// The [`Style`] of a class with the given status. - fn style(&self, class: &Self::Class<'_>, status: Status) -> Style; -} - -/// A styling function for a [`ParamSlider`]. -pub type StyleFn<'a, Theme> = Box Style + 'a>; - -impl Catalog for iced::Theme { - type Class<'a> = StyleFn<'a, Self>; - - fn default<'a>() -> Self::Class<'a> { - Box::new(|theme: &Self, status: Status| -> Style { - use Status::*; - let palette = theme.extended_palette(); - - let (background, bar) = match status { - Active => (palette.background.base, palette.primary.base), - Hovered => (palette.background.strong, palette.primary.strong), - Dragged => (palette.background.base, palette.primary.base), - }; - - let border = Border { - color: palette.background.base.text, - width: BORDER_WIDTH, - radius: 0.0.into(), - }; - - Style { - background, - bar, - border, - } - }) - } - - fn style(&self, class: &Self::Class<'_>, status: Status) -> Style { - class(self, status) - } -} - -impl<'a, P, Theme> ParamSlider<'a, P, Theme> +impl<'a, P> ParamSlider<'a, P> where P: Param + 'a, - Theme: Catalog + text_input::Catalog + 'a, { /// Convert this [`ParamSlider`] into an [`Element`] with the correct message. You should have a /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> + pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, + Theme: text_input::Catalog + 'a, Renderer: TextRenderer + 'a, - Renderer::Font: From, + Renderer::Font: From, { Element::from(self).map(f) } } -impl<'a, P, Theme, Renderer> From> - for Element<'a, ParamMessage, Theme, Renderer> +impl<'a, P, Theme, Renderer> From> for Element<'a, ParamMessage, Theme, Renderer> where P: Param + 'a, - Theme: Catalog + text_input::Catalog + 'a, + Theme: text_input::Catalog + 'a, Renderer: TextRenderer + 'a, - Renderer::Font: From, + Renderer::Font: From, { - fn from(widget: ParamSlider<'a, P, Theme>) -> Self { + fn from(widget: ParamSlider<'a, P>) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/widgets/peak_meter.rs b/nih_plug_iced/src/widgets/peak_meter.rs index b98226cc..bce0204b 100644 --- a/nih_plug_iced/src/widgets/peak_meter.rs +++ b/nih_plug_iced/src/widgets/peak_meter.rs @@ -1,14 +1,13 @@ //! A super simple peak meter widget. use crossbeam::atomic::AtomicCell; -use iced_baseview as iced; use std::marker::PhantomData; use std::time::Duration; use std::time::Instant; -use iced::core::text::{self, Paragraph, Renderer as TextRenderer}; -use iced::core::widget::tree::{self, Tree}; -use iced::core::{ +use crate::core::text::{self, Paragraph, Renderer as TextRenderer}; +use crate::core::widget::tree::{self, Tree}; +use crate::core::{ alignment, layout, mouse, padding, renderer, Background, Border, Color, Element, Font, Layout, Length, Pixels, Point, Rectangle, Size, Widget, }; @@ -101,7 +100,7 @@ impl Widget for PeakMeter, + Renderer::Font: From, { fn tag(&self) -> tree::Tag { tree::Tag::of::() @@ -337,7 +336,7 @@ impl<'a, Theme, Message, Renderer> From> where Message: Clone + 'a, Renderer: TextRenderer + 'a, - Renderer::Font: From, + Renderer::Font: From, { fn from(widget: PeakMeter) -> Self { Element::new(widget) From 5c8a43ab2c67ab1172333ef73293758819a6577a Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 14:56:29 -0700 Subject: [PATCH 04/11] Update iced version to 0.13 --- nih_plug_iced/Cargo.toml | 4 +- nih_plug_iced/src/assets.rs | 1 - nih_plug_iced/src/editor.rs | 67 +- nih_plug_iced/src/lib.rs | 39 +- nih_plug_iced/src/widgets.rs | 6 +- nih_plug_iced/src/widgets/generic_ui.rs | 429 +++++++------ nih_plug_iced/src/widgets/param_slider.rs | 630 ++++++++++--------- nih_plug_iced/src/widgets/peak_meter.rs | 228 ++++--- nih_plug_iced/src/wrapper.rs | 81 ++- plugins/examples/gain_gui_iced/Cargo.toml | 4 +- plugins/examples/gain_gui_iced/src/editor.rs | 83 +-- 11 files changed, 773 insertions(+), 799 deletions(-) diff --git a/nih_plug_iced/Cargo.toml b/nih_plug_iced/Cargo.toml index dec22de8..35f55d23 100644 --- a/nih_plug_iced/Cargo.toml +++ b/nih_plug_iced/Cargo.toml @@ -42,10 +42,10 @@ nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" } raw-window-handle = "0.5" atomic_refcell = "0.1" -baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "fdb43ea" } +baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "579130ecb4f9f315ae52190af42f0ea46aeaa4a2" } crossbeam = "0.8" # This targets iced 0.10 -iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "4feacc03bc1135023f73167093aea953a858a7c2", default_features = false } +iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "a0842a8205c852127981e27de6342cf2e665562f", default_features = false } futures-util = "0.3" # To make the state persistable diff --git a/nih_plug_iced/src/assets.rs b/nih_plug_iced/src/assets.rs index befe1582..70982bd8 100644 --- a/nih_plug_iced/src/assets.rs +++ b/nih_plug_iced/src/assets.rs @@ -4,7 +4,6 @@ use std::borrow::Cow; use crate::core::Font; -use iced_baseview::runtime::{font, Command}; // This module provides a re-export and simple font wrappers around the re-exported fonts. pub use nih_plug_assets::*; diff --git a/nih_plug_iced/src/editor.rs b/nih_plug_iced/src/editor.rs index f073083a..cc98e04e 100644 --- a/nih_plug_iced/src/editor.rs +++ b/nih_plug_iced/src/editor.rs @@ -6,8 +6,8 @@ use crossbeam::channel; use iced_baseview::settings::IcedBaseviewSettings; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use std::{borrow::Cow, sync::atomic::Ordering}; use std::sync::Arc; +use std::{borrow::Cow, sync::atomic::Ordering}; use crate::{wrapper, IcedEditor, IcedState, ParameterUpdate}; @@ -28,32 +28,6 @@ pub(crate) struct IcedEditorWrapper { pub(crate) parameter_updates_receiver: Arc>, } -/// This version of `baseview` uses a different version of `raw_window_handle than NIH-plug, so we -/// need to adapt it ourselves. -struct ParentWindowHandleAdapter(nih_plug::editor::ParentWindowHandle); - -unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter { - fn raw_window_handle(&self) -> RawWindowHandle { - match self.0 { - ParentWindowHandle::X11Window(window) => { - let mut handle = raw_window_handle::XcbWindowHandle::empty(); - handle.window = window; - RawWindowHandle::Xcb(handle) - } - ParentWindowHandle::AppKitNsView(ns_view) => { - let mut handle = raw_window_handle::AppKitWindowHandle::empty(); - handle.ns_view = ns_view; - RawWindowHandle::AppKit(handle) - } - ParentWindowHandle::Win32Hwnd(hwnd) => { - let mut handle = raw_window_handle::Win32WindowHandle::empty(); - handle.hwnd = hwnd; - RawWindowHandle::Win32(handle) - } - } - } -} - impl Editor for IcedEditorWrapper { fn spawn( &self, @@ -66,7 +40,13 @@ impl Editor for IcedEditorWrapper { // TODO: iced_baseview does not have gracefuly error handling for context creation failures. // This will panic if the context could not be created. let window = iced_baseview::open_parented::, _>( - &ParentWindowHandleAdapter(parent), + &parent, + // We use this wrapper to be able to pass the GUI context to the editor + ( + context, + self.parameter_updates_receiver.clone(), + self.initialization_flags.clone(), + ), Settings { window: WindowOpenOptions { title: String::from("iced window"), @@ -77,42 +57,13 @@ impl Editor for IcedEditorWrapper { scale: scaling_factor .map(|factor| WindowScalePolicy::ScaleFactor(factor as f64)) .unwrap_or(WindowScalePolicy::SystemScaleFactor), - - #[cfg(feature = "opengl")] - gl_config: Some(baseview::gl::GlConfig { - // FIXME: glow_glyph forgot to add an `#extension`, so this won't work under - // OpenGL 3.2 at the moment. With that change applied this should work on - // OpenGL 3.2/macOS. - version: (3, 3), - red_bits: 8, - blue_bits: 8, - green_bits: 8, - alpha_bits: 8, - depth_bits: 24, - stencil_bits: 8, - samples: None, - srgb: true, - double_buffer: true, - vsync: true, - ..Default::default() - }), - // FIXME: Rust analyzer always thinks baseview/opengl is enabled even if we - // don't explicitly enable it, so you'd get a compile error if this line - // is missing - // #[cfg(not(feature = "opengl"))] - // gl_config: None, }, iced_baseview: IcedBaseviewSettings { ignore_non_modifier_keys: false, always_redraw: true, }, - // We use this wrapper to be able to pass the GUI context to the editor - flags: ( - context, - self.parameter_updates_receiver.clone(), - self.initialization_flags.clone(), - ), fonts: self.fonts.clone(), + ..Default::default() }, ); diff --git a/nih_plug_iced/src/lib.rs b/nih_plug_iced/src/lib.rs index 54590d2c..d548c23b 100644 --- a/nih_plug_iced/src/lib.rs +++ b/nih_plug_iced/src/lib.rs @@ -39,7 +39,7 @@ //! fn new( //! params: Self::InitializationFlags, //! context: Arc, -//! ) -> (Self, Command) { +//! ) -> (Self, Task) { //! let editor = FooEditor { //! params, //! context, @@ -47,7 +47,7 @@ //! foo_slider_state: Default::default(), //! }; //! -//! (editor, Command::none()) +//! (editor, Task::none()) //! } //! //! fn context(&self) -> &dyn GuiContext { @@ -56,14 +56,13 @@ //! //! fn update( //! &mut self, -//! _window: &mut WindowQueue, //! message: Self::Message, -//! ) -> Command { +//! ) -> Task { //! match message { //! Message::ParamUpdate(message) => self.handle_param_message(message), //! } //! -//! Command::none() +//! Task::none() //! } //! //! fn view(&mut self) -> Element<'_, Self::Message> { @@ -92,13 +91,7 @@ use ::baseview::WindowScalePolicy; use crossbeam::atomic::AtomicCell; use crossbeam::channel; -use iced_baseview::core::{Color, Element, Font}; -use iced_baseview::futures::{Executor, Subscription}; -use iced_baseview::graphics::Antialiasing; -use iced_baseview::runtime::Command; -use iced_baseview::style::application::StyleSheet; -use iced_baseview::widget::renderer::Settings as RendererSettings; -use iced_baseview::window::WindowSubs; +use iced_baseview::futures::Subscription; use nih_plug::params::persist::PersistentField; use nih_plug::prelude::{Editor, GuiContext}; use serde::{Deserialize, Serialize}; @@ -173,13 +166,13 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { /// See [`Application::Flags`]. type InitializationFlags: 'static + Clone + Send + Sync; /// See [`Application::Theme`] - type Theme: Default + StyleSheet; + type Theme: Default + DefaultStyle; /// See [`Application::new`]. This also receivs the GUI context in addition to the flags. fn new( initialization_fags: Self::InitializationFlags, context: Arc, - ) -> (Self, Command); + ) -> (Self, Task); /// Returns a reference to the GUI context. /// [`handle_param_message()`][Self::handle_param_message()] uses this to interact with the @@ -189,10 +182,7 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { /// See [`Application::update`]. When receiving the variant that contains a /// [`widgets::ParamMessage`] you can call /// [`handle_param_message()`][Self::handle_param_message()] to handle the parameter update. - fn update( - &mut self, - message: Self::Message, - ) -> Command; + fn update(&mut self, message: Self::Message) -> Task; /// See [`Application::subscription`]. fn subscription( @@ -203,7 +193,7 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { } /// See [`Application::view`]. - fn view(&self) -> Element<'_, Self::Message, Renderer>; + fn view(&self) -> Element<'_, Self::Message, Self::Theme, Renderer>; /// See [`Application::background_color`]. fn background_color(&self) -> Color { @@ -225,17 +215,6 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { WindowScalePolicy::SystemScaleFactor } - /// See [`Application::renderer_settings`]. - fn renderer_settings() -> RendererSettings { - RendererSettings { - // Enable some anti-aliasing by default. Since GUIs are likely very simple and most of - // the work will be on the CPU anyways this should not affect performance much. - antialiasing: Some(Antialiasing::MSAAx4), - default_font: Font::DEFAULT, - ..RendererSettings::default() - } - } - /// Handle a parameter update using the GUI context. fn handle_param_message(&self, message: ParamMessage) { // We can't use the fancy ParamSetter here because this needs to be type erased diff --git a/nih_plug_iced/src/widgets.rs b/nih_plug_iced/src/widgets.rs index 28856fc0..fa52f029 100644 --- a/nih_plug_iced/src/widgets.rs +++ b/nih_plug_iced/src/widgets.rs @@ -7,12 +7,12 @@ use nih_plug::prelude::ParamPtr; -// pub mod generic_ui; -// pub mod param_slider; +pub mod generic_ui; +pub mod param_slider; pub mod peak_meter; pub mod util; -// pub use param_slider::ParamSlider; +pub use param_slider::ParamSlider; pub use peak_meter::PeakMeter; /// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with diff --git a/nih_plug_iced/src/widgets/generic_ui.rs b/nih_plug_iced/src/widgets/generic_ui.rs index d12281f3..9a9df38d 100644 --- a/nih_plug_iced/src/widgets/generic_ui.rs +++ b/nih_plug_iced/src/widgets/generic_ui.rs @@ -1,31 +1,29 @@ //! A simple generic UI widget that renders all parameters in a [`Params`] object as a scrollable //! list of sliders and labels. -use atomic_refcell::AtomicRefCell; -use baseview::{Event, Point}; -use iced_baseview::Renderer; -use crate::{widget::{self, scrollable::Alignment, Row, Scrollable, Space, Text}}; -use std::borrow::Borrow; -use std::collections::HashMap; +use crate::core::widget::{Id, Operation, Tree}; +use crate::core::{ + alignment, event, layout, renderer, text, Clipboard, Element, Layout, Length, Rectangle, Shell, + Size, Widget, +}; +use crate::widget::{self, row, scrollable, Column, Scrollable, Space}; use std::marker::PhantomData; use std::sync::Arc; use nih_plug::prelude::{Param, ParamFlags, ParamPtr, Params}; use super::{ParamMessage, ParamSlider}; -use crate::core::{alignment, event, layout, renderer, Clipboard, Element, Layout, Length, Rectangle, Shell, Widget}; /// A widget that can be used to create a generic UI with. This is used in conjuction with empty /// structs to emulate existential types. -pub trait ParamWidget { - /// The type of state stores by this parameter type. - type State: Default; - +pub trait ParamWidget { /// Create an [`Element`] for a widget for the specified parameter. fn into_widget_element<'a, P: Param>( param: &'a P, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage, Renderer>; + ) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a; /// The same as [`into_widget_element()`][Self::into_widget_element()], but for a `ParamPtr`. /// @@ -33,14 +31,17 @@ pub trait ParamWidget { /// /// Undefined behavior of the `ParamPtr` does not point to a valid parameter. unsafe fn into_widget_element_raw<'a>( - param: &ParamPtr, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage, Renderer> { + param: &'a ParamPtr, + ) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a, + { match param { - ParamPtr::FloatParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::IntParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::BoolParam(p) => Self::into_widget_element(&**p, state), - ParamPtr::EnumParam(p) => Self::into_widget_element(&**p, state), + ParamPtr::FloatParam(p) => Self::into_widget_element(&**p), + ParamPtr::IntParam(p) => Self::into_widget_element(&**p), + ParamPtr::BoolParam(p) => Self::into_widget_element(&**p), + ParamPtr::EnumParam(p) => Self::into_widget_element(&**p), } } } @@ -53,72 +54,72 @@ pub struct GenericSlider; /// determines what widget to use for this. /// /// TODO: There's no way to configure the individual widgets. -pub struct GenericUi<'a, W: ParamWidget> { - state: &'a mut State, - - params: Arc, +pub struct GenericUi { + // Hacky work around so we can borrow &ParamPtr and ensure references + // stay alive for the lifetime of this object. + params: Vec, + id: Option, width: Length, height: Length, - max_width: u32, - max_height: u32, + max_width: u16, + max_height: u16, + pad_scrollbar: bool, /// We don't emit any messages or store the actual widgets, but iced requires us to define some /// message type anyways. - _phantom: PhantomData, -} - -/// State for a [`GenericUi`]. -#[derive(Debug, Default)] -pub struct State { - /// The internal state for each parameter's widget. - scrollable_state: AtomicRefCell, - /// The internal state for each parameter's widget. - widget_state: AtomicRefCell>, + _phantom: PhantomData<(W, Theme, Renderer)>, } -impl<'a, W> GenericUi<'a, W> -where - W: ParamWidget, -{ +impl GenericUi { /// Creates a new [`GenericUi`] for all provided parameters. - pub fn new(state: &'a mut State, params: Arc) -> Self { + pub fn new(params: Arc) -> Self { + let params = params + .param_map() + .into_iter() + .map(|(_, ptr, _)| ptr) + .collect(); Self { - state, - + id: None, params, width: Length::Fill, height: Length::Fill, - max_width: u32::MAX, - max_height: u32::MAX, + max_width: u16::MAX, + max_height: u16::MAX, pad_scrollbar: false, _phantom: PhantomData, } } + /// Sets the [`Id`] of the [`Container`]. + pub fn id(mut self, id: Id) -> Self { + self.id = Some(id); + self + } + /// Sets the width of the [`GenericUi`]. - pub fn width(mut self, width: Length) -> Self { - self.width = width; + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); self } /// Sets the height of the [`GenericUi`]. - pub fn height(mut self, height: Length) -> Self { - self.height = height; + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); self } /// Sets the maximum width of the [`GenericUi`]. - pub fn max_width(mut self, width: u32) -> Self { + pub fn max_width(mut self, width: u16) -> Self { self.max_width = width; self } /// Sets the maximum height of the [`GenericUi`]. - pub fn max_height(mut self, height: u32) -> Self { + pub fn max_height(mut self, height: u16) -> Self { self.max_height = height; self } @@ -128,210 +129,203 @@ where self.pad_scrollbar = true; self } +} - /// Create a temporary [`Scrollable`]. This needs to be created on demand because it needs to - /// mutably borrow the `Scrollable`'s widget state. - fn with_scrollable_widget( +impl<'a, W, Theme, Renderer> GenericUi +where + W: ParamWidget, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, +{ + fn content( &'a self, - scrollable_state: &'a mut widget::scrollable::State, - widget_state: &'a mut HashMap, - renderer: &Renderer, - f: F, - ) -> T - where - F: FnOnce(Scrollable<'a, ParamMessage>, &Renderer) -> T - { - let text_size = renderer.borrow().default_size(); - let spacing = (text_size as f32 * 0.2).round() as u16; - let padding = (text_size as f32 * 0.5).round() as u16; - - let mut scrollable = Scrollable::new(scrollable_state) - .width(self.width) - .height(self.height) - .max_width(self.max_width) - .max_height(self.max_height) - .spacing(spacing) - .padding(padding) - .align_items(Alignment::Center); - - // Make sure we already have widget state for each widget - let param_map = self.params.param_map(); - for (_, param_ptr, _) in ¶m_map { - let flags = unsafe { param_ptr.flags() }; - if flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) { - continue; - } - - if !widget_state.contains_key(param_ptr) { - widget_state.insert(*param_ptr, Default::default()); - } - } - - for (_, param_ptr, _) in param_map { - let flags = unsafe { param_ptr.flags() }; - if flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) { - continue; - } - - // SAFETY: We only borrow each item once, and the plugin framework statically asserted - // that parameter indices are unique and this widget state cannot outlive this - // function - let widget_state: &'a mut W::State = - unsafe { &mut *(widget_state.get_mut(¶m_ptr).unwrap() as *mut _) }; - - // Show the label next to the parameter for better use of the space - let mut row = Row::new() - .width(Length::Fill) - .align_items(Alignment::Center) - .spacing(spacing * 2) - .push( - Text::new(unsafe { param_ptr.name() }) - .height(20.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Right) - .vertical_alignment(alignment::Vertical::Center), - ) - .push(unsafe { W::into_widget_element_raw(¶m_ptr, widget_state) }); - if self.pad_scrollbar { - // There's already spacing applied, so this element doesn't actually need to hae any - // size of its own - row = row.push(Space::with_width(Length::Units(0))); - } - - scrollable = scrollable.push(row); - } - - f(scrollable, renderer) + renderer: Option<&Renderer>, + ) -> Scrollable<'a, ParamMessage, Theme, Renderer> { + let (spacing, padding) = match renderer { + Some(renderer) => ( + (renderer.default_size() * 0.2).0.round(), + (renderer.default_size() * 0.5).0.round(), + ), + None => (0.0, 0.0), + }; + + let content = Column::with_children( + self.params + .iter() + .filter(|param| is_hidden(*param)) + .map(|param| { + let row = row![ + widget::text(unsafe { param.name() }) + .height(20) + .width(Length::Fill) + .align_x(alignment::Horizontal::Right) + .align_y(alignment::Vertical::Center), + unsafe { W::into_widget_element_raw(param) } + ] + .width(Length::Fill) + .align_y(alignment::Vertical::Center) + .spacing(spacing * 2.0); + + if self.pad_scrollbar { + row.push(Space::with_width(0)) + } else { + row + } + }) + .map(Element::from), + ) + .align_x(alignment::Horizontal::Center) + .spacing(spacing) + .padding(padding) + .width(self.width) + .height(self.height) + .max_width(self.max_width); + + scrollable(content).spacing(spacing) } } -impl<'a, W> Widget for GenericUi<'a, W> +impl<'a, W, Theme, Renderer> Widget for GenericUi where - W: ParamWidget, + W: ParamWidget, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, { - fn width(&self) -> Length { - self.width + fn size(&self) -> iced_baseview::Size { + Size { + width: self.width, + height: self.height, + } } - fn height(&self) -> Length { - self.height + fn children(&self) -> Vec { + let content = self.content(None); + + vec![Tree::new( + &content as &dyn Widget, + )] } - fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, - renderer, - |scrollable, _| scrollable.layout(renderer, limits), - ) + fn layout( + &self, + tree: &mut Tree, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + self.content(Some(renderer)) + .layout(&mut tree.children[0], renderer, limits) } fn draw( &self, - state: &iced_baseview::core::widget::Tree, + tree: &iced_baseview::core::widget::Tree, renderer: &mut Renderer, - theme: &::Theme, + theme: &Theme, style: &renderer::Style, layout: Layout<'_>, cursor: iced_baseview::core::mouse::Cursor, viewport: &Rectangle, ) { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, + self.content(Some(renderer)).draw( + &tree.children[0], renderer, - |scrollable, renderer| { - scrollable.draw(todo!(), renderer, style, todo!(), layout, cursor_position, viewport) - }, + theme, + style, + layout, + cursor, + viewport, ) } + fn operate( + &self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn Operation, + ) { + operation.container(self.id.as_ref(), layout.bounds(), &mut |operation| { + self.content(Some(renderer)).operate( + tree, + layout.children().next().unwrap(), + renderer, + operation, + ) + }); + } + fn on_event( &mut self, - _state: &mut iced_baseview::core::widget::Tree, - _event: event::Event, - _layout: Layout<'_>, - _cursor: iced_baseview::core::mouse::Cursor, - _renderer: &Renderer, - _clipboard: &mut dyn Clipboard, - _shell: &mut Shell<'_, ParamMessage>, - _viewport: &Rectangle, + tree: &mut iced_baseview::core::widget::Tree, + event: event::Event, + layout: Layout<'_>, + cursor: iced_baseview::core::mouse::Cursor, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, ParamMessage>, + viewport: &Rectangle, ) -> event::Status { - let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - let mut widget_state = self.state.widget_state.borrow_mut(); - self.with_scrollable_widget( - &mut scrollable_state, - &mut widget_state, + self.content(Some(renderer)).on_event( + &mut tree.children[0], + event, + layout.children().next().unwrap(), + cursor, renderer, - |mut scrollable, _| { - scrollable.on_event(todo!(), event, layout, cursor_position, renderer, clipboard, shell, todo!()) - }, + clipboard, + shell, + viewport, ) } - // fn draw( - // &self, - // renderer: &mut Renderer, - // style: &mut renderer::Style, - // layout: Layout<'_>, - // cursor_position: Point, - // viewport: &Rectangle, - // ) { - // let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - // let mut widget_state = self.state.widget_state.borrow_mut(); - // self.with_scrollable_widget( - // &mut scrollable_state, - // &mut widget_state, - // renderer, - // |scrollable, renderer| { - // scrollable.draw(todo!(), renderer, style, todo!(), layout, cursor_position, viewport) - // }, - // ) - // } - - // fn on_event( - // &mut self, - // event: Event, - // layout: Layout<'_>, - // cursor_position: Point, - // renderer: &Renderer, - // clipboard: &mut dyn Clipboard, - // shell: &mut Shell<'_, ParamMessage>, - // ) -> event::Status { - // let mut scrollable_state = self.state.scrollable_state.borrow_mut(); - // let mut widget_state = self.state.widget_state.borrow_mut(); - // self.with_scrollable_widget( - // &mut scrollable_state, - // &mut widget_state, - // renderer, - // |mut scrollable, _| { - // scrollable.on_event(todo!(), event, layout, cursor_position, renderer, clipboard, shell, todo!()) - // }, - // ) - // } + fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor: iced_baseview::core::mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> iced_baseview::core::mouse::Interaction { + self.content(Some(renderer)).mouse_interaction( + &tree.children[0], + layout.children().next().unwrap(), + cursor, + viewport, + renderer, + ) + } } -impl ParamWidget for GenericSlider { - type State = super::param_slider::State; +fn is_hidden(param_ptr: &ParamPtr) -> bool { + let flags = unsafe { param_ptr.flags() }; + flags.contains(ParamFlags::HIDE_IN_GENERIC_UI) +} - fn into_widget_element<'a, P: Param>( - param: &'a P, - state: &'a mut Self::State, - ) -> Element<'a, ParamMessage, Renderer> { - ParamSlider::new(state, param).into() +impl ParamWidget for GenericSlider +where + Theme: widget::text_input::Catalog, + Renderer: text::Renderer, + Renderer::Font: From, +{ + fn into_widget_element<'a, P: Param>(param: &'a P) -> Element<'a, ParamMessage, Theme, Renderer> + where + Theme: 'a, + Renderer: 'a, + { + ParamSlider::new(param).into() } } -impl<'a, W: ParamWidget> GenericUi<'a, W> { +impl<'a, W, Theme, Renderer> GenericUi +where + W: ParamWidget + 'a, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, +{ /// Convert this [`GenericUi`] into an [`Element`] with the correct message. You should have a /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message, Renderer> + pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, @@ -340,11 +334,14 @@ impl<'a, W: ParamWidget> GenericUi<'a, W> { } } -impl<'a, W> From> for Element<'a, ParamMessage, Renderer> +impl<'a, W, Theme, Renderer> From> + for Element<'a, ParamMessage, Theme, Renderer> where - W: ParamWidget, + W: ParamWidget + 'a, + Theme: scrollable::Catalog + widget::text::Catalog + 'a, + Renderer: text::Renderer + 'a, { - fn from(widget: GenericUi<'a, W>) -> Self { + fn from(widget: GenericUi) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 939c5272..4a3b4283 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,22 +1,17 @@ -//! A slider that integrates with NIH-plug's [`Param`] types. - -use iced_baseview::widget::text_input; -use iced_baseview::widget::text_input::Id; -use iced_baseview::widget::TextInput; +use nih_plug::nih_log; use nih_plug::prelude::Param; use std::borrow::Borrow; -use iced_baseview::Renderer; -use crate::core::widget; -use crate::core::renderer::Renderer as GraphicsRenderer; -use crate::core::text::Renderer as TextRenderer; +use crate::core::text::{Paragraph, Renderer as TextRenderer, Text}; +use crate::core::widget::tree::{self, Tree}; use crate::core::{ - alignment, event, keyboard, layout, mouse, renderer, text, touch, Background, Clipboard, Color, - Element, Event, Font, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget, + alignment, event, keyboard, layout, mouse, renderer, text, touch, Border, Clipboard, Color, + Element, Event, Font, Layout, Length, Pixels, Rectangle, Shell, Size, Vector, Widget, }; +use crate::widget::text_input; +use crate::widget::text_input::{Id, TextInput}; -use super::util; -use super::ParamMessage; +use super::{util, ParamMessage}; /// When shift+dragging a parameter, one pixel dragged corresponds to this much change in the /// noramlized parameter. @@ -25,24 +20,21 @@ const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1; /// The thickness of this widget's borders. const BORDER_WIDTH: f32 = 1.0; -/// A slider that integrates with NIH-plug's [`Param`] types. -/// -/// TODO: There are currently no styling options at all -/// TODO: Handle scrolling for steps (and shift+scroll for smaller steps?) -pub struct ParamSlider<'a, P: Param> { - state: &'a mut State, - +pub struct ParamSlider<'a, P> +where + P: Param, +{ param: &'a P, - height: Length, width: Length, - text_size: Option, - font: Font, + height: Length, + text_size: Option, + font: Option, } /// State for a [`ParamSlider`]. #[derive(Debug)] -pub struct State { +struct State { keyboard_modifiers: keyboard::Modifiers, /// Will be set to `true` if we're dragging the parameter. Resetting the parameter or entering a /// text value should not initiate a drag. @@ -53,25 +45,37 @@ pub struct State { /// Track clicks for double clicks. last_click: Option, - // /// State for the text input overlay that will be shown when this widget is alt+clicked. - // text_input_state: AtomicRefCell, /// The text that's currently in the text input. If this is set to `None`, then the text input /// is not visible. text_input_value: Option, - text_input_id: Id, } impl Default for State { fn default() -> Self { - Self { + Self { text_input_id: Id::unique(), - ..Default::default() + keyboard_modifiers: Default::default(), + drag_active: Default::default(), + granular_drag_start_x_value: Default::default(), + last_click: Default::default(), + text_input_value: Default::default(), } } } -/// An internal message for intercep- I mean handling output from the embedded [`TextInpu`] widget. +/// The possible UI status of a [`ParamSlider`]. Enables drawing of different styles for each status. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Status { + /// The [`ParamSlider`] can be interacted with. + Active, + /// The [`ParamSlider`] is being hovered. + Hovered, + /// The [`ParamSlider`] is being dragged. + Dragged, +} + +/// An internal message for intercep- I mean handling output from the embedded [`TextInput`] widget. #[derive(Debug, Clone)] enum TextInputMessage { /// A new value was entered in the text input dialog. @@ -80,59 +84,22 @@ enum TextInputMessage { Submit, } -/// The default text input style with the border removed. -struct TextInputStyle; - -impl crate::widget::text_input::StyleSheet for TextInputStyle { - type Style = (); - - fn disabled_color(&self, style: &Self::Style) -> Color { - todo!() - } - - fn disabled(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { - todo!() - } - - fn active(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { - iced_baseview::widget::text_input::Appearance { - background: Background::Color(Color::TRANSPARENT), - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - icon_color: Color::TRANSPARENT, - } - } - - fn focused(&self, style: &Self::Style) -> iced_baseview::widget::text_input::Appearance { - self.active(style) - } - - fn placeholder_color(&self, style: &Self::Style) -> Color { - Color::from_rgb(0.7, 0.7, 0.7) - } +impl<'a, P> ParamSlider<'a, P> +where + P: Param, +{ + pub const DEFAULT_WIDTH: Length = Length::Fixed(180.0); + pub const DEFAULT_HEIGHT: Length = Length::Fixed(30.0); - fn value_color(&self, style: &Self::Style) -> Color { - Color::from_rgb(0.3, 0.3, 0.3) - } - - fn selection_color(&self, style: &Self::Style) -> Color { - Color::from_rgb(0.8, 0.8, 1.0) - } -} - -impl<'a, P: Param> ParamSlider<'a, P> { /// Creates a new [`ParamSlider`] for the given parameter. - pub fn new(state: &'a mut State, param: &'a P) -> Self { + pub fn new(param: &'a P) -> Self { Self { - state, - param, - width: Length::Fixed(180.0), - height: Length::Fixed(30.0), + width: Self::DEFAULT_WIDTH, + height: Self::DEFAULT_HEIGHT, text_size: None, - font: ::Font::default(), + font: None, } } @@ -149,49 +116,70 @@ impl<'a, P: Param> ParamSlider<'a, P> { } /// Sets the text size of the [`ParamSlider`]. - pub fn text_size(mut self, size: f32) -> Self { + pub fn text_size(mut self, size: Pixels) -> Self { self.text_size = Some(size); self } /// Sets the font of the [`ParamSlider`]. pub fn font(mut self, font: Font) -> Self { - self.font = font; + self.font = Some(font); self } /// Create a temporary [`TextInput`] hooked up to [`State::text_input_value`] and outputting /// [`TextInputMessage`] messages and do something with it. This can be used to - fn with_text_input(&self, layout: Layout, renderer: R, current_value: &str, f: F) -> T + fn with_text_input( + &self, + layout: Layout, + renderer: BorrowedRenderer, + current_value: &str, + state: &State, + f: F, + ) -> T where - F: FnOnce(TextInput<'_, TextInputMessage>, Layout, R) -> T, - R: Borrow, + F: FnOnce(TextInput<'_, TextInputMessage, Theme, Renderer>, Layout, BorrowedRenderer) -> T, + Theme: text_input::Catalog, + Renderer: TextRenderer, + Renderer::Font: From, + BorrowedRenderer: Borrow, { - // let mut text_input_state = self.state.text_input_state.borrow_mut(); - // text_input_state.focus(); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.borrow().default_font()); let text_size = self .text_size .unwrap_or_else(|| renderer.borrow().default_size()); - let text_width = renderer - .borrow() - .measure_width(current_value, text_size, self.font, Default::default()); - let text_input = TextInput::new( - "", - current_value, - ) - .id(self.state.text_input_id) - .font(self.font) - .size(text_size) - .width(Length::Fixed(text_width)) - // .style(TextInputStyle) - .on_submit(TextInputMessage::Submit); + let text_width = Renderer::Paragraph::with_text(Text { + content: current_value, + bounds: layout.bounds().size(), + size: text_size, + font, + line_height: Default::default(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + shaping: Default::default(), + wrapping: Default::default(), + }) + .min_width(); + + nih_log!("with_text_input() - {} {}", current_value, text_width); + + let text_input = text_input("", current_value) + .id(state.text_input_id.clone()) + .font(font) + .size(text_size) + .width(text_width) + .on_input(TextInputMessage::Value) + .on_submit(TextInputMessage::Submit); // Make sure to not draw over the borders, and center the text let offset_node = layout::Node::with_children( Size { width: text_width, - height: layout.bounds().size().height - (BORDER_WIDTH * 2.0), + height: layout.bounds().shrink(BORDER_WIDTH).size().height, }, vec![layout::Node::new(layout.bounds().size())], ); @@ -227,50 +215,63 @@ impl<'a, P: Param> ParamSlider<'a, P> { } } -impl<'a, P: Param> Widget for ParamSlider<'a, P> { - fn width(&self) -> Length { - self.width +impl<'a, P, Theme, Renderer> Widget for ParamSlider<'a, P> +where + P: Param, + Theme: text_input::Catalog, + Renderer: TextRenderer, + Renderer::Font: From, +{ + fn tag(&self) -> tree::Tag { + tree::Tag::of::() } - fn height(&self) -> Length { - self.height + fn state(&self) -> tree::State { + tree::State::new(State::default()) } - fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); + fn children(&self) -> Vec { + let input = text_input::("", ""); + + // One child to store text input state. + vec![Tree { + tag: input.tag(), + state: input.state(), + children: input.children(), + }] + } - layout::Node::new(size) + fn size(&self) -> Size { + Size { + width: self.width, + height: self.height, + } + } + + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + layout::atomic(limits, self.width, self.height) } fn draw( &self, - _state: &widget::Tree, + tree: &Tree, renderer: &mut Renderer, - _theme: &::Theme, + theme: &Theme, style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, - _viewport: &Rectangle, + viewport: &Rectangle, ) { + let state = tree.state.downcast_ref::(); let bounds = layout.bounds(); - // I'm sure there's some philosophical meaning behind this - let bounds_without_borders = Rectangle { - x: bounds.x + BORDER_WIDTH, - y: bounds.y + BORDER_WIDTH, - width: bounds.width - (BORDER_WIDTH * 2.0), - height: bounds.height - (BORDER_WIDTH * 2.0), - }; - let is_mouse_over = if let Some(cursor_position) = cursor.position() { - bounds.contains(cursor_position) - } else { - false - }; - // The bar itself, show a different background color when the value is being edited or when - // the mouse is hovering over it to indicate that it's interactive let background_color = - if is_mouse_over || self.state.drag_active || self.state.text_input_value.is_some() { + if cursor.is_over(bounds) || state.drag_active || state.text_input_value.is_some() { Color::new(0.5, 0.5, 0.5, 0.1) } else { Color::TRANSPARENT @@ -279,59 +280,66 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { renderer.fill_quad( renderer::Quad { bounds, - border_color: Color::BLACK, - border_width: BORDER_WIDTH, - border_radius: 0.0.into(), + border: Border { + color: Color::BLACK, + width: BORDER_WIDTH, + radius: 0.0.into(), + }, + ..Default::default() }, background_color, ); - // Only draw the text input widget when it gets focussed. Otherwise, overlay the label with - // the slider. - if let Some(current_value) = &self.state.text_input_value { + // Shrink bounds to inside of the border + let bounds = bounds.shrink(BORDER_WIDTH); + + if let Some(current_value) = &state.text_input_value { self.with_text_input( layout, renderer, current_value, + state, |text_input, layout, renderer| { text_input.draw( - todo!(), + &tree.children[0], renderer, - todo!(), + theme, layout, cursor, - None - ) + None, + viewport, + ); }, - ) + ); } else { // We'll visualize the difference between the current value and the default value if the // default value lies somewhere in the middle and the parameter is continuous. Otherwise // this appraoch looks a bit jarring. let current_value = self.param.modulated_normalized_value(); let default_value = self.param.default_normalized_value(); + let fill_start_x = util::remap_rect_x_t( - &bounds_without_borders, + &bounds, if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { default_value } else { 0.0 }, ); - let fill_end_x = util::remap_rect_x_t(&bounds_without_borders, current_value); + + let fill_end_x = util::remap_rect_x_t(&bounds, current_value); let fill_color = Color::from_rgb8(196, 196, 196); let fill_rect = Rectangle { x: fill_start_x.min(fill_end_x), width: (fill_end_x - fill_start_x).abs(), - ..bounds_without_borders + ..bounds }; + renderer.fill_quad( renderer::Quad { bounds: fill_rect, - border_color: Color::TRANSPARENT, - border_width: 0.0, - border_radius: 0.0.into(), + ..Default::default() }, fill_color, ); @@ -339,90 +347,114 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { // To make it more readable (and because it looks cool), the parts that overlap with the // fill rect will be rendered in white while the rest will be rendered in black. let display_value = self.param.to_string(); - let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()) as f32; + + let text_size = self.text_size.unwrap_or_else(|| renderer.default_size()); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.default_font()); + let text_bounds = Rectangle { x: bounds.center_x(), y: bounds.center_y(), ..bounds }; - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, - size: text_size, - bounds: text_bounds, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Center, - line_height: text::LineHeight::Relative(1.0), - shaping: Default::default(), - }); - - // This will clip to the filled area - renderer.with_layer(fill_rect, |renderer| { - let filled_text_color = Color::from_rgb8(80, 80, 80); - renderer.fill_text(text::Text { - content: &display_value, - font: self.font, + renderer.fill_text( + text::Text { + content: display_value.clone(), + font: font, size: text_size, - bounds: text_bounds, - color: filled_text_color, + bounds: text_bounds.size(), horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Center, line_height: text::LineHeight::Relative(1.0), shaping: Default::default(), - }); + wrapping: Default::default(), + }, + text_bounds.position(), + style.text_color, + *viewport, + ); + + // This will clip to the filled area + renderer.with_layer(fill_rect, |renderer| { + let filled_text_color = Color::from_rgb8(80, 80, 80); + renderer.fill_text( + text::Text { + content: display_value, + font: font, + size: text_size, + bounds: text_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + line_height: text::LineHeight::Relative(1.0), + shaping: Default::default(), + wrapping: Default::default(), + }, + text_bounds.position(), + filled_text_color, + *viewport, + ); }); } } fn on_event( &mut self, - state: &mut widget::Tree, - event: Event, + tree: &mut Tree, + event: event::Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, ParamMessage>, - _viewport: &Rectangle, + viewport: &Rectangle, ) -> event::Status { + let state = tree.state.downcast_mut::(); + // The pressence of a value in `self.state.text_input_value` indicates that the field should // be focussed. The field handles defocussing by itself // FIMXE: This is super hacky, I have no idea how you can reuse the text input widget // otherwise. Widgets are not supposed to handle messages from other widgets, but // we'll do so anyways by using a special `TextInputMessage` type and our own // `Shell`. - let text_input_status = if let Some(current_value) = &self.state.text_input_value { + let text_input_status = if let Some(current_value) = &state.text_input_value { let event = event.clone(); let mut messages = Vec::new(); let mut text_input_shell = Shell::new(&mut messages); + let status = self.with_text_input( layout, renderer, current_value, - |mut text_input, layout, renderer| { + &state, + |mut text_input: TextInput, layout, renderer| { text_input.on_event( - todo!(), + &mut tree.children[0], event, layout, cursor, renderer, clipboard, &mut text_input_shell, - todo!(), + viewport, ) }, ); + // Check if text input is focused. + let text_input_state = tree.children[0] + .state + .downcast_ref::>(); + // Pressing escape will unfocus the text field, so we should propagate that change in // our own model - if state.text_input_state.borrow().is_focused() { + if text_input_state.is_focused() { for message in messages { match message { - TextInputMessage::Value(s) => self.state.text_input_value = Some(s), + TextInputMessage::Value(s) => state.text_input_value = Some(s), TextInputMessage::Submit => { - if let Some(normalized_value) = self - .state + if let Some(normalized_value) = state .text_input_value .as_ref() .and_then(|s| self.param.string_to_normalized_value(s)) @@ -433,12 +465,12 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { } // And defocus the text input widget again - self.state.text_input_value = None; + state.text_input_value = None; } } } } else { - self.state.text_input_value = None; + state.text_input_value = None; } status @@ -449,121 +481,122 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { return event::Status::Captured; } - // Compensate for the border when handling these events - let bounds = layout.bounds(); - let bounds = Rectangle { - x: bounds.x + BORDER_WIDTH, - y: bounds.y + BORDER_WIDTH, - width: bounds.width - (BORDER_WIDTH * 2.0), - height: bounds.height - (BORDER_WIDTH * 2.0), - }; - match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - if let Some(cursor_position) = cursor.position() { - if bounds.contains(cursor_position) { - let click = mouse::Click::new(cursor_position, self.state.last_click); - self.state.last_click = Some(click); - if self.state.keyboard_modifiers.alt() { - // Alt+click should not start a drag, instead it should show the text entry - // widget - self.state.drag_active = false; - - // Changing the parameter happens in the TextInput event handler above - self.state.text_input_value = Some(self.param.to_string()); - - // TODO!!!! send these commands somehow - text_input::move_cursor_to_end(self.state.text_input_id); - text_input::select_all(self.state.text_input_id); - } else if self.state.keyboard_modifiers.command() - || matches!(click.kind(), mouse::click::Kind::Double) - { - // Likewise resetting a parameter should not let you immediately drag it to a new value - self.state.drag_active = false; - - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.set_normalized_value(shell, self.param.default_normalized_value()); - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - } else if self.state.keyboard_modifiers.shift() { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - // When holding down shift while clicking on a parameter we want to - // granuarly edit the parameter without jumping to a new value - self.state.granular_drag_start_x_value = - Some((cursor_position.x, self.param.modulated_normalized_value())); - } else { - shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); - self.state.drag_active = true; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - self.state.granular_drag_start_x_value = None; - } - - return event::Status::Captured; - } + let bounds = layout.bounds(); + + let Some(cursor_position) = cursor.position_over(bounds) else { + return event::Status::Ignored; + }; + + let click = + mouse::Click::new(cursor_position, mouse::Button::Left, state.last_click); + state.last_click = Some(click); + + if state.keyboard_modifiers.alt() { + // Alt+click should not start a drag, instead it should show the text entry + // widget + state.drag_active = false; + + let current_value = self.param.to_string(); + state.text_input_value = Some(current_value.clone()); + + let text_input_state = tree.children[0] + .state + .downcast_mut::>(); + text_input_state.select_all(); + text_input_state.move_cursor_to_end(); + text_input_state.focus(); + } else if state.keyboard_modifiers.command() + || matches!(click.kind(), mouse::click::Kind::Double) + { + // Likewise resetting a parameter should not let you immediately drag it to a new value + state.drag_active = false; + + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + self.set_normalized_value(shell, self.param.default_normalized_value()); + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + } else if state.keyboard_modifiers.shift() { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + // When holding down shift while clicking on a parameter we want to + // granuarly edit the parameter without jumping to a new value + state.granular_drag_start_x_value = + Some((cursor_position.x, self.param.modulated_normalized_value())); + } else { + shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); + state.drag_active = true; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + state.granular_drag_start_x_value = None; } + + event::Status::Captured } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => { - if self.state.drag_active { - shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); - - self.state.drag_active = false; - - return event::Status::Captured; + if !state.drag_active { + return event::Status::Ignored; } + + shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); + state.drag_active = false; + event::Status::Captured } Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { // Don't do anything when we just reset the parameter because that would be weird - if self.state.drag_active { - // If shift is being held then the drag should be more granular instead of - // absolute - if let Some(cursor_position) = cursor.position() { - if self.state.keyboard_modifiers.shift() { - let (drag_start_x, drag_start_value) = *self - .state - .granular_drag_start_x_value - .get_or_insert_with(|| { - (cursor_position.x, self.param.modulated_normalized_value()) - }); - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate( - &bounds, - util::remap_rect_x_t(&bounds, drag_start_value) - + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, - ), - ); - } else { - self.state.granular_drag_start_x_value = None; - - self.set_normalized_value( - shell, - util::remap_rect_x_coordinate(&bounds, cursor_position.x), - ); - } - } + if !state.drag_active { + return event::Status::Ignored; + } + + let bounds = layout.bounds(); + + // If shift is being held then the drag should be more granular instead of + // absolute + if let Some(cursor_position) = cursor.position() { + if state.keyboard_modifiers.shift() { + let (drag_start_x, drag_start_value) = + *state.granular_drag_start_x_value.get_or_insert_with(|| { + (cursor_position.x, self.param.modulated_normalized_value()) + }); - return event::Status::Captured; + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate( + &bounds, + util::remap_rect_x_t(&bounds, drag_start_value) + + (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER, + ), + ); + } else { + state.granular_drag_start_x_value = None; + + self.set_normalized_value( + shell, + util::remap_rect_x_coordinate(&bounds, cursor_position.x), + ); + } } + + event::Status::Captured } Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { - self.state.keyboard_modifiers = modifiers; + state.keyboard_modifiers = modifiers; + let bounds = layout.bounds(); // If this happens while dragging, snap back to reality uh I mean the current screen // position - if self.state.drag_active - && self.state.granular_drag_start_x_value.is_some() + if state.drag_active + && state.granular_drag_start_x_value.is_some() && !modifiers.shift() { - self.state.granular_drag_start_x_value = None; + state.granular_drag_start_x_value = None; if let Some(cursor_position) = cursor.position() { self.set_normalized_value( @@ -573,60 +606,55 @@ impl<'a, P: Param> Widget for ParamSlider<'a, P> { } } - return event::Status::Captured; + event::Status::Captured } - _ => {} + _ => event::Status::Ignored, } - - event::Status::Ignored } - fn mouse_interaction( &self, - _state: &widget::Tree, - _layout: Layout<'_>, - _cursor: mouse::Cursor, + _state: &Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse::Interaction::Idle + if cursor.is_over(layout.bounds()) { + mouse::Interaction::Pointer + } else { + mouse::Interaction::default() + } } - - // fn mouse_interaction( - // &self, - // layout: Layout<'_>, - // cursor_position: Point, - // _viewport: &Rectangle, - // _renderer: &Renderer, - // ) -> mouse::Interaction { - // let bounds = layout.bounds(); - // let is_mouse_over = bounds.contains(cursor_position); - - // if is_mouse_over { - // mouse::Interaction::Pointer - // } else { - // mouse::Interaction::default() - // } - // } - } -impl<'a, P: Param> ParamSlider<'a, P> { +impl<'a, P> ParamSlider<'a, P> +where + P: Param + 'a, +{ /// Convert this [`ParamSlider`] into an [`Element`] with the correct message. You should have a /// variant on your own message type that wraps around [`ParamMessage`] so you can forward those /// messages to /// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()]. - pub fn map(self, f: F) -> Element<'a, Message, Renderer> + pub fn map(self, f: F) -> Element<'a, Message, Theme, Renderer> where Message: 'static, F: Fn(ParamMessage) -> Message + 'static, + Theme: text_input::Catalog + 'a, + Renderer: TextRenderer + 'a, + Renderer::Font: From, { Element::from(self).map(f) } } -impl<'a, P: Param> From> for Element<'a, ParamMessage, Renderer> { +impl<'a, P, Theme, Renderer> From> for Element<'a, ParamMessage, Theme, Renderer> +where + P: Param + 'a, + Theme: text_input::Catalog + 'a, + Renderer: TextRenderer + 'a, + Renderer::Font: From, +{ fn from(widget: ParamSlider<'a, P>) -> Self { Element::new(widget) } diff --git a/nih_plug_iced/src/widgets/peak_meter.rs b/nih_plug_iced/src/widgets/peak_meter.rs index c0435e52..bce0204b 100644 --- a/nih_plug_iced/src/widgets/peak_meter.rs +++ b/nih_plug_iced/src/widgets/peak_meter.rs @@ -5,12 +5,11 @@ use std::marker::PhantomData; use std::time::Duration; use std::time::Instant; -use iced_baseview::Renderer; -use crate::core::renderer::Renderer as GraphicsRenderer; -use crate::core::text::Renderer as TextRenderer; +use crate::core::text::{self, Paragraph, Renderer as TextRenderer}; +use crate::core::widget::tree::{self, Tree}; use crate::core::{ - alignment, layout, renderer, text, Background, Color, Element, Font, Layout, Length, - Rectangle, Size, Widget, + alignment, layout, mouse, padding, renderer, Background, Border, Color, Element, Font, Layout, + Length, Pixels, Point, Rectangle, Size, Widget, }; /// The thickness of this widget's borders. @@ -22,9 +21,7 @@ const TICK_WIDTH: f32 = 1.0; /// /// TODO: There are currently no styling options at all /// TODO: Vertical peak meter, this is just a proof of concept to fit the gain GUI example. -pub struct PeakMeter<'a, Message> { - state: &'a mut State, - +pub struct PeakMeter { /// The current measured value in decibel. current_value_db: f32, @@ -33,8 +30,8 @@ pub struct PeakMeter<'a, Message> { height: Length, width: Length, - text_size: Option, - font: Font, + text_size: Option, + font: Option, /// We don't emit any messages, but iced requires us to define some message type anyways. _phantom: PhantomData, @@ -42,21 +39,19 @@ pub struct PeakMeter<'a, Message> { /// State for a [`PeakMeter`]. #[derive(Debug, Default)] -pub struct State { +struct State { /// The last peak value in decibel. held_peak_value_db: AtomicCell, /// When the last peak value was hit. last_held_peak_value: AtomicCell>, } -impl<'a, Message> PeakMeter<'a, Message> { +impl PeakMeter { /// Creates a new [`PeakMeter`] using the current measurement in decibel. This measurement can /// already have some form of smoothing applied to it. This peak slider widget can draw the last /// hold value for you. - pub fn new(state: &'a mut State, value_db: f32) -> Self { + pub fn new(value_db: f32) -> Self { Self { - state, - current_value_db: value_db, hold_time: None, @@ -64,7 +59,7 @@ impl<'a, Message> PeakMeter<'a, Message> { width: Length::Fixed(180.0), height: Length::Fixed(30.0), text_size: None, - font: ::Font::default(), + font: None, _phantom: PhantomData, } @@ -77,73 +72,72 @@ impl<'a, Message> PeakMeter<'a, Message> { } /// Sets the width of the [`PeakMeter`]. - pub fn width(mut self, width: Length) -> Self { - self.width = width; + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); self } /// Sets the height of the [`PeakMeter`]. - pub fn height(mut self, height: Length) -> Self { - self.height = height; + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); self } /// Sets the text size of the [`PeakMeter`]'s ticks bar. - pub fn text_size(mut self, size: u16) -> Self { - self.text_size = Some(size); + pub fn text_size(mut self, size: impl Into) -> Self { + self.text_size = Some(size.into()); self } /// Sets the font of the [`PeakMeter`]'s ticks bar. pub fn font(mut self, font: Font) -> Self { - self.font = font; + self.font = Some(font); self } } -impl<'a, Message> Widget for PeakMeter<'a, Message> +impl Widget for PeakMeter where Message: Clone, + Renderer: TextRenderer, + Renderer::Font: From, { - fn width(&self) -> Length { - self.width + fn tag(&self) -> tree::Tag { + tree::Tag::of::() } - fn height(&self) -> Length { - self.height + fn state(&self) -> tree::State { + tree::State::new(State::default()) } - fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { - let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); + fn size(&self) -> Size { + (self.width, self.height).into() + } - layout::Node::new(size) + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + layout::atomic(limits, self.width, self.height) } fn draw( &self, - _state: &iced_baseview::core::widget::Tree, + tree: &Tree, renderer: &mut Renderer, - _theme: &::Theme, + _theme: &Theme, style: &renderer::Style, layout: Layout<'_>, - _cursor: iced_baseview::core::mouse::Cursor, - _viewport: &Rectangle, + _cursor: mouse::Cursor, + viewport: &Rectangle, ) { - let bounds = layout.bounds(); - let bar_bounds = Rectangle { - height: bounds.height / 2.0, - ..bounds - }; - let ticks_bounds = Rectangle { - y: bounds.y + (bounds.height / 2.0), - height: bounds.height / 2.0, - ..bounds - }; + let state = tree.state.downcast_ref::(); - let text_size = self - .text_size - .unwrap_or_else(|| (renderer.default_size() as f32 * 0.7).round() as u16); + let bounds = layout.bounds(); + let bar_bounds = bounds.shrink(padding::bottom(bounds.height / 2.0)); + let ticks_bounds = bounds.shrink(padding::top(bounds.height / 2.0)); // We'll draw a simple horizontal for [-90, 20] dB where we'll treat -80 as -infinity, with // a label containing the tick markers below it. If `.hold_time()` was called then we'll @@ -183,9 +177,12 @@ where renderer.fill_quad( renderer::Quad { bounds: tick_bounds, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(tick_color), ); @@ -194,14 +191,14 @@ where // Draw the hold peak value if the hold time option has been set if let Some(hold_time) = self.hold_time { let now = Instant::now(); - let mut held_peak_value_db = self.state.held_peak_value_db.load(); - let last_peak_value = self.state.last_held_peak_value.load(); + let mut held_peak_value_db = state.held_peak_value_db.load(); + let last_peak_value = state.last_held_peak_value.load(); if self.current_value_db >= held_peak_value_db || last_peak_value.is_none() || now > last_peak_value.unwrap() + hold_time { - self.state.held_peak_value_db.store(self.current_value_db); - self.state.last_held_peak_value.store(Some(now)); + state.held_peak_value_db.store(self.current_value_db); + state.last_held_peak_value.store(Some(now)); held_peak_value_db = self.current_value_db; } @@ -213,9 +210,12 @@ where width: TICK_WIDTH, height: bar_bounds.height - (BORDER_WIDTH * 2.0), }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::from_rgb(0.3, 0.3, 0.3)), ); @@ -225,13 +225,24 @@ where renderer.fill_quad( renderer::Quad { bounds: bar_bounds, - border_radius: 0.0.into(), - border_width: BORDER_WIDTH, - border_color: Color::BLACK, + border: Border { + color: Color::BLACK, + width: BORDER_WIDTH, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::TRANSPARENT), ); + let text_size = self + .text_size + .unwrap_or_else(|| Pixels((renderer.default_size().0 * 0.7).round())); + let font = self + .font + .map(Renderer::Font::from) + .unwrap_or_else(|| renderer.default_font()); + // Beneath the bar we want to draw the names of the ticks for tick_db in text_ticks { let x_coordinate = db_to_x_coord(tick_db as f32); @@ -244,9 +255,12 @@ where width: TICK_WIDTH, height: ticks_bounds.height * 0.3, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + ..Default::default() }, Background::Color(Color::from_rgb(0.3, 0.3, 0.3)), ); @@ -256,51 +270,75 @@ where } else { tick_db.to_string() }; - renderer.fill_text(text::Text { - content: &tick_text, - font: self.font, - size: text_size as f32, - bounds: Rectangle { + renderer.fill_text( + text::Text { + content: tick_text, + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), + wrapping: text::Wrapping::None, + }, + Point { x: x_coordinate, y: ticks_bounds.y + (ticks_bounds.height * 0.35), - ..ticks_bounds }, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Center, - vertical_alignment: alignment::Vertical::Top, - line_height: Default::default(), - shaping: Default::default(), - }); + style.text_color, + *viewport, + ); } // Every proper graph needs a unit label let zero_db_x_coordinate = db_to_x_coord(0.0); - let zero_db_text_width = renderer.measure_width("0", text_size.into(), self.font, Default::default()); - renderer.fill_text(text::Text { - // The spacing looks a bit off if we start with a space here so we'll add a little - // offset to the x-coordinate instead - content: "dBFS", - font: self.font, - size: text_size as f32, - bounds: Rectangle { - x: zero_db_x_coordinate + (zero_db_text_width / 2.0) + (text_size as f32 * 0.2), - y: ticks_bounds.y + (ticks_bounds.height * 0.35), - ..ticks_bounds - }, - color: style.text_color, - horizontal_alignment: alignment::Horizontal::Left, + + let zero_db_text_width = Renderer::Paragraph::with_text(text::Text { + content: "0", + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Top, line_height: Default::default(), shaping: Default::default(), - }); + wrapping: text::Wrapping::None, + }) + .min_width(); + + renderer.fill_text( + text::Text { + // The spacing looks a bit off if we start with a space here so we'll add a little + // offset to the x-coordinate instead + content: "dBFS".into(), + font, + size: text_size, + bounds: ticks_bounds.size(), + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + line_height: Default::default(), + shaping: Default::default(), + wrapping: text::Wrapping::None, + }, + Point { + x: zero_db_x_coordinate + (zero_db_text_width / 2.0) + (text_size.0 * 0.2), + y: ticks_bounds.y + (ticks_bounds.height * 0.35), + }, + style.text_color, + *viewport, + ); } } -impl<'a, Message> From> for Element<'a, Message, Renderer> +impl<'a, Theme, Message, Renderer> From> + for Element<'a, Message, Theme, Renderer> where - Message: 'a + Clone, + Message: Clone + 'a, + Renderer: TextRenderer + 'a, + Renderer::Font: From, { - fn from(widget: PeakMeter<'a, Message>) -> Self { + fn from(widget: PeakMeter) -> Self { Element::new(widget) } } diff --git a/nih_plug_iced/src/wrapper.rs b/nih_plug_iced/src/wrapper.rs index 0d5c1bbc..245265c8 100644 --- a/nih_plug_iced/src/wrapper.rs +++ b/nih_plug_iced/src/wrapper.rs @@ -3,7 +3,13 @@ use crossbeam::channel; use futures_util::FutureExt; -use iced_baseview::{baseview::WindowScalePolicy, core::Element, futures::{subscription, Subscription}, runtime::Command, widget::renderer::Settings, window::WindowSubs, Renderer}; +use iced_baseview::{ + baseview::WindowScalePolicy, + core::Element, + futures::{subscription, Subscription}, + window::WindowSubs, + Renderer, Task, +}; use nih_plug::prelude::GuiContext; use std::sync::Arc; @@ -28,7 +34,7 @@ pub enum Message { ParameterUpdate, } -impl Message { +impl Message { fn into_editor_message(self) -> Option { if let Message::EditorMessage(message) = self { Some(message) @@ -68,30 +74,26 @@ impl iced_baseview::Application for IcedEditorWrapperApplication< fn new( (context, parameter_updates_receiver, flags): Self::Flags, - ) -> (Self, Command) { - let (editor, command) = E::new(flags, context); + ) -> (Self, Task) { + let (editor, task) = E::new(flags, context); ( Self { editor, parameter_updates_receiver, }, - command.map(Message::EditorMessage), + task.map(Message::EditorMessage), ) } #[inline] - fn update( - &mut self, - message: Self::Message, - ) -> Command { + fn update(&mut self, message: Self::Message) -> Task { match message { - Message::EditorMessage(message) => self - .editor - .update(message) - .map(Message::EditorMessage), + Message::EditorMessage(message) => { + self.editor.update(message).map(Message::EditorMessage) + } // This message only exists to force a redraw - Message::ParameterUpdate => Command::none(), + Message::ParameterUpdate => Task::none(), } } @@ -106,15 +108,11 @@ impl iced_baseview::Application for IcedEditorWrapperApplication< let mut editor_window_subs: WindowSubs = WindowSubs { on_frame: Some(Arc::new(move || { let cb = on_frame.clone(); - cb.and_then(|cb| { - cb().and_then(|m| m.into_editor_message()) - }) + cb.and_then(|cb| cb().and_then(|m| m.into_editor_message())) })), on_window_will_close: Some(Arc::new(move || { let cb = on_window_will_close.clone(); - cb.and_then(|cb| { - cb().and_then(|m| m.into_editor_message()) - }) + cb.and_then(|cb| cb().and_then(|m| m.into_editor_message())) })), }; @@ -123,17 +121,24 @@ impl iced_baseview::Application for IcedEditorWrapperApplication< // into a stream that doesn't require consuming that receiver (which wouldn't work in // this case since the subscriptions function gets called repeatedly). So we'll just use // a crossbeam queue and this unfold instead. - subscription::unfold( + Subscription::run_with_id( "parameter updates", - self.parameter_updates_receiver.clone(), - |parameter_updates_receiver| match parameter_updates_receiver.try_recv() { - Ok(_) => futures_util::future::ready(( - Message::ParameterUpdate, - parameter_updates_receiver, - )) - .boxed(), - Err(_) => futures_util::future::pending().boxed(), - }, + futures_util::stream::unfold( + self.parameter_updates_receiver.clone(), + |parameter_updates_receiver| match parameter_updates_receiver.try_recv() { + Ok(_) => futures_util::future::ready(Some(( + Message::ParameterUpdate, + parameter_updates_receiver, + ))) + .boxed(), + Err(channel::TryRecvError::Empty) => { + futures_util::future::pending().boxed() + } + Err(channel::TryRecvError::Disconnected) => { + futures_util::future::ready(None).boxed() + } + }, + ), ), self.editor .subscription(&mut editor_window_subs) @@ -142,22 +147,19 @@ impl iced_baseview::Application for IcedEditorWrapperApplication< if let Some(message) = editor_window_subs.on_frame.as_ref() { let message = Arc::clone(message); - window_subs.on_frame = Some(Arc::new(move || { - message().map(Message::EditorMessage) - })); + window_subs.on_frame = Some(Arc::new(move || message().map(Message::EditorMessage))); } if let Some(message) = editor_window_subs.on_window_will_close.as_ref() { let message = Arc::clone(message); - window_subs.on_window_will_close = Some(Arc::new(move || { - message().map(Message::EditorMessage) - })); + window_subs.on_window_will_close = + Some(Arc::new(move || message().map(Message::EditorMessage))); } subscription } #[inline] - fn view(&self) -> Element<'_, Self::Message, Renderer> { + fn view(&self) -> Element<'_, Self::Message, Self::Theme, Renderer> { self.editor.view().map(Message::EditorMessage) } @@ -166,11 +168,6 @@ impl iced_baseview::Application for IcedEditorWrapperApplication< WindowScalePolicy::SystemScaleFactor } - #[inline] - fn renderer_settings() -> Settings { - E::renderer_settings() - } - fn title(&self) -> String { self.editor.title() } diff --git a/plugins/examples/gain_gui_iced/Cargo.toml b/plugins/examples/gain_gui_iced/Cargo.toml index ea4f8f3b..be23f224 100644 --- a/plugins/examples/gain_gui_iced/Cargo.toml +++ b/plugins/examples/gain_gui_iced/Cargo.toml @@ -8,10 +8,10 @@ license = "ISC" description = "A simple gain plugin with an iced GUI" [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "lib"] [dependencies] nih_plug = { path = "../../../", features = ["assert_process_allocs"] } -nih_plug_iced = { path = "../../../nih_plug_iced" } +nih_plug_iced = { path = "../../../nih_plug_iced", features = ["wgpu"] } atomic_float = "0.1" diff --git a/plugins/examples/gain_gui_iced/src/editor.rs b/plugins/examples/gain_gui_iced/src/editor.rs index 7e650b86..eb3433a6 100644 --- a/plugins/examples/gain_gui_iced/src/editor.rs +++ b/plugins/examples/gain_gui_iced/src/editor.rs @@ -1,7 +1,7 @@ use atomic_float::AtomicF32; use nih_plug::prelude::{util, Editor, GuiContext}; use nih_plug_iced::assets::noto_sans_fonts_data; -use nih_plug_iced::style::Theme; +use nih_plug_iced::widget::{column, text, Column, Space, Text}; use nih_plug_iced::widgets as nih_widgets; use nih_plug_iced::*; use std::sync::Arc; @@ -19,7 +19,11 @@ pub(crate) fn create( peak_meter: Arc, editor_state: Arc, ) -> Option> { - create_iced_editor::(editor_state, (params, peak_meter), noto_sans_fonts_data().into()) + create_iced_editor::( + editor_state, + (params, peak_meter), + noto_sans_fonts_data().into(), + ) } struct GainEditor { @@ -27,9 +31,6 @@ struct GainEditor { context: Arc, peak_meter: Arc, - - gain_slider_state: nih_widgets::param_slider::State, - peak_meter_state: nih_widgets::peak_meter::State, } #[derive(Debug, Clone, Copy)] @@ -41,74 +42,58 @@ enum Message { impl IcedEditor for GainEditor { type Executor = executor::Default; type Message = Message; - type InitializationFlags = (Arc, Arc); + type InitializationFlags = (Arc, Arc); type Theme = Theme; fn new( (params, peak_meter): Self::InitializationFlags, context: Arc, - ) -> (Self, Command) { + ) -> (Self, Task) { let editor = GainEditor { params, context, peak_meter, - - gain_slider_state: Default::default(), - peak_meter_state: Default::default(), }; - (editor, Command::none()) + (editor, Task::none()) } fn context(&self) -> &dyn GuiContext { self.context.as_ref() } - fn update( - &mut self, - _window: &mut WindowQueue, - message: Self::Message, - ) -> Command { + fn update(&mut self, message: Self::Message) -> Task { match message { Message::ParamUpdate(message) => self.handle_param_message(message), } - Command::none() + Task::none() } - fn view(&mut self) -> Element<'_, Self::Message> { - Column::new() - .align_items(Alignment::Center) - .push( - Text::new("Gain GUI") - .font(assets::NOTO_SANS_LIGHT) - .size(40) - .height(50.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Bottom), - ) - .push( - Text::new("Gain") - .height(20.into()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center), - ) - .push( - nih_widgets::ParamSlider::new(&mut self.gain_slider_state, &self.params.gain) - .map(Message::ParamUpdate), - ) - .push(Space::with_height(10.into())) - .push( - nih_widgets::PeakMeter::new( - &mut self.peak_meter_state, - util::gain_to_db(self.peak_meter.load(std::sync::atomic::Ordering::Relaxed)), - ) - .hold_time(Duration::from_millis(600)), - ) - .into() + fn view(&self) -> Element<'_, Self::Message> { + let title = text("Gain GUI") + .font(assets::NOTO_SANS_LIGHT) + .size(40) + .height(50) + .width(Length::Fill) + .align_x(alignment::Horizontal::Center) + .align_y(alignment::Vertical::Bottom); + + let text = text("Gain").height(20).width(Length::Fill).center(); + + column![ + title, + text, + nih_widgets::ParamSlider::new(&self.params.gain).map(Message::ParamUpdate), + Space::with_height(10), + nih_widgets::PeakMeter::new(util::gain_to_db( + self.peak_meter.load(std::sync::atomic::Ordering::Relaxed), + )) + .hold_time(Duration::from_millis(600)) + ] + .align_x(alignment::Horizontal::Center) + .into() } fn background_color(&self) -> nih_plug_iced::Color { From 31cafebaf689d01c4a665dd5599857b145fb7cc3 Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:04:25 -0700 Subject: [PATCH 05/11] Update param_slider.rs cleanup --- nih_plug_iced/src/widgets/param_slider.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 4a3b4283..32450217 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -20,10 +20,7 @@ const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1; /// The thickness of this widget's borders. const BORDER_WIDTH: f32 = 1.0; -pub struct ParamSlider<'a, P> -where - P: Param, -{ +pub struct ParamSlider<'a, P: Param> { param: &'a P, width: Length, @@ -84,10 +81,7 @@ enum TextInputMessage { Submit, } -impl<'a, P> ParamSlider<'a, P> -where - P: Param, -{ +impl<'a, P> ParamSlider<'a, P: Param> { pub const DEFAULT_WIDTH: Length = Length::Fixed(180.0); pub const DEFAULT_HEIGHT: Length = Length::Fixed(30.0); From a50ce38ffa47fe6127af0dacf14eb025d247aec3 Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:10:17 -0700 Subject: [PATCH 06/11] cleanup --- Cargo.lock | 75 ++++------------------- nih_plug_iced/src/widgets/param_slider.rs | 13 +--- 2 files changed, 14 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ac2bbf8..3d27ff6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,7 +604,7 @@ dependencies = [ "keyboard-types", "nix 0.22.3", "objc", - "raw-window-handle", + "raw-window-handle 0.5.2", "uuid", "winapi", "x11", @@ -859,6 +859,7 @@ version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" dependencies = [ + "jobserver", "libc", "shlex", ] @@ -1153,7 +1154,6 @@ dependencies = [ "objc", "objc-foundation", "objc_id", - "smithay-clipboard", "x11-clipboard 0.7.1", ] @@ -1690,7 +1690,7 @@ dependencies = [ "egui_glow", "keyboard-types", "log", - "raw-window-handle", + "raw-window-handle 0.5.2", ] [[package]] @@ -1946,15 +1946,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1985,7 +1976,6 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e" dependencies = [ - "fontconfig-parser", "log", "memmap2 0.6.2", "slotmap", @@ -2366,7 +2356,7 @@ dependencies = [ "libloading 0.7.4", "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", - "raw-window-handle", + "raw-window-handle 0.5.2", "windows-sys 0.45.0", "x11-dl", ] @@ -2379,7 +2369,7 @@ checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" dependencies = [ "cfg_aliases 0.1.1", "glutin", - "raw-window-handle", + "raw-window-handle 0.5.2", "winit", ] @@ -2457,16 +2447,6 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "gpu-allocator" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" -dependencies = [ - "backtrace", "log", "presser", "thiserror", @@ -2801,7 +2781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -2922,7 +2902,7 @@ version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "rayon", + "libc", ] [[package]] @@ -3013,12 +2993,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "libc" version = "0.2.157" @@ -3545,19 +3519,6 @@ dependencies = [ "memoffset 0.6.5", ] -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.26.4" @@ -3568,7 +3529,6 @@ dependencies = [ "cfg-if", "libc", "memoffset 0.7.1", - "pin-utils", ] [[package]] @@ -5379,7 +5339,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.3", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -5696,7 +5656,7 @@ dependencies = [ "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4)", "femtovg", "lazy_static", - "raw-window-handle", + "raw-window-handle 0.5.2", "vizia_core", "vizia_id", "vizia_input", @@ -5803,7 +5763,7 @@ dependencies = [ "femtovg", "glutin", "glutin-winit", - "raw-window-handle", + "raw-window-handle 0.5.2", "vizia_core", "vizia_id", "vizia_input", @@ -6616,7 +6576,7 @@ dependencies = [ "once_cell", "orbclient", "percent-encoding", - "raw-window-handle", + "raw-window-handle 0.5.2", "redox_syscall 0.3.5", "wasm-bindgen", "wayland-scanner 0.29.5", @@ -6907,15 +6867,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - [[package]] name = "zvariant" version = "3.15.2" @@ -6945,9 +6896,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" dependencies = [ "proc-macro2", "quote", diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 51ef1fbd..6ddbdc3d 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -65,17 +65,6 @@ impl Default for State { } } -/// The possible UI status of a [`ParamSlider`]. Enables drawing of different styles for each status. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Status { - /// The [`ParamSlider`] can be interacted with. - Active, - /// The [`ParamSlider`] is being hovered. - Hovered, - /// The [`ParamSlider`] is being dragged. - Dragged, -} - /// An internal message for intercep- I mean handling output from the embedded [`TextInput`] widget. #[derive(Debug, Clone)] enum TextInputMessage { @@ -85,7 +74,7 @@ enum TextInputMessage { Submit, } -impl<'a, P> ParamSlider<'a, P: Param> { +impl<'a, P: Param> ParamSlider<'a, P> { pub const DEFAULT_WIDTH: Length = Length::Fixed(180.0); pub const DEFAULT_HEIGHT: Length = Length::Fixed(30.0); From 9aa46fe017266c2a4c2cd8fefc93388ce4861424 Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:15:28 -0700 Subject: [PATCH 07/11] More cleanup --- nih_plug_iced/src/editor.rs | 1 - plugins/examples/gain_gui_iced/src/main.rs | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 plugins/examples/gain_gui_iced/src/main.rs diff --git a/nih_plug_iced/src/editor.rs b/nih_plug_iced/src/editor.rs index cc98e04e..05003404 100644 --- a/nih_plug_iced/src/editor.rs +++ b/nih_plug_iced/src/editor.rs @@ -5,7 +5,6 @@ use crossbeam::atomic::AtomicCell; use crossbeam::channel; use iced_baseview::settings::IcedBaseviewSettings; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle}; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use std::sync::Arc; use std::{borrow::Cow, sync::atomic::Ordering}; diff --git a/plugins/examples/gain_gui_iced/src/main.rs b/plugins/examples/gain_gui_iced/src/main.rs deleted file mode 100644 index ceb89dfd..00000000 --- a/plugins/examples/gain_gui_iced/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -use gain_gui_iced::Gain; -use nih_plug::prelude::*; -use nih_plug::wrapper::standalone::nih_export_standalone; - -fn main() { - nih_export_standalone::(); -} From b3bf24a92746260cab474938d4c8c13f4c543299 Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:16:45 -0700 Subject: [PATCH 08/11] Delete config.toml --- config.toml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 config.toml diff --git a/config.toml b/config.toml deleted file mode 100644 index 18825b8d..00000000 --- a/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[env] -RUST_LOG = "info" From 427d7d029c8303e86150168a7ddbb21d05394698 Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:18:27 -0700 Subject: [PATCH 09/11] Update param_slider.rs --- nih_plug_iced/src/widgets/param_slider.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 6ddbdc3d..a89730a6 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,4 +1,3 @@ -use nih_plug::nih_log; use nih_plug::prelude::Param; use std::borrow::Borrow; @@ -152,8 +151,6 @@ impl<'a, P: Param> ParamSlider<'a, P> { }) .min_width(); - nih_log!("with_text_input() - {} {}", current_value, text_width); - let text_input = text_input("", current_value) .id(state.text_input_id.clone()) .font(font) From 247ac252df3d1f2ba50fb337dfc38d936005361e Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Mon, 28 Oct 2024 15:18:27 -0700 Subject: [PATCH 10/11] Update param_slider.rs --- nih_plug_iced/Cargo.toml | 4 ++-- nih_plug_iced/src/widgets/param_slider.rs | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/nih_plug_iced/Cargo.toml b/nih_plug_iced/Cargo.toml index 35f55d23..723159a0 100644 --- a/nih_plug_iced/Cargo.toml +++ b/nih_plug_iced/Cargo.toml @@ -34,7 +34,7 @@ svg = ["iced_baseview/svg"] canvas = ["iced_baseview/canvas"] [dependencies] -nih_plug = { path = "..", default-features = false } +nih_plug = { path = "..", default_features = false } nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" } # The currently targeted version of baseview uses a different version of @@ -44,7 +44,7 @@ raw-window-handle = "0.5" atomic_refcell = "0.1" baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "579130ecb4f9f315ae52190af42f0ea46aeaa4a2" } crossbeam = "0.8" -# This targets iced 0.10 +# This targets iced 0.13 iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "a0842a8205c852127981e27de6342cf2e665562f", default_features = false } futures-util = "0.3" diff --git a/nih_plug_iced/src/widgets/param_slider.rs b/nih_plug_iced/src/widgets/param_slider.rs index 6ddbdc3d..a89730a6 100644 --- a/nih_plug_iced/src/widgets/param_slider.rs +++ b/nih_plug_iced/src/widgets/param_slider.rs @@ -1,4 +1,3 @@ -use nih_plug::nih_log; use nih_plug::prelude::Param; use std::borrow::Borrow; @@ -152,8 +151,6 @@ impl<'a, P: Param> ParamSlider<'a, P> { }) .min_width(); - nih_log!("with_text_input() - {} {}", current_value, text_width); - let text_input = text_input("", current_value) .id(state.text_input_id.clone()) .font(font) From 216647d2b2e1237e0553dcd1e9be3c7da511955e Mon Sep 17 00:00:00 2001 From: alec-mccormick Date: Thu, 31 Oct 2024 15:29:11 -0700 Subject: [PATCH 11/11] Fix assets.rs doc comment + cleanup imports --- nih_plug_iced/src/assets.rs | 2 +- nih_plug_iced/src/wrapper.rs | 5 +---- plugins/examples/gain_gui_iced/src/editor.rs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/nih_plug_iced/src/assets.rs b/nih_plug_iced/src/assets.rs index 70982bd8..6a136b3f 100644 --- a/nih_plug_iced/src/assets.rs +++ b/nih_plug_iced/src/assets.rs @@ -17,7 +17,7 @@ pub const NOTO_SANS_BOLD: Font = Font::with_name("Noto Sans Bold"); pub const NOTO_SANS_BOLD_ITALIC: Font = Font::with_name("Noto Sans Bold Italic"); /// Useful for initializing the Settings, like this: -/// ```rust +/// ```rust,ignore /// Settings { /// ... /// fonts: noto_sans_fonts_data().into_iter().collect(), diff --git a/nih_plug_iced/src/wrapper.rs b/nih_plug_iced/src/wrapper.rs index 245265c8..f6deb90c 100644 --- a/nih_plug_iced/src/wrapper.rs +++ b/nih_plug_iced/src/wrapper.rs @@ -4,10 +4,7 @@ use crossbeam::channel; use futures_util::FutureExt; use iced_baseview::{ - baseview::WindowScalePolicy, - core::Element, - futures::{subscription, Subscription}, - window::WindowSubs, + baseview::WindowScalePolicy, core::Element, futures::Subscription, window::WindowSubs, Renderer, Task, }; use nih_plug::prelude::GuiContext; diff --git a/plugins/examples/gain_gui_iced/src/editor.rs b/plugins/examples/gain_gui_iced/src/editor.rs index eb3433a6..c2921425 100644 --- a/plugins/examples/gain_gui_iced/src/editor.rs +++ b/plugins/examples/gain_gui_iced/src/editor.rs @@ -1,7 +1,7 @@ use atomic_float::AtomicF32; use nih_plug::prelude::{util, Editor, GuiContext}; use nih_plug_iced::assets::noto_sans_fonts_data; -use nih_plug_iced::widget::{column, text, Column, Space, Text}; +use nih_plug_iced::widget::{column, text, Space}; use nih_plug_iced::widgets as nih_widgets; use nih_plug_iced::*; use std::sync::Arc;