diff --git a/Cargo.lock b/Cargo.lock index fa5edf64e..018e8fd6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ab_glyph" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + [[package]] name = "addr2line" version = "0.19.0" @@ -49,6 +65,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-activity" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" +dependencies = [ + "android-properties", + "bitflags", + "cc", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -137,6 +177,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "arrayvec" version = "0.7.2" @@ -250,6 +296,25 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-sys" +version = "0.1.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" +dependencies = [ + "objc-sys", +] + +[[package]] +name = "block2" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" +dependencies = [ + "block-sys", + "objc2-encode", +] + [[package]] name = "bumpalo" version = "3.12.2" @@ -294,6 +359,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "calloop" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a59225be45a478d772ce015d9743e49e92798ece9e34eda9a6aa2a6a7f40192" +dependencies = [ + "log", + "nix 0.25.1", + "slotmap", + "thiserror", + "vec_map", +] + [[package]] name = "camino" version = "1.1.4" @@ -331,6 +409,9 @@ name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -338,6 +419,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" version = "0.4.24" @@ -465,6 +552,19 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.1.1" @@ -541,6 +641,21 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -706,6 +821,18 @@ dependencies = [ "wgpu", ] +[[package]] +name = "fj-window" +version = "0.46.0" +dependencies = [ + "fj-interop", + "fj-math", + "fj-viewer", + "futures", + "thiserror", + "winit", +] + [[package]] name = "flate2" version = "1.0.26" @@ -1172,6 +1299,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -1224,6 +1354,21 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -1348,6 +1493,24 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "metal" version = "0.24.0" @@ -1368,6 +1531,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1464,6 +1633,70 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -1536,6 +1769,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "objc" version = "0.2.7" @@ -1546,6 +1800,32 @@ dependencies = [ "objc_exception", ] +[[package]] +name = "objc-sys" +version = "0.2.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" + +[[package]] +name = "objc2" +version = "0.3.0-beta.3.patch-leaks.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" +dependencies = [ + "block2", + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "2.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" +dependencies = [ + "objc-sys", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -1657,6 +1937,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978aa494585d3ca4ad74929863093e87cac9790d81fe7aba2b3dc2890643a0fc" +[[package]] +name = "orbclient" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" +dependencies = [ + "redox_syscall 0.3.5", +] + [[package]] name = "os_pipe" version = "0.9.2" @@ -1676,6 +1965,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "owned_ttf_parser" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1825,6 +2123,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2118,6 +2426,12 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.1.0" @@ -2134,6 +2448,19 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sctk-adwaita" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda4e97be1fd174ccc2aae81c8b694e803fa99b34e8fd0f057a9d70698e3ed09" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -2300,6 +2627,25 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smithay-client-toolkit" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" +dependencies = [ + "bitflags", + "calloop", + "dlib", + "lazy_static", + "log", + "memmap2", + "nix 0.24.3", + "pkg-config", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + [[package]] name = "snafu" version = "0.7.4" @@ -2376,6 +2722,12 @@ dependencies = [ "byteorder 0.4.2", ] +[[package]] +name = "strict-num" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df65f20698aeed245efdde3628a6b559ea1239bbb871af1b6e3b58c413b2bd1" + [[package]] name = "strsim" version = "0.10.0" @@ -2496,6 +2848,31 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-skia" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adbfb5d3f3dd57a0e11d12f4f13d4ebbbc1b5c15b7ab0a156d030b21da5f677c" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2594,6 +2971,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml_datetime" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" + +[[package]] +name = "toml_edit" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -2681,6 +3075,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "ttf-parser" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" + [[package]] name = "type-map" version = "0.5.0" @@ -2759,6 +3159,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" @@ -2859,6 +3265,79 @@ version = "2.0.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2f237e2271c3f9ccc633ee16918789514fd5a823bf62ddce21f8a730a1d9930" +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix 0.24.3", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +dependencies = [ + "nix 0.24.3", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +dependencies = [ + "nix 0.24.3", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.63" @@ -3181,6 +3660,50 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winit" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "866db3f712fffba75d31bf0cdecf357c8aeafd158c5b7ab51dba2a2b2d47f196" +dependencies = [ + "android-activity", + "bitflags", + "cfg_aliases", + "core-foundation", + "core-graphics", + "dispatch", + "instant", + "libc", + "log", + "mio", + "ndk", + "objc2", + "once_cell", + "orbclient", + "percent-encoding", + "raw-window-handle", + "redox_syscall 0.3.5", + "sctk-adwaita", + "smithay-client-toolkit", + "wasm-bindgen", + "wayland-client", + "wayland-commons", + "wayland-protocols", + "wayland-scanner", + "web-sys", + "windows-sys 0.45.0", + "x11-dl", +] + +[[package]] +name = "winnow" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" @@ -3190,6 +3713,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom", +] + +[[package]] +name = "xml-rs" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8f380ae16a37b30e6a2cf67040608071384b1450c189e61bea3ff57cde922d" + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index f376828fd..6cdbabfaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "crates/fj-kernel", "crates/fj-math", "crates/fj-viewer", + "crates/fj-window", "tools/autolib", "tools/automator", diff --git a/crates/fj-window/Cargo.toml b/crates/fj-window/Cargo.toml new file mode 100644 index 000000000..be211b88b --- /dev/null +++ b/crates/fj-window/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "fj-window" +version.workspace = true +edition.workspace = true +description.workspace = true +readme.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +keywords.workspace = true +categories.workspace = true + +[dependencies] +fj-interop.workspace = true +fj-math.workspace = true +fj-viewer.workspace = true +futures = "0.3.28" +thiserror = "1.0.40" +winit = "0.28.6" diff --git a/crates/fj-window/src/lib.rs b/crates/fj-window/src/lib.rs new file mode 100644 index 000000000..0a317a64b --- /dev/null +++ b/crates/fj-window/src/lib.rs @@ -0,0 +1,16 @@ +//! # Fornjot Model Viewer +//! +//! [Fornjot] is an early-stage b-rep CAD kernel written in Rust. The kernel is +//! split into multiple libraries that can be used semi-independently, and this +//! is one of those. +//! +//! This library provides a window abstraction based on Winit. +//! +//! [Fornjot]: https://www.fornjot.app/ + +#![warn(missing_docs)] + +mod run; +mod window; + +pub use self::run::run; diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs new file mode 100644 index 000000000..d728a7bc5 --- /dev/null +++ b/crates/fj-window/src/run.rs @@ -0,0 +1,219 @@ +use fj_interop::{ + debug::DebugInfo, mesh::Mesh, processed_shape::ProcessedShape, +}; +use fj_math::{Aabb, Point}; +use fj_viewer::{ + InputEvent, NormalizedScreenPosition, RendererInitError, Screen, + ScreenSize, Viewer, +}; +use futures::executor::block_on; +use winit::{ + dpi::PhysicalPosition, + event::{ + ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, + VirtualKeyCode, WindowEvent, + }, + event_loop::{ControlFlow, EventLoop}, +}; + +use crate::window::{self, Window}; + +/// Initializes a model viewer for a given model and enters its process loop. +pub fn run(mesh: Mesh>, invert_zoom: bool) -> Result<(), Error> { + let event_loop = EventLoop::new(); + let window = Window::new(&event_loop)?; + let mut viewer = block_on(Viewer::new(&window))?; + + viewer.handle_shape_update(ProcessedShape { + aabb: Aabb::<3>::from_points(mesh.vertices()), + mesh, + debug_info: DebugInfo::new(), + }); + + let mut held_mouse_button = None; + let mut new_size = None; + let mut stop_drawing = false; + + event_loop.run(move |event, _, control_flow| { + let input_event = input_event( + &event, + &window, + &held_mouse_button, + &mut viewer.cursor, + invert_zoom, + ); + if let Some(input_event) = input_event { + viewer.handle_input_event(input_event); + } + + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + *control_flow = ControlFlow::Exit; + } + Event::WindowEvent { + event: + WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: ElementState::Pressed, + virtual_keycode: Some(virtual_key_code), + .. + }, + .. + }, + .. + } => match virtual_key_code { + VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit, + VirtualKeyCode::Key1 => { + viewer.toggle_draw_model(); + } + VirtualKeyCode::Key2 => { + viewer.toggle_draw_mesh(); + } + VirtualKeyCode::Key3 => { + viewer.toggle_draw_debug(); + } + _ => {} + }, + Event::WindowEvent { + event: WindowEvent::Resized(size), + .. + } => { + new_size = Some(ScreenSize { + width: size.width, + height: size.height, + }); + } + Event::WindowEvent { + event: WindowEvent::MouseInput { state, button, .. }, + .. + } => match state { + ElementState::Pressed => { + held_mouse_button = Some(button); + viewer.add_focus_point(); + } + ElementState::Released => { + held_mouse_button = None; + viewer.remove_focus_point(); + } + }, + Event::WindowEvent { + event: WindowEvent::MouseWheel { .. }, + .. + } => viewer.add_focus_point(), + Event::MainEventsCleared => { + window.window().request_redraw(); + } + Event::RedrawRequested(_) => { + // Only do a screen resize once per frame. This protects against + // spurious resize events that cause issues with the renderer. + if let Some(size) = new_size.take() { + stop_drawing = size.width == 0 || size.height == 0; + if !stop_drawing { + viewer.handle_screen_resize(size); + } + } + + if !stop_drawing { + viewer.draw(); + } + } + _ => {} + } + }); +} + +/// Main loop initialization error +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Error initializing window + #[error("Error initializing window")] + WindowInit(#[from] window::Error), + + /// Error initializing graphics + #[error("Error initializing graphics")] + GraphicsInit(#[from] RendererInitError), +} + +fn input_event( + event: &Event, + window: &Window, + held_mouse_button: &Option, + previous_cursor: &mut Option, + invert_zoom: bool, +) -> Option { + match event { + Event::WindowEvent { + event: WindowEvent::CursorMoved { position, .. }, + .. + } => { + let [width, height] = window.size().as_f64(); + let aspect_ratio = width / height; + + // Cursor position in normalized coordinates (-1 to +1) with + // aspect ratio taken into account. + let current = NormalizedScreenPosition { + x: position.x / width * 2. - 1., + y: -(position.y / height * 2. - 1.) / aspect_ratio, + }; + let event = match (*previous_cursor, held_mouse_button) { + (Some(previous), Some(button)) => match button { + MouseButton::Left => { + let diff_x = current.x - previous.x; + let diff_y = current.y - previous.y; + let angle_x = -diff_y * ROTATION_SENSITIVITY; + let angle_y = diff_x * ROTATION_SENSITIVITY; + + Some(InputEvent::Rotation { angle_x, angle_y }) + } + MouseButton::Right => { + Some(InputEvent::Translation { previous, current }) + } + _ => None, + }, + _ => None, + }; + *previous_cursor = Some(current); + event + } + Event::WindowEvent { + event: WindowEvent::MouseWheel { delta, .. }, + .. + } => { + let delta = match delta { + MouseScrollDelta::LineDelta(_, y) => { + f64::from(*y) * ZOOM_FACTOR_LINE + } + MouseScrollDelta::PixelDelta(PhysicalPosition { + y, .. + }) => y * ZOOM_FACTOR_PIXEL, + }; + + let delta = if invert_zoom { -delta } else { delta }; + + Some(InputEvent::Zoom(delta)) + } + _ => None, + } +} + +/// Affects the speed of zoom movement given a scroll wheel input in lines. +/// +/// Smaller values will move the camera less with the same input. +/// Larger values will move the camera more with the same input. +const ZOOM_FACTOR_LINE: f64 = 0.075; + +/// Affects the speed of zoom movement given a scroll wheel input in pixels. +/// +/// Smaller values will move the camera less with the same input. +/// Larger values will move the camera more with the same input. +const ZOOM_FACTOR_PIXEL: f64 = 0.005; + +/// Affects the speed of rotation given a change in normalized screen position [-1, 1] +/// +/// Smaller values will move the camera less with the same input. +/// Larger values will move the camera more with the same input. +const ROTATION_SENSITIVITY: f64 = 5.; diff --git a/crates/fj-window/src/window.rs b/crates/fj-window/src/window.rs new file mode 100644 index 000000000..2d94ea7f4 --- /dev/null +++ b/crates/fj-window/src/window.rs @@ -0,0 +1,41 @@ +use fj_viewer::{Screen, ScreenSize}; +use winit::{event_loop::EventLoop, window::WindowBuilder}; + +/// A window that can be used with `fj-viewer` +pub struct Window(winit::window::Window); + +impl Window { + /// Create an instance of `Window` from the given `EventLoop` + pub fn new(event_loop: &EventLoop) -> Result { + let window = WindowBuilder::new() + .with_title("Fornjot") + .with_maximized(true) + .with_decorations(true) + .with_transparent(false) + .build(event_loop)?; + + Ok(Self(window)) + } +} + +impl Screen for Window { + type Window = winit::window::Window; + + fn size(&self) -> ScreenSize { + let size = self.0.inner_size(); + + ScreenSize { + width: size.width, + height: size.height, + } + } + + fn window(&self) -> &winit::window::Window { + &self.0 + } +} + +/// Error initializing window +#[derive(Debug, thiserror::Error)] +#[error("Error initializing window")] +pub struct Error(#[from] pub winit::error::OsError);