From 214d2b5d4f10d58c65593fec93fce305e5d7c4fc Mon Sep 17 00:00:00 2001 From: kud1ing Date: Sun, 19 Dec 2021 21:17:02 +0100 Subject: [PATCH 01/41] Changlog: mention `menu::menu(ui, ...)` => `ui.menu_button(...)` (#956) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb2e98a6..fcee919a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * Replace `scroll_delta` and `zoom_delta` in `RawInput` with `Event::Scroll` and `Event::Zoom`. * Unifiy the four `Memory` data buckets (`data`, `data_temp`, `id_data` and `id_data_temp`) into a single `Memory::data`, with a new interface ([#836](https://github.com/emilk/egui/pull/836)). * Replace `Ui::__test` with `egui::__run_test_ui` ([#872](https://github.com/emilk/egui/pull/872)). +* `menu::menu(ui, ...)` is now `ui.menu_button(...)` ([#543](https://github.com/emilk/egui/pull/543)) ### Fixed 🐛 * Fix `ComboBox` and other popups getting clipped to parent window ([#885](https://github.com/emilk/egui/pull/885)). From dd99f68e825b6d1b57854468b302071a89352859 Mon Sep 17 00:00:00 2001 From: Jay Oster Date: Mon, 20 Dec 2021 13:44:53 -0800 Subject: [PATCH 02/41] Update winit to 0.26 (#930) Also update glium, glutin and rfd --- Cargo.lock | 718 ++++++++++++++++++-------------------- eframe/Cargo.toml | 2 +- egui-winit/CHANGELOG.md | 1 + egui-winit/Cargo.toml | 2 +- egui_demo_app/src/main.rs | 2 +- egui_glium/CHANGELOG.md | 1 + egui_glium/Cargo.toml | 2 +- egui_glow/CHANGELOG.md | 1 + egui_glow/Cargo.toml | 2 +- 9 files changed, 351 insertions(+), 380 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3c897f9..0e5a8a4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,25 +4,25 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0ac006645f86f20f6c6fa4dcaef920bf803df819123626f9440e35835e7d80" +checksum = "20b228f2c198f98d4337ceb560333fb12cbb2f4948a953bf8c57d09deb219603" dependencies = [ "ab_glyph_rasterizer", - "owned_ttf_parser 0.12.1", + "owned_ttf_parser", ] [[package]] name = "ab_glyph_rasterizer" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" +checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" [[package]] name = "addr2line" -version = "0.15.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -53,26 +53,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] -[[package]] -name = "andrew" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" -dependencies = [ - "bitflags", - "rusttype", - "walkdir", - "xdg", - "xml-rs", -] - [[package]] name = "android_glue" version = "0.2.3" @@ -81,18 +68,18 @@ checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ "winapi", ] [[package]] name = "anyhow" -version = "1.0.44" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "atk-sys" @@ -131,9 +118,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.59" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ "addr2line", "cc", @@ -161,9 +148,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.59.1" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" dependencies = [ "bitflags", "cexpr", @@ -203,18 +190,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitvec" -version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block" version = "0.1.6" @@ -223,9 +198,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bstr" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -283,12 +258,12 @@ dependencies = [ [[package]] name = "calloop" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +checksum = "42dcfbd723aa6eff9f024cfd5ad08b11144d79b2d8d37b4a31a006ceab255c77" dependencies = [ "log", - "nix 0.18.0", + "nix", ] [[package]] @@ -302,9 +277,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cesu8" @@ -314,11 +289,11 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cexpr" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 6.2.1", + "nom", ] [[package]] @@ -361,7 +336,7 @@ dependencies = [ "libc", "num-integer", "num-traits", - "time", + "time 0.1.43", "wasm-bindgen", "winapi", ] @@ -380,20 +355,20 @@ checksum = "5d83feae28854d73f33659f9018546157422ddf5b84264ce171a766d8547d77b" [[package]] name = "clang-sys" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10612c0ec0e0a1ff0e97980647cb058a6e7aedb913d01d009c406b8b7d0b26ee" +checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" dependencies = [ "glob", "libc", - "libloading 0.7.1", + "libloading", ] [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", @@ -424,7 +399,7 @@ dependencies = [ "block", "cocoa-foundation", "core-foundation 0.9.2", - "core-graphics 0.22.2", + "core-graphics 0.22.3", "foreign-types", "libc", "objc", @@ -453,9 +428,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "combine" -version = "4.6.1" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a909e4d93292cd8e9c42e189f61681eff9d67b6541f96b8a1a737f23737bd001" +checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5" dependencies = [ "bytes", "memchr", @@ -527,9 +502,9 @@ dependencies = [ [[package]] name = "core-graphics" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags", "core-foundation 0.9.2", @@ -565,9 +540,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ "cfg-if 1.0.0", ] @@ -608,20 +583,6 @@ dependencies = [ "itertools", ] -[[package]] -name = "crossbeam" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - [[package]] name = "crossbeam-channel" version = "0.5.1" @@ -656,16 +617,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.5" @@ -684,7 +635,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -698,14 +649,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + [[package]] name = "darling" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.10.2", + "darling_macro 0.10.2", +] + +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core 0.13.1", + "darling_macro 0.13.1", ] [[package]] @@ -722,13 +689,38 @@ dependencies = [ "syn", ] +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + [[package]] name = "darling_macro" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ - "darling_core", + "darling_core 0.10.2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core 0.13.1", "quote", "syn", ] @@ -764,26 +756,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -801,22 +773,13 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" -[[package]] -name = "dlib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" -dependencies = [ - "libloading 0.6.7", -] - [[package]] name = "dlib" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" dependencies = [ - "libloading 0.7.1", + "libloading", ] [[package]] @@ -1007,9 +970,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", @@ -1096,12 +1059,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "gcc" version = "0.3.55" @@ -1151,9 +1108,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.24.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "gio-sys" @@ -1191,9 +1148,9 @@ dependencies = [ [[package]] name = "glium" -version = "0.30.2" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "506a2aa1564891d447ae5d1ba37519a8efd6d01ea3e7952da81aa30430c90007" +checksum = "0ab4f09b43d8ee427a700cb9ed3b20e0e858d62a509edded1a98ca5707d68e19" dependencies = [ "backtrace", "fnv", @@ -1213,9 +1170,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "glow" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f04649123493bc2483cbef4daddb45d40bbdae5adb221a63a23efdb0cc99520" +checksum = "4c07210904884e8e2e6a2d7f36f39040a9cefe3b379b721969b5275e9f5b464a" dependencies = [ "js-sys", "slotmap", @@ -1225,9 +1182,9 @@ dependencies = [ [[package]] name = "glutin" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762d6cd2e1b855d99668ebe591cc9058659d85ac39a9a2078000eb122ddba8f0" +checksum = "00ea9dbe544bc8a657c4c4a798c2d16cd01b549820e47657297549d28371f6d2" dependencies = [ "android_glue", "cgl", @@ -1239,7 +1196,7 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "lazy_static", - "libloading 0.7.1", + "libloading", "log", "objc", "osmesa-sys", @@ -1410,13 +1367,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -1427,6 +1387,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jni" version = "0.19.0" @@ -1488,25 +1454,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.104" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" +checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" dependencies = [ "cfg-if 1.0.0", "winapi", @@ -1562,42 +1518,33 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" -version = "0.1.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" -dependencies = [ - "libc", -] - -[[package]] -name = "memmap2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" +checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] [[package]] name = "minimal-lexical" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" @@ -1626,9 +1573,9 @@ checksum = "162e591484b4b8fe9e1ca16ebf07ab584fdc3334508d76a788cd54d89cfc20dc" [[package]] name = "mio" -version = "0.7.14" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", "log", @@ -1637,18 +1584,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "mio-misc" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ddf05411bb159cdb5801bb10002afb66cb4572be656044315e363460ce69dc2" -dependencies = [ - "crossbeam", - "crossbeam-queue", - "log", - "mio", -] - [[package]] name = "miow" version = "0.3.7" @@ -1670,6 +1605,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ndk" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + [[package]] name = "ndk-glue" version = "0.3.0" @@ -1679,8 +1627,22 @@ dependencies = [ "lazy_static", "libc", "log", - "ndk", - "ndk-macro", + "ndk 0.3.0", + "ndk-macro 0.2.0", + "ndk-sys", +] + +[[package]] +name = "ndk-glue" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc291b8de2095cba8dab7cf381bf582ff4c17a09acf854c32e46545b08085d28" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk 0.5.0", + "ndk-macro 0.3.0", "ndk-sys", ] @@ -1690,7 +1652,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" dependencies = [ - "darling", + "darling 0.10.2", "proc-macro-crate 0.1.5", "proc-macro2", "quote", @@ -1698,33 +1660,35 @@ dependencies = [ ] [[package]] -name = "ndk-sys" -version = "0.2.1" +name = "ndk-macro" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" - -[[package]] -name = "nix" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", + "darling 0.13.1", + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "nix" -version = "0.20.0" +name = "ndk-sys" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" + +[[package]] +name = "nix" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", + "memoffset", ] [[package]] @@ -1735,21 +1699,9 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "6.2.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" -dependencies = [ - "bitvec", - "funty", - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ "memchr", "minimal-lexical", @@ -1879,15 +1831,18 @@ dependencies = [ [[package]] name = "object" -version = "0.24.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "oorandom" @@ -1906,20 +1861,11 @@ dependencies = [ [[package]] name = "owned_ttf_parser" -version = "0.6.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +checksum = "65ee3f72636e6f164cc41c9f9057f4e58c4e13507699ea7f5e5242b64b8198ee" dependencies = [ - "ttf-parser 0.6.2", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60ac8dda2e5cc09bf6480e3b3feff9783db251710c922ae9369a429c51efdeb0" -dependencies = [ - "ttf-parser 0.12.3", + "ttf-parser", ] [[package]] @@ -1973,21 +1919,21 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pkg-config" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e2fcbb64ecbe64c8e040a386c3104d384583af58b956d870aaaf229df6e66d" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "plist" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38d026d73eeaf2ade76309d0c65db5a35ecf649e3cec428db316243ea9d6711" +checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" dependencies = [ "base64", - "chrono", "indexmap", "line-wrap", "serde", + "time 0.3.5", "xml-rs", ] @@ -2052,13 +1998,22 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ "unicode-xid", ] +[[package]] +name = "quick-xml" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.10" @@ -2068,19 +2023,13 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "raw-window-handle" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" dependencies = [ - "libc", + "cty", ] [[package]] @@ -2129,9 +2078,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.6" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", @@ -2152,9 +2101,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rfd" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acac5884e3a23b02ebd6ce50fd2729732cdbdb16ea944fbbfbfa638a67992aa" +checksum = "df102be679ae47c269a6393851bc2cff8760173e7e67a2f1e8110d6578b7c555" dependencies = [ "block", "dispatch", @@ -2170,7 +2119,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winapi", + "windows 0.28.0", ] [[package]] @@ -2222,9 +2171,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5ac6078ca424dc1d3ae2328526a76787fecc7f8011f520e3276730e711fc95" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ "log", "ring", @@ -2232,21 +2181,11 @@ dependencies = [ "webpki", ] -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser 0.6.0", -] - [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "safemem" @@ -2293,9 +2232,9 @@ checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "serde" -version = "1.0.130" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" dependencies = [ "serde_derive", ] @@ -2312,9 +2251,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" dependencies = [ "proc-macro2", "quote", @@ -2323,11 +2262,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -2365,35 +2304,18 @@ checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "smithay-client-toolkit" -version = "0.12.3" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" +checksum = "210cf40de565aaaa085face1d860b17f6aee9f76f9d2816307ea2cc45eeb64f3" dependencies = [ - "andrew", "bitflags", "calloop", - "dlib 0.4.2", + "dlib", "lazy_static", "log", - "memmap2 0.1.0", - "nix 0.18.0", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-client-toolkit" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec783683499a2cfc85b6df3d04f83b1907b5cbd98a1aed44667dbdf1eac4e64c" -dependencies = [ - "bitflags", - "dlib 0.5.0", - "lazy_static", - "log", - "memmap2 0.2.3", - "nix 0.20.0", + "memmap2", + "nix", + "pkg-config", "wayland-client", "wayland-cursor", "wayland-protocols", @@ -2401,11 +2323,11 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "986c5b4a7bd4f50d4c51f81f844745535cb488360f9cf63293780b109b9295f3" +checksum = "610b551bd25378bfd2b8e7a0fcbd83d427e8f2f6a40c47ae0f70688e9949dd55" dependencies = [ - "smithay-client-toolkit 0.14.0", + "smithay-client-toolkit", "wayland-client", ] @@ -2447,6 +2369,12 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.21.0" @@ -2467,9 +2395,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", @@ -2522,12 +2450,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36ae8932fcfea38b7d3883ae2ab357b0d57a02caaa18ebb4f5ece08beaec4aa0" -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "termcolor" version = "1.1.2" @@ -2576,6 +2498,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" +dependencies = [ + "itoa 0.4.8", + "libc", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -2588,9 +2520,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -2612,15 +2544,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.6.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" - -[[package]] -name = "ttf-parser" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" +checksum = "76dacc724328b3d5e2ed67f9e30cdb56893a34ab239032502cc8f19f8dae4bbc" [[package]] name = "tts" @@ -2634,13 +2560,13 @@ dependencies = [ "lazy_static", "libc", "log", - "ndk-glue", + "ndk-glue 0.3.0", "objc", "speech-dispatcher", "thiserror", "wasm-bindgen", "web-sys", - "windows", + "windows 0.9.1", ] [[package]] @@ -2690,9 +2616,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd912a3d096959150c4d71ac752e13f1683085922658c205b89b40fe8ebe07f" +checksum = "c5c448dcb78ec38c7d59ec61f87f70a98ea19171e06c139357e012ee226fec90" dependencies = [ "base64", "chunked_transfer", @@ -2819,14 +2745,14 @@ checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "wayland-client" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" +checksum = "9108ec1c37f4774d0c2937ba1a6c23d1786b2152c4a13bd9fdb20e42d16e8841" dependencies = [ "bitflags", "downcast-rs", "libc", - "nix 0.20.0", + "nix", "scoped-tls", "wayland-commons", "wayland-scanner", @@ -2835,11 +2761,11 @@ dependencies = [ [[package]] name = "wayland-commons" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" +checksum = "265ef51b3b3e5c9ef098f10425c39624663f459c3821dcaacc4748be975f1beb" dependencies = [ - "nix 0.20.0", + "nix", "once_cell", "smallvec", "wayland-sys", @@ -2847,20 +2773,20 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" +checksum = "6c19bb6628daf4097e58b7911481e8371e13318d5a60894779901bd3267407a7" dependencies = [ - "nix 0.20.0", + "nix", "wayland-client", "xcursor", ] [[package]] name = "wayland-egl" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ba1ab1e18756b23982d36f08856d521d7df45015f404a2d7c4f0b2d2f66956" +checksum = "accf27d1e5e1f64ba30b683fd926c2c916cc1014bea3376fb258e80abf622e40" dependencies = [ "wayland-client", "wayland-sys", @@ -2868,9 +2794,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" +checksum = "7b3b6f1dc0193072ef4eadcb144da30d58c1f2895516c063804d213310703c8e" dependencies = [ "bitflags", "wayland-client", @@ -2880,9 +2806,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" +checksum = "eaaf2bc85e7b9143159af96bd23d954a5abe391c4376db712320643280fdc6f4" dependencies = [ "proc-macro2", "quote", @@ -2891,11 +2817,11 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.28.6" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +checksum = "ba9e06acb775b3007f8d3094438306979e572d1d3b844d7a71557a84b055d959" dependencies = [ - "dlib 0.5.0", + "dlib", "lazy_static", "pkg-config", ] @@ -2942,10 +2868,12 @@ dependencies = [ [[package]] name = "which" -version = "3.1.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" dependencies = [ + "either", + "lazy_static", "libc", ] @@ -2997,6 +2925,34 @@ dependencies = [ "windows_macros", ] +[[package]] +name = "windows" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054d31561409bbf7e1ee4a4f0a1233ac2bb79cfadf2a398438a04d8dda69225f" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" + [[package]] name = "windows_gen" version = "0.9.1" @@ -3006,6 +2962,18 @@ dependencies = [ "syn", ] +[[package]] +name = "windows_i686_gnu" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" + +[[package]] +name = "windows_i686_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" + [[package]] name = "windows_macros" version = "0.9.1" @@ -3017,15 +2985,28 @@ dependencies = [ ] [[package]] -name = "winit" -version = "0.25.0" +name = "windows_x86_64_gnu" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79610794594d5e86be473ef7763f604f2159cbac8c94debd00df8fb41e86c2f8" +checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" + +[[package]] +name = "winit" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70466a5f4825cc88c92963591b06dbc255420bffe19d847bfcda475e82d079c0" dependencies = [ "bitflags", + "block", "cocoa", "core-foundation 0.9.2", - "core-graphics 0.22.2", + "core-graphics 0.22.3", "core-video-sys", "dispatch", "instant", @@ -3033,32 +3014,27 @@ dependencies = [ "libc", "log", "mio", - "mio-misc", - "ndk", - "ndk-glue", + "ndk 0.5.0", + "ndk-glue 0.5.0", "ndk-sys", "objc", "parking_lot", "percent-encoding", "raw-window-handle", - "scopeguard", - "smithay-client-toolkit 0.12.3", + "smithay-client-toolkit", + "wasm-bindgen", "wayland-client", + "wayland-protocols", + "web-sys", "winapi", "x11-dl", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "x11-clipboard" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b397ace6e980510de59a4fe3d4c758dffab231d6d747ce9fa1aba6b6035d5f32" +checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" dependencies = [ "xcb", ] @@ -3076,12 +3052,13 @@ dependencies = [ [[package]] name = "xcb" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62056f63138b39116f82a540c983cc11f1c90cd70b3d492a70c25eaa50bd22a6" +checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" dependencies = [ "libc", "log", + "quick-xml", ] [[package]] @@ -3090,16 +3067,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" dependencies = [ - "nom 7.0.0", -] - -[[package]] -name = "xdg" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a23fe958c70412687039c86f578938b4a0bb50ec788e96bce4d6ab00ddd5803" -dependencies = [ - "dirs", + "nom", ] [[package]] diff --git a/eframe/Cargo.toml b/eframe/Cargo.toml index 66185b3b..cfb5d552 100644 --- a/eframe/Cargo.toml +++ b/eframe/Cargo.toml @@ -38,7 +38,7 @@ egui_web = { version = "0.15.0", path = "../egui_web", default-features = false [dev-dependencies] image = { version = "0.23", default-features = false, features = ["png"] } -rfd = "0.5.0" +rfd = "0.6" [features] default = ["default_fonts", "egui_glium"] diff --git a/egui-winit/CHANGELOG.md b/egui-winit/CHANGELOG.md index 3c1a56b7..757a92cb 100644 --- a/egui-winit/CHANGELOG.md +++ b/egui-winit/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the `egui-winit` integration will be noted in this file. * Add helper `EpiIntegration` ([#871](https://github.com/emilk/egui/pull/871)). * Fix shift key getting stuck enabled with the X11 option `shift:both_capslock` enabled ([#849](https://github.com/emilk/egui/pull/849)). * Remove `State::is_quit_event` and `State::is_quit_shortcut` ([#881](https://github.com/emilk/egui/pull/881)). +* Updated `winit` to 0.26 ([#930](https://github.com/emilk/egui/pull/930)). ## 0.15.0 - 2021-10-24 First stand-alone release. Previously part of `egui_glium`. diff --git a/egui-winit/Cargo.toml b/egui-winit/Cargo.toml index ecfe7166..761e08af 100644 --- a/egui-winit/Cargo.toml +++ b/egui-winit/Cargo.toml @@ -22,7 +22,7 @@ all-features = true [dependencies] egui = { version = "0.15.0", path = "../egui", default-features = false, features = ["single_threaded"] } -winit = "0.25" +winit = "0.26" epi = { version = "0.15.0", path = "../epi", optional = true } diff --git a/egui_demo_app/src/main.rs b/egui_demo_app/src/main.rs index a0295142..eae34c46 100644 --- a/egui_demo_app/src/main.rs +++ b/egui_demo_app/src/main.rs @@ -8,7 +8,7 @@ fn main() { let app = egui_demo_lib::WrapApp::default(); let options = eframe::NativeOptions { // Let's show off that we support transparent windows - transparent: true, + // transparent: true, drag_and_drop_support: true, ..Default::default() }; diff --git a/egui_glium/CHANGELOG.md b/egui_glium/CHANGELOG.md index 698be31d..3ca59c04 100644 --- a/egui_glium/CHANGELOG.md +++ b/egui_glium/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to the `egui_glium` integration will be noted in this file. ## Unreleased * Simplify `EguiGlium` interface ([#871](https://github.com/emilk/egui/pull/871)). * Remove `EguiGlium::is_quit_event` ([#881](https://github.com/emilk/egui/pull/881)). +* Updated `glium` to 0.31 ([#930](https://github.com/emilk/egui/pull/930)). ## 0.15.0 - 2021-10-24 diff --git a/egui_glium/Cargo.toml b/egui_glium/Cargo.toml index 60fb0dba..15b45cbc 100644 --- a/egui_glium/Cargo.toml +++ b/egui_glium/Cargo.toml @@ -26,7 +26,7 @@ egui = { version = "0.15.0", path = "../egui", default-features = false, feature egui-winit = { version = "0.15.0", path = "../egui-winit", default-features = false, features = ["epi"] } epi = { version = "0.15.0", path = "../epi", optional = true } -glium = "0.30" +glium = "0.31" [dev-dependencies] image = { version = "0.23", default-features = false, features = ["png"] } diff --git a/egui_glow/CHANGELOG.md b/egui_glow/CHANGELOG.md index 4a0b85dd..21b5b4e8 100644 --- a/egui_glow/CHANGELOG.md +++ b/egui_glow/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the `egui_glow` integration will be noted in this file. * Make winit/glutin an optional dependency ([#868](https://github.com/emilk/egui/pull/868)). * Simplify `EguiGlow` interface ([#871](https://github.com/emilk/egui/pull/871)). * Remove `EguiGlow::is_quit_event` ([#881](https://github.com/emilk/egui/pull/881)). +* Updated `glutin` to 0.28 ([#930](https://github.com/emilk/egui/pull/930)). ## 0.15.0 - 2021-10-24 diff --git a/egui_glow/Cargo.toml b/egui_glow/Cargo.toml index 4994b570..ac7acc3f 100644 --- a/egui_glow/Cargo.toml +++ b/egui_glow/Cargo.toml @@ -30,7 +30,7 @@ memoffset = "0.6" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] egui-winit = { version = "0.15.0", path = "../egui-winit", default-features = false, features = ["epi"], optional = true } -glutin = { version = "0.27.0", optional = true } +glutin = { version = "0.28.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = { version = "0.3", features=["console"] } From c69fe941afdea5ef6f3f84ed063554500b6262e8 Mon Sep 17 00:00:00 2001 From: Aevyrie Date: Mon, 20 Dec 2021 14:00:38 -0800 Subject: [PATCH 03/41] Reverse horizontal scrolling on windows (#966) * Reverse horizontal scrolling on windows * Add link to winit issue Co-authored-by: Emil Ernerfeldt --- egui-winit/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index 7232a14b..4bcc3a42 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -458,6 +458,9 @@ impl State { // https://github.com/rust-windowing/winit/issues/1695 being closed delta.x *= -1.0; } + if cfg!(target_os = "windows") { + delta.x *= -1.0; // until https://github.com/rust-windowing/winit/pull/2101 is merged + } if self.egui_input.modifiers.ctrl || self.egui_input.modifiers.command { // Treat as zoom instead: From d05379902cbfe78a9e0b9e3a6d1888f0a9562863 Mon Sep 17 00:00:00 2001 From: Victor Sergienko Date: Sat, 25 Dec 2021 07:29:11 -0800 Subject: [PATCH 04/41] #972: ScrollArea::stick_to_bottom() has no effect if ScrollArea is not initialized. (#973) --- egui/src/containers/scroll_area.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/egui/src/containers/scroll_area.rs b/egui/src/containers/scroll_area.rs index e6a70530..6bfc942a 100644 --- a/egui/src/containers/scroll_area.rs +++ b/egui/src/containers/scroll_area.rs @@ -733,13 +733,16 @@ impl Prepared { state.offset = state.offset.min(available_offset); state.offset = state.offset.max(Vec2::ZERO); - // Is scroll handle at end of content? If so enter sticky mode. + // Is scroll handle at end of content, or is there no scrollbar + // yet (not enough content), but sticking is requested? If so, enter sticky mode. // Only has an effect if stick_to_end is enabled but we save in // state anyway so that entering sticky mode at an arbitrary time // has appropriate effect. state.scroll_stuck_to_end = [ - state.offset[0] == available_offset[0], - state.offset[1] == available_offset[1], + (state.offset[0] == available_offset[0]) + || (self.stick_to_end[0] && available_offset[0] < 0.), + (state.offset[1] == available_offset[1]) + || (self.stick_to_end[1] && available_offset[1] < 0.), ]; state.show_scroll = show_scroll_this_frame; From 26885c20d0c40786b9bf8d24986c83fe8ca76e08 Mon Sep 17 00:00:00 2001 From: "Ivgeni \"Iv\" Segal" Date: Sat, 25 Dec 2021 07:29:29 -0800 Subject: [PATCH 05/41] Add ability to customize the display of hover plot labels (#934) * Add ability to customize the display of hover plot labels * Ergonomic enhancement to plot hover label function * Use Option instead of empty string for custom hover label name arg * Revert "Use Option instead of empty string for custom hover label name arg" This reverts commit 296caebb74b7ee993fbff97187791180d16708af. Co-authored-by: Ivgeni Segal --- egui/src/widgets/plot/items/mod.rs | 33 ++++++++++++++++++----- egui/src/widgets/plot/mod.rs | 42 ++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/egui/src/widgets/plot/items/mod.rs b/egui/src/widgets/plot/items/mod.rs index 30a2be70..87d27f38 100644 --- a/egui/src/widgets/plot/items/mod.rs +++ b/egui/src/widgets/plot/items/mod.rs @@ -7,7 +7,7 @@ use epaint::Mesh; use crate::*; -use super::{PlotBounds, ScreenTransform}; +use super::{CustomLabelFuncRef, PlotBounds, ScreenTransform}; use rect_elem::*; use values::*; @@ -61,7 +61,13 @@ pub(super) trait PlotItem { } } - fn on_hover(&self, elem: ClosestElem, shapes: &mut Vec, plot: &PlotConfig<'_>) { + fn on_hover( + &self, + elem: ClosestElem, + shapes: &mut Vec, + plot: &PlotConfig<'_>, + custom_label_func: &CustomLabelFuncRef, + ) { let points = match self.geometry() { PlotGeometry::Points(points) => points, PlotGeometry::None => { @@ -83,7 +89,7 @@ pub(super) trait PlotItem { let pointer = plot.transform.position_from_value(&value); shapes.push(Shape::circle_filled(pointer, 3.0, line_color)); - rulers_at_value(pointer, value, self.name(), plot, shapes); + rulers_at_value(pointer, value, self.name(), plot, shapes, custom_label_func); } } @@ -1365,7 +1371,13 @@ impl PlotItem for BarChart { find_closest_rect(&self.bars, point, transform) } - fn on_hover(&self, elem: ClosestElem, shapes: &mut Vec, plot: &PlotConfig<'_>) { + fn on_hover( + &self, + elem: ClosestElem, + shapes: &mut Vec, + plot: &PlotConfig<'_>, + _: &CustomLabelFuncRef, + ) { let bar = &self.bars[elem.index]; bar.add_shapes(plot.transform, true, shapes); @@ -1501,7 +1513,13 @@ impl PlotItem for BoxPlot { find_closest_rect(&self.boxes, point, transform) } - fn on_hover(&self, elem: ClosestElem, shapes: &mut Vec, plot: &PlotConfig<'_>) { + fn on_hover( + &self, + elem: ClosestElem, + shapes: &mut Vec, + plot: &PlotConfig<'_>, + _: &CustomLabelFuncRef, + ) { let box_plot = &self.boxes[elem.index]; box_plot.add_shapes(plot.transform, true, shapes); @@ -1619,6 +1637,7 @@ pub(super) fn rulers_at_value( name: &str, plot: &PlotConfig<'_>, shapes: &mut Vec, + custom_label_func: &CustomLabelFuncRef, ) { let line_color = rulers_color(plot.ui); if plot.show_x { @@ -1638,7 +1657,9 @@ pub(super) fn rulers_at_value( let scale = plot.transform.dvalue_dpos(); let x_decimals = ((-scale[0].abs().log10()).ceil().at_least(0.0) as usize).at_most(6); let y_decimals = ((-scale[1].abs().log10()).ceil().at_least(0.0) as usize).at_most(6); - if plot.show_x && plot.show_y { + if let Some(custom_label) = custom_label_func { + custom_label(name, &value) + } else if plot.show_x && plot.show_y { format!( "{}x = {:.*}\ny = {:.*}", prefix, x_decimals, value.x, y_decimals, value.y diff --git a/egui/src/widgets/plot/mod.rs b/egui/src/widgets/plot/mod.rs index b37b0447..3dbf71fd 100644 --- a/egui/src/widgets/plot/mod.rs +++ b/egui/src/widgets/plot/mod.rs @@ -18,6 +18,9 @@ mod items; mod legend; mod transform; +type CustomLabelFunc = dyn Fn(&str, &Value) -> String; +type CustomLabelFuncRef = Option>; + // ---------------------------------------------------------------------------- /// Information about the plot that has to persist between frames. @@ -76,6 +79,7 @@ pub struct Plot { show_x: bool, show_y: bool, + custom_label_func: CustomLabelFuncRef, legend_config: Option, show_background: bool, show_axes: [bool; 2], @@ -102,6 +106,7 @@ impl Plot { show_x: true, show_y: true, + custom_label_func: None, legend_config: None, show_background: true, show_axes: [true; 2], @@ -182,6 +187,35 @@ impl Plot { self } + /// Provide a function to customize the on-hovel label for the x and y axis + /// + /// ``` + /// # egui::__run_test_ui(|ui| { + /// use egui::plot::{Line, Plot, Value, Values}; + /// let sin = (0..1000).map(|i| { + /// let x = i as f64 * 0.01; + /// Value::new(x, x.sin()) + /// }); + /// let line = Line::new(Values::from_values_iter(sin)); + /// Plot::new("my_plot").view_aspect(2.0) + /// .custom_label_func(|name, value| { + /// if !name.is_empty() { + /// format!("{}: {:.*}%", name, 1, value.y).to_string() + /// } else { + /// "".to_string() + /// } + /// }) + /// .show(ui, |plot_ui| plot_ui.line(line)); + /// # }); + /// ``` + pub fn custom_label_func String>( + mut self, + custom_lebel_func: F, + ) -> Self { + self.custom_label_func = Some(Box::new(custom_lebel_func)); + self + } + /// Expand bounds to include the given x value. /// For instance, to always show the y axis, call `plot.include_x(0.0)`. pub fn include_x(mut self, x: impl Into) -> Self { @@ -235,6 +269,7 @@ impl Plot { view_aspect, mut show_x, mut show_y, + custom_label_func, legend_config, show_background, show_axes, @@ -406,6 +441,7 @@ impl Plot { items, show_x, show_y, + custom_label_func, show_axes, transform: transform.clone(), }; @@ -613,6 +649,7 @@ struct PreparedPlot { items: Vec>, show_x: bool, show_y: bool, + custom_label_func: CustomLabelFuncRef, show_axes: [bool; 2], transform: ScreenTransform, } @@ -731,6 +768,7 @@ impl PreparedPlot { transform, show_x, show_y, + custom_label_func, items, .. } = self; @@ -760,10 +798,10 @@ impl PreparedPlot { }; if let Some((item, elem)) = closest { - item.on_hover(elem, shapes, &plot); + item.on_hover(elem, shapes, &plot, custom_label_func); } else { let value = transform.value_from_position(pointer); - items::rulers_at_value(pointer, value, "", &plot, shapes); + items::rulers_at_value(pointer, value, "", &plot, shapes, custom_label_func); } } } From ee002145117df5be9c8889bfbcf569f3493dec79 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 25 Dec 2021 16:56:24 +0100 Subject: [PATCH 06/41] Add a badge and link to the official discord server Closes https://github.com/emilk/egui/pull/990 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 92cd8f50..13d6ae77 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Build Status](https://github.com/emilk/egui/workflows/CI/badge.svg)](https://github.com/emilk/egui/actions?workflow=CI) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) +[![Discord](https://img.shields.io/discord/900275882684477440?label=egui%20discord)](https://discord.gg/JFcEma9bJq) egui is a simple, fast, and highly portable immediate mode GUI library for Rust. egui runs on the web, natively, and [in your favorite game engine](#integrations) (or will soon). @@ -35,7 +36,7 @@ If you just want to write a GUI application in Rust (for the web or for native), If you want to integrate egui into an existing engine, go to the [Integrations](#integrations) section. -If you have questions, use [Discussions](https://github.com/emilk/egui/discussions). If you want to contribute to egui, please read the [Contributing Guidelines](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) +If you have questions, use [GitHub Discussions](https://github.com/emilk/egui/discussions). There is also [an egui discord server](https://discord.gg/JFcEma9bJq). If you want to contribute to egui, please read the [Contributing Guidelines](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) ## Demo From c60d17b91bb447f1d81343cf8be7809961b03d44 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 25 Dec 2021 19:32:25 +0100 Subject: [PATCH 07/41] Set MSRV to 1.56.0 and use rust edition 2021 (#998) --- .github/workflows/rust.yml | 18 +++++++++--------- CHANGELOG.md | 1 + eframe/Cargo.toml | 3 ++- egui-winit/Cargo.toml | 3 ++- egui-winit/src/epi.rs | 3 +-- egui/Cargo.toml | 3 ++- egui/src/lib.rs | 2 +- egui_demo_app/Cargo.toml | 3 ++- egui_demo_lib/Cargo.toml | 3 ++- egui_glium/Cargo.toml | 3 ++- egui_glow/Cargo.toml | 3 ++- egui_web/Cargo.toml | 3 ++- egui_web/src/backend.rs | 3 +-- emath/Cargo.toml | 3 ++- epaint/Cargo.toml | 3 ++- epaint/src/mesh.rs | 3 --- epi/Cargo.toml | 3 ++- rust-toolchain | 2 +- 18 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2c1f4a1e..96db0602 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: sudo apt-get update && sudo apt-get install libspeechd-dev - uses: actions-rs/cargo@v1 @@ -32,7 +32,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: sudo apt-get update && sudo apt-get install libspeechd-dev - uses: actions-rs/cargo@v1 @@ -48,7 +48,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: rustup target add wasm32-unknown-unknown - uses: actions-rs/cargo@v1 @@ -64,7 +64,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: rustup target add wasm32-unknown-unknown - uses: actions-rs/cargo@v1 @@ -80,7 +80,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: sudo apt-get update && sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libspeechd-dev libxkbcommon-dev libssl-dev libgtk-3-dev # libgtk-3-dev is used by rfd - uses: actions-rs/cargo@v1 @@ -96,7 +96,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 @@ -112,7 +112,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: rustup component add clippy - run: sudo apt-get update && sudo apt-get install libspeechd-dev libgtk-3-dev # libgtk-3-dev is used by rfd @@ -129,7 +129,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: sudo apt-get update && sudo apt-get install libspeechd-dev - run: cargo doc -p emath -p epaint -p egui -p eframe -p epi -p egui_web -p egui-winit -p egui_glium -p egui_glow --lib --no-deps --all-features @@ -142,7 +142,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.54.0 + toolchain: 1.56.0 override: true - run: sudo apt-get update && sudo apt-get install libspeechd-dev - run: rustup target add wasm32-unknown-unknown diff --git a/CHANGELOG.md b/CHANGELOG.md index fcee919a..03b3e3aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * Add `Button::image_and_text` ([#832](https://github.com/emilk/egui/pull/832)). ### Changed 🔧 +* MSRV (Minimum Supported Rust Version) is now `1.56.0`. * `ui.add(Button::new("…").text_color(…))` is now `ui.button(RichText::new("…").color(…))` (same for `Label` )([#855](https://github.com/emilk/egui/pull/855)). * Plots now provide a `show` method that has to be used to add items to and show the plot ([#766](https://github.com/emilk/egui/pull/766)). * Replace `CtxRef::begin_frame` and `end_frame` with `CtxRef::run` ([#872](https://github.com/emilk/egui/pull/872)). diff --git a/eframe/Cargo.toml b/eframe/Cargo.toml index cfb5d552..548a7902 100644 --- a/eframe/Cargo.toml +++ b/eframe/Cargo.toml @@ -3,7 +3,8 @@ name = "eframe" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "egui framework - write GUI apps that compiles to web and/or natively" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/eframe" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/egui-winit/Cargo.toml b/egui-winit/Cargo.toml index 761e08af..4027960f 100644 --- a/egui-winit/Cargo.toml +++ b/egui-winit/Cargo.toml @@ -3,7 +3,8 @@ name = "egui-winit" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Bindings for using egui with winit" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/egui-winit" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/egui-winit/src/epi.rs b/egui-winit/src/epi.rs index a10dcd7a..9daa2f98 100644 --- a/egui-winit/src/epi.rs +++ b/egui-winit/src/epi.rs @@ -292,9 +292,8 @@ impl EpiIntegration { } .build(); - let app = &mut self.app; // TODO: remove when we update MSVR to 1.56 let (egui_output, shapes) = self.egui_ctx.run(raw_input, |egui_ctx| { - app.update(egui_ctx, &mut frame); + self.app.update(egui_ctx, &mut frame); }); let needs_repaint = egui_output.needs_repaint; diff --git a/egui/Cargo.toml b/egui/Cargo.toml index d2091dde..72747052 100644 --- a/egui/Cargo.toml +++ b/egui/Cargo.toml @@ -3,7 +3,8 @@ name = "egui" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Simple, portable immediate mode GUI library for Rust" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui" license = "MIT OR Apache-2.0" readme = "../README.md" diff --git a/egui/src/lib.rs b/egui/src/lib.rs index e35d5c2b..4a9e7eca 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -3,7 +3,7 @@ //! Try the live web demo: . Read more about egui at . //! //! `egui` is in heavy development, with each new version having breaking changes. -//! You need to have rust 1.54.0 or later to use `egui`. +//! You need to have rust 1.56.0 or later to use `egui`. //! //! To quickly get started with egui, you can take a look at [`eframe_template`](https://github.com/emilk/eframe_template) //! which uses [`eframe`](https://docs.rs/eframe). diff --git a/egui_demo_app/Cargo.toml b/egui_demo_app/Cargo.toml index 0694c317..b214a817 100644 --- a/egui_demo_app/Cargo.toml +++ b/egui_demo_app/Cargo.toml @@ -3,7 +3,8 @@ name = "egui_demo_app" version = "0.15.0" authors = ["Emil Ernerfeldt "] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" +rust-version = "1.56" publish = false [lib] diff --git a/egui_demo_lib/Cargo.toml b/egui_demo_lib/Cargo.toml index 75bbef7a..a2e3cf1c 100644 --- a/egui_demo_lib/Cargo.toml +++ b/egui_demo_lib/Cargo.toml @@ -3,7 +3,8 @@ name = "egui_demo_lib" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Example library for egui" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/egui_demo_lib" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/egui_glium/Cargo.toml b/egui_glium/Cargo.toml index 15b45cbc..53a9de6e 100644 --- a/egui_glium/Cargo.toml +++ b/egui_glium/Cargo.toml @@ -3,7 +3,8 @@ name = "egui_glium" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Bindings for using egui natively using the glium library" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/egui_glium" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/egui_glow/Cargo.toml b/egui_glow/Cargo.toml index ac7acc3f..4db2ba1a 100644 --- a/egui_glow/Cargo.toml +++ b/egui_glow/Cargo.toml @@ -3,7 +3,8 @@ name = "egui_glow" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Bindings for using egui natively using the glow library" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/egui_glow" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/egui_web/Cargo.toml b/egui_web/Cargo.toml index da45cc48..4352f554 100644 --- a/egui_web/Cargo.toml +++ b/egui_web/Cargo.toml @@ -4,7 +4,8 @@ version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Bindings for compiling egui code to WASM for a web page" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/egui_web" readme = "README.md" repository = "https://github.com/emilk/egui/tree/master/egui_web" diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index d1118f52..c8c2efe5 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -198,9 +198,8 @@ impl AppRunner { } .build(); - let app = &mut self.app; // TODO: remove when we bump MSRV to 1.56 let (egui_output, shapes) = self.egui_ctx.run(raw_input, |egui_ctx| { - app.update(egui_ctx, &mut frame); + self.app.update(egui_ctx, &mut frame); }); let clipped_meshes = self.egui_ctx.tessellate(shapes); diff --git a/emath/Cargo.toml b/emath/Cargo.toml index ea7e8d8f..90046b08 100644 --- a/emath/Cargo.toml +++ b/emath/Cargo.toml @@ -3,7 +3,8 @@ name = "emath" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Minimal 2D math library for GUI work" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/emath" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/epaint/Cargo.toml b/epaint/Cargo.toml index 7e5d966a..6efb7e0a 100644 --- a/epaint/Cargo.toml +++ b/epaint/Cargo.toml @@ -3,7 +3,8 @@ name = "epaint" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Minimal 2D graphics library for GUI work" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/epaint" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/epaint/src/mesh.rs b/epaint/src/mesh.rs index 6ff3289a..78f1a9fb 100644 --- a/epaint/src/mesh.rs +++ b/epaint/src/mesh.rs @@ -64,7 +64,6 @@ impl Mesh { /// Are all indices within the bounds of the contained vertices? pub fn is_valid(&self) -> bool { - use std::convert::TryFrom; if let Ok(n) = u32::try_from(self.vertices.len()) { self.indices.iter().all(|&i| i < n) } else { @@ -223,7 +222,6 @@ impl Mesh { MAX_SIZE ); - use std::convert::TryFrom; let mesh = Mesh16 { indices: self.indices[span_start..index_cursor] .iter() @@ -267,7 +265,6 @@ pub struct Mesh16 { impl Mesh16 { /// Are all indices within the bounds of the contained vertices? pub fn is_valid(&self) -> bool { - use std::convert::TryFrom; if let Ok(n) = u16::try_from(self.vertices.len()) { self.indices.iter().all(|&i| i < n) } else { diff --git a/epi/Cargo.toml b/epi/Cargo.toml index 062ce2ec..83d0f762 100644 --- a/epi/Cargo.toml +++ b/epi/Cargo.toml @@ -3,7 +3,8 @@ name = "epi" version = "0.15.0" authors = ["Emil Ernerfeldt "] description = "Backend-agnostic interface for writing apps using egui" -edition = "2018" +edition = "2021" +rust-version = "1.56" homepage = "https://github.com/emilk/egui/tree/master/epi" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/rust-toolchain b/rust-toolchain index fd917d1c..7e94f20b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,6 +5,6 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "1.54.0" +channel = "1.56.0" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown" ] From d5efa4bbcad743b3a59244a3929ff0cb2ca5a43b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 26 Dec 2021 09:55:13 +0100 Subject: [PATCH 08/41] 1.56 fix: missing_crate_level_docs -> rusdoc::missing_crate_level_docs --- eframe/src/lib.rs | 7 ++++++- egui-winit/src/lib.rs | 4 ++-- egui/src/lib.rs | 4 ++-- egui_demo_lib/src/lib.rs | 4 ++-- egui_glium/src/lib.rs | 4 ++-- egui_glow/src/lib.rs | 4 ++-- egui_web/src/lib.rs | 2 +- emath/src/lib.rs | 4 ++-- epaint/src/lib.rs | 4 ++-- epi/src/lib.rs | 4 ++-- 10 files changed, 23 insertions(+), 18 deletions(-) diff --git a/eframe/src/lib.rs b/eframe/src/lib.rs index dd9036db..c63386ca 100644 --- a/eframe/src/lib.rs +++ b/eframe/src/lib.rs @@ -55,7 +55,12 @@ // Forbid warnings in release builds: #![cfg_attr(not(debug_assertions), deny(warnings))] #![forbid(unsafe_code)] -#![warn(clippy::all, missing_crate_level_docs, missing_docs, rust_2018_idioms)] +#![warn( + clippy::all, + missing_docs, + rust_2018_idioms, + rustdoc::missing_crate_level_docs +)] #![allow(clippy::needless_doctest_main)] pub use {egui, epi}; diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index 4bcc3a42..473e2d17 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -76,9 +76,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/egui/src/lib.rs b/egui/src/lib.rs index 4a9e7eca..dc9cc561 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -349,9 +349,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/egui_demo_lib/src/lib.rs b/egui_demo_lib/src/lib.rs index 0d7ffb06..c5d4caef 100644 --- a/egui_demo_lib/src/lib.rs +++ b/egui_demo_lib/src/lib.rs @@ -77,9 +77,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/egui_glium/src/lib.rs b/egui_glium/src/lib.rs index 0cbab9b4..c020b372 100644 --- a/egui_glium/src/lib.rs +++ b/egui_glium/src/lib.rs @@ -80,9 +80,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/egui_glow/src/lib.rs b/egui_glow/src/lib.rs index f1daded6..ce1d745d 100644 --- a/egui_glow/src/lib.rs +++ b/egui_glow/src/lib.rs @@ -80,9 +80,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/egui_web/src/lib.rs b/egui_web/src/lib.rs index fa82d838..6815ebb1 100644 --- a/egui_web/src/lib.rs +++ b/egui_web/src/lib.rs @@ -12,7 +12,7 @@ // Forbid warnings in release builds: #![cfg_attr(not(debug_assertions), deny(warnings))] #![forbid(unsafe_code)] -#![warn(clippy::all, missing_crate_level_docs, rust_2018_idioms)] +#![warn(clippy::all, rustdoc::missing_crate_level_docs, rust_2018_idioms)] pub mod backend; #[cfg(feature = "glow")] diff --git a/emath/src/lib.rs b/emath/src/lib.rs index 268cd6b0..efd11c6f 100644 --- a/emath/src/lib.rs +++ b/emath/src/lib.rs @@ -84,9 +84,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/epaint/src/lib.rs b/epaint/src/lib.rs index e4d75ba3..046a911e 100644 --- a/epaint/src/lib.rs +++ b/epaint/src/lib.rs @@ -80,9 +80,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 3cd5b7db..4629c0bb 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -81,9 +81,9 @@ clippy::verbose_file_reads, clippy::zero_sized_map_values, future_incompatible, - missing_crate_level_docs, nonstandard_style, - rust_2018_idioms + rust_2018_idioms, + rustdoc::missing_crate_level_docs )] #![allow(clippy::float_cmp)] #![allow(clippy::manual_range_contains)] From 647e020824401bd499f368427f0ab9ae58365409 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 26 Dec 2021 18:13:29 +0100 Subject: [PATCH 09/41] file_dialogs example: remove macos exemption this got fixed in the latest winit upgrade --- eframe/examples/file_dialog.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/eframe/examples/file_dialog.rs b/eframe/examples/file_dialog.rs index 2de6e3f4..ccc757a1 100644 --- a/eframe/examples/file_dialog.rs +++ b/eframe/examples/file_dialog.rs @@ -15,9 +15,7 @@ impl epi::App for MyApp { egui::CentralPanel::default().show(ctx, |ui| { ui.label("Drag-and-drop files onto the window!"); - if cfg!(target_os = "macos") { - // Awaiting fix of winit bug: https://github.com/rust-windowing/winit/pull/2027 - } else if ui.button("Open file…").clicked() { + if ui.button("Open file…").clicked() { if let Some(path) = rfd::FileDialog::new().pick_file() { self.picked_path = Some(path.display().to_string()); } From b7441eeee7d0ac70c063f008860df183a9374348 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 26 Dec 2021 21:21:28 +0100 Subject: [PATCH 10/41] Make epi::Frame cloneable so you can allocate textures in other threads (#999) Closes https://github.com/emilk/egui/issues/673 Also adds `epi::Image` --- eframe/CHANGELOG.md | 3 + eframe/examples/file_dialog.rs | 2 +- eframe/examples/hello_world.rs | 2 +- eframe/examples/image.rs | 16 +- eframe/src/lib.rs | 4 +- egui-winit/CHANGELOG.md | 1 + egui-winit/src/epi.rs | 108 ++++----- egui_demo_lib/src/apps/color_test.rs | 31 ++- egui_demo_lib/src/apps/demo/app.rs | 4 +- egui_demo_lib/src/apps/fractal_clock.rs | 2 +- egui_demo_lib/src/apps/http_app.rs | 60 ++--- egui_demo_lib/src/backend_panel.rs | 10 +- .../src/easy_mark/easy_mark_editor.rs | 2 +- egui_demo_lib/src/wrap_app.rs | 6 +- egui_glium/CHANGELOG.md | 1 + egui_glium/src/epi_backend.rs | 34 ++- egui_glium/src/painter.rs | 125 +++------- egui_glow/CHANGELOG.md | 1 + egui_glow/src/epi_backend.rs | 17 +- egui_glow/src/lib.rs | 2 +- egui_glow/src/painter.rs | 215 +++++------------- egui_web/CHANGELOG.md | 1 + egui_web/src/backend.rs | 84 ++++--- egui_web/src/glow_wrapping.rs | 17 +- egui_web/src/painter.rs | 4 +- egui_web/src/webgl1.rs | 205 +++++------------ egui_web/src/webgl2.rs | 204 +++++------------ epi/src/lib.rs | 211 ++++++++++++----- 28 files changed, 548 insertions(+), 824 deletions(-) diff --git a/eframe/CHANGELOG.md b/eframe/CHANGELOG.md index a49b7349..97debfae 100644 --- a/eframe/CHANGELOG.md +++ b/eframe/CHANGELOG.md @@ -5,6 +5,9 @@ NOTE: [`egui_web`](egui_web/CHANGELOG.md), [`egui-winit`](egui-winit/CHANGELOG.m ## Unreleased +* `Frame` can now be cloned, saved, and passed to background threads ([#999](https://github.com/emilk/egui/pull/999)). +* Added `Frame::request_repaint` to replace `repaint_signal` ([#999](https://github.com/emilk/egui/pull/999)). +* Added `Frame::alloc_texture/free_texture` to replace `tex_allocator` ([#999](https://github.com/emilk/egui/pull/999)). ## 0.15.0 - 2021-10-24 diff --git a/eframe/examples/file_dialog.rs b/eframe/examples/file_dialog.rs index ccc757a1..d1c0ca79 100644 --- a/eframe/examples/file_dialog.rs +++ b/eframe/examples/file_dialog.rs @@ -11,7 +11,7 @@ impl epi::App for MyApp { "Native file dialogs and drag-and-drop files" } - fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { egui::CentralPanel::default().show(ctx, |ui| { ui.label("Drag-and-drop files onto the window!"); diff --git a/eframe/examples/hello_world.rs b/eframe/examples/hello_world.rs index 4437f1a3..49a07d50 100644 --- a/eframe/examples/hello_world.rs +++ b/eframe/examples/hello_world.rs @@ -19,7 +19,7 @@ impl epi::App for MyApp { "My egui App" } - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { let Self { name, age } = self; egui::CentralPanel::default().show(ctx, |ui| { diff --git a/eframe/examples/image.rs b/eframe/examples/image.rs index ebf5850e..dda07f36 100644 --- a/eframe/examples/image.rs +++ b/eframe/examples/image.rs @@ -10,26 +10,20 @@ impl epi::App for MyApp { "Show an image with eframe/egui" } - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { if self.texture.is_none() { // Load the image: let image_data = include_bytes!("rust-logo-256x256.png"); use image::GenericImageView; let image = image::load_from_memory(image_data).expect("Failed to load image"); let image_buffer = image.to_rgba8(); - let size = (image.width() as usize, image.height() as usize); + let size = [image.width() as usize, image.height() as usize]; let pixels = image_buffer.into_vec(); - assert_eq!(size.0 * size.1 * 4, pixels.len()); - let pixels: Vec<_> = pixels - .chunks_exact(4) - .map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3])) - .collect(); + let image = epi::Image::from_rgba_unmultiplied(size, &pixels); // Allocate a texture: - let texture = frame - .tex_allocator() - .alloc_srgba_premultiplied(size, &pixels); - let size = egui::Vec2::new(size.0 as f32, size.1 as f32); + let texture = frame.alloc_texture(image); + let size = egui::Vec2::new(size[0] as f32, size[1] as f32); self.texture = Some((size, texture)); } diff --git a/eframe/src/lib.rs b/eframe/src/lib.rs index c63386ca..ba4bda87 100644 --- a/eframe/src/lib.rs +++ b/eframe/src/lib.rs @@ -24,7 +24,7 @@ //! "My egui App" //! } //! -//! fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { +//! fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { //! egui::CentralPanel::default().show(ctx, |ui| { //! ui.heading("Hello World!"); //! }); @@ -127,7 +127,7 @@ pub fn start_web(canvas_id: &str, app: Box) -> Result<(), wasm_bin /// "My egui App" /// } /// -/// fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { +/// fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { /// egui::CentralPanel::default().show(ctx, |ui| { /// ui.heading("Hello World!"); /// }); diff --git a/egui-winit/CHANGELOG.md b/egui-winit/CHANGELOG.md index 757a92cb..35d68f32 100644 --- a/egui-winit/CHANGELOG.md +++ b/egui-winit/CHANGELOG.md @@ -9,5 +9,6 @@ All notable changes to the `egui-winit` integration will be noted in this file. * Remove `State::is_quit_event` and `State::is_quit_shortcut` ([#881](https://github.com/emilk/egui/pull/881)). * Updated `winit` to 0.26 ([#930](https://github.com/emilk/egui/pull/930)). + ## 0.15.0 - 2021-10-24 First stand-alone release. Previously part of `egui_glium`. diff --git a/egui-winit/src/epi.rs b/egui-winit/src/epi.rs index 9daa2f98..bbd82d3d 100644 --- a/egui-winit/src/epi.rs +++ b/egui-winit/src/epi.rs @@ -55,9 +55,10 @@ pub fn handle_app_output( window: &winit::window::Window, current_pixels_per_point: f32, app_output: epi::backend::AppOutput, -) { +) -> epi::backend::TexAllocationData { let epi::backend::AppOutput { quit: _, + tex_allocation_data, window_size, window_title, decorated, @@ -85,6 +86,8 @@ pub fn handle_app_output( if drag_window { let _ = window.drag_window(); } + + tex_allocation_data } // ---------------------------------------------------------------------------- @@ -186,13 +189,11 @@ impl Persistence { /// Everything needed to make a winit-based integration for [`epi`]. pub struct EpiIntegration { - integration_name: &'static str, + frame: epi::Frame, persistence: crate::epi::Persistence, - repaint_signal: std::sync::Arc, pub egui_ctx: egui::CtxRef, egui_winit: crate::State, pub app: Box, - latest_frame_time: Option, /// When set, it is time to quit quit: bool, } @@ -201,8 +202,7 @@ impl EpiIntegration { pub fn new( integration_name: &'static str, window: &winit::window::Window, - tex_allocator: &mut dyn epi::TextureAllocator, - repaint_signal: std::sync::Arc, + repaint_signal: std::sync::Arc, persistence: crate::epi::Persistence, app: Box, ) -> Self { @@ -210,54 +210,50 @@ impl EpiIntegration { *egui_ctx.memory() = persistence.load_memory().unwrap_or_default(); - let mut slf = Self { - integration_name, - persistence, + let frame = epi::Frame::new(epi::backend::FrameData { + info: epi::IntegrationInfo { + name: integration_name, + web_info: None, + prefer_dark_mode: None, // TODO: figure out system default + cpu_usage: None, + native_pixels_per_point: Some(crate::native_pixels_per_point(window)), + }, + output: Default::default(), repaint_signal, + }); + + let mut slf = Self { + frame, + persistence, egui_ctx, egui_winit: crate::State::new(window), app, - latest_frame_time: None, quit: false, }; - slf.setup(window, tex_allocator); + slf.setup(window); if slf.app.warm_up_enabled() { - slf.warm_up(window, tex_allocator); + slf.warm_up(window); } slf } - fn setup( - &mut self, - window: &winit::window::Window, - tex_allocator: &mut dyn epi::TextureAllocator, - ) { - let mut app_output = epi::backend::AppOutput::default(); - let mut frame = epi::backend::FrameBuilder { - info: integration_info(self.integration_name, window, None), - tex_allocator, - output: &mut app_output, - repaint_signal: self.repaint_signal.clone(), - } - .build(); + fn setup(&mut self, window: &winit::window::Window) { self.app - .setup(&self.egui_ctx, &mut frame, self.persistence.storage()); - + .setup(&self.egui_ctx, &self.frame, self.persistence.storage()); + let app_output = self.frame.take_app_output(); self.quit |= app_output.quit; - - crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output); + let tex_alloc_data = + crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output); + self.frame.lock().output.tex_allocation_data = tex_alloc_data; // Do it later } - fn warm_up( - &mut self, - window: &winit::window::Window, - tex_allocator: &mut dyn epi::TextureAllocator, - ) { + fn warm_up(&mut self, window: &winit::window::Window) { let saved_memory = self.egui_ctx.memory().clone(); self.egui_ctx.memory().set_everything_is_visible(true); - self.update(window, tex_allocator); + let (_, tex_alloc_data, _) = self.update(window); + self.frame.lock().output.tex_allocation_data = tex_alloc_data; // handle it next frame *self.egui_ctx.memory() = saved_memory; // We don't want to remember that windows were huge. self.egui_ctx.clear_animations(); } @@ -277,37 +273,31 @@ impl EpiIntegration { pub fn update( &mut self, window: &winit::window::Window, - tex_allocator: &mut dyn epi::TextureAllocator, - ) -> (bool, Vec) { + ) -> ( + bool, + epi::backend::TexAllocationData, + Vec, + ) { let frame_start = std::time::Instant::now(); let raw_input = self.egui_winit.take_egui_input(window); - - let mut app_output = epi::backend::AppOutput::default(); - let mut frame = epi::backend::FrameBuilder { - info: integration_info(self.integration_name, window, self.latest_frame_time), - tex_allocator, - output: &mut app_output, - repaint_signal: self.repaint_signal.clone(), - } - .build(); - let (egui_output, shapes) = self.egui_ctx.run(raw_input, |egui_ctx| { - self.app.update(egui_ctx, &mut frame); + self.app.update(egui_ctx, &self.frame); }); let needs_repaint = egui_output.needs_repaint; self.egui_winit .handle_output(window, &self.egui_ctx, egui_output); + let app_output = self.frame.take_app_output(); self.quit |= app_output.quit; - - crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output); + let tex_allocation_data = + crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output); let frame_time = (std::time::Instant::now() - frame_start).as_secs_f64() as f32; - self.latest_frame_time = Some(frame_time); + self.frame.lock().info.cpu_usage = Some(frame_time); - (needs_repaint, shapes) + (needs_repaint, tex_allocation_data, shapes) } pub fn maybe_autosave(&mut self, window: &winit::window::Window) { @@ -321,17 +311,3 @@ impl EpiIntegration { .save(&mut *self.app, &self.egui_ctx, window); } } - -fn integration_info( - integration_name: &'static str, - window: &winit::window::Window, - previous_frame_time: Option, -) -> epi::IntegrationInfo { - epi::IntegrationInfo { - name: integration_name, - web_info: None, - prefer_dark_mode: None, // TODO: figure out system default - cpu_usage: previous_frame_time, - native_pixels_per_point: Some(crate::native_pixels_per_point(window)), - } -} diff --git a/egui_demo_lib/src/apps/color_test.rs b/egui_demo_lib/src/apps/color_test.rs index c1af7255..231e68ca 100644 --- a/egui_demo_lib/src/apps/color_test.rs +++ b/egui_demo_lib/src/apps/color_test.rs @@ -34,7 +34,7 @@ impl epi::App for ColorTest { "🎨 Color test" } - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { egui::CentralPanel::default().show(ctx, |ui| { if frame.is_web() { ui.label( @@ -43,18 +43,14 @@ impl epi::App for ColorTest { ui.separator(); } ScrollArea::both().auto_shrink([false; 2]).show(ui, |ui| { - self.ui(ui, &mut Some(frame.tex_allocator())); + self.ui(ui, Some(frame)); }); }); } } impl ColorTest { - pub fn ui( - &mut self, - ui: &mut Ui, - mut tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>, - ) { + pub fn ui(&mut self, ui: &mut Ui, tex_allocator: Option<&dyn epi::TextureAllocator>) { ui.set_max_width(680.0); ui.vertical_centered(|ui| { @@ -105,10 +101,10 @@ impl ColorTest { self.vertex_gradient(ui, "Ground truth (vertices)", WHITE, &g); self.tex_gradient(ui, tex_allocator, "Ground truth (texture)", WHITE, &g); } - if let Some(tex_allocator) = &mut tex_allocator { + if let Some(tex_allocator) = tex_allocator { ui.horizontal(|ui| { let g = Gradient::one_color(Color32::from(tex_color)); - let tex = self.tex_mngr.get(*tex_allocator, &g); + let tex = self.tex_mngr.get(tex_allocator, &g); let texel_offset = 0.5 / (g.0.len() as f32); let uv = Rect::from_min_max(pos2(texel_offset, 0.0), pos2(1.0 - texel_offset, 1.0)); @@ -167,7 +163,7 @@ impl ColorTest { fn show_gradients( &mut self, ui: &mut Ui, - tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>, + tex_allocator: Option<&dyn epi::TextureAllocator>, bg_fill: Color32, (left, right): (Color32, Color32), ) { @@ -261,7 +257,7 @@ impl ColorTest { fn tex_gradient( &mut self, ui: &mut Ui, - tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>, + tex_allocator: Option<&dyn epi::TextureAllocator>, label: &str, bg_fill: Color32, gradient: &Gradient, @@ -271,7 +267,7 @@ impl ColorTest { } if let Some(tex_allocator) = tex_allocator { ui.horizontal(|ui| { - let tex = self.tex_mngr.get(*tex_allocator, gradient); + let tex = self.tex_mngr.get(tex_allocator, gradient); let texel_offset = 0.5 / (gradient.0.len() as f32); let uv = Rect::from_min_max(pos2(texel_offset, 0.0), pos2(1.0 - texel_offset, 1.0)); ui.add(Image::new(tex, GRADIENT_SIZE).bg_fill(bg_fill).uv(uv)) @@ -391,16 +387,15 @@ impl Gradient { struct TextureManager(HashMap); impl TextureManager { - fn get( - &mut self, - tex_allocator: &mut dyn epi::TextureAllocator, - gradient: &Gradient, - ) -> TextureId { + fn get(&mut self, tex_allocator: &dyn epi::TextureAllocator, gradient: &Gradient) -> TextureId { *self.0.entry(gradient.clone()).or_insert_with(|| { let pixels = gradient.to_pixel_row(); let width = pixels.len(); let height = 1; - tex_allocator.alloc_srgba_premultiplied((width, height), &pixels) + tex_allocator.alloc(epi::Image { + size: [width, height], + pixels, + }) }) } } diff --git a/egui_demo_lib/src/apps/demo/app.rs b/egui_demo_lib/src/apps/demo/app.rs index 7cd2ba38..2ba8e34b 100644 --- a/egui_demo_lib/src/apps/demo/app.rs +++ b/egui_demo_lib/src/apps/demo/app.rs @@ -17,7 +17,7 @@ impl epi::App for DemoApp { fn setup( &mut self, _ctx: &egui::CtxRef, - _frame: &mut epi::Frame<'_>, + _frame: &epi::Frame, _storage: Option<&dyn epi::Storage>, ) { #[cfg(feature = "persistence")] @@ -31,7 +31,7 @@ impl epi::App for DemoApp { epi::set_value(storage, epi::APP_KEY, self); } - fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { self.demo_windows.ui(ctx); } } diff --git a/egui_demo_lib/src/apps/fractal_clock.rs b/egui_demo_lib/src/apps/fractal_clock.rs index 2bf040b9..813ab343 100644 --- a/egui_demo_lib/src/apps/fractal_clock.rs +++ b/egui_demo_lib/src/apps/fractal_clock.rs @@ -37,7 +37,7 @@ impl epi::App for FractalClock { "🕑 Fractal Clock" } - fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { egui::CentralPanel::default() .frame(Frame::dark_canvas(&ctx.style())) .show(ctx, |ui| self.ui(ui, crate::seconds_since_midnight())); diff --git a/egui_demo_lib/src/apps/http_app.rs b/egui_demo_lib/src/apps/http_app.rs index 7605f6de..c7b823d8 100644 --- a/egui_demo_lib/src/apps/http_app.rs +++ b/egui_demo_lib/src/apps/http_app.rs @@ -7,7 +7,7 @@ struct Resource { text: Option, /// If set, the response was an image. - image: Option, + image: Option, /// If set, the response was text with some supported syntax highlighting (e.g. ".rs" or ".md"). colored_text: Option, @@ -17,7 +17,7 @@ impl Resource { fn from_response(ctx: &egui::Context, response: ehttp::Response) -> Self { let content_type = response.content_type().unwrap_or_default(); let image = if content_type.starts_with("image/") { - Image::decode(&response.bytes) + decode_image(&response.bytes) } else { None }; @@ -67,7 +67,7 @@ impl epi::App for HttpApp { "⬇ HTTP" } - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { if let Some(receiver) = &mut self.in_progress { // Are we there yet? if let Ok(result) = receiver.try_recv() { @@ -95,13 +95,13 @@ impl epi::App for HttpApp { if trigger_fetch { let request = ehttp::Request::get(&self.url); - let repaint_signal = frame.repaint_signal(); + let frame = frame.clone(); let (sender, receiver) = std::sync::mpsc::channel(); self.in_progress = Some(receiver); ehttp::fetch(request, move |response| { sender.send(response).ok(); - repaint_signal.request_repaint(); + frame.request_repaint(); }); } @@ -127,7 +127,7 @@ impl epi::App for HttpApp { } } -fn ui_url(ui: &mut egui::Ui, frame: &mut epi::Frame<'_>, url: &mut String) -> bool { +fn ui_url(ui: &mut egui::Ui, frame: &epi::Frame, url: &mut String) -> bool { let mut trigger_fetch = false; ui.horizontal(|ui| { @@ -160,12 +160,7 @@ fn ui_url(ui: &mut egui::Ui, frame: &mut epi::Frame<'_>, url: &mut String) -> bo trigger_fetch } -fn ui_resource( - ui: &mut egui::Ui, - frame: &mut epi::Frame<'_>, - tex_mngr: &mut TexMngr, - resource: &Resource, -) { +fn ui_resource(ui: &mut egui::Ui, frame: &epi::Frame, tex_mngr: &mut TexMngr, resource: &Resource) { let Resource { response, text, @@ -218,7 +213,7 @@ fn ui_resource( if let Some(image) = image { if let Some(texture_id) = tex_mngr.texture(frame, &response.url, image) { - let mut size = egui::Vec2::new(image.size.0 as f32, image.size.1 as f32); + let mut size = egui::Vec2::new(image.size[0] as f32, image.size[1] as f32); size *= (ui.available_width() / size.x).min(1.0); ui.image(texture_id, size); } @@ -304,44 +299,27 @@ struct TexMngr { impl TexMngr { fn texture( &mut self, - frame: &mut epi::Frame<'_>, + frame: &epi::Frame, url: &str, - image: &Image, + image: &epi::Image, ) -> Option { if self.loaded_url != url { if let Some(texture_id) = self.texture_id.take() { - frame.tex_allocator().free(texture_id); + frame.free_texture(texture_id); } - self.texture_id = Some( - frame - .tex_allocator() - .alloc_srgba_premultiplied(image.size, &image.pixels), - ); + self.texture_id = Some(frame.alloc_texture(image.clone())); self.loaded_url = url.to_owned(); } self.texture_id } } -struct Image { - size: (usize, usize), - pixels: Vec, -} - -impl Image { - fn decode(bytes: &[u8]) -> Option { - use image::GenericImageView; - let image = image::load_from_memory(bytes).ok()?; - let image_buffer = image.to_rgba8(); - let size = (image.width() as usize, image.height() as usize); - let pixels = image_buffer.into_vec(); - assert_eq!(size.0 * size.1 * 4, pixels.len()); - let pixels = pixels - .chunks(4) - .map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3])) - .collect(); - - Some(Image { size, pixels }) - } +fn decode_image(bytes: &[u8]) -> Option { + use image::GenericImageView; + let image = image::load_from_memory(bytes).ok()?; + let image_buffer = image.to_rgba8(); + let size = [image.width() as usize, image.height() as usize]; + let pixels = image_buffer.into_vec(); + Some(epi::Image::from_rgba_unmultiplied(size, &pixels)) } diff --git a/egui_demo_lib/src/backend_panel.rs b/egui_demo_lib/src/backend_panel.rs index 478979ae..170d7081 100644 --- a/egui_demo_lib/src/backend_panel.rs +++ b/egui_demo_lib/src/backend_panel.rs @@ -78,7 +78,7 @@ impl Default for BackendPanel { } impl BackendPanel { - pub fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + pub fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { self.frame_history .on_new_frame(ctx.input().time, frame.info().cpu_usage); @@ -92,7 +92,7 @@ impl BackendPanel { self.egui_windows.windows(ctx); } - pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) { + pub fn ui(&mut self, ui: &mut egui::Ui, frame: &epi::Frame) { egui::trace!(ui); ui.vertical_centered(|ui| { ui.heading("💻 Backend"); @@ -147,7 +147,7 @@ impl BackendPanel { } } - fn integration_ui(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) { + fn integration_ui(&mut self, ui: &mut egui::Ui, frame: &epi::Frame) { if frame.is_web() { ui.label("egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."); ui.label( @@ -170,13 +170,13 @@ impl BackendPanel { } } - show_integration_name(ui, frame.info()); + show_integration_name(ui, &frame.info()); // For instance: `egui_web` sets `pixels_per_point` every frame to force // egui to use the same scale as the web zoom factor. let integration_controls_pixels_per_point = ui.input().raw.pixels_per_point.is_some(); if !integration_controls_pixels_per_point { - if let Some(new_pixels_per_point) = self.pixels_per_point_ui(ui, frame.info()) { + if let Some(new_pixels_per_point) = self.pixels_per_point_ui(ui, &frame.info()) { ui.ctx().set_pixels_per_point(new_pixels_per_point); } } diff --git a/egui_demo_lib/src/easy_mark/easy_mark_editor.rs b/egui_demo_lib/src/easy_mark/easy_mark_editor.rs index 50360d94..729d1a5f 100644 --- a/egui_demo_lib/src/easy_mark/easy_mark_editor.rs +++ b/egui_demo_lib/src/easy_mark/easy_mark_editor.rs @@ -34,7 +34,7 @@ impl epi::App for EasyMarkEditor { "🖹 EasyMark editor" } - fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { egui::TopBottomPanel::bottom("easy_mark_bottom").show(ctx, |ui| { let layout = egui::Layout::top_down(egui::Align::Center).with_main_justify(true); ui.allocate_ui_with_layout(ui.available_size(), layout, |ui| { diff --git a/egui_demo_lib/src/wrap_app.rs b/egui_demo_lib/src/wrap_app.rs index c9a04f6b..5eed1b0b 100644 --- a/egui_demo_lib/src/wrap_app.rs +++ b/egui_demo_lib/src/wrap_app.rs @@ -45,7 +45,7 @@ impl epi::App for WrapApp { fn setup( &mut self, _ctx: &egui::CtxRef, - _frame: &mut epi::Frame<'_>, + _frame: &epi::Frame, _storage: Option<&dyn epi::Storage>, ) { #[cfg(feature = "persistence")] @@ -72,7 +72,7 @@ impl epi::App for WrapApp { cfg!(not(debug_assertions)) } - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) { + fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { if let Some(web_info) = frame.info().web_info.as_ref() { if let Some(anchor) = web_info.web_location_hash.strip_prefix('#') { self.selected_anchor = anchor.to_owned(); @@ -126,7 +126,7 @@ impl epi::App for WrapApp { } impl WrapApp { - fn bar_contents(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) { + fn bar_contents(&mut self, ui: &mut egui::Ui, frame: &epi::Frame) { // A menu-bar is a horizontal layout with some special styles applied. // egui::menu::bar(ui, |ui| { ui.horizontal_wrapped(|ui| { diff --git a/egui_glium/CHANGELOG.md b/egui_glium/CHANGELOG.md index 3ca59c04..02302c72 100644 --- a/egui_glium/CHANGELOG.md +++ b/egui_glium/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the `egui_glium` integration will be noted in this file. * Simplify `EguiGlium` interface ([#871](https://github.com/emilk/egui/pull/871)). * Remove `EguiGlium::is_quit_event` ([#881](https://github.com/emilk/egui/pull/881)). * Updated `glium` to 0.31 ([#930](https://github.com/emilk/egui/pull/930)). +* Changed the `Painter` inteface slightly ([#999](https://github.com/emilk/egui/pull/999)). ## 0.15.0 - 2021-10-24 diff --git a/egui_glium/src/epi_backend.rs b/egui_glium/src/epi_backend.rs index ea17bd76..1dd52810 100644 --- a/egui_glium/src/epi_backend.rs +++ b/egui_glium/src/epi_backend.rs @@ -1,22 +1,6 @@ -use crate::*; -use egui::Color32; use glium::glutin; -impl epi::TextureAllocator for Painter { - fn alloc_srgba_premultiplied( - &mut self, - size: (usize, usize), - srgba_pixels: &[Color32], - ) -> egui::TextureId { - let id = self.alloc_user_texture(); - self.set_user_texture(id, size, srgba_pixels); - id - } - - fn free(&mut self, id: egui::TextureId) { - self.free_user_texture(id); - } -} +use crate::*; struct RequestRepaintEvent; @@ -24,7 +8,7 @@ struct GliumRepaintSignal( std::sync::Mutex>, ); -impl epi::RepaintSignal for GliumRepaintSignal { +impl epi::backend::RepaintSignal for GliumRepaintSignal { fn request_repaint(&self) { self.0.lock().unwrap().send_event(RequestRepaintEvent).ok(); } @@ -64,7 +48,6 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { let mut integration = egui_winit::epi::EpiIntegration::new( "egui_glium", display.gl_window().window(), - &mut painter, repaint_signal, persistence, app, @@ -83,10 +66,15 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { std::thread::sleep(std::time::Duration::from_millis(10)); } - let (needs_repaint, shapes) = - integration.update(display.gl_window().window(), &mut painter); + let (needs_repaint, mut tex_allocation_data, shapes) = + integration.update(display.gl_window().window()); let clipped_meshes = integration.egui_ctx.tessellate(shapes); + for (id, image) in tex_allocation_data.creations { + painter.set_texture(&display, id, &image); + } + + // paint: { use glium::Surface as _; let mut target = display.draw(); @@ -104,6 +92,10 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { target.finish().unwrap(); } + for id in tex_allocation_data.destructions.drain(..) { + painter.free_texture(id); + } + { *control_flow = if integration.should_quit() { glutin::event_loop::ControlFlow::Exit diff --git a/egui_glium/src/painter.rs b/egui_glium/src/painter.rs index 2febdc39..e5dc378d 100644 --- a/egui_glium/src/painter.rs +++ b/egui_glium/src/painter.rs @@ -14,7 +14,7 @@ use { uniform, uniforms::{MagnifySamplerFilter, SamplerWrapFunction}, }, - std::rc::Rc, + std::{collections::HashMap, rc::Rc}, }; pub struct Painter { @@ -22,19 +22,11 @@ pub struct Painter { egui_texture: Option, egui_texture_version: Option, - /// `None` means unallocated (freed) slot. - user_textures: Vec>, -} + /// Index is the same as in [`egui::TextureId::User`]. + user_textures: HashMap>, -#[derive(Default)] -struct UserTexture { - /// Pending upload (will be emptied later). - /// This is the format glium likes. - pixels: Vec>, - - /// Lazily uploaded from [`Self::pixels`], - /// or owned by the user via `register_native_texture`. - gl_texture: Option>, + // TODO: 128-bit texture space? + next_native_tex_id: u64, } impl Painter { @@ -65,6 +57,7 @@ impl Painter { egui_texture: None, egui_texture_version: None, user_textures: Default::default(), + next_native_tex_id: 1 << 32, } } @@ -106,7 +99,6 @@ impl Painter { egui_texture: &egui::Texture, ) { self.upload_egui_texture(display, egui_texture); - self.upload_pending_user_textures(display); for egui::ClippedMesh(clip_rect, mesh) in cipped_meshes { self.paint_mesh(target, display, pixels_per_point, clip_rect, &mesh); @@ -114,7 +106,7 @@ impl Painter { } #[inline(never)] // Easier profiling - pub fn paint_mesh( + fn paint_mesh( &mut self, target: &mut T, display: &glium::Display, @@ -229,82 +221,40 @@ impl Painter { } // ------------------------------------------------------------------------ - // user textures: this is an experimental feature. - // No need to implement this in your egui integration! - pub fn alloc_user_texture(&mut self) -> egui::TextureId { - for (i, tex) in self.user_textures.iter_mut().enumerate() { - if tex.is_none() { - *tex = Some(Default::default()); - return egui::TextureId::User(i as u64); - } - } - let id = egui::TextureId::User(self.user_textures.len() as u64); - self.user_textures.push(Some(Default::default())); - id - } - - pub fn set_user_texture( + pub fn set_texture( &mut self, - id: egui::TextureId, - size: (usize, usize), - pixels: &[Color32], + facade: &dyn glium::backend::Facade, + tex_id: u64, + image: &epi::Image, ) { assert_eq!( - size.0 * size.1, - pixels.len(), + image.size[0] * image.size[1], + image.pixels.len(), "Mismatch between texture size and texel count" ); - if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - let pixels: Vec> = pixels - .chunks(size.0 as usize) - .map(|row| row.iter().map(|srgba| srgba.to_tuple()).collect()) - .collect(); + let pixels: Vec> = image + .pixels + .chunks(image.size[0] as usize) + .map(|row| row.iter().map(|srgba| srgba.to_tuple()).collect()) + .collect(); - *user_texture = UserTexture { - pixels, - gl_texture: None, - }; - } - } + let format = texture::SrgbFormat::U8U8U8U8; + let mipmaps = texture::MipmapsOption::NoMipmap; + let gl_texture = SrgbTexture2d::with_format(facade, pixels, format, mipmaps).unwrap(); + + self.user_textures.insert(tex_id, gl_texture.into()); } - pub fn free_user_texture(&mut self, id: egui::TextureId) { - if let egui::TextureId::User(id) = id { - let index = id as usize; - if index < self.user_textures.len() { - self.user_textures[index] = None; - } - } + pub fn free_texture(&mut self, tex_id: u64) { + self.user_textures.remove(&tex_id); } - pub fn get_texture(&self, texture_id: egui::TextureId) -> Option<&SrgbTexture2d> { + fn get_texture(&self, texture_id: egui::TextureId) -> Option<&SrgbTexture2d> { match texture_id { egui::TextureId::Egui => self.egui_texture.as_ref(), - egui::TextureId::User(id) => self - .user_textures - .get(id as usize)? - .as_ref()? - .gl_texture - .as_ref() - .map(|rc| rc.as_ref()), - } - } - - pub fn upload_pending_user_textures(&mut self, facade: &dyn glium::backend::Facade) { - for user_texture in self.user_textures.iter_mut().flatten() { - if user_texture.gl_texture.is_none() { - let pixels = std::mem::take(&mut user_texture.pixels); - let format = texture::SrgbFormat::U8U8U8U8; - let mipmaps = texture::MipmapsOption::NoMipmap; - user_texture.gl_texture = Some( - SrgbTexture2d::with_format(facade, pixels, format, mipmaps) - .unwrap() - .into(), - ); - } + egui::TextureId::User(id) => self.user_textures.get(&id).map(|rc| rc.as_ref()), } } } @@ -314,26 +264,15 @@ impl epi::NativeTexture for Painter { type Texture = Rc; fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { - let id = self.alloc_user_texture(); - if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - *user_texture = UserTexture { - pixels: vec![], - gl_texture: Some(native), - } - } - } - id + let id = self.next_native_tex_id; + self.next_native_tex_id += 1; + self.user_textures.insert(id, native); + egui::TextureId::User(id as u64) } fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - *user_texture = UserTexture { - pixels: vec![], - gl_texture: Some(replacing), - }; - } + self.user_textures.insert(id, replacing); } } } diff --git a/egui_glow/CHANGELOG.md b/egui_glow/CHANGELOG.md index 21b5b4e8..19c13f47 100644 --- a/egui_glow/CHANGELOG.md +++ b/egui_glow/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the `egui_glow` integration will be noted in this file. * Simplify `EguiGlow` interface ([#871](https://github.com/emilk/egui/pull/871)). * Remove `EguiGlow::is_quit_event` ([#881](https://github.com/emilk/egui/pull/881)). * Updated `glutin` to 0.28 ([#930](https://github.com/emilk/egui/pull/930)). +* Changed the `Painter` inteface slightly ([#999](https://github.com/emilk/egui/pull/999)). ## 0.15.0 - 2021-10-24 diff --git a/egui_glow/src/epi_backend.rs b/egui_glow/src/epi_backend.rs index 8f38d854..73afcde6 100644 --- a/egui_glow/src/epi_backend.rs +++ b/egui_glow/src/epi_backend.rs @@ -4,7 +4,7 @@ struct RequestRepaintEvent; struct GlowRepaintSignal(std::sync::Mutex>); -impl epi::RepaintSignal for GlowRepaintSignal { +impl epi::backend::RepaintSignal for GlowRepaintSignal { fn request_repaint(&self) { self.0.lock().unwrap().send_event(RequestRepaintEvent).ok(); } @@ -64,7 +64,6 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { let mut integration = egui_winit::epi::EpiIntegration::new( "egui_glow", gl_window.window(), - &mut painter, repaint_signal, persistence, app, @@ -83,9 +82,15 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { std::thread::sleep(std::time::Duration::from_millis(10)); } - let (needs_repaint, shapes) = integration.update(gl_window.window(), &mut painter); + let (needs_repaint, mut tex_allocation_data, shapes) = + integration.update(gl_window.window()); let clipped_meshes = integration.egui_ctx.tessellate(shapes); + for (id, image) in tex_allocation_data.creations { + painter.set_texture(&gl, id, &image); + } + + // paint: { let color = integration.app.clear_color(); unsafe { @@ -96,8 +101,8 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { } painter.upload_egui_texture(&gl, &integration.egui_ctx.texture()); painter.paint_meshes( - gl_window.window().inner_size().into(), &gl, + gl_window.window().inner_size().into(), integration.egui_ctx.pixels_per_point(), clipped_meshes, ); @@ -105,6 +110,10 @@ pub fn run(app: Box, native_options: &epi::NativeOptions) -> ! { gl_window.swap_buffers().unwrap(); } + for id in tex_allocation_data.destructions.drain(..) { + painter.free_texture(id); + } + { *control_flow = if integration.should_quit() { glutin::event_loop::ControlFlow::Exit diff --git a/egui_glow/src/lib.rs b/egui_glow/src/lib.rs index ce1d745d..fcf82179 100644 --- a/egui_glow/src/lib.rs +++ b/egui_glow/src/lib.rs @@ -166,8 +166,8 @@ impl EguiGlow { self.painter .upload_egui_texture(gl, &self.egui_ctx.texture()); self.painter.paint_meshes( - dimensions, gl, + dimensions, self.egui_ctx.pixels_per_point(), clipped_meshes, ); diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index 5fb62c3e..0c848094 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -1,14 +1,13 @@ #![allow(unsafe_code)] +use std::collections::HashMap; + use egui::{ emath::Rect, epaint::{Color32, Mesh, Vertex}, }; -pub use glow::Context; - -use memoffset::offset_of; - use glow::HasContext; +use memoffset::offset_of; use crate::misc_util::{ as_u8_slice, compile_shader, glow_debug_print, link_program, srgbtexture2d, @@ -17,6 +16,8 @@ use crate::post_process::PostProcess; use crate::shader_version::ShaderVersion; use crate::vao_emulate; +pub use glow::Context; + const VERT_SRC: &str = include_str!("shader/vertex.glsl"); const FRAG_SRC: &str = include_str!("shader/fragment.glsl"); @@ -34,29 +35,21 @@ pub struct Painter { is_embedded: bool, vertex_array: crate::misc_util::VAO, srgb_support: bool, - /// `None` means unallocated (freed) slot. - pub(crate) user_textures: Vec>, post_process: Option, vertex_buffer: glow::Buffer, element_array_buffer: glow::Buffer, - // Stores outdated OpenGL textures that are yet to be deleted - old_textures: Vec, - // Only used in debug builds, to make sure we are destroyed correctly. + /// Index is the same as in [`egui::TextureId::User`]. + user_textures: HashMap, + // TODO: 128-bit texture space? + next_native_tex_id: u64, + /// Stores outdated OpenGL textures that are yet to be deleted + textures_to_destroy: Vec, + + /// Only used in debug builds, to make sure we are destroyed correctly. destroyed: bool, } -#[derive(Default)] -pub(crate) struct UserTexture { - /// Pending upload (will be emptied later). - /// This is the format glow likes. - pub(crate) data: Vec, - pub(crate) size: (usize, usize), - - /// Lazily uploaded - pub(crate) gl_texture: Option, -} - impl Painter { /// Create painter. /// @@ -195,11 +188,12 @@ impl Painter { is_embedded: matches!(shader_version, ShaderVersion::Es100 | ShaderVersion::Es300), vertex_array, srgb_support, - user_textures: Default::default(), post_process, vertex_buffer, element_array_buffer, - old_textures: Vec::new(), + user_textures: Default::default(), + next_native_tex_id: 1 << 32, + textures_to_destroy: Vec::new(), destroyed: false, }) } @@ -298,15 +292,13 @@ impl Painter { /// of the effects your program might have on this code. Look at the source if in doubt. pub fn paint_meshes( &mut self, - inner_size: [u32; 2], gl: &glow::Context, + inner_size: [u32; 2], pixels_per_point: f32, clipped_meshes: Vec, ) { - //chimera of egui_glow and egui_web self.assert_not_destroyed(); - self.upload_pending_user_textures(gl); if let Some(ref mut post_process) = self.post_process { unsafe { post_process.begin(gl, inner_size[0] as i32, inner_size[1] as i32); @@ -393,128 +385,47 @@ impl Painter { } // ------------------------------------------------------------------------ - // user textures: this is an experimental feature. - // No need to implement this in your egui integration! - pub fn alloc_user_texture(&mut self) -> egui::TextureId { + pub fn set_texture(&mut self, gl: &glow::Context, tex_id: u64, image: &epi::Image) { self.assert_not_destroyed(); - for (i, tex) in self.user_textures.iter_mut().enumerate() { - if tex.is_none() { - *tex = Some(Default::default()); - return egui::TextureId::User(i as u64); - } - } - let id = egui::TextureId::User(self.user_textures.len() as u64); - self.user_textures.push(Some(Default::default())); - id - } - - /// register glow texture as egui texture - /// Usable for render to image rectangle - #[allow(clippy::needless_pass_by_value)] - pub fn register_glow_texture(&mut self, texture: glow::Texture) -> egui::TextureId { - self.assert_not_destroyed(); - - let id = self.alloc_user_texture(); - if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - if let UserTexture { - gl_texture: Some(old_tex), - .. - } = std::mem::replace( - user_texture, - UserTexture { - data: vec![], - size: (0, 0), - gl_texture: Some(texture), - }, - ) { - self.old_textures.push(old_tex); - } - } - } - id - } - - pub fn set_user_texture( - &mut self, - id: egui::TextureId, - size: (usize, usize), - pixels: &[Color32], - ) { - self.assert_not_destroyed(); assert_eq!( - size.0 * size.1, - pixels.len(), - "Mismatch between size and texel count" + image.size[0] * image.size[1], + image.pixels.len(), + "Mismatch between texture size and texel count" ); - if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - let data: Vec = pixels - .iter() - .flat_map(|srgba| Vec::from(srgba.to_array())) - .collect(); + // TODO: optimize + let pixels: Vec = image + .pixels + .iter() + .flat_map(|srgba| Vec::from(srgba.to_array())) + .collect(); - if let UserTexture { - gl_texture: Some(old_tex), - .. - } = std::mem::replace( - user_texture, - UserTexture { - data, - size, - gl_texture: None, - }, - ) { - self.old_textures.push(old_tex); - } - } + let gl_texture = srgbtexture2d( + gl, + self.is_webgl_1, + self.srgb_support, + &pixels, + image.size[0], + image.size[1], + ); + + if let Some(old_tex) = self.user_textures.insert(tex_id, gl_texture) { + self.textures_to_destroy.push(old_tex); } } - pub fn free_user_texture(&mut self, id: egui::TextureId) { - self.assert_not_destroyed(); - - if let egui::TextureId::User(id) = id { - let index = id as usize; - if index < self.user_textures.len() { - self.user_textures[index] = None; - } - } + pub fn free_texture(&mut self, tex_id: u64) { + self.user_textures.remove(&tex_id); } - pub fn get_texture(&self, texture_id: egui::TextureId) -> Option { + fn get_texture(&self, texture_id: egui::TextureId) -> Option { self.assert_not_destroyed(); match texture_id { egui::TextureId::Egui => self.egui_texture, - egui::TextureId::User(id) => self.user_textures.get(id as usize)?.as_ref()?.gl_texture, - } - } - - pub fn upload_pending_user_textures(&mut self, gl: &glow::Context) { - self.assert_not_destroyed(); - - for user_texture in self.user_textures.iter_mut().flatten() { - if user_texture.gl_texture.is_none() { - let data = std::mem::take(&mut user_texture.data); - user_texture.gl_texture = Some(srgbtexture2d( - gl, - self.is_webgl_1, - self.srgb_support, - &data, - user_texture.size.0, - user_texture.size.1, - )); - user_texture.size = (0, 0); - } - } - for t in self.old_textures.drain(..) { - unsafe { - gl.delete_texture(t); - } + egui::TextureId::User(id) => self.user_textures.get(&id).copied(), } } @@ -523,14 +434,12 @@ impl Painter { if let Some(tex) = self.egui_texture { gl.delete_texture(tex); } - for tex in self.user_textures.iter().flatten() { - if let Some(t) = tex.gl_texture { - gl.delete_texture(t); - } + for tex in self.user_textures.values() { + gl.delete_texture(*tex); } gl.delete_buffer(self.vertex_buffer); gl.delete_buffer(self.element_array_buffer); - for t in &self.old_textures { + for t in &self.textures_to_destroy { gl.delete_texture(*t); } } @@ -580,39 +489,25 @@ impl Drop for Painter { } } -#[cfg(feature = "epi")] -impl epi::TextureAllocator for Painter { - fn alloc_srgba_premultiplied( - &mut self, - size: (usize, usize), - srgba_pixels: &[Color32], - ) -> egui::TextureId { - let id = self.alloc_user_texture(); - self.set_user_texture(id, size, srgba_pixels); - id - } - - fn free(&mut self, id: egui::TextureId) { - self.free_user_texture(id); - } -} - #[cfg(feature = "epi")] impl epi::NativeTexture for Painter { type Texture = glow::Texture; fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { - self.register_glow_texture(native) + self.assert_not_destroyed(); + + let id = self.next_native_tex_id; + self.next_native_tex_id += 1; + + self.user_textures.insert(id, native); + + egui::TextureId::User(id as u64) } fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - *user_texture = UserTexture { - data: vec![], - gl_texture: Some(replacing), - size: (0, 0), - }; + if let Some(old_tex) = self.user_textures.insert(id, replacing) { + self.textures_to_destroy.push(old_tex); } } } diff --git a/egui_web/CHANGELOG.md b/egui_web/CHANGELOG.md index 45db3ee9..b1583810 100644 --- a/egui_web/CHANGELOG.md +++ b/egui_web/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the `egui_web` integration will be noted in this file. * Fix [dark rendering in WebKitGTK](https://github.com/emilk/egui/issues/794) ([#888](https://github.com/emilk/egui/pull/888/)). * Add feature `glow` to switch to a [`glow`](https://github.com/grovesNL/glow) based painter ([#868](https://github.com/emilk/egui/pull/868)). + ## 0.15.0 - 2021-10-24 ### Added * Remove "http" feature (use https://github.com/emilk/ehttp instead!). diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index c8c2efe5..eda65ee6 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -67,7 +67,7 @@ impl NeedRepaint { } } -impl epi::RepaintSignal for NeedRepaint { +impl epi::backend::RepaintSignal for NeedRepaint { fn request_repaint(&self) { self.0.store(true, SeqCst); } @@ -76,28 +76,44 @@ impl epi::RepaintSignal for NeedRepaint { // ---------------------------------------------------------------------------- pub struct AppRunner { + frame: epi::Frame, egui_ctx: egui::CtxRef, painter: Box, - previous_frame_time: Option, pub(crate) input: WebInput, app: Box, pub(crate) needs_repaint: std::sync::Arc, storage: LocalStorage, - prefer_dark_mode: Option, last_save_time: f64, screen_reader: crate::screen_reader::ScreenReader, pub(crate) text_cursor_pos: Option, pub(crate) mutable_text_under_cursor: bool, + pending_texture_destructions: Vec, } impl AppRunner { pub fn new(canvas_id: &str, app: Box) -> Result { - let egui_ctx = egui::CtxRef::default(); - - load_memory(&egui_ctx); + let painter = create_painter(canvas_id)?; let prefer_dark_mode = crate::prefer_dark_mode(); + let needs_repaint: std::sync::Arc = Default::default(); + + let frame = epi::Frame::new(epi::backend::FrameData { + info: epi::IntegrationInfo { + name: painter.name(), + web_info: Some(epi::WebInfo { + web_location_hash: location_hash().unwrap_or_default(), + }), + prefer_dark_mode, + cpu_usage: None, + native_pixels_per_point: Some(native_pixels_per_point()), + }, + output: Default::default(), + repaint_signal: needs_repaint.clone(), + }); + + let egui_ctx = egui::CtxRef::default(); + load_memory(&egui_ctx); if prefer_dark_mode == Some(true) { egui_ctx.set_visuals(egui::Visuals::dark()); } else { @@ -107,32 +123,24 @@ impl AppRunner { let storage = LocalStorage::default(); let mut runner = Self { + frame, egui_ctx, - painter: create_painter(canvas_id)?, - previous_frame_time: None, + painter, input: Default::default(), app, - needs_repaint: Default::default(), + needs_repaint, storage, - prefer_dark_mode, last_save_time: now_sec(), screen_reader: Default::default(), text_cursor_pos: None, mutable_text_under_cursor: false, + pending_texture_destructions: Default::default(), }; { - let mut app_output = epi::backend::AppOutput::default(); - let mut frame = epi::backend::FrameBuilder { - info: runner.integration_info(), - tex_allocator: runner.painter.as_tex_allocator(), - output: &mut app_output, - repaint_signal: runner.needs_repaint.clone(), - } - .build(); runner .app - .setup(&runner.egui_ctx, &mut frame, Some(&runner.storage)); + .setup(&runner.egui_ctx, &runner.frame, Some(&runner.storage)); } Ok(runner) @@ -170,18 +178,6 @@ impl AppRunner { Ok(()) } - fn integration_info(&self) -> epi::IntegrationInfo { - epi::IntegrationInfo { - name: self.painter.name(), - web_info: Some(epi::WebInfo { - web_location_hash: location_hash().unwrap_or_default(), - }), - prefer_dark_mode: self.prefer_dark_mode, - cpu_usage: self.previous_frame_time, - native_pixels_per_point: Some(native_pixels_per_point()), - } - } - pub fn logic(&mut self) -> Result<(egui::Output, Vec), JsValue> { let frame_start = now_sec(); @@ -189,33 +185,31 @@ impl AppRunner { let canvas_size = canvas_size_in_points(self.canvas_id()); let raw_input = self.input.new_frame(canvas_size); - let mut app_output = epi::backend::AppOutput::default(); - let mut frame = epi::backend::FrameBuilder { - info: self.integration_info(), - tex_allocator: self.painter.as_tex_allocator(), - output: &mut app_output, - repaint_signal: self.needs_repaint.clone(), - } - .build(); - let (egui_output, shapes) = self.egui_ctx.run(raw_input, |egui_ctx| { - self.app.update(egui_ctx, &mut frame); + self.app.update(egui_ctx, &self.frame); }); let clipped_meshes = self.egui_ctx.tessellate(shapes); self.handle_egui_output(&egui_output); { + let app_output = self.frame.take_app_output(); let epi::backend::AppOutput { quit: _, // Can't quit a web page window_size: _, // Can't resize a web page window_title: _, // TODO: change title of window decorated: _, // Can't toggle decorations drag_window: _, // Can't be dragged + tex_allocation_data, } = app_output; + + for (id, image) in tex_allocation_data.creations { + self.painter.set_texture(id, image); + } + self.pending_texture_destructions = tex_allocation_data.destructions; } - self.previous_frame_time = Some((now_sec() - frame_start) as f32); + self.frame.lock().info.cpu_usage = Some((now_sec() - frame_start) as f32); Ok((egui_output, clipped_meshes)) } @@ -223,7 +217,11 @@ impl AppRunner { self.painter.upload_egui_texture(&self.egui_ctx.texture()); self.painter.clear(self.app.clear_color()); self.painter - .paint_meshes(clipped_meshes, self.egui_ctx.pixels_per_point()) + .paint_meshes(clipped_meshes, self.egui_ctx.pixels_per_point())?; + for id in self.pending_texture_destructions.drain(..) { + self.painter.free_texture(id); + } + Ok(()) } fn handle_egui_output(&mut self, output: &egui::Output) { diff --git a/egui_web/src/glow_wrapping.rs b/egui_web/src/glow_wrapping.rs index 2411ed80..5709774d 100644 --- a/egui_web/src/glow_wrapping.rs +++ b/egui_web/src/glow_wrapping.rs @@ -1,13 +1,12 @@ -#[cfg(not(target_arch = "wasm32"))] -use crate::web_sys::WebGl2RenderingContext; -use crate::web_sys::WebGlRenderingContext; use crate::{canvas_element_or_die, console_error}; use egui::{ClippedMesh, Rgba, Texture}; use egui_glow::glow; -use epi::TextureAllocator; use wasm_bindgen::JsCast; use wasm_bindgen::JsValue; use web_sys::HtmlCanvasElement; +#[cfg(not(target_arch = "wasm32"))] +use web_sys::WebGl2RenderingContext; +use web_sys::WebGlRenderingContext; pub(crate) struct WrappedGlowPainter { pub(crate) gl_ctx: glow::Context, @@ -67,8 +66,12 @@ fn requires_brightening(canvas: &web_sys::HtmlCanvasElement) -> bool { } impl crate::Painter for WrappedGlowPainter { - fn as_tex_allocator(&mut self) -> &mut dyn TextureAllocator { - &mut self.painter + fn set_texture(&mut self, tex_id: u64, image: epi::Image) { + self.painter.set_texture(&self.gl_ctx, tex_id, &image); + } + + fn free_texture(&mut self, tex_id: u64) { + self.painter.free_texture(tex_id); } fn debug_info(&self) -> String { @@ -99,8 +102,8 @@ impl crate::Painter for WrappedGlowPainter { ) -> Result<(), JsValue> { let canvas_dimension = [self.canvas.width(), self.canvas.height()]; self.painter.paint_meshes( - canvas_dimension, &self.gl_ctx, + canvas_dimension, pixels_per_point, clipped_meshes, ); diff --git a/egui_web/src/painter.rs b/egui_web/src/painter.rs index 0a414b94..079b9fd5 100644 --- a/egui_web/src/painter.rs +++ b/egui_web/src/painter.rs @@ -1,7 +1,9 @@ use wasm_bindgen::prelude::JsValue; pub trait Painter { - fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator; + fn set_texture(&mut self, tex_id: u64, image: epi::Image); + + fn free_texture(&mut self, tex_id: u64); fn debug_info(&self) -> String; diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index 73856838..db7751fc 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use { js_sys::WebAssembly, wasm_bindgen::{prelude::*, JsCast}, @@ -29,19 +31,11 @@ pub struct WebGlPainter { egui_texture: WebGlTexture, egui_texture_version: Option, - /// `None` means unallocated (freed) slot. - user_textures: Vec>, -} + /// Index is the same as in [`egui::TextureId::User`]. + user_textures: HashMap, -#[derive(Default)] -struct UserTexture { - size: (usize, usize), - - /// Pending upload (will be emptied later). - pixels: Vec, - - /// Lazily uploaded - gl_texture: Option, + // TODO: 128-bit texture space? + next_native_tex_id: u64, } impl WebGlPainter { @@ -111,109 +105,14 @@ impl WebGlPainter { egui_texture, egui_texture_version: None, user_textures: Default::default(), + next_native_tex_id: 1 << 32, }) } - fn alloc_user_texture_index(&mut self) -> usize { - for (index, tex) in self.user_textures.iter_mut().enumerate() { - if tex.is_none() { - *tex = Some(Default::default()); - return index; - } - } - let index = self.user_textures.len(); - self.user_textures.push(Some(Default::default())); - index - } - - fn alloc_user_texture( - &mut self, - size: (usize, usize), - srgba_pixels: &[Color32], - ) -> egui::TextureId { - let index = self.alloc_user_texture_index(); - assert_eq!( - size.0 * size.1, - srgba_pixels.len(), - "Mismatch between texture size and texel count" - ); - - if let Some(Some(user_texture)) = self.user_textures.get_mut(index) { - let mut pixels: Vec = Vec::with_capacity(srgba_pixels.len() * 4); - for srgba in srgba_pixels { - pixels.push(srgba.r()); - pixels.push(srgba.g()); - pixels.push(srgba.b()); - pixels.push(srgba.a()); - } - - *user_texture = UserTexture { - size, - pixels, - gl_texture: None, - }; - } - - egui::TextureId::User(index as u64) - } - - fn free_user_texture(&mut self, id: egui::TextureId) { - if let egui::TextureId::User(id) = id { - let index = id as usize; - if index < self.user_textures.len() { - self.user_textures[index] = None; - } - } - } - - pub fn get_texture(&self, texture_id: egui::TextureId) -> Option<&WebGlTexture> { + fn get_texture(&self, texture_id: egui::TextureId) -> Option<&WebGlTexture> { match texture_id { egui::TextureId::Egui => Some(&self.egui_texture), - egui::TextureId::User(id) => self - .user_textures - .get(id as usize)? - .as_ref()? - .gl_texture - .as_ref(), - } - } - - fn upload_user_textures(&mut self) { - let gl = &self.gl; - - for user_texture in self.user_textures.iter_mut().flatten() { - if user_texture.gl_texture.is_none() { - let pixels = std::mem::take(&mut user_texture.pixels); - - let gl_texture = gl.create_texture().unwrap(); - gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_S, Gl::CLAMP_TO_EDGE as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_T, Gl::CLAMP_TO_EDGE as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as i32); - - gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); - - let level = 0; - let internal_format = self.texture_format; - let border = 0; - let src_format = self.texture_format; - let src_type = Gl::UNSIGNED_BYTE; - gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - Gl::TEXTURE_2D, - level, - internal_format as i32, - user_texture.size.0 as i32, - user_texture.size.1 as i32, - border, - src_format, - src_type, - Some(&pixels), - ) - .unwrap(); - - user_texture.gl_texture = Some(gl_texture); - } + egui::TextureId::User(id) => self.user_textures.get(&id), } } @@ -338,51 +237,75 @@ impl WebGlPainter { } } -impl epi::TextureAllocator for WebGlPainter { - fn alloc_srgba_premultiplied( - &mut self, - size: (usize, usize), - srgba_pixels: &[egui::Color32], - ) -> egui::TextureId { - self.alloc_user_texture(size, srgba_pixels) - } - - fn free(&mut self, id: egui::TextureId) { - self.free_user_texture(id) - } -} - impl epi::NativeTexture for WebGlPainter { type Texture = WebGlTexture; fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { - let id = self.alloc_user_texture_index(); - if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { - *user_texture = UserTexture { - size: (0, 0), - pixels: vec![], - gl_texture: Some(native), - } - } + let id = self.next_native_tex_id; + self.next_native_tex_id += 1; + self.user_textures.insert(id, native); egui::TextureId::User(id as u64) } fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - *user_texture = UserTexture { - size: (0, 0), - pixels: vec![], - gl_texture: Some(replacing), - } + if let Some(user_texture) = self.user_textures.get_mut(&id) { + *user_texture = replacing; } } } } impl crate::Painter for WebGlPainter { - fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator { - self + fn set_texture(&mut self, tex_id: u64, image: epi::Image) { + assert_eq!( + image.size[0] * image.size[1], + image.pixels.len(), + "Mismatch between texture size and texel count" + ); + + // TODO: optimize + let mut pixels: Vec = Vec::with_capacity(image.pixels.len() * 4); + for srgba in image.pixels { + pixels.push(srgba.r()); + pixels.push(srgba.g()); + pixels.push(srgba.b()); + pixels.push(srgba.a()); + } + + let gl = &self.gl; + let gl_texture = gl.create_texture().unwrap(); + gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_S, Gl::CLAMP_TO_EDGE as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_T, Gl::CLAMP_TO_EDGE as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as _); + + gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); + + let level = 0; + let internal_format = self.texture_format; + let border = 0; + let src_format = self.texture_format; + let src_type = Gl::UNSIGNED_BYTE; + gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( + Gl::TEXTURE_2D, + level, + internal_format as _, + image.size[0] as _, + image.size[1] as _, + border, + src_format, + src_type, + Some(&pixels), + ) + .unwrap(); + + self.user_textures.insert(tex_id, gl_texture); + } + + fn free_texture(&mut self, tex_id: u64) { + self.user_textures.remove(&tex_id); } fn debug_info(&self) -> String { @@ -467,8 +390,6 @@ impl crate::Painter for WebGlPainter { clipped_meshes: Vec, pixels_per_point: f32, ) -> Result<(), JsValue> { - self.upload_user_textures(); - let gl = &self.gl; if let Some(ref mut post_process) = self.post_process { diff --git a/egui_web/src/webgl2.rs b/egui_web/src/webgl2.rs index de3a5090..e774f984 100644 --- a/egui_web/src/webgl2.rs +++ b/egui_web/src/webgl2.rs @@ -1,4 +1,5 @@ //! Mostly a carbon-copy of `webgl1.rs`. +use std::collections::HashMap; use { js_sys::WebAssembly, @@ -30,19 +31,11 @@ pub struct WebGl2Painter { egui_texture: WebGlTexture, egui_texture_version: Option, - /// `None` means unallocated (freed) slot. - user_textures: Vec>, -} + /// Index is the same as in [`egui::TextureId::User`]. + user_textures: HashMap, -#[derive(Default)] -struct UserTexture { - size: (usize, usize), - - /// Pending upload (will be emptied later). - pixels: Vec, - - /// Lazily uploaded - gl_texture: Option, + // TODO: 128-bit texture space? + next_native_tex_id: u64, } impl WebGl2Painter { @@ -96,109 +89,14 @@ impl WebGl2Painter { egui_texture, egui_texture_version: None, user_textures: Default::default(), + next_native_tex_id: 1 << 32, }) } - fn alloc_user_texture_index(&mut self) -> usize { - for (index, tex) in self.user_textures.iter_mut().enumerate() { - if tex.is_none() { - *tex = Some(Default::default()); - return index; - } - } - let index = self.user_textures.len(); - self.user_textures.push(Some(Default::default())); - index - } - - fn alloc_user_texture( - &mut self, - size: (usize, usize), - srgba_pixels: &[Color32], - ) -> egui::TextureId { - let index = self.alloc_user_texture_index(); - assert_eq!( - size.0 * size.1, - srgba_pixels.len(), - "Mismatch between texture size and texel count" - ); - - if let Some(Some(user_texture)) = self.user_textures.get_mut(index) { - let mut pixels: Vec = Vec::with_capacity(srgba_pixels.len() * 4); - for srgba in srgba_pixels { - pixels.push(srgba.r()); - pixels.push(srgba.g()); - pixels.push(srgba.b()); - pixels.push(srgba.a()); - } - - *user_texture = UserTexture { - size, - pixels, - gl_texture: None, - }; - } - - egui::TextureId::User(index as u64) - } - - fn free_user_texture(&mut self, id: egui::TextureId) { - if let egui::TextureId::User(id) = id { - let index = id as usize; - if index < self.user_textures.len() { - self.user_textures[index] = None; - } - } - } - - pub fn get_texture(&self, texture_id: egui::TextureId) -> Option<&WebGlTexture> { + fn get_texture(&self, texture_id: egui::TextureId) -> Option<&WebGlTexture> { match texture_id { egui::TextureId::Egui => Some(&self.egui_texture), - egui::TextureId::User(id) => self - .user_textures - .get(id as usize)? - .as_ref()? - .gl_texture - .as_ref(), - } - } - - fn upload_user_textures(&mut self) { - let gl = &self.gl; - for user_texture in self.user_textures.iter_mut().flatten() { - if user_texture.gl_texture.is_none() { - let pixels = std::mem::take(&mut user_texture.pixels); - - let gl_texture = gl.create_texture().unwrap(); - gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_S, Gl::CLAMP_TO_EDGE as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_T, Gl::CLAMP_TO_EDGE as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as i32); - gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as i32); - - gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); - - let level = 0; - let internal_format = Gl::SRGB8_ALPHA8; - let border = 0; - let src_format = Gl::RGBA; - let src_type = Gl::UNSIGNED_BYTE; - gl.pixel_storei(Gl::UNPACK_ALIGNMENT, 1); - gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( - Gl::TEXTURE_2D, - level, - internal_format as i32, - user_texture.size.0 as i32, - user_texture.size.1 as i32, - border, - src_format, - src_type, - Some(&pixels), - ) - .unwrap(); - - user_texture.gl_texture = Some(gl_texture); - } + egui::TextureId::User(id) => self.user_textures.get(&id), } } @@ -323,51 +221,75 @@ impl WebGl2Painter { } } -impl epi::TextureAllocator for WebGl2Painter { - fn alloc_srgba_premultiplied( - &mut self, - size: (usize, usize), - srgba_pixels: &[egui::Color32], - ) -> egui::TextureId { - self.alloc_user_texture(size, srgba_pixels) - } - - fn free(&mut self, id: egui::TextureId) { - self.free_user_texture(id) - } -} - impl epi::NativeTexture for WebGl2Painter { type Texture = WebGlTexture; fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { - let id = self.alloc_user_texture_index(); - if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { - *user_texture = UserTexture { - size: (0, 0), - pixels: vec![], - gl_texture: Some(native), - } - } + let id = self.next_native_tex_id; + self.next_native_tex_id += 1; + self.user_textures.insert(id, native); egui::TextureId::User(id as u64) } fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { if let egui::TextureId::User(id) = id { - if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { - *user_texture = UserTexture { - size: (0, 0), - pixels: vec![], - gl_texture: Some(replacing), - } + if let Some(user_texture) = self.user_textures.get_mut(&id) { + *user_texture = replacing; } } } } impl crate::Painter for WebGl2Painter { - fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator { - self + fn set_texture(&mut self, tex_id: u64, image: epi::Image) { + assert_eq!( + image.size[0] * image.size[1], + image.pixels.len(), + "Mismatch between texture size and texel count" + ); + + // TODO: optimize + let mut pixels: Vec = Vec::with_capacity(image.pixels.len() * 4); + for srgba in image.pixels { + pixels.push(srgba.r()); + pixels.push(srgba.g()); + pixels.push(srgba.b()); + pixels.push(srgba.a()); + } + + let gl = &self.gl; + let gl_texture = gl.create_texture().unwrap(); + gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_S, Gl::CLAMP_TO_EDGE as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_WRAP_T, Gl::CLAMP_TO_EDGE as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as _); + gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as _); + + gl.bind_texture(Gl::TEXTURE_2D, Some(&gl_texture)); + + let level = 0; + let internal_format = Gl::SRGB8_ALPHA8; + let border = 0; + let src_format = Gl::RGBA; + let src_type = Gl::UNSIGNED_BYTE; + gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array( + Gl::TEXTURE_2D, + level, + internal_format as _, + image.size[0] as _, + image.size[1] as _, + border, + src_format, + src_type, + Some(&pixels), + ) + .unwrap(); + + self.user_textures.insert(tex_id, gl_texture); + } + + fn free_texture(&mut self, tex_id: u64) { + self.user_textures.remove(&tex_id); } fn debug_info(&self) -> String { @@ -448,8 +370,6 @@ impl crate::Painter for WebGl2Painter { clipped_meshes: Vec, pixels_per_point: f32, ) -> Result<(), JsValue> { - self.upload_user_textures(); - let gl = &self.gl; self.post_process diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 4629c0bb..3dbcd86f 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -95,6 +95,8 @@ pub mod file_storage; pub use egui; // Re-export for user convenience +use std::sync::{Arc, Mutex}; + // ---------------------------------------------------------------------------- /// Implement this trait to write apps that can be compiled both natively using the [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium) crate, @@ -104,8 +106,11 @@ pub trait App { /// /// Put your widgets into a [`egui::SidePanel`], [`egui::TopBottomPanel`], [`egui::CentralPanel`], [`egui::Window`] or [`egui::Area`]. /// - /// To force a repaint, call either [`egui::Context::request_repaint`] or use [`Frame::repaint_signal`]. - fn update(&mut self, ctx: &egui::CtxRef, frame: &mut Frame<'_>); + /// The given [`egui::CtxRef`] is only valid for the duration of this call. + /// The [`Frame`] however can be cloned and saved. + /// + /// To force a repaint, call either [`egui::Context::request_repaint`] or [`Frame::request_repaint`]. + fn update(&mut self, ctx: &egui::CtxRef, frame: &Frame); /// Called once before the first frame. /// @@ -113,13 +118,7 @@ pub trait App { /// [`egui::Context::set_visuals`] etc. /// /// Also allows you to restore state, if there is a storage (required the "persistence" feature). - fn setup( - &mut self, - _ctx: &egui::CtxRef, - _frame: &mut Frame<'_>, - _storage: Option<&dyn Storage>, - ) { - } + fn setup(&mut self, _ctx: &egui::CtxRef, _frame: &Frame, _storage: Option<&dyn Storage>) {} /// If `true` a warm-up call to [`Self::update`] will be issued where /// `ctx.memory().everything_is_visible()` will be set to `true`. @@ -240,7 +239,7 @@ impl Default for NativeOptions { /// Image data for the icon. #[derive(Clone)] pub struct IconData { - /// RGBA pixels. + /// RGBA pixels, unmultiplied. pub rgba: Vec, /// Image width. This should be a multiple of 4. @@ -254,57 +253,99 @@ pub struct IconData { /// /// It provides methods to inspect the surroundings (are we on the web?), /// allocate textures, and change settings (e.g. window size). -pub struct Frame<'a>(backend::FrameBuilder<'a>); +/// +/// [`Frame`] is cheap to clone and is safe to pass to other threads. +#[derive(Clone)] +pub struct Frame(pub Arc>); + +impl Frame { + /// Create a `Frame` - called by the integration. + #[doc(hidden)] + pub fn new(frame_data: backend::FrameData) -> Self { + Self(Arc::new(Mutex::new(frame_data))) + } + + /// Convenience to access the underlying `backend::FrameData`. + #[doc(hidden)] + #[inline] + pub fn lock(&self) -> std::sync::MutexGuard<'_, backend::FrameData> { + self.0.lock().unwrap() + } -impl<'a> Frame<'a> { /// True if you are in a web environment. pub fn is_web(&self) -> bool { - self.info().web_info.is_some() + self.lock().info.web_info.is_some() } /// Information about the integration. - pub fn info(&self) -> &IntegrationInfo { - &self.0.info - } - - /// A way to allocate textures. - pub fn tex_allocator(&mut self) -> &mut dyn TextureAllocator { - self.0.tex_allocator + pub fn info(&self) -> IntegrationInfo { + self.lock().info.clone() } /// Signal the app to stop/exit/quit the app (only works for native apps, not web apps). /// The framework will not quit immediately, but at the end of the this frame. - pub fn quit(&mut self) { - self.0.output.quit = true; + pub fn quit(&self) { + self.lock().output.quit = true; } /// Set the desired inner size of the window (in egui points). - pub fn set_window_size(&mut self, size: egui::Vec2) { - self.0.output.window_size = Some(size); + pub fn set_window_size(&self, size: egui::Vec2) { + self.lock().output.window_size = Some(size); } /// Set the desired title of the window. - pub fn set_window_title(&mut self, title: &str) { - self.0.output.window_title = Some(title.to_owned()); + pub fn set_window_title(&self, title: &str) { + self.lock().output.window_title = Some(title.to_owned()); } /// Set whether to show window decorations (i.e. a frame around you app). /// If false it will be difficult to move and resize the app. - pub fn set_decorations(&mut self, decorated: bool) { - self.0.output.decorated = Some(decorated); + pub fn set_decorations(&self, decorated: bool) { + self.lock().output.decorated = Some(decorated); } /// When called, the native window will follow the /// movement of the cursor while the primary mouse button is down. /// - /// Does not work on the web, and works badly on Mac. - pub fn drag_window(&mut self) { - self.0.output.drag_window = true; + /// Does not work on the web. + pub fn drag_window(&self) { + self.lock().output.drag_window = true; } - /// If you need to request a repaint from another thread, clone this and send it to that other thread. - pub fn repaint_signal(&self) -> std::sync::Arc { - self.0.repaint_signal.clone() + /// This signals the [`egui`] integration that a repaint is required. + /// + /// Call this e.g. when a background process finishes in an async context and/or background thread. + pub fn request_repaint(&self) { + self.lock().repaint_signal.request_repaint(); + } + + /// for integrations only: call once per frame + pub fn take_app_output(&self) -> crate::backend::AppOutput { + let mut lock = self.lock(); + let next_id = lock.output.tex_allocation_data.next_id; + let app_output = std::mem::take(&mut lock.output); + lock.output.tex_allocation_data.next_id = next_id; + app_output + } + + /// Allocate a texture. Free it again with [`Self::free_texture`]. + pub fn alloc_texture(&self, image: Image) -> egui::TextureId { + self.lock().output.tex_allocation_data.alloc(image) + } + + /// Free a texture that has been previously allocated with [`Self::alloc_texture`]. Idempotent. + pub fn free_texture(&self, id: egui::TextureId) { + self.lock().output.tex_allocation_data.free(id); + } +} + +impl TextureAllocator for Frame { + fn alloc(&self, image: Image) -> egui::TextureId { + self.lock().output.tex_allocation_data.alloc(image) + } + + fn free(&self, id: egui::TextureId) { + self.lock().output.tex_allocation_data.free(id); } } @@ -344,14 +385,33 @@ pub trait TextureAllocator { /// /// There is no way to change a texture. /// Instead allocate a new texture and free the previous one with [`Self::free`]. - fn alloc_srgba_premultiplied( - &mut self, - size: (usize, usize), - srgba_pixels: &[egui::Color32], - ) -> egui::TextureId; + fn alloc(&self, image: Image) -> egui::TextureId; /// Free the given texture. - fn free(&mut self, id: egui::TextureId); + fn free(&self, id: egui::TextureId); +} + +/// A 2D color image in RAM. +#[derive(Clone, Default)] +pub struct Image { + /// width, height + pub size: [usize; 2], + /// The pixels, row by row, from top to bottom. + pub pixels: Vec, +} + +impl Image { + /// Create an `Image` from flat RGBA data. + /// Panics unless `size[0] * size[1] * 4 == rgba.len()`. + /// This is usually what you want to use after having loaded an image. + pub fn from_rgba_unmultiplied(size: [usize; 2], rgba: &[u8]) -> Self { + assert_eq!(size[0] * size[1] * 4, rgba.len()); + let pixels = rgba + .chunks_exact(4) + .map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3])) + .collect(); + Self { size, pixels } + } } /// Abstraction for platform dependent texture reference @@ -367,13 +427,6 @@ pub trait NativeTexture { fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture); } -/// How to signal the [`egui`] integration that a repaint is required. -pub trait RepaintSignal: Send + Sync { - /// This signals the [`egui`] integration that a repaint is required. - /// This is meant to be called when a background process finishes in an async context and/or background thread. - fn request_repaint(&self); -} - // ---------------------------------------------------------------------------- /// A place where you can store custom data in a way that persists when you restart the app. @@ -423,29 +476,68 @@ pub const APP_KEY: &str = "app"; /// You only need to look here if you are writing a backend for `epi`. pub mod backend { + use std::collections::HashMap; + use super::*; + /// How to signal the [`egui`] integration that a repaint is required. + pub trait RepaintSignal: Send + Sync { + /// This signals the [`egui`] integration that a repaint is required. + /// + /// Call this e.g. when a background process finishes in an async context and/or background thread. + fn request_repaint(&self); + } + /// The data required by [`Frame`] each frame. - pub struct FrameBuilder<'a> { + pub struct FrameData { /// Information about the integration. pub info: IntegrationInfo, - /// A way to allocate textures (on integrations that support it). - pub tex_allocator: &'a mut dyn TextureAllocator, /// Where the app can issue commands back to the integration. - pub output: &'a mut AppOutput, + pub output: AppOutput, /// If you need to request a repaint from another thread, clone this and send it to that other thread. pub repaint_signal: std::sync::Arc, } - impl<'a> FrameBuilder<'a> { - /// Wrap us in a [`Frame`] to send to [`App::update`]. - pub fn build(self) -> Frame<'a> { - Frame(self) + /// The data needed in order to allocate and free textures/images. + #[derive(Default)] + #[must_use] + pub struct TexAllocationData { + /// We allocate texture id linearly. + pub(crate) next_id: u64, + /// New creations this frame + pub creations: HashMap, + /// destructions this frame. + pub destructions: Vec, + } + + impl TexAllocationData { + /// Should only be used by integrations + pub fn take(&mut self) -> Self { + let next_id = self.next_id; + let ret = std::mem::take(self); + self.next_id = next_id; + ret + } + + /// Allocate a new texture. + pub fn alloc(&mut self, image: Image) -> egui::TextureId { + let id = self.next_id; + self.next_id += 1; + self.creations.insert(id, image); + egui::TextureId::User(id) + } + + /// Free an existing texture. + pub fn free(&mut self, id: egui::TextureId) { + if let egui::TextureId::User(id) = id { + self.destructions.push(id); + } } } /// Action that can be taken by the user app. - #[derive(Clone, Debug, Default, PartialEq)] + #[derive(Default)] + #[must_use] pub struct AppOutput { /// Set to `true` to stop the app. /// This does nothing for web apps. @@ -457,10 +549,13 @@ pub mod backend { /// Set to some string to rename the outer window (e.g. glium window) to this title. pub window_title: Option, - /// Set to some bool to change window decorations + /// Set to some bool to change window decorations. pub decorated: Option, - /// Set to true to drap window + /// Set to true to drag window while primary mouse button is down. pub drag_window: bool, + + /// A way to allocate textures (on integrations that support it). + pub tex_allocation_data: TexAllocationData, } } From b88bec9ca338e9d9f4bf269d52866b5040e3ac78 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 10:05:10 +0100 Subject: [PATCH 11/41] Document that `CtxRef` is generational and shouldn't be stored Related to https://github.com/emilk/egui/issues/1005 --- egui/src/context.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 83032b2d..c506b3b4 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -26,6 +26,9 @@ use epaint::{stats::*, text::Fonts, *}; /// /// [`CtxRef`] is cheap to clone, and any clones refers to the same mutable data. /// +/// A [`CtxRef`] is only valid for the duration of a frame, and so you should not store a [`CtxRef`] between frames. +/// A new [`CtxRef`] is created each frame by calling [`Self::run`]. +/// /// # Example: /// /// ``` no_run @@ -49,7 +52,6 @@ use epaint::{stats::*, text::Fonts, *}; /// paint(clipped_meshes); /// } /// ``` -/// #[derive(Clone)] pub struct CtxRef(std::sync::Arc); @@ -325,16 +327,17 @@ impl CtxRef { // ---------------------------------------------------------------------------- -/// This is the first thing you need when working with egui. Create using [`CtxRef`]. +/// Your handle to egui. /// -/// Contains the [`InputState`], [`Memory`], [`Output`], and more. +/// This is the first thing you need when working with egui. +/// Use [`CtxRef`] to create and refer to a [`Context`]. /// -/// Your handle to Egui. +/// Contains the [`InputState`], [`Memory`], [`Output`], and more./// /// -/// Almost all methods are marked `&self`, `Context` has interior mutability (protected by mutexes). +/// Almost all methods are marked `&self`, [`Context`] has interior mutability (protected by mutexes). /// Multi-threaded access to a [`Context`] is behind the feature flag `multi_threaded`. /// Normally you'd always do all ui work on one thread, or perhaps use multiple contexts, -/// but if you really want to access the same Context from multiple threads, it *SHOULD* be fine, +/// but if you really want to access the same [`Context`] from multiple threads, it *SHOULD* be fine, /// but you are likely the first person to try it. #[derive(Default)] pub struct Context { @@ -343,7 +346,7 @@ pub struct Context { // This means everything else needs to be behind an Arc. // We can probably come up with a nicer design. // - /// None until first call to `begin_frame`. + /// `None` until the start of the first frame. fonts: Option>, memory: Arc>, animation_manager: Arc>, From c63996179b73dfa83918d973ccb72a0dfd18d084 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 10:03:56 +0100 Subject: [PATCH 12/41] README.md: add link to discussion of begin/end calls vs closures --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13d6ae77..07feea9b 100644 --- a/README.md +++ b/README.md @@ -339,7 +339,7 @@ All colors have premultiplied alpha. egui uses the builder pattern for construction widgets. For instance: `ui.add(Label::new("Hello").text_color(RED));` I am not a big fan of the builder pattern (it is quite verbose both in implementation and in use) but until Rust has named, default arguments it is the best we can do. To alleviate some of the verbosity there are common-case helper functions, like `ui.label("Hello");`. -Instead of using matching `begin/end` style function calls (which can be error prone) egui prefers to use `FnOnce` closures passed to a wrapping function. Lambdas are a bit ugly though, so I'd like to find a nicer solution to this. +Instead of using matching `begin/end` style function calls (which can be error prone) egui prefers to use `FnOnce` closures passed to a wrapping function. Lambdas are a bit ugly though, so I'd like to find a nicer solution to this. More discussion of this at . ### Inspiration From 2684929a5d9efa2d0fd869a7cbd33d13ea27162a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 10:08:28 +0100 Subject: [PATCH 13/41] Make Memory::lock_focus public closes https://github.com/emilk/egui/issues/993 --- egui/src/memory.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/egui/src/memory.rs b/egui/src/memory.rs index b5350f5c..f8d615ed 100644 --- a/egui/src/memory.rs +++ b/egui/src/memory.rs @@ -327,13 +327,16 @@ impl Memory { self.interaction.focus.id } - pub(crate) fn lock_focus(&mut self, id: Id, lock_focus: bool) { + /// Prevent keyboard focus from moving away from this widget even if users presses the tab key. + /// You must first give focus to the widget before calling this. + pub fn lock_focus(&mut self, id: Id, lock_focus: bool) { if self.had_focus_last_frame(id) && self.has_focus(id) { self.interaction.focus.is_focus_locked = lock_focus; } } - pub(crate) fn has_lock_focus(&mut self, id: Id) -> bool { + /// Is the keyboard focus locked on this widget? If so the focus won't move even if the user presses the tab key. + pub fn has_lock_focus(&mut self, id: Id) -> bool { if self.had_focus_last_frame(id) && self.has_focus(id) { self.interaction.focus.is_focus_locked } else { From 369ce95bbdbf14143861c6af4afdf2d106c29e9b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 10:45:32 +0100 Subject: [PATCH 14/41] Add `CollapsingHeader::open` to control if it is open or collapsed (#1006) Closes https://github.com/emilk/egui/issues/978 --- CHANGELOG.md | 1 + egui/src/containers/collapsing_header.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03b3e3aa..036e675a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * When using a custom font you can now specify a font index ([#873](https://github.com/emilk/egui/pull/873)). * Add vertical sliders with `Slider::new(…).vertical()` ([#875](https://github.com/emilk/egui/pull/875)). * Add `Button::image_and_text` ([#832](https://github.com/emilk/egui/pull/832)). +* Add `CollapsingHeader::open` to control if it is open or collapsed ([#1006](https://github.com/emilk/egui/pull/1006)). ### Changed 🔧 * MSRV (Minimum Supported Rust Version) is now `1.56.0`. diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index 9618b5b8..0411c163 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -144,6 +144,7 @@ pub(crate) fn paint_icon(ui: &mut Ui, openness: f32, response: &Response) { pub struct CollapsingHeader { text: WidgetText, default_open: bool, + open: Option, id_source: Id, enabled: bool, selectable: bool, @@ -164,6 +165,7 @@ impl CollapsingHeader { Self { text, default_open: false, + open: None, id_source, enabled: true, selectable: false, @@ -179,6 +181,16 @@ impl CollapsingHeader { self } + /// Calling `.open(Some(true))` will make the collapsing header open this frame (or stay open). + /// + /// Calling `.open(Some(false))` will make the collapsing header close this frame (or stay closed). + /// + /// Calling `.open(None)` has no effect (default). + pub fn open(mut self, open: Option) -> Self { + self.open = open; + self + } + /// Explicitly set the source of the `Id` of this widget, instead of using title label. /// This is useful if the title label is dynamic or not unique. pub fn id_source(mut self, id_source: impl Hash) -> Self { @@ -256,6 +268,7 @@ impl CollapsingHeader { let Self { text, default_open, + open, id_source, enabled: _, selectable: _, @@ -291,10 +304,16 @@ impl CollapsingHeader { ); let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open); - if header_response.clicked() { + if let Some(open) = open { + if open != state.open { + state.toggle(ui); + header_response.mark_changed(); + } + } else if header_response.clicked() { state.toggle(ui); header_response.mark_changed(); } + header_response .widget_info(|| WidgetInfo::labeled(WidgetType::CollapsingHeader, text.text())); From f919b0cc056c2cbb01703e7c70e22d15df724161 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 13:09:14 +0100 Subject: [PATCH 15/41] Clean up context menu documentation --- egui/src/context.rs | 12 +----------- egui/src/menu.rs | 29 ++++++++++++++++++++++------- egui/src/response.rs | 4 +++- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index c506b3b4..10790675 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -313,16 +313,6 @@ impl CtxRef { pub fn debug_painter(&self) -> Painter { Self::layer_painter(self, LayerId::debug()) } - - /// Respond to secondary clicks (right-clicks) by showing the given menu. - pub(crate) fn show_context_menu( - &self, - response: &Response, - add_contents: impl FnOnce(&mut Ui), - ) { - self.context_menu_system() - .context_menu(response, add_contents); - } } // ---------------------------------------------------------------------------- @@ -332,7 +322,7 @@ impl CtxRef { /// This is the first thing you need when working with egui. /// Use [`CtxRef`] to create and refer to a [`Context`]. /// -/// Contains the [`InputState`], [`Memory`], [`Output`], and more./// +/// Contains the [`InputState`], [`Memory`], [`Output`], and more. /// /// Almost all methods are marked `&self`, [`Context`] has interior mutability (protected by mutexes). /// Multi-threaded access to a [`Context`] is behind the feature flag `multi_threaded`. diff --git a/egui/src/menu.rs b/egui/src/menu.rs index 18231460..986d695e 100644 --- a/egui/src/menu.rs +++ b/egui/src/menu.rs @@ -42,7 +42,7 @@ impl BarState { ctx.memory().data.insert_temp(bar_id, self); } - /// Show a menu at pointer if right-clicked response. + /// Show a menu at pointer if primary-clicked response. /// Should be called from [`Context`] on a [`Response`] pub fn bar_menu( &mut self, @@ -87,8 +87,11 @@ pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResp add_contents(ui) }) } + /// Construct a top level menu in a menu bar. This would be e.g. "File", "Edit" etc. /// +/// Responds to primary clicks. +/// /// Returns `None` if the menu is not open. pub fn menu_button( ui: &mut Ui, @@ -97,8 +100,11 @@ pub fn menu_button( ) -> InnerResponse> { stationary_menu_impl(ui, title, Box::new(add_contents)) } + /// Construct a nested sub menu in another menu. /// +/// Opens on hover. +/// /// Returns `None` if the menu is not open. pub(crate) fn submenu_button( ui: &mut Ui, @@ -150,7 +156,9 @@ pub(crate) fn menu_ui<'c, R>( inner_response } -/// build a top level menu with a button +/// Build a top level menu with a button. +/// +/// Responds to primary clicks. fn stationary_menu_impl<'c, R>( ui: &mut Ui, title: impl Into, @@ -275,7 +283,10 @@ impl MenuRoot { } (MenuResponse::Stay, None) } - /// interaction with a stationary menu, i.e. fixed in another Ui + + /// Interaction with a stationary menu, i.e. fixed in another Ui. + /// + /// Responds to primary clicks. fn stationary_interaction( response: &Response, root: &mut MenuRootManager, @@ -310,7 +321,8 @@ impl MenuRoot { } MenuResponse::Stay } - /// interaction with a context menu + + /// Interaction with a context menu (secondary clicks). fn context_interaction( response: &Response, root: &mut Option, @@ -328,10 +340,9 @@ impl MenuRoot { destroy = root.id == response.id; } if !in_old_menu { - let in_target = response.hovered(); - if in_target && pointer.secondary_down() { + if response.hovered() && pointer.secondary_down() { return MenuResponse::Create(pos, id); - } else if (in_target && pointer.primary_down()) || destroy { + } else if (response.hovered() && pointer.primary_down()) || destroy { return MenuResponse::Close; } } @@ -339,6 +350,7 @@ impl MenuRoot { } MenuResponse::Stay } + fn handle_menu_response(root: &mut MenuRootManager, menu_response: MenuResponse) { match menu_response { MenuResponse::Create(pos, id) => { @@ -348,11 +360,14 @@ impl MenuRoot { MenuResponse::Stay => {} } } + /// Respond to secondary (right) clicks. pub fn context_click_interaction(response: &Response, root: &mut MenuRootManager, id: Id) { let menu_response = Self::context_interaction(response, root, id); Self::handle_menu_response(root, menu_response); } + + // Responds to primary clicks. pub fn stationary_click_interaction(response: &Response, root: &mut MenuRootManager, id: Id) { let menu_response = Self::stationary_interaction(response, root, id); Self::handle_menu_response(root, menu_response); diff --git a/egui/src/response.rs b/egui/src/response.rs index 177f66cd..e28efd4c 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -491,7 +491,9 @@ impl Response { /// # }); /// ``` pub fn context_menu(self, add_contents: impl FnOnce(&mut Ui)) -> Self { - self.ctx.show_context_menu(&self, add_contents); + self.ctx + .context_menu_system() + .context_menu(&self, add_contents); self } } From cda4c8ba13d06fd932e9c2963b4c371551fc37c5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 13:22:01 +0100 Subject: [PATCH 16/41] Minor cleanup following https://github.com/emilk/egui/pull/999 --- egui_glium/src/painter.rs | 6 ++++-- egui_glow/src/misc_util.rs | 2 -- egui_glow/src/painter.rs | 8 ++++++-- egui_web/src/webgl1.rs | 3 +-- egui_web/src/webgl2.rs | 3 +-- epi/src/lib.rs | 5 ++--- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/egui_glium/src/painter.rs b/egui_glium/src/painter.rs index e5dc378d..e190171a 100644 --- a/egui_glium/src/painter.rs +++ b/egui_glium/src/painter.rs @@ -25,8 +25,8 @@ pub struct Painter { /// Index is the same as in [`egui::TextureId::User`]. user_textures: HashMap>, - // TODO: 128-bit texture space? - next_native_tex_id: u64, + #[cfg(feature = "epi")] + next_native_tex_id: u64, // TODO: 128-bit texture space? } impl Painter { @@ -57,6 +57,7 @@ impl Painter { egui_texture: None, egui_texture_version: None, user_textures: Default::default(), + #[cfg(feature = "epi")] next_native_tex_id: 1 << 32, } } @@ -222,6 +223,7 @@ impl Painter { // ------------------------------------------------------------------------ + #[cfg(feature = "epi")] pub fn set_texture( &mut self, facade: &dyn glium::backend::Facade, diff --git a/egui_glow/src/misc_util.rs b/egui_glow/src/misc_util.rs index 6d527ed6..0ce12000 100644 --- a/egui_glow/src/misc_util.rs +++ b/egui_glow/src/misc_util.rs @@ -1,8 +1,6 @@ #![allow(unsafe_code)] use glow::HasContext; use std::option::Option::Some; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen::JsValue; pub(crate) fn srgbtexture2d( gl: &glow::Context, diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index 0c848094..1a45281d 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -41,8 +41,10 @@ pub struct Painter { /// Index is the same as in [`egui::TextureId::User`]. user_textures: HashMap, - // TODO: 128-bit texture space? - next_native_tex_id: u64, + + #[cfg(feature = "epi")] + next_native_tex_id: u64, // TODO: 128-bit texture space? + /// Stores outdated OpenGL textures that are yet to be deleted textures_to_destroy: Vec, @@ -192,6 +194,7 @@ impl Painter { vertex_buffer, element_array_buffer, user_textures: Default::default(), + #[cfg(feature = "epi")] next_native_tex_id: 1 << 32, textures_to_destroy: Vec::new(), destroyed: false, @@ -386,6 +389,7 @@ impl Painter { // ------------------------------------------------------------------------ + #[cfg(feature = "epi")] pub fn set_texture(&mut self, gl: &glow::Context, tex_id: u64, image: &epi::Image) { self.assert_not_destroyed(); diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index db7751fc..39cba041 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -34,8 +34,7 @@ pub struct WebGlPainter { /// Index is the same as in [`egui::TextureId::User`]. user_textures: HashMap, - // TODO: 128-bit texture space? - next_native_tex_id: u64, + next_native_tex_id: u64, // TODO: 128-bit texture space? } impl WebGlPainter { diff --git a/egui_web/src/webgl2.rs b/egui_web/src/webgl2.rs index e774f984..207bc833 100644 --- a/egui_web/src/webgl2.rs +++ b/egui_web/src/webgl2.rs @@ -34,8 +34,7 @@ pub struct WebGl2Painter { /// Index is the same as in [`egui::TextureId::User`]. user_textures: HashMap, - // TODO: 128-bit texture space? - next_native_tex_id: u64, + next_native_tex_id: u64, // TODO: 128-bit texture space? } impl WebGl2Painter { diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 3dbcd86f..436041b0 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -419,11 +419,10 @@ pub trait NativeTexture { /// The native texture type. type Texture; - /// Bind native texture to egui texture + /// Bind native texture to an egui texture id. fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId; - /// Change id's actual pointing texture - /// only for user texture + /// Change what texture the given id refers to. fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture); } From c412fd4a9c5d2964f10522c238eead601188fcaa Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 14:13:51 +0100 Subject: [PATCH 17/41] Add loading animation while waiting for wasm to load Closes https://github.com/emilk/egui/issues/1009 --- docs/index.html | 57 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/docs/index.html b/docs/index.html index 9cfcb27a..47975923 100644 --- a/docs/index.html +++ b/docs/index.html @@ -45,12 +45,59 @@ left: 50%; transform: translate(-50%, 0%); } + + .loading { + margin-right: auto; + margin-left: auto; + display: block; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-size: 24px; + font-family: Ubuntu-Light, Helvetica, sans-serif; + } + + /* ---------------------------------------------- */ + /* Loading animation from https://loading.io/css/ */ + .lds-dual-ring { + display: inline-block; + width: 24px; + height: 24px; + } + + .lds-dual-ring:after { + content: " "; + display: block; + width: 24px; + height: 24px; + margin: 0px; + border-radius: 50%; + border: 3px solid #fff; + border-color: #fff transparent #fff transparent; + animation: lds-dual-ring 1.2s linear infinite; + } + + @keyframes lds-dual-ring { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } + } - + +
+ Loading…   +
+
From beb2ea2ef6e5ab89be82ef4af1d0fe4638239cb5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 14:14:49 +0100 Subject: [PATCH 18/41] Add favicon.ico - a single "e" for "egui", using the Ubuntu-Light font --- docs/favicon.ico | Bin 0 -> 15406 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 docs/favicon.ico diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..61ad031aa5b8aadf968a2b864649c3bb84b91735 GIT binary patch literal 15406 zcmeHOTS%2z6#ku=ri~V2rUhCUy zul?_}*Iq}Ge57xsMT;aZO;YxElJv7ANhZ^$``{lX=}&$Z8anqrNRqmKlB8g+!%euw zr{`RJ@nCr{}7`SYslo9iGvJe)p!_&^sfT%aRIj?AMq zYu4E185R~M+PAj0((T)~1wjYkxnaWwyX}ExaBz^$oH?V^J$(2uO-xKsU|^u~%p9}j zb#`_(O-@cyd3iYhqMwiQ$ zE&J%GjJY|up!xg7kAjAW_|BM^Vwily6<>V$_YLFyjr%*v^q-@BR@)9T=42Hz93RM5 z+g9&-jN@0PDZTls`}gms?(S}}?qTh-B&=tfHf=Hl!_lKh>D{|`ip*E9UQv5{JGHd52uzUu z{{4Fj4Gq;@er#+kO;1k?+2iBml#`S5*}9FjG$|=bciFJ9YuBy`+324ZpGyz>39vPGDmw)&*y-Oimm75SF) z&Dy=5b{H8MsmO0=Xb`p!`?sX4SFbAdfLTi)?bUt${JG$L@7_JDe9xXeE9zj5z+bn= zQ_K6x%1Xg|c6OGwZQJ%4?-eUnP)|>fr~@0(!dp#UjKS;IuLXbXBerbWqR7Dhp{lA% zyn{WImX<2-)bLhY=g^@;V*dsi(8K-v_o=?VUhG3;JH*InNhwf%9l9=?Zr_Uxh4r%zK^Ss4`+6i`e|jNx(}#p`Y789tq}#|irn-v7-w zTdpjRnnS5-=NhE)N z|3yoeE=_0Mb+HcrVKRKYwAuqOF}}aK>}I?NeSLiqZkGJ~{C?o)mB6i)r>p8S){l(& zcl2S&k|hUl?g$^~YO1NWoTQ68>t$9?E#@)*0Z)EBTbx!qi~#A)r`ld)UtllQsT zC-mCD*KGqh_r%#HVw;F3AZCR!E-sFuqoc)M+8xga*RNkM_T1O6U#G6FE*c#jrJ0!- z5tG3A^2?VmskgV6nwpvj@xs*9R9d-mrCaRJ_wLeVj84t*eIhj|I?u!n(x0ouHIvr92)8K)aJZYXwx^QVf63b)Ohu_R*Hy-aQe6* z=g1sC>>p==ju5`Hdg@jUFRWSS_!n|rTwLsQ{P11OG2=Vh-`}r_%;!CLAV)xr&h)Ia zapT5$_(w)Y2+!87TW6Q<+_^Kat(IItz50MP)ZA}?&#+_14!e59cekyrO~H?KPtP-9 zE&W5jrEEj+lW}fk&!5286Mq;$bJ3c;M1RlnU8z={$+8unb4^I9u!Z~d=3Hs>9G@A!LdKpz{x`5mACYW^>myXc>>|HXaq z*z;?~-@*73nLO?c8<;uge%6kDFuC2CJTL(pW9&rE T$>PO}zeoOz_vh8XLNxF{TPS{( literal 0 HcmV?d00001 From 5b9a349c264bc65488aa96abca9cc1d33c551484 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 14:24:59 +0100 Subject: [PATCH 19/41] Clean up glow painter destroy code --- egui_glow/src/painter.rs | 26 ++++++++++++++------------ egui_glow/src/post_process.rs | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index 1a45281d..b2bb84cf 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -48,7 +48,7 @@ pub struct Painter { /// Stores outdated OpenGL textures that are yet to be deleted textures_to_destroy: Vec, - /// Only used in debug builds, to make sure we are destroyed correctly. + /// Used to make sure we are destroyed correctly. destroyed: bool, } @@ -452,18 +452,19 @@ impl Painter { /// that should be deleted. pub fn destroy(&mut self, gl: &glow::Context) { - debug_assert!(!self.destroyed, "Only destroy once!"); - unsafe { - self.destroy_gl(gl); - if let Some(ref post_process) = self.post_process { - post_process.destroy(gl); + if !self.destroyed { + unsafe { + self.destroy_gl(gl); + if let Some(ref post_process) = self.post_process { + post_process.destroy(gl); + } } + self.destroyed = true; } - self.destroyed = true; } fn assert_not_destroyed(&self) { - debug_assert!(!self.destroyed, "the egui glow has already been destroyed!"); + assert!(!self.destroyed, "the egui glow has already been destroyed!"); } } @@ -486,10 +487,11 @@ pub fn clear(gl: &glow::Context, dimension: [u32; 2], clear_color: egui::Rgba) { impl Drop for Painter { fn drop(&mut self) { - debug_assert!( - self.destroyed, - "Make sure to call destroy() before dropping to avoid leaking OpenGL objects!" - ); + if !self.destroyed { + eprintln!( + "You forgot to call destroy() on the egui glow painter. Resources will leak!" + ); + } } } diff --git a/egui_glow/src/post_process.rs b/egui_glow/src/post_process.rs index 7a4ef3d1..ecfc2abc 100644 --- a/egui_glow/src/post_process.rs +++ b/egui_glow/src/post_process.rs @@ -221,6 +221,7 @@ impl PostProcess { gl.bind_texture(glow::TEXTURE_2D, None); gl.use_program(None); } + pub(crate) unsafe fn destroy(&self, gl: &glow::Context) { gl.delete_buffer(self.pos_buffer); gl.delete_buffer(self.index_buffer); From 811b974003110f7d42a1c0d2252b2fab51e41141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Br=C3=B6nneg=C3=A5rd?= <1162652+rasmusgo@users.noreply.github.com> Date: Tue, 28 Dec 2021 16:42:22 +0100 Subject: [PATCH 20/41] Fix typo "the close" -> "this close" in style.rs (#887) --- egui/src/style.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/egui/src/style.rs b/egui/src/style.rs index 137c426e..bb8159b4 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -154,10 +154,10 @@ impl Spacing { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct Interaction { - /// Mouse must be the close to the side of a window to resize + /// Mouse must be this close to the side of a window to resize pub resize_grab_radius_side: f32, - /// Mouse must be the close to the corner of a window to resize + /// Mouse must be this close to the corner of a window to resize pub resize_grab_radius_corner: f32, /// If `false`, tooltips will show up anytime you hover anything, even is mouse is still moving From 00f965de87ddb07805505a0b7ed3738e0da51a48 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 17:22:48 +0100 Subject: [PATCH 21/41] Add Context::animate_bool_with_time Closes https://github.com/emilk/egui/discussions/984 --- egui/src/context.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/egui/src/context.rs b/egui/src/context.rs index 10790675..0553dc1a 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -767,8 +767,15 @@ impl Context { /// Calling this with `value = false` will always yield a number less than one, quickly going towards zero. /// /// The function will call [`Self::request_repaint()`] when appropriate. + /// + /// The animation time is taken from [`Style::animation_time`]. pub fn animate_bool(&self, id: Id, value: bool) -> f32 { let animation_time = self.style().animation_time; + self.animate_bool_with_time(id, value, animation_time) + } + + /// Like [`Self::animate_bool`] but allows you to control the animation time. + pub fn animate_bool_with_time(&self, id: Id, value: bool, animation_time: f32) -> f32 { let animated_value = self.animation_manager .lock() From 68fca09df90271fa90f940d78540ff2f8365360d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 28 Dec 2021 17:33:49 +0100 Subject: [PATCH 22/41] Improve documentation --- README.md | 4 ++-- docs/README.md | 3 +++ egui/src/ui.rs | 2 ++ epi/src/lib.rs | 4 +++- 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index 07feea9b..e2c2fd6b 100644 --- a/README.md +++ b/README.md @@ -32,11 +32,11 @@ Sections: ## Quick start -If you just want to write a GUI application in Rust (for the web or for native), go to and follow the instructions there! +If you just want to write a GUI application in Rust (for the web or for native), go to and follow the instructions there! The official docs are at . For inspiration, check out the [the egui web demo](https://emilk.github.io/egui/index.html) and follow the links in it to its source code. There is also an excellent tutorial video at . If you want to integrate egui into an existing engine, go to the [Integrations](#integrations) section. -If you have questions, use [GitHub Discussions](https://github.com/emilk/egui/discussions). There is also [an egui discord server](https://discord.gg/JFcEma9bJq). If you want to contribute to egui, please read the [Contributing Guidelines](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) +If you have questions, use [GitHub Discussions](https://github.com/emilk/egui/discussions). There is also [an egui discord server](https://discord.gg/JFcEma9bJq). If you want to contribute to egui, please read the [Contributing Guidelines](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md). ## Demo diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..077fb745 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +This folder contains the files required for the egui web demo hosted at . + +The reason the folder is called "docs" is because that is the name that GitHub requires in order to host a web page from the `master` branch of a repository. diff --git a/egui/src/ui.rs b/egui/src/ui.rs index bdccf422..cbaba6f6 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -119,6 +119,8 @@ impl Ui { } /// Style options for this `Ui` and its children. + /// + /// Note that this may be a different [`Style`] than that of [`Context::style`]. #[inline] pub fn style(&self) -> &std::sync::Arc