From 8a68683a9339bf230579e3faa33c42c0932bad22 Mon Sep 17 00:00:00 2001 From: mTvare Date: Tue, 8 Jul 2025 14:54:54 +0530 Subject: [PATCH] Add pivot type selection with Custom Pivot, Origin (Average Point), and Origin (Active Object) to the Select tool (#2730) * add origin * cleanup pivot * a lot of stuff * reset pivot * fix transform with pivot issues * fixes * some more cleanup * fixes * finally works * origin fixes * fix spaces * fix using dragged_layers * simplify pivot logic * fix bugs * fix the final bug * fix in select_tool * fix updates * some more refactors to fix misunderstanding and refactor * add checkboxes * fix labels * fix stuff which broke at merge * update * cargo fmt * fix serde crash * fix pivot not updating on move * fix pivot not becoming last active refernce * fix redraw issues * add: active pivot * cargo fmt * fix pivot showing up in default mode * add: pivot pin * fix: use pin icons * cargo: cargo lock update? * fix: use checkbox instead of Overlays * refactor: add dot to path_tool * add: active origins * UI tweaks * add: add all of the stuff for path tool * remove: unused layer * fix: pivot pinning and origin angle * fix: pin only if moved in first place * cargo: fmt * fix: pivot use disabled method * fix: remove redudant NoOp * fix: 3 stuff * fix: select from elsewhere * fix: compass rose wobbling around * add: move pivot on grab * add: move pivot on nudge * add: move pivot on Grab * Code review and tooltips * fixes * fixes * fixes * fix: skipping artboard on bounds calculation * fix: by default have origin * Fix prior fix --------- Co-authored-by: Keavon Chambers --- Cargo.lock | 1751 +++++++++-------- editor/src/consts.rs | 3 +- .../utility_types/widgets/input_widgets.rs | 2 + .../document/document_message_handler.rs | 28 + .../graph_operation_message.rs | 6 +- .../graph_operation_message_handler.rs | 9 - .../document/graph_operation/utility_types.rs | 8 +- .../node_graph/document_node_definitions.rs | 3 - .../document/node_graph/utility_types.rs | 2 +- .../document/overlays/utility_types.rs | 62 +- .../portfolio/document/utility_types/nodes.rs | 18 + .../document/utility_types/transformation.rs | 12 - .../tool/common_functionality/compass_rose.rs | 42 +- .../graph_modification_utils.rs | 22 +- .../tool/common_functionality/pivot.rs | 311 ++- .../common_functionality/utility_functions.rs | 36 +- .../src/messages/tool/tool_message_handler.rs | 5 + .../messages/tool/tool_messages/path_tool.rs | 96 +- .../tool/tool_messages/select_tool.rs | 271 ++- .../messages/tool/tool_messages/shape_tool.rs | 2 +- .../messages/tool/tool_messages/text_tool.rs | 3 - .../transform_layer_message.rs | 2 + .../transform_layer_message_handler.rs | 299 +-- .../widgets/inputs/ReferencePointInput.svelte | 3 +- frontend/src/messages.ts | 3 + node-graph/gcore/src/transform_nodes.rs | 1 - node-graph/gcore/src/vector/vector_nodes.rs | 3 +- 27 files changed, 1864 insertions(+), 1139 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da16bddb..5487e27d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "Inflector" @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "ab_glyph" -version = "0.2.29" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +checksum = "1e0f4f6fbdc5ee39f2ede9f5f3ec79477271a6d6a2baff22310d51736bda6cea" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" [[package]] name = "addr2line" @@ -35,21 +35,21 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom 0.3.3", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -63,9 +63,12 @@ dependencies = [ [[package]] name = "aligned-vec" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] [[package]] name = "alloc-no-stdlib" @@ -95,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" dependencies = [ "android-properties", - "bitflags 2.9.0", + "bitflags 2.9.1", "cc", "cesu8", "jni", @@ -138,9 +141,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -153,44 +156,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arbitrary" @@ -206,7 +209,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -233,7 +236,7 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.8.6", + "libloading 0.8.8", ] [[package]] @@ -267,15 +270,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "av1-grain" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" dependencies = [ "anyhow", "arrayvec", @@ -287,18 +290,18 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +checksum = "19135c0c7a60bfee564dbe44ab5ce0557c6bf3884e5291a50be76a15640c4fbd" dependencies = [ "arrayvec", ] [[package]] name = "axum" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ "axum-core", "bytes", @@ -309,7 +312,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "itoa 1.0.15", + "itoa", "matchit", "memchr", "mime", @@ -330,12 +333,12 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "http-body-util", @@ -350,9 +353,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -434,9 +437,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" dependencies = [ "serde", ] @@ -501,9 +504,9 @@ dependencies = [ [[package]] name = "brotli" -version = "7.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -512,9 +515,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -528,9 +531,9 @@ checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" @@ -543,13 +546,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.8.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -579,7 +582,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cairo-sys-rs", "glib", "libc", @@ -604,7 +607,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "log", "polling", "rustix 0.38.44", @@ -626,9 +629,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" dependencies = [ "serde", ] @@ -674,9 +677,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "jobserver", "libc", @@ -712,9 +715,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -730,9 +733,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -772,9 +775,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -782,9 +785,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -794,21 +797,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "codespan-reporting" @@ -842,9 +845,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" @@ -931,9 +934,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -964,8 +967,8 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.9.1", + "core-foundation 0.10.1", "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", @@ -988,8 +991,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.9.1", + "core-foundation 0.10.1", "libc", ] @@ -1058,9 +1061,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -1092,9 +1095,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -1108,15 +1111,15 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.27.2" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ "cssparser-macros", "dtoa-short", - "itoa 0.4.8", + "itoa", "matches", - "phf 0.8.0", + "phf 0.10.1", "proc-macro2", "quote", "smallvec", @@ -1130,7 +1133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1140,14 +1143,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "cursor-icon" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] name = "darling" @@ -1170,7 +1173,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1181,7 +1184,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1213,15 +1216,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1258,7 +1261,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1273,7 +1276,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", ] @@ -1285,7 +1288,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1294,7 +1297,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.6", + "libloading 0.8.8", ] [[package]] @@ -1311,13 +1314,13 @@ dependencies = [ [[package]] name = "dlopen2_derive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1337,9 +1340,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dpi" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" dependencies = [ "serde", ] @@ -1381,7 +1384,7 @@ dependencies = [ "dyn-any", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1398,9 +1401,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "embed-resource" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbc6e0d8e0c03a655b53ca813f0463d2c956bc4db8138dbc89f120b066551e3" +checksum = "0963f530273dc3022ab2bdc3fcd6d488e850256f2284a82b7413cb9481ee85dd" dependencies = [ "cc", "memchr", @@ -1437,17 +1440,37 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1466,12 +1489,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1556,9 +1579,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -1578,15 +1601,15 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "font-types" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d868ec188a98bb014c606072edd47e52e7ab7297db943b0b28503121e1d037bd" +checksum = "1fa6a5e5a77b5f3f7f9e32879f484aa5b3632ddfbe568a16266c904a6f32cdaf" dependencies = [ "bytemuck", ] @@ -1612,9 +1635,9 @@ dependencies = [ [[package]] name = "fontconfig-parser" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" dependencies = [ "roxmltree", ] @@ -1683,7 +1706,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1784,7 +1807,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -1958,34 +1981,36 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] name = "gif" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" dependencies = [ "color_quant", "weezl", @@ -2042,9 +2067,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.29.2" +version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" +checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" dependencies = [ "serde", ] @@ -2055,7 +2080,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "futures-channel", "futures-core", "futures-executor", @@ -2083,7 +2108,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -2140,7 +2165,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "gpu-alloc-types", ] @@ -2150,7 +2175,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -2167,11 +2192,11 @@ dependencies = [ [[package]] name = "gpu-descriptor" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "gpu-descriptor-types", "hashbrown 0.15.4", ] @@ -2182,7 +2207,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -2281,7 +2306,7 @@ dependencies = [ "num-traits", "parley", "petgraph 0.7.1", - "rand 0.9.0", + "rand 0.9.1", "rand_chacha 0.9.0", "rustc-hash 2.1.1", "serde", @@ -2302,7 +2327,7 @@ dependencies = [ "log", "math-parser", "node-macro", - "rand 0.9.0", + "rand 0.9.1", ] [[package]] @@ -2334,7 +2359,7 @@ dependencies = [ "image", "ndarray", "node-macro", - "rand 0.9.0", + "rand 0.9.1", "rand_chacha 0.9.0", "serde", "specta", @@ -2363,7 +2388,7 @@ dependencies = [ "log", "ndarray", "node-macro", - "rand 0.9.0", + "rand 0.9.1", "rand_chacha 0.9.0", "reqwest", "tokio", @@ -2413,7 +2438,7 @@ name = "graphite-editor" version = "0.0.0" dependencies = [ "bezier-rs", - "bitflags 2.9.0", + "bitflags 2.9.1", "derivative", "dyn-any", "env_logger", @@ -2451,7 +2476,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -2521,7 +2546,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -2536,9 +2561,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -2546,7 +2571,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.7.1", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -2555,9 +2580,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "bytemuck", "cfg-if", @@ -2596,15 +2621,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hermit-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -2620,27 +2639,25 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "html5ever" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" dependencies = [ "log", "mac", "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", + "match_token", ] [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", - "itoa 1.0.15", + "itoa", ] [[package]] @@ -2655,12 +2672,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -2678,12 +2695,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "1.6.0" @@ -2698,7 +2709,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.15", + "itoa", "pin-project-lite", "smallvec", "tokio", @@ -2707,11 +2718,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", @@ -2741,21 +2751,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2780,7 +2797,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -2794,16 +2811,17 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.61.2", ] [[package]] @@ -2838,16 +2856,30 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap 0.8.0", + "tinystr 0.8.1", + "writeable 0.6.1", + "zerovec", +] + [[package]] name = "icu_locid" version = "1.5.0" @@ -2855,37 +2887,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "litemap 0.7.5", + "tinystr 0.7.6", + "writeable 0.5.5", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -2893,67 +2904,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", - "tinystr", - "writeable", + "tinystr 0.8.1", + "writeable 0.6.1", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2973,9 +2971,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -2983,16 +2981,16 @@ dependencies = [ [[package]] name = "image" -version = "0.25.5" +version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" dependencies = [ "bytemuck", "byteorder-lite", "color_quant", "exr", "gif", - "image-webp 0.2.1", + "image-webp 0.2.3", "num-traits", "png", "qoi", @@ -3016,9 +3014,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" dependencies = [ "byteorder-lite", "quick-error", @@ -3049,9 +3047,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", @@ -3081,7 +3079,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -3108,6 +3106,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is-docker" version = "0.2.0" @@ -3123,7 +3131,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi", "libc", "windows-sys 0.59.0", ] @@ -3162,12 +3170,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.15" @@ -3197,6 +3199,30 @@ dependencies = [ "system-deps", ] +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "jni" version = "0.21.1" @@ -3221,18 +3247,19 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "jpeg-decoder" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" [[package]] name = "js-sys" @@ -3272,7 +3299,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "serde", "unicode-segmentation", ] @@ -3284,7 +3311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.6", + "libloading 0.8.8", "pkg-config", ] @@ -3296,14 +3323,13 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kuchikiki" -version = "0.8.2" +version = "0.8.8-speedreader" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" dependencies = [ "cssparser", "html5ever", - "indexmap 1.9.3", - "matches", + "indexmap 2.10.0", "selectors", ] @@ -3356,9 +3382,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.170" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libfuzzer-sys" @@ -3382,29 +3408,29 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.2", ] [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.13", ] [[package]] @@ -3415,9 +3441,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" @@ -3425,6 +3451,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + [[package]] name = "litrs" version = "0.4.1" @@ -3433,9 +3465,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -3443,9 +3475,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "loop9" @@ -3456,6 +3488,12 @@ dependencies = [ "imgref", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mac" version = "0.1.1" @@ -3473,18 +3511,29 @@ dependencies = [ [[package]] name = "markup5ever" -version = "0.11.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" dependencies = [ "log", - "phf 0.10.1", - "phf_codegen 0.10.0", + "phf 0.11.3", + "phf_codegen 0.11.3", "string_cache", "string_cache_codegen", "tendril", ] +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "matches" version = "0.1.10" @@ -3511,9 +3560,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -3531,9 +3580,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" @@ -3559,7 +3608,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block", "core-graphics-types 0.1.3", "foreign-types 0.5.0", @@ -3582,9 +3631,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -3592,20 +3641,20 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] name = "muda" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de14a9b5d569ca68d7c891d613b390cf5ab4f851c77aaa2f9e435555d3d9492" +checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988" dependencies = [ "crossbeam-channel", "dpi", @@ -3630,11 +3679,11 @@ checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg_aliases 0.1.1", "codespan-reporting", "hexf-parse", - "indexmap 2.7.1", + "indexmap 2.10.0", "log", "petgraph 0.6.5", "rustc-hash 1.1.0", @@ -3682,7 +3731,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "jni-sys", "log", "ndk-sys 0.5.0+25.2.9519653", @@ -3697,7 +3746,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "jni-sys", "log", "ndk-sys 0.6.0+11769913", @@ -3747,7 +3796,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -3805,7 +3854,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -3839,23 +3888,24 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -3905,11 +3955,11 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.6.1", "libc", "objc2 0.6.1", @@ -3919,27 +3969,27 @@ dependencies = [ "objc2-core-graphics", "objc2-core-image", "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.0", + "objc2-quartz-core 0.3.1", ] [[package]] name = "objc2-cloud-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c1948a9be5f469deadbd6bcb86ad7ff9e47b4f632380139722f7d9840c0d42c" +checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", "objc2-foundation 0.3.1", ] [[package]] name = "objc2-core-data" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f860f8e841f6d32f754836f51e6bc7777cd7e7053cf18528233f6811d3eceb4" +checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", "objc2-foundation 0.3.1", ] @@ -3950,18 +4000,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "dispatch2", "objc2 0.6.1", ] [[package]] name = "objc2-core-graphics" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", + "dispatch2", "objc2 0.6.1", "objc2-core-foundation", "objc2-io-surface", @@ -3969,9 +4020,9 @@ dependencies = [ [[package]] name = "objc2-core-image" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffa6bea72bf42c78b0b34e89c0bafac877d5f80bf91e159a5d96ea7f693ca56" +checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" dependencies = [ "objc2 0.6.1", "objc2-foundation 0.3.1", @@ -3983,7 +4034,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ba833d4a1cb1aac330f8c973fd92b6ff1858e4aef5cdd00a255eefb28022fb5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2-core-foundation", ] @@ -4014,7 +4065,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -4026,7 +4077,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.6.1", "libc", "objc2 0.6.1", @@ -4035,11 +4086,11 @@ dependencies = [ [[package]] name = "objc2-io-surface" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161a8b87e32610086e1a7a9e9ec39f84459db7b3a0881c1f16ca5a2605581c19" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", "objc2-core-foundation", ] @@ -4050,7 +4101,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -4062,7 +4113,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -4071,22 +4122,22 @@ dependencies = [ [[package]] name = "objc2-quartz-core" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", "objc2-foundation 0.3.1", ] [[package]] name = "objc2-ui-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777a571be14a42a3990d4ebedaeb8b54cd17377ec21b92e8200ac03797b3bee1" +checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "objc2 0.6.1", "objc2-core-foundation", "objc2-foundation 0.3.1", @@ -4094,11 +4145,11 @@ dependencies = [ [[package]] name = "objc2-web-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b717127e4014b0f9f3e8bba3d3f2acec81f1bde01f656823036e823ed2c94dce" +checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "block2 0.6.1", "objc2 0.6.1", "objc2-app-kit", @@ -4117,9 +4168,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "oorandom" @@ -4141,11 +4198,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "foreign-types 0.3.2", "libc", @@ -4162,7 +4219,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -4173,9 +4230,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -4200,9 +4257,9 @@ dependencies = [ [[package]] name = "os_pipe" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +checksum = "db335f4760b14ead6290116f2427bf33a14d4f0617d49f78a246de10c1831224" dependencies = [ "libc", "windows-sys 0.59.0", @@ -4244,9 +4301,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -4254,13 +4311,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.13", "smallvec", "windows-targets 0.52.6", ] @@ -4333,9 +4390,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" dependencies = [ "memchr", "thiserror 2.0.12", @@ -4344,9 +4401,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.15" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" dependencies = [ "pest", "pest_generator", @@ -4354,24 +4411,23 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.15" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "pest_meta" -version = "2.7.15" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" dependencies = [ - "once_cell", "pest", "sha2", ] @@ -4383,7 +4439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.7.1", + "indexmap 2.10.0", ] [[package]] @@ -4393,7 +4449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.7.1", + "indexmap 2.10.0", ] [[package]] @@ -4402,9 +4458,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", "phf_shared 0.8.0", - "proc-macro-hack", ] [[package]] @@ -4413,7 +4467,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ + "phf_macros 0.10.0", "phf_shared 0.10.0", + "proc-macro-hack", ] [[package]] @@ -4438,12 +4494,12 @@ dependencies = [ [[package]] name = "phf_codegen" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator 0.11.3", + "phf_shared 0.11.3", ] [[package]] @@ -4478,12 +4534,12 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro-hack", "proc-macro2", "quote", @@ -4500,7 +4556,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -4556,13 +4612,13 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d" +checksum = "3d77244ce2d584cd84f6a15f86195b8c9b2a0dfbfd817c09e0464244091a58ed" dependencies = [ "base64 0.22.1", - "indexmap 2.7.1", - "quick-xml 0.32.0", + "indexmap 2.10.0", + "quick-xml", "serde", "time", ] @@ -4610,24 +4666,24 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.4" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", - "rustix 0.38.44", + "rustix 1.0.7", "tracing", "windows-sys 0.59.0", ] [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -4638,6 +4694,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -4646,11 +4711,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -4709,7 +4774,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ - "toml_edit 0.22.24", + "toml_edit 0.22.27", ] [[package]] @@ -4755,7 +4820,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -4766,30 +4831,30 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" dependencies = [ "profiling-procmacros", ] [[package]] name = "profiling-procmacros" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -4825,29 +4890,21 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.32.0" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" -dependencies = [ - "memchr", -] - -[[package]] -name = "quick-xml" -version = "0.37.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", + "cfg_aliases 0.2.1", "pin-project-lite", "quinn-proto", "quinn-udp", @@ -4857,17 +4914,19 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tracing", + "web-time 1.1.0", ] [[package]] name = "quinn-proto" -version = "0.11.9" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "getrandom 0.2.15", - "rand 0.8.5", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", "ring", "rustc-hash 2.1.1", "rustls", @@ -4881,9 +4940,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" dependencies = [ "cfg_aliases 0.2.1", "libc", @@ -4895,13 +4954,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.7.3" @@ -4929,13 +4994,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -4983,7 +5047,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -4992,7 +5056,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", ] [[package]] @@ -5056,9 +5120,9 @@ dependencies = [ [[package]] name = "ravif" -version = "0.11.11" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" dependencies = [ "avif-serialize", "imgref", @@ -5108,7 +5172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f9e8a4f503e5c8750e4cd3b32a4e090035c46374b305a15c70bad833dca05f" dependencies = [ "bytemuck", - "font-types 0.8.3", + "font-types 0.8.4", ] [[package]] @@ -5142,11 +5206,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -5155,11 +5219,31 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 2.0.12", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "regex" version = "1.11.1" @@ -5197,9 +5281,9 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "reqwest" -version = "0.12.12" +version = "0.12.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" dependencies = [ "base64 0.22.1", "bytes", @@ -5217,28 +5301,25 @@ dependencies = [ "hyper-rustls", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", @@ -5246,7 +5327,6 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots", - "windows-registry", ] [[package]] @@ -5277,13 +5357,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -5296,7 +5376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags 2.9.0", + "bitflags 2.9.1", "serde", "serde_derive", ] @@ -5309,9 +5389,9 @@ checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -5340,7 +5420,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -5349,22 +5429,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys 0.9.2", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" dependencies = [ "once_cell", "ring", @@ -5374,29 +5454,21 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time 1.1.0", + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -5405,9 +5477,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rustybuzz" @@ -5415,7 +5487,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c85d1ccd519e61834798eb52c4e886e8c2d7d698dd3d6ce0b1b47eb8557f1181" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "bytemuck", "core_maths", "log", @@ -5466,6 +5538,30 @@ dependencies = [ "uuid", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schemars_derive" version = "0.8.22" @@ -5475,7 +5571,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -5509,7 +5605,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -5528,22 +5624,20 @@ dependencies = [ [[package]] name = "selectors" -version = "0.22.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" dependencies = [ "bitflags 1.3.2", "cssparser", "derive_more", "fxhash", "log", - "matches", "phf 0.8.0", "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", - "thin-slice", ] [[package]] @@ -5594,7 +5688,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -5605,7 +5699,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -5614,7 +5708,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "itoa 1.0.15", + "itoa", "memchr", "ryu", "serde", @@ -5626,7 +5720,7 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" dependencies = [ - "itoa 1.0.15", + "itoa", "serde", ] @@ -5638,14 +5732,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -5657,22 +5751,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.15", + "itoa", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.3", "serde", "serde_derive", "serde_json", @@ -5682,14 +5778,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -5716,9 +5812,9 @@ dependencies = [ [[package]] name = "servo_arc" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" dependencies = [ "nodrop", "stable_deref_trait", @@ -5726,9 +5822,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -5737,12 +5833,13 @@ dependencies = [ [[package]] name = "shared_child" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" +checksum = "c2778001df1384cf20b6dc5a5a90f48da35539885edaaefd887f8d744e939c0b" dependencies = [ "libc", - "windows-sys 0.59.0", + "sigchld", + "windows-sys 0.60.2", ] [[package]] @@ -5751,6 +5848,36 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "sigchld" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1219ef50fc0fdb04fcc243e6aa27f855553434ffafe4fa26554efb78b5b4bf89" +dependencies = [ + "libc", + "os_pipe", + "signal-hook", +] + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -5819,12 +5946,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "slotmap" @@ -5850,7 +5974,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "calloop", "calloop-wayland-source", "cursor-icon", @@ -5880,9 +6004,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5904,7 +6028,7 @@ dependencies = [ "objc2-foundation 0.2.2", "objc2-quartz-core 0.2.2", "raw-window-handle", - "redox_syscall 0.5.10", + "redox_syscall 0.5.13", "wasm-bindgen", "web-sys", "windows-sys 0.59.0", @@ -5956,7 +6080,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -5974,7 +6098,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -6043,9 +6167,9 @@ checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" [[package]] name = "svg_fmt" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" [[package]] name = "svgtypes" @@ -6092,9 +6216,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -6112,13 +6236,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -6127,7 +6251,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6157,12 +6281,12 @@ dependencies = [ [[package]] name = "tao" -version = "0.32.8" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c8b1020610b9138dd7b1e06cf259ae91aa05c30f3bd0d6b42a03997b92dec1" +checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.9.1", + "core-foundation 0.10.1", "core-graphics 0.24.0", "crossbeam-channel", "dispatch", @@ -6188,8 +6312,8 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows 0.60.0", - "windows-core 0.60.1", + "windows 0.61.3", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -6202,7 +6326,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -6213,17 +6337,16 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.4.1" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d08db1ff9e011e04014e737ec022610d756c0eae0b3b3a9037bccaf3003173a" +checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d" dependencies = [ "anyhow", "bytes", "dirs", "dunce", "embed_plist", - "futures-util", - "getrandom 0.2.15", + "getrandom 0.3.3", "glob", "gtk", "heck 0.5.0", @@ -6236,6 +6359,7 @@ dependencies = [ "objc2 0.6.1", "objc2-app-kit", "objc2-foundation 0.3.1", + "objc2-ui-kit", "percent-encoding", "plist", "raw-window-handle", @@ -6258,14 +6382,14 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows 0.60.0", + "windows 0.61.3", ] [[package]] name = "tauri-build" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd20e4661c2cce65343319e6e8da256958f5af958cafc47c0d0af66a55dcd17" +checksum = "12f025c389d3adb83114bec704da973142e82fc6ec799c7c750c5e21cefaec83" dependencies = [ "anyhow", "cargo_toml", @@ -6273,7 +6397,7 @@ dependencies = [ "glob", "heck 0.5.0", "json-patch", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde_json", @@ -6285,9 +6409,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458258b19032450ccf975840116ecf013e539eadbb74420bd890e8c56ab2b1a4" +checksum = "f5df493a1075a241065bc865ed5ef8d0fbc1e76c7afdc0bf0eccfaa7d4f0e406" dependencies = [ "base64 0.22.1", "brotli", @@ -6301,7 +6425,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.99", + "syn 2.0.104", "tauri-utils", "thiserror 2.0.12", "time", @@ -6312,28 +6436,28 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.1.1" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d402813d3b9c773a0fa58697c457c771f10e735498fdcb7b343264d18e5a601f" +checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4190775d6ff73fe66d9af44c012739a2659720efd9c0e1e56a918678038699d" +checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3" dependencies = [ "anyhow", "glob", "plist", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "tauri-utils", @@ -6343,15 +6467,15 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.2.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88371e340ad2f07409a3b68294abe73f20bc9c1bc1b631a31dc37a3d0161f682" +checksum = "c341290d31991dbca38b31d412c73dfbdb070bb11536784f19dd2211d13b778f" dependencies = [ "anyhow", "dunce", "glob", "percent-encoding", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "serde_repr", @@ -6361,14 +6485,13 @@ dependencies = [ "thiserror 2.0.12", "toml", "url", - "uuid", ] [[package]] name = "tauri-plugin-http" -version = "2.4.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40dcd6c922a1885e1f0bcebc6768fec6e005bd4b9001c5d90a2f5d4cab297729" +checksum = "b0c1a38da944b357ffa23bafd563b1579f18e6fbd118fcd84769406d35dcc5c7" dependencies = [ "bytes", "cookie_store", @@ -6376,7 +6499,7 @@ dependencies = [ "http", "regex", "reqwest", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "tauri", @@ -6390,16 +6513,16 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d5eb3368b959937ad2aeaf6ef9a8f5d11e01ffe03629d3530707bbcb27ff5d" +checksum = "2b9ffadec5c3523f11e8273465cacb3d86ea7652a28e6e2a2e9b5c182f791d25" dependencies = [ "encoding_rs", "log", "open", "os_pipe", "regex", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "shared_child", @@ -6411,29 +6534,31 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00ada7ac2f9276f09b8c3afffd3215fd5d9bff23c22df8a7c70e7ef67cacd532" +checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4" dependencies = [ "cookie", "dpi", "gtk", "http", "jni", + "objc2 0.6.1", + "objc2-ui-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", "thiserror 2.0.12", "url", - "windows 0.60.0", + "windows 0.61.3", ] [[package]] name = "tauri-runtime-wry" -version = "2.5.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2e5842c57e154af43a20a49c7efee0ce2578c20b4c2bdf266852b422d2e421" +checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad" dependencies = [ "gtk", "http", @@ -6452,15 +6577,15 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows 0.60.0", + "windows 0.61.3", "wry", ] [[package]] name = "tauri-utils" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f037e66c7638cc0a2213f61566932b9a06882b8346486579c90e4b019bac447" +checksum = "41743bbbeb96c3a100d234e5a0b60a46d5aa068f266160862c7afdbf828ca02e" dependencies = [ "anyhow", "brotli", @@ -6479,7 +6604,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde-untagged", @@ -6496,25 +6621,25 @@ dependencies = [ [[package]] name = "tauri-winres" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56eaa45f707bedf34d19312c26d350bc0f3c59a47e58e8adbeecdc850d2c13a0" +checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" dependencies = [ "embed-resource", + "indexmap 2.10.0", "toml", ] [[package]] name = "tempfile" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c317e0a526ee6120d8dabad239c8dadca62b24b6f168914bbbc8e2fb1f0e567" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.3", "once_cell", - "rustix 1.0.1", + "rustix 1.0.7", "windows-sys 0.59.0", ] @@ -6538,12 +6663,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - [[package]] name = "thiserror" version = "1.0.69" @@ -6570,7 +6689,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -6581,7 +6700,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -6602,7 +6721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", - "itoa 1.0.15", + "itoa", "num-conv", "powerfmt", "serde", @@ -6657,6 +6776,15 @@ name = "tinystr" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -6689,9 +6817,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -6711,7 +6839,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -6736,9 +6864,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -6749,21 +6877,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.24", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -6774,7 +6902,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.10.0", "toml_datetime", "winnow 0.5.40", ] @@ -6785,24 +6913,31 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.10.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.7.3", + "toml_write", + "winnow 0.7.11", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" version = "0.5.2" @@ -6819,6 +6954,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -6844,18 +6997,18 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] [[package]] name = "tray-icon" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d433764348e7084bad2c5ea22c96c71b61b17afe3a11645710f533bd72b6a2b5" +checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a" dependencies = [ "crossbeam-channel", "dirs", @@ -7076,12 +7229,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -7096,19 +7243,21 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] name = "v_frame" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" dependencies = [ "aligned-vec", "num-traits", @@ -7221,15 +7370,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -7256,7 +7405,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -7291,7 +7440,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7320,9 +7469,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" +checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" dependencies = [ "cc", "downcast-rs", @@ -7334,11 +7483,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" +checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "rustix 0.38.44", "wayland-backend", "wayland-scanner", @@ -7350,16 +7499,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" +checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" dependencies = [ "rustix 0.38.44", "wayland-client", @@ -7372,7 +7521,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-scanner", @@ -7384,7 +7533,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7397,7 +7546,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -7411,7 +7560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" dependencies = [ "proc-macro2", - "quick-xml 0.37.2", + "quick-xml", "quote", ] @@ -7503,24 +7652,24 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.8" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" dependencies = [ "rustls-pki-types", ] [[package]] name = "webview2-com" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d606f600e5272b514dbb66539dd068211cc20155be8d3958201b4b5bd79ed3" +checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows 0.60.0", - "windows-core 0.60.1", - "windows-implement 0.59.0", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-implement 0.60.0", "windows-interface 0.59.1", ] @@ -7532,25 +7681,25 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "webview2-com-sys" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb27fccd3c27f68e9a6af1bcf48c2d82534b8675b83608a4d81446d095a17ac" +checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" dependencies = [ "thiserror 2.0.12", - "windows 0.60.0", - "windows-core 0.60.1", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "wgpu" @@ -7585,11 +7734,11 @@ checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" dependencies = [ "arrayvec", "bit-vec", - "bitflags 2.9.0", + "bitflags 2.9.1", "bytemuck", "cfg_aliases 0.1.1", "document-features", - "indexmap 2.7.1", + "indexmap 2.10.0", "log", "naga", "once_cell", @@ -7631,7 +7780,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.9.0", + "bitflags 2.9.1", "block", "bytemuck", "cfg_aliases 0.1.1", @@ -7644,7 +7793,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.6", + "libloading 0.8.8", "log", "metal", "naga", @@ -7672,7 +7821,7 @@ version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "js-sys", "web-sys", ] @@ -7735,12 +7884,12 @@ dependencies = [ [[package]] name = "windows" -version = "0.60.0" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core 0.60.1", + "windows-core 0.61.2", "windows-future", "windows-link", "windows-numerics", @@ -7748,20 +7897,11 @@ dependencies = [ [[package]] name = "windows-collections" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core 0.60.1", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.61.2", ] [[package]] @@ -7779,25 +7919,26 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.60.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.59.0", + "windows-implement 0.60.0", "windows-interface 0.59.1", "windows-link", - "windows-result 0.3.1", - "windows-strings 0.3.1", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] name = "windows-future" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core 0.60.1", + "windows-core 0.61.2", "windows-link", + "windows-threading", ] [[package]] @@ -7808,18 +7949,18 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "windows-implement" -version = "0.59.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -7830,7 +7971,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -7841,34 +7982,34 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] name = "windows-link" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-numerics" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core 0.60.1", + "windows-core 0.61.2", "windows-link", ] [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", + "windows-link", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -7882,9 +8023,9 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] @@ -7901,9 +8042,9 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -7944,6 +8085,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7983,7 +8133,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -7991,10 +8141,35 @@ dependencies = [ ] [[package]] -name = "windows-version" -version = "0.1.3" +name = "windows-targets" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfbcc4996dd183ff1376a20ade1242da0d2dcaff83cc76710a588d24fd4c5db" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-version" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" dependencies = [ "windows-link", ] @@ -8017,6 +8192,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -8035,6 +8216,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -8053,12 +8240,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -8077,6 +8276,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -8095,6 +8300,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -8113,6 +8324,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -8131,6 +8348,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winit" version = "0.29.15" @@ -8140,7 +8363,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.9.0", + "bitflags 2.9.1", "bytemuck", "calloop", "cfg_aliases 0.1.1", @@ -8190,38 +8413,32 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.52.0" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" version = "0.5.5" @@ -8229,10 +8446,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] -name = "wry" -version = "0.50.5" +name = "writeable" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19b78efae8b853c6c817e8752fc1dbf9cab8a8ffe9c30f399bd750ccf0f0730" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wry" +version = "0.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9" dependencies = [ "base64 0.22.1", "block2 0.6.1", @@ -8266,8 +8489,8 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows 0.60.0", - "windows-core 0.60.1", + "windows 0.61.3", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -8302,7 +8525,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.6", + "libloading 0.8.8", "once_cell", "rustix 0.38.44", "x11rb-protocol", @@ -8316,9 +8539,9 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" [[package]] name = "xkbcommon-dl" @@ -8326,7 +8549,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "dlib", "log", "once_cell", @@ -8341,9 +8564,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmlwriter" @@ -8365,9 +8588,9 @@ checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -8377,13 +8600,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", "synstructure", ] @@ -8395,43 +8618,22 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -8451,7 +8653,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", "synstructure", ] @@ -8462,10 +8664,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -8474,13 +8687,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.104", ] [[package]] @@ -8500,9 +8713,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa" dependencies = [ "zune-core", ] diff --git a/editor/src/consts.rs b/editor/src/consts.rs index 9adba6d9..58585e2d 100644 --- a/editor/src/consts.rs +++ b/editor/src/consts.rs @@ -61,6 +61,7 @@ pub const SELECTION_DRAG_ANGLE: f64 = 90.; pub const PIVOT_CROSSHAIR_THICKNESS: f64 = 1.; pub const PIVOT_CROSSHAIR_LENGTH: f64 = 9.; pub const PIVOT_DIAMETER: f64 = 5.; +pub const DOWEL_PIN_RADIUS: f64 = 4.; // COMPASS ROSE pub const COMPASS_ROSE_RING_INNER_DIAMETER: f64 = 13.; @@ -133,8 +134,8 @@ pub const SCALE_EFFECT: f64 = 0.5; // COLORS pub const COLOR_OVERLAY_BLUE: &str = "#00a8ff"; -pub const COLOR_OVERLAY_BLUE_50: &str = "rgba(0, 168, 255, 0.5)"; pub const COLOR_OVERLAY_YELLOW: &str = "#ffc848"; +pub const COLOR_OVERLAY_YELLOW_DULL: &str = "#d7ba8b"; pub const COLOR_OVERLAY_GREEN: &str = "#63ce63"; pub const COLOR_OVERLAY_RED: &str = "#ef5454"; pub const COLOR_OVERLAY_GRAY: &str = "#cccccc"; diff --git a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs index b76f23a0..893b301c 100644 --- a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs @@ -471,6 +471,8 @@ pub struct ReferencePointInput { pub disabled: bool, + pub tooltip: String, + // Callbacks #[serde(skip)] #[derivative(Debug = "ignore", PartialEq = "ignore")] diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index f306663a..89e0aaac 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -750,6 +750,7 @@ impl MessageHandler> for DocumentMessag // Nudge translation without resizing if !resize { let transform = DAffine2::from_translation(DVec2::from_angle(-self.document_ptz.tilt()).rotate(DVec2::new(delta_x, delta_y))); + responses.add(SelectToolMessage::ShiftSelectedNodes { offset: transform.translation }); for layer in self.network_interface.shallowest_unique_layers(&[]).filter(|layer| can_move(*layer)) { responses.add(GraphOperationMessage::TransformChange { @@ -1185,6 +1186,7 @@ impl MessageHandler> for DocumentMessag OverlaysType::HoverOutline => visibility_settings.hover_outline = visible, OverlaysType::SelectionOutline => visibility_settings.selection_outline = visible, OverlaysType::Pivot => visibility_settings.pivot = visible, + OverlaysType::Origin => visibility_settings.origin = visible, OverlaysType::Path => visibility_settings.path = visible, OverlaysType::Anchors => { visibility_settings.anchors = visible; @@ -1716,6 +1718,14 @@ impl DocumentMessageHandler { .reduce(graphene_std::renderer::Quad::combine_bounds) } + pub fn selected_visible_and_unlock_layers_bounding_box_document(&self) -> Option<[DVec2; 2]> { + self.network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers(&self.network_interface) + .map(|layer| self.metadata().nonzero_bounding_box(layer)) + .reduce(graphene_std::renderer::Quad::combine_bounds) + } + pub fn document_network(&self) -> &NodeNetwork { self.network_interface.document_network() } @@ -2269,6 +2279,24 @@ impl DocumentMessageHandler { ] }, }, + LayoutGroup::Row { + widgets: { + let mut checkbox_id = CheckboxId::default(); + vec![ + CheckboxInput::new(self.overlays_visibility_settings.pivot) + .on_update(|optional_input: &CheckboxInput| { + DocumentMessage::SetOverlaysVisibility { + visible: optional_input.checked, + overlays_type: Some(OverlaysType::Origin), + } + .into() + }) + .for_label(checkbox_id.clone()) + .widget_holder(), + TextLabel::new("Transform Origin".to_string()).for_checkbox(&mut checkbox_id).widget_holder(), + ] + }, + }, LayoutGroup::Row { widgets: { let mut checkbox_id = CheckboxId::default(); diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs index abb1aa85..31ea8312 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs @@ -3,7 +3,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate; use crate::messages::prelude::*; use bezier_rs::Subpath; -use glam::{DAffine2, DVec2, IVec2}; +use glam::{DAffine2, IVec2}; use graph_craft::document::NodeId; use graphene_std::Artboard; use graphene_std::brush::brush_stroke::BrushStroke; @@ -52,10 +52,6 @@ pub enum GraphOperationMessage { transform_in: TransformIn, skip_rerender: bool, }, - TransformSetPivot { - layer: LayerNodeIdentifier, - pivot: DVec2, - }, Vector { layer: LayerNodeIdentifier, modification_type: VectorModificationType, diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 375ae5ef..40653e4a 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -89,15 +89,6 @@ impl MessageHandler> for Gr modify_inputs.transform_set(transform, transform_in, skip_rerender); } } - GraphOperationMessage::TransformSetPivot { layer, pivot } => { - if layer == LayerNodeIdentifier::ROOT_PARENT { - log::error!("Cannot run TransformSetPivot on ROOT_PARENT"); - return; - } - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) { - modify_inputs.pivot_set(pivot); - } - } GraphOperationMessage::Vector { layer, modification_type } => { if layer == LayerNodeIdentifier::ROOT_PARENT { log::error!("Cannot run Vector on ROOT_PARENT"); diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index 216dc8bf..23a878f0 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -4,7 +4,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector}; use crate::messages::prelude::*; use bezier_rs::Subpath; -use glam::{DAffine2, DVec2, IVec2}; +use glam::{DAffine2, IVec2}; use graph_craft::concrete; use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; @@ -458,12 +458,6 @@ impl<'a> ModifyInputsContext<'a> { } } - pub fn pivot_set(&mut self, new_pivot: DVec2) { - let Some(transform_node_id) = self.existing_node_id("Transform", true) else { return }; - - self.set_input_with_refresh(InputConnector::node(transform_node_id, 5), NodeInput::value(TaggedValue::DVec2(new_pivot), false), false); - } - pub fn vector_modify(&mut self, modification_type: VectorModificationType) { let Some(path_node_id) = self.existing_node_id("Path", true) else { return }; self.network_interface.vector_modify(&path_node_id, modification_type); diff --git a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs index ce937885..594f8125 100644 --- a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs +++ b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs @@ -1308,7 +1308,6 @@ fn static_nodes() -> Vec { NodeInput::value(TaggedValue::F64(0.), false), NodeInput::value(TaggedValue::DVec2(DVec2::ONE), false), NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false), - NodeInput::value(TaggedValue::DVec2(DVec2::splat(0.5)), false), ], implementation: DocumentNodeImplementation::Network(NodeNetwork { exports: vec![NodeInput::node(NodeId(1), 0)], @@ -1327,7 +1326,6 @@ fn static_nodes() -> Vec { NodeInput::network(concrete!(f64), 2), NodeInput::network(concrete!(DVec2), 3), NodeInput::network(concrete!(DVec2), 4), - NodeInput::network(concrete!(DVec2), 5), ], manual_composition: Some(concrete!(Context)), implementation: DocumentNodeImplementation::ProtoNode(transform_nodes::transform::IDENTIFIER), @@ -1395,7 +1393,6 @@ fn static_nodes() -> Vec { }), ), InputMetadata::with_name_description_override("Skew", "TODO", WidgetOverride::Custom("transform_skew".to_string())), - InputMetadata::with_name_description_override("Pivot", "TODO", WidgetOverride::Hidden), ], output_names: vec!["Data".to_string()], ..Default::default() diff --git a/editor/src/messages/portfolio/document/node_graph/utility_types.rs b/editor/src/messages/portfolio/document/node_graph/utility_types.rs index 0cfd4928..e752c9d7 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -191,7 +191,7 @@ pub struct FrontendClickTargets { pub modify_import_export: Vec, } -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] pub enum Direction { Up, Down, diff --git a/editor/src/messages/portfolio/document/overlays/utility_types.rs b/editor/src/messages/portfolio/document/overlays/utility_types.rs index a17d711a..6e25bb77 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_types.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_types.rs @@ -1,12 +1,12 @@ use super::utility_functions::overlay_canvas_context; use crate::consts::{ - COLOR_OVERLAY_BLUE, COLOR_OVERLAY_BLUE_50, COLOR_OVERLAY_GREEN, COLOR_OVERLAY_RED, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, COMPASS_ROSE_ARROW_SIZE, COMPASS_ROSE_HOVER_RING_DIAMETER, - COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, + COLOR_OVERLAY_BLUE, COLOR_OVERLAY_GREEN, COLOR_OVERLAY_RED, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, COLOR_OVERLAY_YELLOW_DULL, COMPASS_ROSE_ARROW_SIZE, COMPASS_ROSE_HOVER_RING_DIAMETER, + COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, DOWEL_PIN_RADIUS, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, }; use crate::messages::prelude::Message; use bezier_rs::{Bezier, Subpath}; use core::borrow::Borrow; -use core::f64::consts::{FRAC_PI_2, TAU}; +use core::f64::consts::{FRAC_PI_2, PI, TAU}; use glam::{DAffine2, DVec2}; use graphene_std::Color; use graphene_std::math::quad::Quad; @@ -33,12 +33,14 @@ pub enum OverlaysType { HoverOutline, SelectionOutline, Pivot, + Origin, Path, Anchors, Handles, } #[derive(PartialEq, Copy, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] +#[serde(default)] pub struct OverlaysVisibilitySettings { pub all: bool, pub artboard_name: bool, @@ -49,6 +51,7 @@ pub struct OverlaysVisibilitySettings { pub hover_outline: bool, pub selection_outline: bool, pub pivot: bool, + pub origin: bool, pub path: bool, pub anchors: bool, pub handles: bool, @@ -66,6 +69,7 @@ impl Default for OverlaysVisibilitySettings { hover_outline: true, selection_outline: true, pivot: true, + origin: true, path: true, anchors: true, handles: true, @@ -110,6 +114,10 @@ impl OverlaysVisibilitySettings { self.all && self.pivot } + pub fn origin(&self) -> bool { + self.all && self.origin + } + pub fn path(&self) -> bool { self.all && self.path } @@ -423,10 +431,7 @@ impl OverlayContext { pub fn draw_scale(&mut self, start: DVec2, scale: f64, radius: f64, text: &str) { let sign = scale.signum(); - let mut fill_color = graphene_std::Color::from_rgb_str(crate::consts::COLOR_OVERLAY_WHITE.strip_prefix('#').unwrap()) - .unwrap() - .with_alpha(0.05) - .to_rgba_hex_srgb(); + let mut fill_color = Color::from_rgb_str(COLOR_OVERLAY_WHITE.strip_prefix('#').unwrap()).unwrap().with_alpha(0.05).to_rgba_hex_srgb(); fill_color.insert(0, '#'); let fill_color = Some(fill_color.as_str()); self.line(start + DVec2::X * radius * sign, start + DVec2::X * (radius * scale), None, None); @@ -463,10 +468,7 @@ impl OverlayContext { // Hover ring if show_hover_ring { - let mut fill_color = graphene_std::Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap()) - .unwrap() - .with_alpha(0.5) - .to_rgba_hex_srgb(); + let mut fill_color = Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap()).unwrap().with_alpha(0.5).to_rgba_hex_srgb(); fill_color.insert(0, '#'); self.render_context.set_line_width(HOVER_RING_STROKE_WIDTH); @@ -550,6 +552,36 @@ impl OverlayContext { self.end_dpi_aware_transform(); } + pub fn dowel_pin(&mut self, position: DVec2, angle: f64, color: Option<&str>) { + let (x, y) = (position.round() - DVec2::splat(0.5)).into(); + let color = color.unwrap_or(COLOR_OVERLAY_YELLOW_DULL); + + self.start_dpi_aware_transform(); + + // Draw the background circle with a white fill and blue outline + self.render_context.begin_path(); + self.render_context.arc(x, y, DOWEL_PIN_RADIUS, 0., TAU).expect("Failed to draw the circle"); + self.render_context.set_fill_style_str(COLOR_OVERLAY_WHITE); + self.render_context.fill(); + self.render_context.set_stroke_style_str(color); + self.render_context.stroke(); + + // Draw the two blue filled sectors + self.render_context.begin_path(); + // Top-left sector + self.render_context.move_to(x, y); + self.render_context.arc(x, y, DOWEL_PIN_RADIUS, FRAC_PI_2 + angle, PI + angle).expect("Failed to draw arc"); + self.render_context.close_path(); + // Bottom-right sector + self.render_context.move_to(x, y); + self.render_context.arc(x, y, DOWEL_PIN_RADIUS, PI + FRAC_PI_2 + angle, TAU + angle).expect("Failed to draw arc"); + self.render_context.close_path(); + self.render_context.set_fill_style_str(color); + self.render_context.fill(); + + self.end_dpi_aware_transform(); + } + /// Used by the Pen and Path tools to outline the path of the shape. pub fn outline_vector(&mut self, vector_data: &VectorData, transform: DAffine2) { self.start_dpi_aware_transform(); @@ -599,9 +631,11 @@ impl OverlayContext { pub fn outline_overlay_bezier(&mut self, bezier: Bezier, transform: DAffine2) { self.start_dpi_aware_transform(); + let color = Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap()).unwrap().with_alpha(0.05).to_rgba_hex_srgb(); + self.render_context.begin_path(); self.bezier_command(bezier, transform, true); - self.render_context.set_stroke_style_str(COLOR_OVERLAY_BLUE_50); + self.render_context.set_stroke_style_str(&color); self.render_context.set_line_width(4.); self.render_context.stroke(); @@ -731,11 +765,11 @@ impl OverlayContext { // └──┴──┴──┴──┘ let pixels = [(0, 0), (2, 2)]; for &(x, y) in &pixels { - let index = (x + y * PATTERN_WIDTH as usize) * 4; + let index = (x + y * PATTERN_WIDTH) * 4; data[index..index + 4].copy_from_slice(&color.to_rgba8_srgb()); } - let image_data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(wasm_bindgen::Clamped(&mut data), PATTERN_WIDTH as u32, PATTERN_HEIGHT as u32).unwrap(); + let image_data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(wasm_bindgen::Clamped(&data), PATTERN_WIDTH as u32, PATTERN_HEIGHT as u32).unwrap(); pattern_context.put_image_data(&image_data, 0., 0.).unwrap(); let pattern = self.render_context.create_pattern_with_offscreen_canvas(&pattern_canvas, "repeat").unwrap().unwrap(); diff --git a/editor/src/messages/portfolio/document/utility_types/nodes.rs b/editor/src/messages/portfolio/document/utility_types/nodes.rs index d81f1693..66369026 100644 --- a/editor/src/messages/portfolio/document/utility_types/nodes.rs +++ b/editor/src/messages/portfolio/document/utility_types/nodes.rs @@ -1,5 +1,7 @@ use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use super::network_interface::NodeNetworkInterface; +use crate::messages::tool::common_functionality::graph_modification_utils; +use glam::DVec2; use graph_craft::document::{NodeId, NodeNetwork}; use serde::ser::SerializeStruct; @@ -98,6 +100,22 @@ impl SelectedNodes { .filter(move |&layer| self.layer_visible(layer, network_interface) && !self.layer_locked(layer, network_interface)) } + pub fn selected_visible_and_unlocked_layers_mean_average_origin<'a>(&'a self, network_interface: &'a NodeNetworkInterface) -> DVec2 { + let (sum, count) = self + .selected_visible_and_unlocked_layers(network_interface) + .map(|layer| graph_modification_utils::get_viewport_origin(layer, network_interface)) + .fold((glam::DVec2::ZERO, 0), |(sum, count), item| (sum + item, count + 1)); + if count == 0 { DVec2::ZERO } else { sum / count as f64 } + } + + pub fn selected_visible_and_unlocked_median_points<'a>(&'a self, network_interface: &'a NodeNetworkInterface) -> DVec2 { + let (sum, count) = self + .selected_visible_and_unlocked_layers(network_interface) + .map(|layer| graph_modification_utils::get_viewport_center(layer, network_interface)) + .fold((glam::DVec2::ZERO, 0), |(sum, count), item| (sum + item, count + 1)); + if count == 0 { DVec2::ZERO } else { sum / count as f64 } + } + pub fn selected_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator + 'a { metadata.all_layers().filter(|layer| self.0.contains(&layer.to_node())) } diff --git a/editor/src/messages/portfolio/document/utility_types/transformation.rs b/editor/src/messages/portfolio/document/utility_types/transformation.rs index e0149939..cefcb614 100644 --- a/editor/src/messages/portfolio/document/utility_types/transformation.rs +++ b/editor/src/messages/portfolio/document/utility_types/transformation.rs @@ -4,7 +4,6 @@ use crate::messages::portfolio::document::graph_operation::transform_utils; use crate::messages::portfolio::document::graph_operation::utility_types::{ModifyInputsContext, TransformIn}; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use crate::messages::prelude::*; -use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::utility_types::ToolType; use glam::{DAffine2, DMat2, DVec2}; @@ -537,17 +536,6 @@ impl<'a> Selected<'a> { } } - pub fn mean_average_of_pivots(&mut self) -> DVec2 { - let xy_summation = self - .selected - .iter() - .map(|&layer| graph_modification_utils::get_viewport_pivot(layer, self.network_interface)) - .reduce(|a, b| a + b) - .unwrap_or_default(); - - xy_summation / self.selected.len() as f64 - } - pub fn center_of_aabb(&mut self) -> DVec2 { let [min, max] = self .selected diff --git a/editor/src/messages/tool/common_functionality/compass_rose.rs b/editor/src/messages/tool/common_functionality/compass_rose.rs index 8a7a2f6b..bedc1ca2 100644 --- a/editor/src/messages/tool/common_functionality/compass_rose.rs +++ b/editor/src/messages/tool/common_functionality/compass_rose.rs @@ -1,5 +1,4 @@ use crate::consts::{COMPASS_ROSE_ARROW_CLICK_TARGET_ANGLE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER}; -use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::prelude::DocumentMessageHandler; use glam::{DAffine2, DVec2}; use std::f64::consts::FRAC_PI_2; @@ -10,25 +9,32 @@ pub struct CompassRose { } impl CompassRose { - fn get_layer_pivot_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 { - let [min, max] = document.metadata().nonzero_bounding_box(layer); - - let bounds_transform = DAffine2::from_translation(min) * DAffine2::from_scale(max - min); - let layer_transform = document.metadata().transform_to_viewport(layer); - layer_transform * bounds_transform - } pub fn refresh_position(&mut self, document: &DocumentMessageHandler) { - let selected_nodes = document.network_interface.selected_nodes(); - let mut layers = selected_nodes.selected_visible_and_unlocked_layers(&document.network_interface); + let selected = document.network_interface.selected_nodes(); - let Some(first) = layers.next() else { return }; - let count = layers.count() + 1; - let transform = if count == 1 { - Self::get_layer_pivot_transform(first, document) - } else { - let [min, max] = document.selected_visible_and_unlock_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]); - DAffine2::from_translation(min) * DAffine2::from_scale(max - min) - }; + if !selected.has_selected_nodes() { + return; + } + + let transform = selected + .selected_visible_and_unlocked_layers(&document.network_interface) + .find(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[])) + .map(|layer| document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface)) + .unwrap_or_default(); + + let bounds = document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers(&document.network_interface) + .filter_map(|layer| { + document + .metadata() + .bounding_box_with_transform(layer, transform.inverse() * document.metadata().transform_to_viewport(layer)) + }) + .reduce(graphene_std::renderer::Quad::combine_bounds); + + let [min, max] = bounds.unwrap_or([DVec2::ZERO, DVec2::ONE]); + let transform = transform * DAffine2::from_translation(min) * DAffine2::from_scale(max - min); self.compass_center = transform.transform_point2(DVec2::splat(0.5)); } diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index 22c53f11..33c19d0c 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -243,20 +243,26 @@ pub fn new_custom(id: NodeId, nodes: Vec<(NodeId, NodeTemplate)>, parent: LayerN LayerNodeIdentifier::new_unchecked(id) } -/// Locate the final pivot from the transform (TODO: decide how the pivot should actually work) -pub fn get_pivot(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { - let pivot_node_input_index = 5; - if let TaggedValue::DVec2(pivot) = NodeGraphLayer::new(layer, network_interface).find_input("Transform", pivot_node_input_index)? { - Some(*pivot) +/// Locate the origin of the transform node +pub fn get_origin(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + use graphene_std::transform_nodes::transform::TranslateInput; + + if let TaggedValue::DVec2(origin) = NodeGraphLayer::new(layer, network_interface).find_input("Transform", TranslateInput::INDEX)? { + Some(*origin) } else { None } } -pub fn get_viewport_pivot(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> DVec2 { +pub fn get_viewport_origin(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> DVec2 { + let origin = get_origin(layer, network_interface).unwrap_or_default(); + network_interface.document_metadata().document_to_viewport.transform_point2(origin) +} + +pub fn get_viewport_center(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> DVec2 { let [min, max] = network_interface.document_metadata().nonzero_bounding_box(layer); - let pivot = get_pivot(layer, network_interface).unwrap_or(DVec2::splat(0.5)); - network_interface.document_metadata().transform_to_viewport(layer).transform_point2(min + (max - min) * pivot) + let center = DVec2::splat(0.5); + network_interface.document_metadata().transform_to_viewport(layer).transform_point2(min + (max - min) * center) } /// Get the current gradient of a layer from the closest "Fill" node. diff --git a/editor/src/messages/tool/common_functionality/pivot.rs b/editor/src/messages/tool/common_functionality/pivot.rs index 67ce7f5d..10ea3837 100644 --- a/editor/src/messages/tool/common_functionality/pivot.rs +++ b/editor/src/messages/tool/common_functionality/pivot.rs @@ -1,26 +1,184 @@ -//! Handler for the pivot overlay visible on the selected layer(s) whilst using the Select tool which controls the center of rotation/scale and origin of the layer. +//! Handler for the pivot overlay visible on the selected layer(s) whilst using the Select tool which controls the center of rotation/scale. -use super::graph_modification_utils; use crate::consts::PIVOT_DIAMETER; -use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::prelude::*; +use crate::messages::tool::common_functionality::graph_modification_utils; +use crate::messages::tool::tool_messages::path_tool::PathOptionsUpdate; +use crate::messages::tool::tool_messages::select_tool::SelectOptionsUpdate; +use crate::messages::tool::tool_messages::tool_prelude::*; use glam::{DAffine2, DVec2}; -use graphene_std::transform::ReferencePoint; -use std::collections::VecDeque; +use graphene_std::{transform::ReferencePoint, vector::ManipulatorPointId}; +use std::fmt; -#[derive(Clone, Debug)] +pub fn pin_pivot_widget(active: bool, enabled: bool, source: PivotToolSource) -> WidgetHolder { + IconButton::new(if active { "PinActive" } else { "PinInactive" }, 24) + .tooltip(String::from(if active { "Unpin Custom Pivot" } else { "Pin Custom Pivot" }) + "\n\nUnless pinned, the pivot will return to its prior reference point when a new selection is made.") + .disabled(!enabled) + .on_update(move |_| match source { + PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::TogglePivotPinned).into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::TogglePivotPinned).into(), + }) + .widget_holder() +} + +pub fn pivot_reference_point_widget(disabled: bool, reference_point: ReferencePoint, source: PivotToolSource) -> WidgetHolder { + ReferencePointInput::new(reference_point) + .tooltip("Custom Pivot Reference Point\n\nPlaces the pivot at a corner, edge, or center of the selection bounds, unless it is dragged elsewhere.") + .disabled(disabled) + .on_update(move |pivot_input: &ReferencePointInput| match source { + PivotToolSource::Select => SelectToolMessage::SetPivot { position: pivot_input.value }.into(), + PivotToolSource::Path => PathToolMessage::SetPivot { position: pivot_input.value }.into(), + }) + .widget_holder() +} + +pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource) -> Vec { + let gizmo_type_entries = [PivotGizmoType::Pivot, PivotGizmoType::Average, PivotGizmoType::Active] + .iter() + .map(|gizmo_type| { + MenuListEntry::new(format!("{gizmo_type:?}")).label(gizmo_type.to_string()).on_commit({ + let value = source.clone(); + move |_| match value { + PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::PivotGizmoType(*gizmo_type)).into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::PivotGizmoType(*gizmo_type)).into(), + } + }) + }) + .collect(); + + vec![ + CheckboxInput::new(!state.disabled) + .tooltip( + "Pivot Gizmo\n\ + \n\ + Enabled: the chosen gizmo type is shown and used to control rotation and scaling.\n\ + Disabled: rotation and scaling occurs about the center of the selection bounds.", + ) + .on_update(move |optional_input: &CheckboxInput| match source { + PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::TogglePivotGizmoType(optional_input.checked)).into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::TogglePivotGizmoType(optional_input.checked)).into(), + }) + .widget_holder(), + Separator::new(SeparatorType::Related).widget_holder(), + DropdownInput::new(vec![gizmo_type_entries]) + .selected_index(Some(match state.gizmo_type { + PivotGizmoType::Pivot => 0, + PivotGizmoType::Average => 1, + PivotGizmoType::Active => 2, + })) + .tooltip( + "Pivot Gizmo Type\n\ + \n\ + Selects which gizmo type is shown and used as the center of rotation/scaling transformations.\n\ + \n\ + Custom Pivot: rotates and scales relative to the selection bounds, or elsewhere if dragged.\n\ + Origin (Average Point): rotates and scales about the average point of all selected layer origins.\n\ + Origin (Active Object): rotates and scales about the origin of the most recently selected layer.", + ) + .disabled(state.disabled) + .widget_holder(), + ] +} + +#[derive(PartialEq, Clone, Debug, Default, serde::Serialize, serde::Deserialize)] +pub enum PivotToolSource { + Path, + #[default] + Select, +} + +#[derive(PartialEq, Clone, Debug, Default, serde::Serialize, serde::Deserialize)] +pub struct PivotGizmo { + pub pivot: Pivot, + pub state: PivotGizmoState, + pub layer: Option, + pub point: Option, +} + +impl PivotGizmo { + pub fn position(&self, document: &DocumentMessageHandler) -> DVec2 { + let network = &document.network_interface; + (!self.state.disabled) + .then_some({ + match self.state.gizmo_type { + PivotGizmoType::Average => Some(network.selected_nodes().selected_visible_and_unlocked_layers_mean_average_origin(network)), + PivotGizmoType::Pivot => self.pivot.pivot, + PivotGizmoType::Active => self.layer.map(|layer| graph_modification_utils::get_viewport_origin(layer, network)), + } + }) + .flatten() + .unwrap_or_else(|| self.pivot.transform_from_normalized.transform_point2(DVec2::splat(0.5))) + } + + pub fn recalculate_transform(&mut self, document: &DocumentMessageHandler) -> DAffine2 { + self.pivot.recalculate_pivot(document); + self.pivot.transform_from_normalized + } + + pub fn pin_active(&self) -> bool { + self.pivot.pinned && self.state.is_pivot_type() + } + + pub fn pivot_disconnected(&self) -> bool { + self.pivot.old_pivot_position == ReferencePoint::None + } +} + +#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)] +pub enum PivotGizmoType { + // Pivot + #[default] + Pivot, + // Origin + Average, + Active, + // TODO: Add "Individual" +} + +#[derive(PartialEq, Eq, Clone, Copy, Default, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct PivotGizmoState { + pub disabled: bool, + pub gizmo_type: PivotGizmoType, +} + +impl PivotGizmoState { + pub fn is_pivot_type(&self) -> bool { + self.gizmo_type == PivotGizmoType::Pivot || self.disabled + } + + pub fn is_pivot(&self) -> bool { + self.gizmo_type == PivotGizmoType::Pivot && !self.disabled + } +} + +impl fmt::Display for PivotGizmoType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PivotGizmoType::Pivot => write!(f, "Custom Pivot"), + PivotGizmoType::Average => write!(f, "Origin (Average Point)"), + PivotGizmoType::Active => write!(f, "Origin (Active Object)"), + // TODO: Add "Origin (Individual)" + } + } +} + +#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct Pivot { /// Pivot between (0,0) and (1,1) normalized_pivot: DVec2, /// Transform to get from normalized pivot to viewspace - transform_from_normalized: DAffine2, - /// The viewspace pivot position (if applicable) - pivot: Option, + pub transform_from_normalized: DAffine2, + /// The viewspace pivot position + pub pivot: Option, /// The old pivot position in the GUI, used to reduce refreshes of the document bar - old_pivot_position: ReferencePoint, + pub old_pivot_position: ReferencePoint, + /// The last ReferencePoint which wasn't none + pub last_non_none_reference_point: ReferencePoint, /// Used to enable and disable the pivot - active: bool, + pub pinned: bool, + /// Had selected_visible_and_unlocked_layers + pub empty: bool, } impl Default for Pivot { @@ -30,84 +188,62 @@ impl Default for Pivot { transform_from_normalized: Default::default(), pivot: Default::default(), old_pivot_position: ReferencePoint::Center, - active: true, + last_non_none_reference_point: ReferencePoint::Center, + pinned: false, + empty: true, } } } impl Pivot { - /// Calculates the transform that gets from normalized pivot to viewspace. - fn get_layer_pivot_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 { - let [min, max] = document.metadata().nonzero_bounding_box(layer); - - let bounds_transform = DAffine2::from_translation(min) * DAffine2::from_scale(max - min); - let layer_transform = document.metadata().transform_to_viewport(layer); - layer_transform * bounds_transform - } - /// Recomputes the pivot position and transform. - fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) { - if !self.active { + pub fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) { + let selected = document.network_interface.selected_nodes(); + self.empty = !selected.has_selected_nodes(); + if !selected.has_selected_nodes() { return; } - let selected_nodes = document.network_interface.selected_nodes(); - let mut layers = selected_nodes.selected_visible_and_unlocked_layers(&document.network_interface); - let Some(first) = layers.next() else { - // If no layers are selected then we revert things back to default + let transform = selected + .selected_visible_and_unlocked_layers(&document.network_interface) + .find(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[])) + .map(|layer| document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface)) + .unwrap_or_default(); + + let bounds = document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers(&document.network_interface) + .filter_map(|layer| { + document + .metadata() + .bounding_box_with_transform(layer, transform.inverse() * document.metadata().transform_to_viewport(layer)) + }) + .reduce(graphene_std::renderer::Quad::combine_bounds); + + let [min, max] = bounds.unwrap_or([DVec2::ZERO, DVec2::ONE]); + self.transform_from_normalized = transform * DAffine2::from_translation(min) * DAffine2::from_scale(max - min); + + if self.old_pivot_position != ReferencePoint::None { + self.pivot = Some(self.transform_from_normalized.transform_point2(self.normalized_pivot)); + } + } + + pub fn recalculate_pivot_for_layer(&mut self, document: &DocumentMessageHandler, bounds: Option<[DVec2; 2]>) { + let selected = document.network_interface.selected_nodes(); + if !selected.has_selected_nodes() { self.normalized_pivot = DVec2::splat(0.5); self.pivot = None; return; }; - // Add one because the first item is consumed above. - let selected_layers_count = layers.count() + 1; - - // If just one layer is selected we can use its inner transform (as it accounts for rotation) - if selected_layers_count == 1 { - let normalized_pivot = graph_modification_utils::get_pivot(first, &document.network_interface).unwrap_or(DVec2::splat(0.5)); - self.normalized_pivot = normalized_pivot; - self.transform_from_normalized = Self::get_layer_pivot_transform(first, document); - self.pivot = Some(self.transform_from_normalized.transform_point2(normalized_pivot)); - } else { - // If more than one layer is selected we use the AABB with the mean of the pivots - let xy_summation = document - .network_interface - .selected_nodes() - .selected_visible_and_unlocked_layers(&document.network_interface) - .map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network_interface)) - .reduce(|a, b| a + b) - .unwrap_or_default(); - - let pivot = xy_summation / selected_layers_count as f64; - self.pivot = Some(pivot); - let [min, max] = document.selected_visible_and_unlock_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]); - self.normalized_pivot = (pivot - min) / (max - min); - - self.transform_from_normalized = DAffine2::from_translation(min) * DAffine2::from_scale(max - min); - } - } - - pub fn update_pivot(&mut self, document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, draw_data: Option<(f64,)>) { - if !overlay_context.visibility_settings.pivot() { - self.active = false; - return; - } else { - self.active = true; - } - - self.recalculate_pivot(document); - if let (Some(pivot), Some(data)) = (self.pivot, draw_data) { - overlay_context.pivot(pivot, data.0); - } + let [min, max] = bounds.unwrap_or([DVec2::ZERO, DVec2::ONE]); + self.transform_from_normalized = DAffine2::from_translation(min) * DAffine2::from_scale(max - min); + self.pivot = Some(self.transform_from_normalized.transform_point2(self.normalized_pivot)); } /// Answers if the pivot widget has changed (so we should refresh the tool bar at the top of the canvas). pub fn should_refresh_pivot_position(&mut self) -> bool { - if !self.active { - return false; - } - let new = self.to_pivot_position(); let should_refresh = new != self.old_pivot_position; self.old_pivot_position = new; @@ -118,37 +254,24 @@ impl Pivot { self.normalized_pivot.into() } - /// Sets the viewport position of the pivot for all selected layers. - pub fn set_viewport_position(&self, position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque) { - if !self.active { + /// Sets the viewport position of the pivot. + pub fn set_viewport_position(&mut self, position: DVec2) { + if self.transform_from_normalized.matrix2.determinant().abs() <= f64::EPSILON { return; - } + }; - for layer in document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface) { - let transform = Self::get_layer_pivot_transform(layer, document); - // Only update the pivot when computed position is finite. - if transform.matrix2.determinant().abs() <= f64::EPSILON { - return; - }; - let pivot = transform.inverse().transform_point2(position); - responses.add(GraphOperationMessage::TransformSetPivot { layer, pivot }); - } + self.normalized_pivot = self.transform_from_normalized.inverse().transform_point2(position); + self.pivot = Some(position); } - /// Set the pivot using the normalized transform that is set above. - pub fn set_normalized_position(&self, position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque) { - if !self.active { - return; - } - - self.set_viewport_position(self.transform_from_normalized.transform_point2(position), document, responses); + /// Set the pivot using a normalized position. + pub fn set_normalized_position(&mut self, position: DVec2) { + self.normalized_pivot = position; + self.pivot = Some(self.transform_from_normalized.transform_point2(position)); } /// Answers if the pointer is currently positioned over the pivot. pub fn is_over(&self, mouse: DVec2) -> bool { - if !self.active { - return false; - } self.pivot.filter(|&pivot| mouse.distance_squared(pivot) < (PIVOT_DIAMETER / 2.).powi(2)).is_some() } } diff --git a/editor/src/messages/tool/common_functionality/utility_functions.rs b/editor/src/messages/tool/common_functionality/utility_functions.rs index 23829271..6ae3f130 100644 --- a/editor/src/messages/tool/common_functionality/utility_functions.rs +++ b/editor/src/messages/tool/common_functionality/utility_functions.rs @@ -393,6 +393,7 @@ pub fn transforming_transform_cage( input: &InputPreprocessorMessageHandler, responses: &mut VecDeque, layers_dragging: &mut Vec, + center_of_transformation: Option, ) -> (bool, bool, bool) { let dragging_bounds = bounding_box_manager.as_mut().and_then(|bounding_box| { let edges = bounding_box.check_selected_edges(input.mouse.position); @@ -429,17 +430,12 @@ pub fn transforming_transform_cage( } }); - let mut selected = Selected::new( - &mut bounds.original_transforms, - &mut bounds.center_of_transformation, - layers_dragging, - responses, - &document.network_interface, - None, - &ToolType::Select, - None, - ); - bounds.center_of_transformation = selected.mean_average_of_pivots(); + bounds.center_of_transformation = center_of_transformation.unwrap_or_else(|| { + document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers_mean_average_origin(&document.network_interface) + }); // Check if we're hovering over a skew triangle let edges = bounds.check_selected_edges(input.mouse.position); @@ -469,18 +465,12 @@ pub fn transforming_transform_cage( } }); - let mut selected = Selected::new( - &mut bounds.original_transforms, - &mut bounds.center_of_transformation, - &selected, - responses, - &document.network_interface, - None, - &ToolType::Select, - None, - ); - - bounds.center_of_transformation = selected.mean_average_of_pivots(); + bounds.center_of_transformation = center_of_transformation.unwrap_or_else(|| { + document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers_mean_average_origin(&document.network_interface) + }); } *layers_dragging = selected; diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 94134954..e20d0989 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -181,6 +181,11 @@ impl MessageHandler> for ToolMessageHandler { send: Box::new(TransformLayerMessage::SelectionChanged.into()), }); + responses.add(BroadcastMessage::SubscribeEvent { + on: BroadcastEvent::SelectionChanged, + send: Box::new(SelectToolMessage::SyncHistory.into()), + }); + self.tool_is_active = true; let tool_data = &mut self.tool_state.tool_data; diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 54a6ceb4..0642613c 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -11,6 +11,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node use crate::messages::portfolio::document::utility_types::transformation::Axis; use crate::messages::preferences::SelectionMode; use crate::messages::tool::common_functionality::auto_panning::AutoPanning; +use crate::messages::tool::common_functionality::pivot::{PivotGizmo, PivotGizmoType, PivotToolSource, pin_pivot_widget, pivot_gizmo_type_widget, pivot_reference_point_widget}; use crate::messages::tool::common_functionality::shape_editor::{ ClosestSegment, ManipulatorAngle, OpposingHandleLengths, SelectedLayerState, SelectedPointsInfo, SelectionChange, SelectionShape, SelectionShapeType, ShapeState, }; @@ -18,6 +19,7 @@ use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandi use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, find_two_param_best_approximate}; use bezier_rs::{Bezier, BezierHandles, TValue}; use graphene_std::renderer::Quad; +use graphene_std::transform::ReferencePoint; use graphene_std::vector::{HandleExt, HandleId, NoHashBuilder, SegmentId, VectorData}; use graphene_std::vector::{ManipulatorPointId, PointId, VectorModificationType}; use std::vec; @@ -106,6 +108,9 @@ pub enum PathToolMessage { SelectedPointYChanged { new_y: f64, }, + SetPivot { + position: ReferencePoint, + }, SwapSelectedHandles, UpdateOptions(PathOptionsUpdate), UpdateSelectedPointsStatus { @@ -141,6 +146,9 @@ pub enum PathOptionsUpdate { OverlayModeType(PathOverlayMode), PointEditingMode { enabled: bool }, SegmentEditingMode { enabled: bool }, + PivotGizmoType(PivotGizmoType), + TogglePivotGizmoType(bool), + TogglePivotPinned, } impl ToolMetadata for PathTool { @@ -255,6 +263,20 @@ impl LayoutHolder for PathTool { .selected_index(Some(self.options.path_overlay_mode as u32)) .widget_holder(); + let [_checkbox, _dropdown] = { + let pivot_gizmo_type_widget = pivot_gizmo_type_widget(self.tool_data.pivot_gizmo.state, PivotToolSource::Path); + [pivot_gizmo_type_widget[0].clone(), pivot_gizmo_type_widget[2].clone()] + }; + + let has_something = !self.tool_data.saved_points_before_anchor_convert_smooth_sharp.is_empty(); + let _pivot_reference = pivot_reference_point_widget( + has_something || !self.tool_data.pivot_gizmo.state.is_pivot(), + self.tool_data.pivot_gizmo.pivot.to_pivot_position(), + PivotToolSource::Path, + ); + + let _pin_pivot = pin_pivot_widget(self.tool_data.pivot_gizmo.pin_active(), false, PivotToolSource::Path); + Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets: vec![ x_location, @@ -268,8 +290,16 @@ impl LayoutHolder for PathTool { point_editing_mode, related_seperator.clone(), segment_editing_mode, - unrelated_seperator, + unrelated_seperator.clone(), path_overlay_mode_widget, + unrelated_seperator.clone(), + // checkbox.clone(), + // related_seperator.clone(), + // dropdown.clone(), + // unrelated_seperator, + // pivot_reference, + // related_seperator.clone(), + // pin_pivot, ], }])) } @@ -293,6 +323,29 @@ impl<'a> MessageHandler> for PathToo self.options.path_editing_mode.segment_editing_mode = enabled; responses.add(OverlaysMessage::Draw); } + PathOptionsUpdate::PivotGizmoType(gizmo_type) => { + if !self.tool_data.pivot_gizmo.state.disabled { + self.tool_data.pivot_gizmo.state.gizmo_type = gizmo_type; + responses.add(ToolMessage::UpdateHints); + let pivot_gizmo = self.tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + responses.add(NodeGraphMessage::RunDocumentGraph); + self.send_layout(responses, LayoutTarget::ToolOptions); + } + } + PathOptionsUpdate::TogglePivotGizmoType(state) => { + self.tool_data.pivot_gizmo.state.disabled = !state; + responses.add(ToolMessage::UpdateHints); + responses.add(NodeGraphMessage::RunDocumentGraph); + self.send_layout(responses, LayoutTarget::ToolOptions); + } + + PathOptionsUpdate::TogglePivotPinned => { + self.tool_data.pivot_gizmo.pivot.pinned = !self.tool_data.pivot_gizmo.pivot.pinned; + responses.add(ToolMessage::UpdateHints); + responses.add(NodeGraphMessage::RunDocumentGraph); + self.send_layout(responses, LayoutTarget::ToolOptions); + } }, ToolMessage::Path(PathToolMessage::ClosePath) => { responses.add(DocumentMessage::AddTransaction); @@ -443,6 +496,8 @@ struct PathToolData { last_click_time: u64, dragging_state: DraggingState, angle: f64, + pivot_gizmo: PivotGizmo, + ordered_points: Vec, opposite_handle_position: Option, last_clicked_point_was_selected: bool, last_clicked_segment_was_selected: bool, @@ -1315,6 +1370,16 @@ impl PathToolData { } } } + + fn pivot_gizmo(&self) -> PivotGizmo { + self.pivot_gizmo.clone() + } + + fn sync_history(&mut self, points: &[ManipulatorPointId]) { + self.ordered_points.retain(|layer| points.contains(layer)); + self.ordered_points.extend(points.iter().find(|&layer| !self.ordered_points.contains(layer))); + self.pivot_gizmo.point = self.ordered_points.last().copied() + } } impl Fsm for PathToolFsmState { @@ -1327,6 +1392,10 @@ impl Fsm for PathToolFsmState { update_dynamic_hints(self, responses, shape_editor, document, tool_data, tool_options); let ToolMessage::Path(event) = event else { return self }; + + // TODO(mTvare6): Remove once gizmos are implemented for path_tool + tool_data.pivot_gizmo.state.disabled = true; + match (self, event) { (_, PathToolMessage::SelectionChanged) => { // Set the newly targeted layers to visible @@ -1343,6 +1412,9 @@ impl Fsm for PathToolFsmState { shape_editor.update_selected_anchors_status(display_anchors); shape_editor.update_selected_handles_status(display_handles); + let new_points = shape_editor.selected_points().copied().collect::>(); + tool_data.sync_history(&new_points); + self } (_, PathToolMessage::Overlays(mut overlay_context)) => { @@ -1710,14 +1782,8 @@ impl Fsm for PathToolFsmState { } (PathToolFsmState::Ready, PathToolMessage::PointerMove { delete_segment, .. }) => { tool_data.delete_segment_pressed = input.keyboard.get(delete_segment as usize); - - if !tool_data.saved_points_before_anchor_convert_smooth_sharp.is_empty() { - tool_data.saved_points_before_anchor_convert_smooth_sharp.clear(); - } - - if tool_data.adjacent_anchor_offset.is_some() { - tool_data.adjacent_anchor_offset = None; - } + tool_data.saved_points_before_anchor_convert_smooth_sharp.clear(); + tool_data.adjacent_anchor_offset = None; tool_data.stored_selection = None; responses.add(OverlaysMessage::Draw); @@ -2208,6 +2274,18 @@ impl Fsm for PathToolFsmState { responses.add(DocumentMessage::EndTransaction); PathToolFsmState::Ready } + (_, PathToolMessage::SetPivot { position }) => { + responses.add(DocumentMessage::StartTransaction); + + tool_data.pivot_gizmo.pivot.last_non_none_reference_point = position; + let position: Option = position.into(); + tool_data.pivot_gizmo.pivot.set_normalized_position(position.unwrap()); + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + responses.add(NodeGraphMessage::RunDocumentGraph); + + self + } (_, _) => PathToolFsmState::Ready, } } diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 76158d08..9ae3459a 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -12,9 +12,10 @@ use crate::messages::portfolio::document::utility_types::nodes::SelectedNodes; use crate::messages::preferences::SelectionMode; use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::compass_rose::{Axis, CompassRose}; +use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name; use crate::messages::tool::common_functionality::measure; -use crate::messages::tool::common_functionality::pivot::Pivot; +use crate::messages::tool::common_functionality::pivot::{PivotGizmo, PivotGizmoType, PivotToolSource, pin_pivot_widget, pivot_gizmo_type_widget, pivot_reference_point_widget}; use crate::messages::tool::common_functionality::shape_editor::SelectionShapeType; use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData, SnapManager}; use crate::messages::tool::common_functionality::transformation_cage::*; @@ -43,6 +44,9 @@ pub struct SelectOptions { #[derive(PartialEq, Eq, Clone, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)] pub enum SelectOptionsUpdate { NestedSelectionBehavior(NestedSelectionBehavior), + PivotGizmoType(PivotGizmoType), + TogglePivotGizmoType(bool), + TogglePivotPinned, } #[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)] @@ -95,6 +99,14 @@ pub enum SelectToolMessage { SetPivot { position: ReferencePoint, }, + SyncHistory, + ShiftSelectedNodes { + offset: DVec2, + }, + PivotShift { + offset: Option, + flush: bool, + }, } impl ToolMetadata for SelectTool { @@ -122,14 +134,12 @@ impl SelectTool { DropdownInput::new(vec![layer_selection_behavior_entries]) .selected_index(Some((self.tool_data.nested_selection_behavior == NestedSelectionBehavior::Deepest) as u32)) - .tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking") - .widget_holder() - } - - fn pivot_reference_point_widget(&self, disabled: bool) -> WidgetHolder { - ReferencePointInput::new(self.tool_data.pivot.to_pivot_position()) - .on_update(|pivot_input: &ReferencePointInput| SelectToolMessage::SetPivot { position: pivot_input.value }.into()) - .disabled(disabled) + .tooltip( + "Selection Mode\n\ + \n\ + Shallow Select: clicks initially select the least-nested layers and double clicks drill deeper into the folder hierarchy.\n\ + Deep Select: clicks directly select the most-nested layers in the folder hierarchy.", + ) .widget_holder() } @@ -178,7 +188,7 @@ impl SelectTool { fn boolean_widgets(&self, selected_count: usize) -> impl Iterator + use<> { let list = ::list(); - list.into_iter().map(|i| i.into_iter()).flatten().map(move |(operation, info)| { + list.iter().flat_map(|i| i.iter()).map(move |(operation, info)| { let mut tooltip = info.label.to_string(); if let Some(doc) = info.docstring.as_deref() { tooltip.push_str("\n\n"); @@ -203,9 +213,29 @@ impl LayoutHolder for SelectTool { // Select mode (Deep/Shallow) widgets.push(self.deep_selection_widget()); - // Pivot + // Pivot gizmo type (checkbox + dropdown for pivot/origin) widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); - widgets.push(self.pivot_reference_point_widget(self.tool_data.selected_layers_count == 0)); + widgets.extend(pivot_gizmo_type_widget(self.tool_data.pivot_gizmo.state, PivotToolSource::Select)); + + if self.tool_data.pivot_gizmo.state.is_pivot_type() { + // Nine-position reference point widget + widgets.push(Separator::new(SeparatorType::Related).widget_holder()); + widgets.push(pivot_reference_point_widget( + self.tool_data.selected_layers_count == 0 || !self.tool_data.pivot_gizmo.state.is_pivot(), + self.tool_data.pivot_gizmo.pivot.to_pivot_position(), + PivotToolSource::Select, + )); + + // Pivot pin button + widgets.push(Separator::new(SeparatorType::Related).widget_holder()); + + let pin_active = self.tool_data.pivot_gizmo.pin_active(); + let pin_enabled = self.tool_data.pivot_gizmo.pivot.old_pivot_position == ReferencePoint::None && !self.tool_data.pivot_gizmo.state.disabled; + + if pin_active || pin_enabled { + widgets.push(pin_pivot_widget(pin_active, pin_enabled, PivotToolSource::Select)); + } + } // Align let disabled = self.tool_data.selected_layers_count < 2; @@ -244,14 +274,43 @@ impl LayoutHolder for SelectTool { impl<'a> MessageHandler> for SelectTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { - if let ToolMessage::Select(SelectToolMessage::SelectOptions(SelectOptionsUpdate::NestedSelectionBehavior(nested_selection_behavior))) = message { - self.tool_data.nested_selection_behavior = nested_selection_behavior; - responses.add(ToolMessage::UpdateHints); + let mut redraw_reference_pivot = false; + + if let ToolMessage::Select(SelectToolMessage::SelectOptions(ref option_update)) = message { + match option_update { + SelectOptionsUpdate::NestedSelectionBehavior(nested_selection_behavior) => { + self.tool_data.nested_selection_behavior = *nested_selection_behavior; + responses.add(ToolMessage::UpdateHints); + } + SelectOptionsUpdate::PivotGizmoType(gizmo_type) => { + if !self.tool_data.pivot_gizmo.state.disabled { + self.tool_data.pivot_gizmo.state.gizmo_type = *gizmo_type; + responses.add(ToolMessage::UpdateHints); + let pivot_gizmo = self.tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + responses.add(NodeGraphMessage::RunDocumentGraph); + redraw_reference_pivot = true; + } + } + SelectOptionsUpdate::TogglePivotGizmoType(state) => { + self.tool_data.pivot_gizmo.state.disabled = !state; + responses.add(ToolMessage::UpdateHints); + responses.add(NodeGraphMessage::RunDocumentGraph); + redraw_reference_pivot = true; + } + + SelectOptionsUpdate::TogglePivotPinned => { + self.tool_data.pivot_gizmo.pivot.pinned = !self.tool_data.pivot_gizmo.pivot.pinned; + responses.add(ToolMessage::UpdateHints); + responses.add(NodeGraphMessage::RunDocumentGraph); + redraw_reference_pivot = true; + } + } } self.fsm_state.process_event(message, &mut self.tool_data, tool_data, &(), responses, false); - if self.tool_data.pivot.should_refresh_pivot_position() || self.tool_data.selected_layers_changed { + if self.tool_data.pivot_gizmo.pivot.should_refresh_pivot_position() || self.tool_data.selected_layers_changed || redraw_reference_pivot { // Send the layout containing the updated pivot position (a bit ugly to do it here not in the fsm but that doesn't have SelectTool) self.send_layout(responses, LayoutTarget::ToolOptions); self.tool_data.selected_layers_changed = false; @@ -323,7 +382,8 @@ struct SelectToolData { drag_current: ViewportPosition, lasso_polygon: Vec, selection_mode: Option, - layers_dragging: Vec, + layers_dragging: Vec, // Unordered, often used as temporary buffer + ordered_layers: Vec, // Ordered list of layers layer_selected_on_start: Option, select_single_layer: Option, axis_align: bool, @@ -331,7 +391,9 @@ struct SelectToolData { bounding_box_manager: Option, snap_manager: SnapManager, cursor: MouseCursorIcon, - pivot: Pivot, + pivot_gizmo: PivotGizmo, + pivot_gizmo_start: Option, + pivot_gizmo_shift: Option, compass_rose: CompassRose, line_center: DVec2, skew_edge: EdgeBool, @@ -497,6 +559,24 @@ impl SelectToolData { responses.add(NodeGraphMessage::SendGraph); self.layers_dragging = original; } + + fn state_from_pivot_gizmo(&self, mouse: DVec2) -> Option { + match self.pivot_gizmo.state.gizmo_type { + PivotGizmoType::Pivot if self.pivot_gizmo.state.is_pivot() => self.pivot_gizmo.pivot.is_over(mouse).then_some(SelectToolFsmState::DraggingPivot), + _ => None, + } + } + + fn pivot_gizmo(&self) -> PivotGizmo { + self.pivot_gizmo.clone() + } + + fn sync_history(&mut self, document: &DocumentMessageHandler) { + let layers: Vec<_> = document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface).collect(); + self.ordered_layers.retain(|layer| layers.contains(layer)); + self.ordered_layers.extend(layers.iter().find(|&layer| !self.ordered_layers.contains(layer))); + self.pivot_gizmo.layer = self.ordered_layers.last().copied() + } } impl Fsm for SelectToolFsmState { @@ -710,8 +790,63 @@ impl Fsm for SelectToolFsmState { .flatten() }); - // Update pivot - tool_data.pivot.update_pivot(document, &mut overlay_context, Some((angle,))); + let mut active_origin = None; + let mut origin_angle = 0.; + if overlay_context.visibility_settings.origin() && !tool_data.pivot_gizmo.state.is_pivot_type() { + let get_angle = |layer: LayerNodeIdentifier| -> f64 { + let quad = Quad::from_box([DVec2::ZERO, DVec2::ONE]); + let bounds = document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface) * quad; + (bounds.top_left() - bounds.top_right()).to_angle() + }; + if tool_data.pivot_gizmo.state.gizmo_type == PivotGizmoType::Average { + let mut count = 0_usize; + + let sum: f64 = document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers(&document.network_interface) + .map(get_angle) + .inspect(|_| count += 1) + .sum(); + if count > 0 { + origin_angle = sum / count as f64; + } + } else if tool_data.pivot_gizmo.state.gizmo_type == PivotGizmoType::Active { + origin_angle = document + .network_interface + .selected_nodes() + .selected_visible_and_unlocked_layers(&document.network_interface) + .find(|&layer| Some(layer) == tool_data.pivot_gizmo.layer) + .iter() + .map(|&layer| get_angle(layer)) + .sum(); + } + + for layer in document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface) { + let origin = graph_modification_utils::get_viewport_origin(layer, &document.network_interface); + if Some(layer) == tool_data.pivot_gizmo.layer { + active_origin = Some(origin); + continue; + } + overlay_context.dowel_pin(origin, origin_angle, None); + } + } + if let Some(origin) = active_origin { + overlay_context.dowel_pin(origin, origin_angle, Some(COLOR_OVERLAY_YELLOW)); + } + + let has_layers = document.network_interface.selected_nodes().has_selected_nodes(); + let draw_pivot = tool_data.pivot_gizmo.state.is_pivot() && overlay_context.visibility_settings.pivot() && has_layers; + tool_data.pivot_gizmo.pivot.recalculate_pivot(document); + let pivot = draw_pivot.then_some(tool_data.pivot_gizmo.pivot.pivot).flatten(); + if let Some(pivot) = pivot { + let offset = tool_data + .pivot_gizmo_start + .map(|offset| tool_data.pivot_gizmo.pivot_disconnected().then_some(tool_data.drag_current - offset).unwrap_or_default()) + .unwrap_or_default(); + let shift = tool_data.pivot_gizmo_shift.unwrap_or_default(); + overlay_context.pivot(pivot + offset + shift, angle); + } // Update compass rose if overlay_context.visibility_settings.compass_rose() { @@ -837,6 +972,7 @@ impl Fsm for SelectToolFsmState { (SelectionShapeType::Lasso, _) => overlay_context.polygon(polygon, None, fill_color), } } + self } (_, SelectToolMessage::EditLayer) => { @@ -868,7 +1004,8 @@ impl Fsm for SelectToolFsmState { let intersection_list = document.click_list(input).collect::>(); let intersection = document.find_deepest(&intersection_list); - let (resize, rotate, skew) = transforming_transform_cage(document, &mut tool_data.bounding_box_manager, input, responses, &mut tool_data.layers_dragging); + let position = tool_data.pivot_gizmo().position(document); + let (resize, rotate, skew) = transforming_transform_cage(document, &mut tool_data.bounding_box_manager, input, responses, &mut tool_data.layers_dragging, Some(position)); // If the user is dragging the bounding box bounds, go into ResizingBounds mode. // If the user is dragging the rotate trigger, go into RotatingBounds mode. @@ -883,20 +1020,17 @@ impl Fsm for SelectToolFsmState { let angle = bounds.map_or(0., |quad| (quad.top_left() - quad.top_right()).to_angle()); let mouse_position = input.mouse.position; let compass_rose_state = tool_data.compass_rose.compass_rose_state(mouse_position, angle); - let is_over_pivot = tool_data.pivot.is_over(mouse_position); let show_compass = bounds.is_some_and(|quad| quad.all_sides_at_least_width(COMPASS_ROSE_HOVER_RING_DIAMETER) && quad.contains(mouse_position)); let can_grab_compass_rose = compass_rose_state.can_grab() && (show_compass || bounds.is_none()); - let state = if is_over_pivot - // Dragging the pivot - { + let state = if let Some(state) = tool_data.state_from_pivot_gizmo(input.mouse.position) { responses.add(DocumentMessage::StartTransaction); // tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); // tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); - SelectToolFsmState::DraggingPivot + state } // Dragging one (or two, forming a corner) of the transform cage bounding box edges else if resize { @@ -917,12 +1051,14 @@ impl Fsm for SelectToolFsmState { } tool_data.layers_dragging = selected; - tool_data.get_snap_candidates(document, input); let (axis, using_compass) = { let axis_state = compass_rose_state.axis_type().filter(|_| can_grab_compass_rose); (axis_state.unwrap_or_default(), axis_state.is_some()) }; + + tool_data.pivot_gizmo_start = Some(tool_data.drag_current); + SelectToolFsmState::Dragging { axis, using_compass, @@ -941,6 +1077,12 @@ impl Fsm for SelectToolFsmState { let extend = input.keyboard.key(extend_selection); if !extend && !input.keyboard.key(remove_from_selection) { responses.add(DocumentMessage::DeselectAllLayers); + + if !tool_data.pivot_gizmo.pivot.pinned { + let position = tool_data.pivot_gizmo.pivot.last_non_none_reference_point; + responses.add(SelectToolMessage::SetPivot { position }); + } + tool_data.layers_dragging.clear(); } @@ -955,6 +1097,9 @@ impl Fsm for SelectToolFsmState { tool_data.get_snap_candidates(document, input); responses.add(DocumentMessage::StartTransaction); + + tool_data.pivot_gizmo_start = Some(tool_data.drag_current); + SelectToolFsmState::Dragging { axis: Axis::None, using_compass: false, @@ -1098,7 +1243,10 @@ impl Fsm for SelectToolFsmState { (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerMove(modifier_keys)) => { let mouse_position = input.mouse.position; let snapped_mouse_position = mouse_position; - tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses); + + tool_data.pivot_gizmo.pivot.set_viewport_position(snapped_mouse_position); + + responses.add(NodeGraphMessage::RunDocumentGraph); // Auto-panning let messages = [ @@ -1143,7 +1291,7 @@ impl Fsm for SelectToolFsmState { .map_or(MouseCursorIcon::Default, |bounds| bounds.get_cursor(input, true, dragging_bounds, Some(tool_data.skew_edge))); // Dragging the pivot overrules the other operations - if tool_data.pivot.is_over(input.mouse.position) { + if tool_data.state_from_pivot_gizmo(input.mouse.position).is_some() { cursor = MouseCursorIcon::Move; } @@ -1283,20 +1431,32 @@ impl Fsm for SelectToolFsmState { tool_data.snap_manager.cleanup(responses); tool_data.select_single_layer = None; + if let Some(start) = tool_data.pivot_gizmo_start { + let offset = tool_data.pivot_gizmo.pivot_disconnected().then_some(tool_data.drag_current - start).unwrap_or_default(); + if let Some(v) = tool_data.pivot_gizmo.pivot.pivot.as_mut() { + *v += offset; + } + } + tool_data.pivot_gizmo_start = None; + + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + let selection = tool_data.nested_selection_behavior; SelectToolFsmState::Ready { selection } } ( - SelectToolFsmState::ResizingBounds - | SelectToolFsmState::SkewingBounds { .. } - | SelectToolFsmState::RotatingBounds - | SelectToolFsmState::Dragging { .. } - | SelectToolFsmState::DraggingPivot, + SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. } | SelectToolFsmState::RotatingBounds | SelectToolFsmState::DraggingPivot, SelectToolMessage::DragStop { .. } | SelectToolMessage::Enter, ) => { let drag_too_small = input.mouse.position.distance(tool_data.drag_start) < 10. * f64::EPSILON; let response = if drag_too_small { DocumentMessage::AbortTransaction } else { DocumentMessage::EndTransaction }; + + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + responses.add(response); + tool_data.axis_align = false; tool_data.snap_manager.cleanup(responses); @@ -1432,8 +1592,48 @@ impl Fsm for SelectToolFsmState { (_, SelectToolMessage::SetPivot { position }) => { responses.add(DocumentMessage::StartTransaction); + tool_data.pivot_gizmo.pivot.last_non_none_reference_point = position; + tool_data.pivot_gizmo.pivot.pinned = false; + let pos: Option = position.into(); - tool_data.pivot.set_normalized_position(pos.unwrap(), document, responses); + + tool_data.pivot_gizmo.pivot.set_normalized_position(pos.unwrap()); + + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + + responses.add(NodeGraphMessage::RunDocumentGraph); + + self + } + (_, SelectToolMessage::SyncHistory) => { + tool_data.sync_history(document); + + self + } + (_, SelectToolMessage::ShiftSelectedNodes { offset }) => { + let offset = document.metadata().document_to_viewport.transform_vector2(offset); + if tool_data.pivot_gizmo.pivot_disconnected() { + if let Some(v) = tool_data.pivot_gizmo.pivot.pivot.as_mut() { + *v += offset; + } + + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + } + + self + } + (_, SelectToolMessage::PivotShift { offset, flush }) => { + if flush { + tool_data.pivot_gizmo.pivot.pivot.as_mut().map(|v| *v += tool_data.pivot_gizmo_shift.take().unwrap_or_default()); + let pivot_gizmo = tool_data.pivot_gizmo(); + responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo }); + return self; + } + if tool_data.pivot_gizmo.pivot_disconnected() { + tool_data.pivot_gizmo_shift = offset; + } self } @@ -1658,6 +1858,7 @@ fn drag_deepest_manipulation(responses: &mut VecDeque, selected: Vec, - pivot: Pivot, snap_candidates: Vec, // TODO: Handle multiple layers in the future layer_dragging: Option, @@ -526,7 +524,6 @@ impl Fsm for TextToolFsmState { } bounding_box_manager.render_overlays(&mut overlay_context, false); - tool_data.pivot.update_pivot(document, &mut overlay_context, None); } } else { tool_data.bounding_box_manager.take(); diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message.rs b/editor/src/messages/tool/transform_layer/transform_layer_message.rs index e68d2702..c819260e 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message.rs @@ -2,6 +2,7 @@ use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::transformation::TransformType; use crate::messages::prelude::*; +use crate::messages::tool::common_functionality::pivot::PivotGizmo; use glam::DVec2; #[impl_message(Message, ToolMessage, TransformLayer)] @@ -29,4 +30,5 @@ pub enum TransformLayerMessage { TypeDecimalPoint, TypeDigit { digit: u8 }, TypeNegate, + SetPivotGizmo { pivot_gizmo: PivotGizmo }, } diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index e449bbd3..72581637 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -5,6 +5,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye use crate::messages::portfolio::document::utility_types::misc::PTZ; use crate::messages::portfolio::document::utility_types::transformation::{Axis, OriginalTransforms, Selected, TransformOperation, TransformType, Typing}; use crate::messages::prelude::*; +use crate::messages::tool::common_functionality::pivot::{PivotGizmo, PivotGizmoType}; use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::tool_messages::tool_prelude::Key; use crate::messages::tool::utility_types::{ToolData, ToolType}; @@ -34,8 +35,11 @@ pub struct TransformLayerMessageHandler { start_mouse: ViewportPosition, original_transforms: OriginalTransforms, + pivot_gizmo: PivotGizmo, pivot: ViewportPosition, + path_bounds: Option<[DVec2; 2]>, + local_pivot: DocumentPosition, local_mouse_start: DocumentPosition, grab_target: DocumentPosition, @@ -61,27 +65,64 @@ impl TransformLayerMessageHandler { } } -fn calculate_pivot(selected_points: &Vec<&ManipulatorPointId>, vector_data: &VectorData, viewspace: DAffine2, get_location: impl Fn(&ManipulatorPointId) -> Option) -> Option<(DVec2, DVec2)> { +fn calculate_pivot( + document: &DocumentMessageHandler, + selected_points: &Vec<&ManipulatorPointId>, + vector_data: &VectorData, + viewspace: DAffine2, + get_location: impl Fn(&ManipulatorPointId) -> Option, + gizmo: &mut PivotGizmo, +) -> (Option<(DVec2, DVec2)>, Option<[DVec2; 2]>) { + let average_position = || { + let mut point_count = 0_usize; + selected_points.iter().filter_map(|p| get_location(p)).inspect(|_| point_count += 1).sum::() / point_count as f64 + }; + let bounds = selected_points.iter().filter_map(|p| get_location(p)).fold(None, |acc: Option<[DVec2; 2]>, point| { + if let Some([mut min, mut max]) = acc { + min.x = min.x.min(point.x); + min.y = min.y.min(point.y); + max.x = max.x.max(point.x); + max.y = max.y.max(point.y); + Some([min, max]) + } else { + Some([point, point]) + } + }); + gizmo.pivot.recalculate_pivot_for_layer(document, bounds); + let position = || { + (if !gizmo.state.disabled { + match gizmo.state.gizmo_type { + PivotGizmoType::Average => None, + PivotGizmoType::Active => gizmo.point.and_then(|p| get_location(&p)), + PivotGizmoType::Pivot => gizmo.pivot.pivot, + } + } else { + None + }) + .unwrap_or_else(average_position) + }; let [point] = selected_points.as_slice() else { // Handle the case where there are multiple points - let mut point_count = 0; - let average_position = selected_points.iter().filter_map(|p| get_location(p)).inspect(|_| point_count += 1).sum::() / point_count as f64; - - return Some((average_position, average_position)); + let position = position(); + return (Some((position, position)), bounds); }; match point { ManipulatorPointId::PrimaryHandle(_) | ManipulatorPointId::EndHandle(_) => { // Get the anchor position and transform it to the pivot - let pivot_pos = point.get_anchor_position(vector_data).map(|anchor_position| viewspace.transform_point2(anchor_position))?; - let target = viewspace.transform_point2(point.get_position(vector_data)?); - Some((pivot_pos, target)) + let (Some(pivot_position), Some(position)) = ( + point.get_anchor_position(vector_data).map(|anchor_position| viewspace.transform_point2(anchor_position)), + point.get_position(vector_data), + ) else { + return (None, None); + }; + let target = viewspace.transform_point2(position); + (Some((pivot_position, target)), None) } _ => { // Calculate the average position of all selected points - let mut point_count = 0; - let average_position = selected_points.iter().filter_map(|p| get_location(p)).inspect(|_| point_count += 1).sum::() / point_count as f64; - Some((average_position, average_position)) + let position = position(); + (Some((position, position)), bounds) } } } @@ -177,18 +218,17 @@ impl MessageHandler> for TransformLayer } if !using_path_tool { - *selected.pivot = selected.mean_average_of_pivots(); + self.pivot_gizmo.recalculate_transform(document); + *selected.pivot = self.pivot_gizmo.position(document); self.local_pivot = document.metadata().document_to_viewport.inverse().transform_point2(*selected.pivot); - self.grab_target = document.metadata().document_to_viewport.inverse().transform_point2(selected.mean_average_of_pivots()); + self.grab_target = self.local_pivot; } // Here vector data from all layers is not considered which can be a problem in pivot calculation else if let Some(vector_data) = selected_layers.first().and_then(|&layer| document.network_interface.compute_modified_vector(layer)) { *selected.original_transforms = OriginalTransforms::default(); let viewspace = document.metadata().transform_to_viewport(selected_layers[0]); - let selected_segments = shape_editor.selected_segments().collect::>(); - let mut affected_points = shape_editor.selected_points().copied().collect::>(); for (segment_id, _, start, end) in vector_data.segment_bezier_iter() { @@ -201,8 +241,16 @@ impl MessageHandler> for TransformLayer let affected_point_refs = affected_points.iter().collect(); let get_location = |point: &&ManipulatorPointId| point.get_position(&vector_data).map(|position| viewspace.transform_point2(position)); - if let Some((new_pivot, grab_target)) = calculate_pivot(&affected_point_refs, &vector_data, viewspace, |point: &ManipulatorPointId| get_location(&point)) { + if let (Some((new_pivot, grab_target)), bounds) = calculate_pivot( + document, + &affected_point_refs, + &vector_data, + viewspace, + |point: &ManipulatorPointId| get_location(&point), + &mut self.pivot_gizmo, + ) { *selected.pivot = new_pivot; + self.path_bounds = bounds; self.local_pivot = document_to_viewport.inverse().transform_point2(*selected.pivot); self.grab_target = document_to_viewport.inverse().transform_point2(grab_target); @@ -228,116 +276,115 @@ impl MessageHandler> for TransformLayer return; } - for layer in document.metadata().all_layers() { - if !document.network_interface.is_artboard(&layer.to_node(), &[]) { - continue; - }; + let viewport_box = input.viewport_bounds.size(); + let axis_constraint = self.transform_operation.axis_constraint(); - let viewport_box = input.viewport_bounds.size(); - let axis_constraint = self.transform_operation.axis_constraint(); + let format_rounded = |value: f64, precision: usize| { + if self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() { + format!("{:.*}", precision, value).trim_end_matches('0').trim_end_matches('.').to_string() + } else { + self.typing.string.clone() + } + }; - let format_rounded = |value: f64, precision: usize| { - if self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() { - format!("{:.*}", precision, value).trim_end_matches('0').trim_end_matches('.').to_string() + // TODO: Ensure removing this and adding this doesn't change the position of layers under PTZ ops + // responses.add(TransformLayerMessage::PointerMove { + // slow_key: SLOW_KEY, + // increments_key: INCREMENTS_KEY, + // }); + + match self.transform_operation { + TransformOperation::None => (), + TransformOperation::Grabbing(translation) => { + let translation = translation.to_dvec(self.initial_transform, self.increments); + let viewport_translate = document_to_viewport.transform_vector2(translation); + let pivot = document_to_viewport.transform_point2(self.grab_target); + let quad = Quad::from_box([pivot, pivot + viewport_translate]).0; + let e1 = (self.layer_bounding_box.0[1] - self.layer_bounding_box.0[0]).normalize_or(DVec2::X); + + responses.add(SelectToolMessage::PivotShift { + offset: Some(viewport_translate), + flush: false, + }); + + if matches!(axis_constraint, Axis::Both | Axis::X) && translation.x != 0. { + let end = if self.local { (quad[1] - quad[0]).rotate(e1) + quad[0] } else { quad[1] }; + overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5)); + + let x_transform = DAffine2::from_translation((quad[0] + end) / 2.); + overlay_context.text(&format_rounded(translation.x, 3), COLOR_OVERLAY_BLUE, None, x_transform, 4., [Pivot::Middle, Pivot::End]); + } + + if matches!(axis_constraint, Axis::Both | Axis::Y) && translation.y != 0. { + let end = if self.local { (quad[3] - quad[0]).rotate(e1) + quad[0] } else { quad[3] }; + overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5)); + let x_parameter = viewport_translate.x.clamp(-1., 1.); + let y_transform = DAffine2::from_translation((quad[0] + end) / 2. + x_parameter * DVec2::X * 0.); + let pivot_selection = if x_parameter >= -1e-3 { Pivot::Start } else { Pivot::End }; + if axis_constraint != Axis::Both || self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() { + overlay_context.text(&format_rounded(translation.y, 2), COLOR_OVERLAY_BLUE, None, y_transform, 3., [pivot_selection, Pivot::Middle]); + } + } + + if matches!(axis_constraint, Axis::Both) && translation.x != 0. && translation.y != 0. { + overlay_context.line(quad[1], quad[2], None, None); + overlay_context.line(quad[3], quad[2], None, None); + } + } + TransformOperation::Scaling(scale) => { + let scale = scale.to_f64(self.increments); + let text = format!("{}x", format_rounded(scale, 3)); + let pivot = document_to_viewport.transform_point2(self.local_pivot); + let start_mouse = document_to_viewport.transform_point2(self.local_mouse_start); + let local_edge = start_mouse - pivot; + let local_edge = project_edge_to_quad(local_edge, &self.layer_bounding_box, self.local, axis_constraint); + let boundary_point = pivot + local_edge * scale.min(1.); + let end_point = pivot + local_edge * scale.max(1.); + + if scale > 0. { + overlay_context.dashed_line(pivot, boundary_point, None, None, Some(2.), Some(2.), Some(0.5)); + } + overlay_context.line(boundary_point, end_point, None, None); + + let transform = DAffine2::from_translation(boundary_point.midpoint(pivot) + local_edge.perp().normalize_or(DVec2::X) * local_edge.element_product().signum() * 24.); + overlay_context.text(&text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]); + } + TransformOperation::Rotating(rotation) => { + let angle = rotation.to_f64(self.increments); + let pivot = document_to_viewport.transform_point2(self.local_pivot); + let start_mouse = document_to_viewport.transform_point2(self.local_mouse_start); + let offset_angle = if self.grs_pen_handle { + self.handle - self.last_point + } else if using_path_tool { + start_mouse - pivot } else { - self.typing.string.clone() - } - }; - - // TODO: Ensure removing this and adding this doesn't change the position of layers under PTZ ops - // responses.add(TransformLayerMessage::PointerMove { - // slow_key: SLOW_KEY, - // increments_key: INCREMENTS_KEY, - // }); - - match self.transform_operation { - TransformOperation::None => (), - TransformOperation::Grabbing(translation) => { - let translation = translation.to_dvec(self.initial_transform, self.increments); - let viewport_translate = document_to_viewport.transform_vector2(translation); - let pivot = document_to_viewport.transform_point2(self.grab_target); - let quad = Quad::from_box([pivot, pivot + viewport_translate]).0; - let e1 = (self.layer_bounding_box.0[1] - self.layer_bounding_box.0[0]).normalize_or(DVec2::X); - - if matches!(axis_constraint, Axis::Both | Axis::X) && translation.x != 0. { - let end = if self.local { (quad[1] - quad[0]).rotate(e1) + quad[0] } else { quad[1] }; - overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5)); - - let x_transform = DAffine2::from_translation((quad[0] + end) / 2.); - overlay_context.text(&format_rounded(translation.x, 3), COLOR_OVERLAY_BLUE, None, x_transform, 4., [Pivot::Middle, Pivot::End]); - } - - if matches!(axis_constraint, Axis::Both | Axis::Y) && translation.y != 0. { - let end = if self.local { (quad[3] - quad[0]).rotate(e1) + quad[0] } else { quad[3] }; - overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5)); - let x_parameter = viewport_translate.x.clamp(-1., 1.); - let y_transform = DAffine2::from_translation((quad[0] + end) / 2. + x_parameter * DVec2::X * 0.); - let pivot_selection = if x_parameter >= -1e-3 { Pivot::Start } else { Pivot::End }; - if axis_constraint != Axis::Both || self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() { - overlay_context.text(&format_rounded(translation.y, 2), COLOR_OVERLAY_BLUE, None, y_transform, 3., [pivot_selection, Pivot::Middle]); - } - } - - if matches!(axis_constraint, Axis::Both) && translation.x != 0. && translation.y != 0. { - overlay_context.line(quad[1], quad[2], None, None); - overlay_context.line(quad[3], quad[2], None, None); - } - } - TransformOperation::Scaling(scale) => { - let scale = scale.to_f64(self.increments); - let text = format!("{}x", format_rounded(scale, 3)); - let pivot = document_to_viewport.transform_point2(self.local_pivot); - let start_mouse = document_to_viewport.transform_point2(self.local_mouse_start); - let local_edge = start_mouse - pivot; - let local_edge = project_edge_to_quad(local_edge, &self.layer_bounding_box, self.local, axis_constraint); - let boundary_point = pivot + local_edge * scale.min(1.); - let end_point = pivot + local_edge * scale.max(1.); - - if scale > 0. { - overlay_context.dashed_line(pivot, boundary_point, None, None, Some(2.), Some(2.), Some(0.5)); - } - overlay_context.line(boundary_point, end_point, None, None); - - let transform = DAffine2::from_translation(boundary_point.midpoint(pivot) + local_edge.perp().normalize_or(DVec2::X) * local_edge.element_product().signum() * 24.); - overlay_context.text(&text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]); - } - TransformOperation::Rotating(rotation) => { - let angle = rotation.to_f64(self.increments); - let pivot = document_to_viewport.transform_point2(self.local_pivot); - let start_mouse = document_to_viewport.transform_point2(self.local_mouse_start); - let offset_angle = if self.grs_pen_handle { - self.handle - self.last_point - } else if using_path_tool { - start_mouse - pivot - } else { - self.layer_bounding_box.top_right() - self.layer_bounding_box.top_right() - }; - let tilt_offset = document.document_ptz.unmodified_tilt(); - let offset_angle = offset_angle.to_angle() + tilt_offset; - let width = viewport_box.max_element(); - let radius = start_mouse.distance(pivot); - let arc_radius = ANGLE_MEASURE_RADIUS_FACTOR * width; - let radius = radius.clamp(ARC_MEASURE_RADIUS_FACTOR_RANGE.0 * width, ARC_MEASURE_RADIUS_FACTOR_RANGE.1 * width); - let angle_in_degrees = angle.to_degrees(); - let display_angle = if angle_in_degrees.is_sign_positive() { - angle_in_degrees - (angle_in_degrees / 360.).floor() * 360. - } else if angle_in_degrees.is_sign_negative() { - angle_in_degrees - ((angle_in_degrees / 360.).floor() + 1.) * 360. - } else { - angle_in_degrees - }; - let text = format!("{}°", format_rounded(display_angle, 2)); - let text_texture_width = overlay_context.get_width(&text) / 2.; - let text_texture_height = 12.; - let text_angle_on_unit_circle = DVec2::from_angle((angle % TAU) / 2. + offset_angle); - let text_texture_position = DVec2::new( - (arc_radius + 4. + text_texture_width) * text_angle_on_unit_circle.x, - (arc_radius + text_texture_height) * text_angle_on_unit_circle.y, - ); - let transform = DAffine2::from_translation(text_texture_position + pivot); - overlay_context.draw_angle(pivot, radius, arc_radius, offset_angle, angle); - overlay_context.text(&text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]); - } + self.layer_bounding_box.top_right() - self.layer_bounding_box.top_right() + }; + let tilt_offset = document.document_ptz.unmodified_tilt(); + let offset_angle = offset_angle.to_angle() + tilt_offset; + let width = viewport_box.max_element(); + let radius = start_mouse.distance(pivot); + let arc_radius = ANGLE_MEASURE_RADIUS_FACTOR * width; + let radius = radius.clamp(ARC_MEASURE_RADIUS_FACTOR_RANGE.0 * width, ARC_MEASURE_RADIUS_FACTOR_RANGE.1 * width); + let angle_in_degrees = angle.to_degrees(); + let display_angle = if angle_in_degrees.is_sign_positive() { + angle_in_degrees - (angle_in_degrees / 360.).floor() * 360. + } else if angle_in_degrees.is_sign_negative() { + angle_in_degrees - ((angle_in_degrees / 360.).floor() + 1.) * 360. + } else { + angle_in_degrees + }; + let text = format!("{}°", format_rounded(display_angle, 2)); + let text_texture_width = overlay_context.get_width(&text) / 2.; + let text_texture_height = 12.; + let text_angle_on_unit_circle = DVec2::from_angle((angle % TAU) / 2. + offset_angle); + let text_texture_position = DVec2::new( + (arc_radius + 4. + text_texture_width) * text_angle_on_unit_circle.x, + (arc_radius + text_texture_height) * text_angle_on_unit_circle.y, + ); + let transform = DAffine2::from_translation(text_texture_position + pivot); + overlay_context.draw_angle(pivot, radius, arc_radius, offset_angle, angle); + overlay_context.text(&text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]); } } } @@ -364,6 +411,8 @@ impl MessageHandler> for TransformLayer responses.add(NodeGraphMessage::RunDocumentGraph); } + responses.add(SelectToolMessage::PivotShift { offset: None, flush: true }); + if final_transform { responses.add(OverlaysMessage::RemoveProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); } @@ -487,6 +536,7 @@ impl MessageHandler> for TransformLayer responses.add(ToolMessage::UpdateHints); } + responses.add(SelectToolMessage::PivotShift { offset: None, flush: false }); responses.add(OverlaysMessage::RemoveProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); } TransformLayerMessage::ConstrainX => { @@ -694,6 +744,9 @@ impl MessageHandler> for TransformLayer self.initial_transform, ) } + TransformLayerMessage::SetPivotGizmo { pivot_gizmo } => { + self.pivot_gizmo = pivot_gizmo; + } } } diff --git a/frontend/src/components/widgets/inputs/ReferencePointInput.svelte b/frontend/src/components/widgets/inputs/ReferencePointInput.svelte index 14531e48..fe1839d0 100644 --- a/frontend/src/components/widgets/inputs/ReferencePointInput.svelte +++ b/frontend/src/components/widgets/inputs/ReferencePointInput.svelte @@ -7,13 +7,14 @@ export let value: string; export let disabled = false; + export let tooltip: string | undefined = undefined; function setValue(newValue: ReferencePoint) { dispatch("value", newValue); } -
+
diff --git a/frontend/src/messages.ts b/frontend/src/messages.ts index 53cd2a26..28b777f8 100644 --- a/frontend/src/messages.ts +++ b/frontend/src/messages.ts @@ -1340,6 +1340,9 @@ export class ReferencePointInput extends WidgetProps { value!: ReferencePoint; disabled!: boolean; + + @Transform(({ value }: { value: string }) => value || undefined) + tooltip!: string | undefined; } // WIDGET diff --git a/node-graph/gcore/src/transform_nodes.rs b/node-graph/gcore/src/transform_nodes.rs index 1c28a308..4cde6a74 100644 --- a/node-graph/gcore/src/transform_nodes.rs +++ b/node-graph/gcore/src/transform_nodes.rs @@ -20,7 +20,6 @@ async fn transform( rotate: f64, scale: DVec2, skew: DVec2, - _pivot: DVec2, ) -> Instances { let matrix = DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., skew.y, skew.x, 1., 0., 0.]); diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index 118c2fbf..b3b47e48 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -352,8 +352,7 @@ async fn copy_to_points( let transform = DAffine2::from_scale_angle_translation(DVec2::splat(scale), rotation, translation); for mut instance in instance.instance_ref_iter().map(|instance| instance.to_instance_cloned()) { - let local_matrix = DAffine2::from_mat2(instance.transform.matrix2); - instance.transform = transform * local_matrix; + instance.transform = transform * instance.transform; result_table.push(instance); }