From 159c5f1c5de390fa685f8921989ade9941e466f2 Mon Sep 17 00:00:00 2001 From: erenoku Date: Thu, 27 Oct 2022 19:54:36 +0300 Subject: [PATCH 1/6] Make it not crash if no model argument is supplied --- crates/fj-app/src/main.rs | 6 +++--- crates/fj-app/src/path.rs | 11 +++-------- crates/fj-host/src/host.rs | 22 ++++++++++++++-------- crates/fj-window/src/run.rs | 32 ++++++++++++++++++++------------ 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index b89c9cd70..c1e775540 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -42,18 +42,18 @@ fn main() -> anyhow::Result<()> { let args = Args::parse(); let config = Config::load()?; - let model_path = ModelPath::from_args_and_config(&args, &config)?; + let model_path = ModelPath::from_args_and_config(&args, &config); let parameters = args.parameters.unwrap_or_else(Parameters::empty); let shape_processor = ShapeProcessor { tolerance: args.tolerance, }; - let model = model_path.load_model(parameters)?; + let model = model_path.map(|m| m.load_model(parameters)).transpose()?; if let Some(export_path) = args.export { // export only mode. just load model, process, export and exit - let evaluation = model.evaluate()?; + let evaluation = model.unwrap().evaluate()?; let shape = shape_processor.process(&evaluation.shape)?; export(&shape.mesh, &export_path)?; diff --git a/crates/fj-app/src/path.rs b/crates/fj-app/src/path.rs index 3fd33d361..95c4c90c5 100644 --- a/crates/fj-app/src/path.rs +++ b/crates/fj-app/src/path.rs @@ -14,10 +14,7 @@ pub struct ModelPath { } impl ModelPath { - pub fn from_args_and_config( - args: &Args, - config: &Config, - ) -> anyhow::Result { + pub fn from_args_and_config(args: &Args, config: &Config) -> Option { let default_path = config.default_path.clone(); let model_path_from_args = args @@ -28,11 +25,9 @@ impl ModelPath { .default_model .as_ref() .map(|model| ModelPathSource::Config(model.clone())); - let model_path = model_path_from_args - .or(model_path_from_config) - .ok_or_else(no_model_error)?; + let model_path = model_path_from_args.or(model_path_from_config)?; - Ok(Self { + Some(Self { default_path, model_path, }) diff --git a/crates/fj-host/src/host.rs b/crates/fj-host/src/host.rs index 191423c5c..615ec1a68 100644 --- a/crates/fj-host/src/host.rs +++ b/crates/fj-host/src/host.rs @@ -13,15 +13,21 @@ impl Host { /// /// This is only useful, if you want to continuously watch the model for /// changes. If you don't just keep using `Model`. - pub fn from_model(model: Model) -> Result { - let watch_path = model.watch_path(); - let evaluator = Evaluator::from_model(model); - let _watcher = Watcher::watch_model(&watch_path, &evaluator)?; + pub fn from_model(model: Option) -> Option> { + if let Some(model) = model { + let watch_path = model.watch_path(); + let evaluator = Evaluator::from_model(model); + let _watcher = match Watcher::watch_model(&watch_path, &evaluator) { + Ok(_watcher) => _watcher, + Err(e) => return Some(Err(e)), + }; - Ok(Self { - evaluator, - _watcher, - }) + return Some(Ok(Self { + evaluator, + _watcher, + })); + } + None } /// Access a channel with evaluation events diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index b7066e928..e1753fc75 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -27,18 +27,21 @@ use crate::window::{self, Window}; /// Initializes a model viewer for a given model and enters its process loop. pub fn run( - model: Model, + model: Option, shape_processor: ShapeProcessor, invert_zoom: bool, ) -> Result<(), Error> { let mut status = StatusReport::new(); - let host = Host::from_model(model)?; + let host = Host::from_model(model).transpose()?; let event_loop = EventLoop::new(); let window = Window::new(&event_loop)?; let mut viewer = block_on(Viewer::new(&window))?; - let events = host.events(); + let events = match host { + Some(ref host) => Some(host.events()), + None => None, + }; let mut held_mouse_button = None; @@ -54,17 +57,22 @@ pub fn run( trace!("Handling event: {:?}", event); loop { - let event = events - .try_recv() - .map_err(|err| { - if err.is_disconnected() { - panic!("Expected channel to never disconnect"); - } - }) - .ok(); + let event = events.as_ref().map(|events| { + events + .try_recv() + .map_err(|err| { + if err.is_disconnected() { + panic!("Expected channel to never disconnect"); + } + }) + .ok() + }); let event = match event { - Some(status_update) => status_update, + Some(event) => match event { + Some(status_update) => status_update, + None => break, + }, None => break, }; From 48666d1f0aa9d80dec708daaebff6b95ecd386c2 Mon Sep 17 00:00:00 2001 From: erenoku Date: Fri, 28 Oct 2022 16:38:00 +0300 Subject: [PATCH 2/6] Handle no model parameter being passed --- Cargo.lock | 234 ++++++++++++++++++++++ crates/fj-viewer/Cargo.toml | 2 + crates/fj-viewer/src/file_dialog.rs | 9 + crates/fj-viewer/src/graphics/renderer.rs | 11 +- crates/fj-viewer/src/gui.rs | 77 ++++++- crates/fj-viewer/src/lib.rs | 3 +- crates/fj-viewer/src/viewer.rs | 16 +- crates/fj-window/Cargo.toml | 1 + crates/fj-window/src/run.rs | 46 ++++- crates/fj-window/src/window.rs | 6 +- 10 files changed, 390 insertions(+), 15 deletions(-) create mode 100644 crates/fj-viewer/src/file_dialog.rs diff --git a/Cargo.lock b/Cargo.lock index 90a9219fd..8a05b146c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,6 +142,18 @@ dependencies = [ "syn", ] +[[package]] +name = "atk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "atomic" version = "0.5.1" @@ -293,6 +305,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cairo-sys-rs" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "calloop" version = "0.10.1" @@ -344,6 +366,15 @@ version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +[[package]] +name = "cfg-expr" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -1066,12 +1097,14 @@ name = "fj-viewer" version = "0.21.0" dependencies = [ "bytemuck", + "crossbeam-channel", "egui", "egui-wgpu", "fj-interop", "fj-math", "getrandom", "raw-window-handle 0.4.3", + "rfd", "thiserror", "tracing", "wgpu", @@ -1082,6 +1115,7 @@ dependencies = [ name = "fj-window" version = "0.21.0" dependencies = [ + "crossbeam-channel", "egui-winit", "fj-host", "fj-interop", @@ -1290,6 +1324,36 @@ dependencies = [ "byteorder 1.4.3", ] +[[package]] +name = "gdk-pixbuf-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -1309,6 +1373,29 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +[[package]] +name = "gio-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "glow" version = "0.11.2" @@ -1360,6 +1447,17 @@ dependencies = [ "xi-unicode", ] +[[package]] +name = "gobject-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "gpu-alloc" version = "0.5.3" @@ -1399,6 +1497,24 @@ dependencies = [ "bitflags", ] +[[package]] +name = "gtk-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + [[package]] name = "h2" version = "0.3.15" @@ -2177,6 +2293,17 @@ dependencies = [ "objc_exception", ] +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -2186,6 +2313,15 @@ dependencies = [ "cc", ] +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "object" version = "0.29.0" @@ -2325,6 +2461,18 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "pango-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -2744,6 +2892,30 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfd" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" +dependencies = [ + "block", + "dispatch", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "lazy_static", + "log", + "objc", + "objc-foundation", + "objc_id", + "raw-window-handle 0.5.0", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows", +] + [[package]] name = "ring" version = "0.16.20" @@ -3175,6 +3347,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -3581,6 +3766,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" + [[package]] name = "version_check" version = "0.9.4" @@ -3916,6 +4107,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" +dependencies = [ + "windows_aarch64_msvc 0.37.0", + "windows_i686_gnu 0.37.0", + "windows_i686_msvc 0.37.0", + "windows_x86_64_gnu 0.37.0", + "windows_x86_64_msvc 0.37.0", +] + [[package]] name = "windows-sys" version = "0.36.1" @@ -3956,6 +4160,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" + [[package]] name = "windows_aarch64_msvc" version = "0.42.0" @@ -3968,6 +4178,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" + [[package]] name = "windows_i686_gnu" version = "0.42.0" @@ -3980,6 +4196,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" + [[package]] name = "windows_i686_msvc" version = "0.42.0" @@ -3992,6 +4214,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" + [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -4010,6 +4238,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" + [[package]] name = "windows_x86_64_msvc" version = "0.42.0" diff --git a/crates/fj-viewer/Cargo.toml b/crates/fj-viewer/Cargo.toml index 9c18ed9e9..6639ca4aa 100644 --- a/crates/fj-viewer/Cargo.toml +++ b/crates/fj-viewer/Cargo.toml @@ -12,11 +12,13 @@ categories.workspace = true [dependencies] bytemuck = "1.12.1" +crossbeam-channel = "0.5.6" egui = "0.19.0" egui-wgpu = "0.19.0" fj-interop.workspace = true fj-math.workspace = true raw-window-handle = "0.4.3" +rfd = "0.10.0" thiserror = "1.0.35" tracing = "0.1.37" wgpu_glyph = "0.17.0" diff --git a/crates/fj-viewer/src/file_dialog.rs b/crates/fj-viewer/src/file_dialog.rs new file mode 100644 index 000000000..504a6c261 --- /dev/null +++ b/crates/fj-viewer/src/file_dialog.rs @@ -0,0 +1,9 @@ +use std::{env::current_dir, path::PathBuf}; + +use rfd::FileDialog; + +pub fn show_file_dialog() -> Option { + FileDialog::new() + .set_directory(current_dir().unwrap_or_else(|_| PathBuf::from("/"))) + .pick_folder() +} diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 8cf46d9cb..eb63ba059 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -1,5 +1,6 @@ use std::{io, mem::size_of}; +use crossbeam_channel::{Receiver, Sender}; use thiserror::Error; use tracing::debug; use wgpu::util::DeviceExt as _; @@ -7,7 +8,7 @@ use wgpu_glyph::ab_glyph::InvalidFont; use crate::{ camera::Camera, - gui::Gui, + gui::{Gui, GuiEvent}, screen::{Screen, ScreenSize}, }; @@ -156,8 +157,12 @@ impl Renderer { }) } - pub(crate) fn init_gui(&self) -> Gui { - Gui::new(&self.device, self.surface_config.format) + pub(crate) fn init_gui( + &self, + event_rx: Receiver, + event_tx: Sender, + ) -> Gui { + Gui::new(&self.device, self.surface_config.format, event_rx, event_tx) } /// Updates the geometry of the model being rendered. diff --git a/crates/fj-viewer/src/gui.rs b/crates/fj-viewer/src/gui.rs index a01fab7fd..bceffd089 100644 --- a/crates/fj-viewer/src/gui.rs +++ b/crates/fj-viewer/src/gui.rs @@ -14,22 +14,47 @@ //! //! +use std::path::PathBuf; + +use crossbeam_channel::{Receiver, Sender}; + use fj_interop::status_report::StatusReport; use fj_math::{Aabb, Scalar}; -use crate::graphics::DrawConfig; +use crate::{file_dialog::show_file_dialog, graphics::DrawConfig}; + +/// Event that are passed between the event_loop and gui +pub enum GuiEvent { + AskModel, + LoadModel(PathBuf), +} + +struct GuiState { + has_model: bool, +} + +impl Default for GuiState { + fn default() -> Self { + Self { has_model: true } + } +} /// The GUI pub struct Gui { context: egui::Context, render_pass: egui_wgpu::renderer::RenderPass, options: Options, + event_rx: Receiver, + event_tx: Sender, + state: GuiState, } impl Gui { pub(crate) fn new( device: &wgpu::Device, texture_format: wgpu::TextureFormat, + event_rx: Receiver, + event_tx: Sender, ) -> Self { // The implementation of the integration with `egui` is likely to need // to change "significantly" depending on what architecture approach is @@ -69,6 +94,9 @@ impl Gui { context, render_pass, options: Default::default(), + event_rx, + event_tx, + state: Default::default(), } } @@ -86,6 +114,28 @@ impl Gui { status: &StatusReport, line_drawing_available: bool, ) { + loop { + let event = self + .event_rx + .try_recv() + .map_err(|err| { + if err.is_disconnected() { + panic!("Expected channel to never disconnect"); + } + }) + .ok(); + + let event = match event { + Some(gui_event) => gui_event, + None => break, + }; + + match event { + GuiEvent::AskModel => self.state.has_model = false, + _ => {} + } + } + self.context.set_pixels_per_point(pixels_per_point); self.context.begin_frame(egui_input); @@ -241,6 +291,31 @@ impl Gui { )) }) }); + + if !self.state.has_model { + egui::Area::new("ask-model") + .anchor(egui::Align2::CENTER_CENTER, [0_f32, -5_f32]) + .show(&self.context, |ui| { + ui.vertical_centered(|ui| { + ui.label( + "No model selected please choose a model to view.", + ); + if ui + .button(egui::RichText::new("Pick a file")) + .clicked() + { + let model_dir = show_file_dialog(); + if let Some(model_dir) = model_dir { + self.event_tx + .send(GuiEvent::LoadModel(model_dir)) + .expect("Channel is disconnected"); + + self.state.has_model = true; + } + } + }) + }); + } } pub(crate) fn draw( diff --git a/crates/fj-viewer/src/lib.rs b/crates/fj-viewer/src/lib.rs index eea0499fb..81d728862 100644 --- a/crates/fj-viewer/src/lib.rs +++ b/crates/fj-viewer/src/lib.rs @@ -15,6 +15,7 @@ #![warn(missing_docs)] mod camera; +mod file_dialog; mod graphics; mod gui; mod input; @@ -24,7 +25,7 @@ mod viewer; pub use self::{ camera::Camera, graphics::{DrawConfig, Renderer, RendererInitError}, - gui::Gui, + gui::{Gui, GuiEvent}, input::{InputEvent, InputHandler}, screen::{NormalizedScreenPosition, Screen, ScreenSize}, viewer::Viewer, diff --git a/crates/fj-viewer/src/viewer.rs b/crates/fj-viewer/src/viewer.rs index 7f53e9d5c..81419067b 100644 --- a/crates/fj-viewer/src/viewer.rs +++ b/crates/fj-viewer/src/viewer.rs @@ -4,9 +4,13 @@ use fj_interop::{ use fj_math::Aabb; use tracing::warn; +use crossbeam_channel::{Receiver, Sender}; + use crate::{ - camera::FocusPoint, gui::Gui, Camera, DrawConfig, InputEvent, InputHandler, - NormalizedScreenPosition, Renderer, RendererInitError, Screen, ScreenSize, + camera::FocusPoint, + gui::{Gui, GuiEvent}, + Camera, DrawConfig, InputEvent, InputHandler, NormalizedScreenPosition, + Renderer, RendererInitError, Screen, ScreenSize, }; /// The Fornjot model viewer @@ -38,9 +42,13 @@ pub struct Viewer { impl Viewer { /// Construct a new instance of `Viewer` - pub async fn new(screen: &impl Screen) -> Result { + pub async fn new( + screen: &impl Screen, + event_rx: Receiver, + event_tx: Sender, + ) -> Result { let renderer = Renderer::new(screen).await?; - let gui = renderer.init_gui(); + let gui = renderer.init_gui(event_rx, event_tx); Ok(Self { camera: Camera::default(), diff --git a/crates/fj-window/Cargo.toml b/crates/fj-window/Cargo.toml index 551c4e8ea..684269adb 100644 --- a/crates/fj-window/Cargo.toml +++ b/crates/fj-window/Cargo.toml @@ -15,6 +15,7 @@ fj-host.workspace = true fj-operations.workspace = true fj-viewer.workspace = true fj-interop.workspace = true +crossbeam-channel = "0.5.6" futures = "0.3.25" thiserror = "1.0.35" tracing = "0.1.37" diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index e1753fc75..3c0229637 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -5,11 +5,11 @@ use std::error; -use fj_host::{Host, Model, ModelEvent}; +use fj_host::{Host, Model, ModelEvent, Parameters}; use fj_interop::status_report::StatusReport; use fj_operations::shape_processor::ShapeProcessor; use fj_viewer::{ - InputEvent, NormalizedScreenPosition, RendererInitError, Screen, + GuiEvent, InputEvent, NormalizedScreenPosition, RendererInitError, Screen, ScreenSize, Viewer, }; use futures::executor::block_on; @@ -31,14 +31,25 @@ pub fn run( shape_processor: ShapeProcessor, invert_zoom: bool, ) -> Result<(), Error> { + let (send_gui, gui_event_rx) = crossbeam_channel::bounded::(5); + + let (gui_event_tx, recv_gui) = crossbeam_channel::bounded::(5); + + if model.is_none() { + send_gui + .send(GuiEvent::AskModel) + .expect("Channel is disconnected"); + } + let mut status = StatusReport::new(); - let host = Host::from_model(model).transpose()?; + let mut host = Host::from_model(model).transpose()?; let event_loop = EventLoop::new(); let window = Window::new(&event_loop)?; - let mut viewer = block_on(Viewer::new(&window))?; + let mut viewer = + block_on(Viewer::new(&window, gui_event_rx, gui_event_tx))?; - let events = match host { + let mut events = match host { Some(ref host) => Some(host.events()), None => None, }; @@ -56,6 +67,31 @@ pub fn run( event_loop.run(move |event, _, control_flow| { trace!("Handling event: {:?}", event); + let gui_event = recv_gui + .try_recv() + .map_err(|err| { + if err.is_disconnected() { + panic!("Expected channel to never disconnect"); + } + }) + .ok(); + + if let Some(gui_event) = gui_event { + match gui_event { + GuiEvent::LoadModel(model_path) => { + let model = + Model::new(model_path, Parameters::empty()).unwrap(); + host = + Some(Host::from_model(Some(model)).unwrap().unwrap()); + events = match host { + Some(ref host) => Some(host.events()), + None => None, + }; + } + _ => {} + } + } + loop { let event = events.as_ref().map(|events| { events diff --git a/crates/fj-window/src/window.rs b/crates/fj-window/src/window.rs index 25d709d39..7b676ef01 100644 --- a/crates/fj-window/src/window.rs +++ b/crates/fj-window/src/window.rs @@ -1,7 +1,10 @@ //! CAD viewer utility windowing abstraction use fj_viewer::{Screen, ScreenSize}; -use winit::{event_loop::EventLoop, window::WindowBuilder}; +use winit::{ + event_loop::EventLoop, + window::{Fullscreen, WindowBuilder}, +}; /// Window abstraction providing details such as the width or height and easing initialization. pub struct Window(winit::window::Window); @@ -12,6 +15,7 @@ impl Window { let window = WindowBuilder::new() .with_title("Fornjot") .with_maximized(true) + .with_fullscreen(Some(Fullscreen::Borderless(None))) .with_decorations(true) .with_transparent(false) .build(event_loop)?; From 2cf7b802a626f34ae1ab484ee4b37066f89f8611 Mon Sep 17 00:00:00 2001 From: erenoku Date: Fri, 28 Oct 2022 19:10:20 +0300 Subject: [PATCH 3/6] Cleanup --- crates/fj-app/src/main.rs | 11 +++++++++- crates/fj-app/src/path.rs | 10 +--------- crates/fj-viewer/src/file_dialog.rs | 9 --------- crates/fj-viewer/src/gui.rs | 19 ++++++++++++------ crates/fj-viewer/src/lib.rs | 1 - crates/fj-window/src/run.rs | 31 ++++++++++++++--------------- crates/fj-window/src/window.rs | 6 +----- 7 files changed, 40 insertions(+), 47 deletions(-) delete mode 100644 crates/fj-viewer/src/file_dialog.rs diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index c1e775540..7ee52ec66 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -16,6 +16,7 @@ mod args; mod config; mod path; +use anyhow::{anyhow, Context}; use fj_export::export; use fj_host::Parameters; use fj_operations::shape_processor::ShapeProcessor; @@ -53,7 +54,7 @@ fn main() -> anyhow::Result<()> { if let Some(export_path) = args.export { // export only mode. just load model, process, export and exit - let evaluation = model.unwrap().evaluate()?; + let evaluation = model.with_context(no_model_error)?.evaluate()?; let shape = shape_processor.process(&evaluation.shape)?; export(&shape.mesh, &export_path)?; @@ -66,3 +67,11 @@ fn main() -> anyhow::Result<()> { Ok(()) } + +fn no_model_error() -> anyhow::Error { + anyhow!( + "You must specify a model to start Fornjot.\n\ + - Pass a model as a command-line argument. See `fj-app --help`.\n\ + - Specify a default model in the configuration file." + ) +} diff --git a/crates/fj-app/src/path.rs b/crates/fj-app/src/path.rs index 95c4c90c5..5d0a7c02e 100644 --- a/crates/fj-app/src/path.rs +++ b/crates/fj-app/src/path.rs @@ -3,7 +3,7 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{anyhow, Context}; +use anyhow::Context; use fj_host::{Model, Parameters}; use crate::{args::Args, config::Config}; @@ -137,11 +137,3 @@ fn load_error_context_inner( Ok(context) } - -fn no_model_error() -> anyhow::Error { - anyhow!( - "You must specify a model to start Fornjot.\n\ - - Pass a model as a command-line argument. See `fj-app --help`.\n\ - - Specify a default model in the configuration file." - ) -} diff --git a/crates/fj-viewer/src/file_dialog.rs b/crates/fj-viewer/src/file_dialog.rs deleted file mode 100644 index 504a6c261..000000000 --- a/crates/fj-viewer/src/file_dialog.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::{env::current_dir, path::PathBuf}; - -use rfd::FileDialog; - -pub fn show_file_dialog() -> Option { - FileDialog::new() - .set_directory(current_dir().unwrap_or_else(|_| PathBuf::from("/"))) - .pick_folder() -} diff --git a/crates/fj-viewer/src/gui.rs b/crates/fj-viewer/src/gui.rs index bceffd089..739ef719a 100644 --- a/crates/fj-viewer/src/gui.rs +++ b/crates/fj-viewer/src/gui.rs @@ -14,14 +14,15 @@ //! //! -use std::path::PathBuf; +use std::{env::current_dir, path::PathBuf}; use crossbeam_channel::{Receiver, Sender}; +use rfd::FileDialog; use fj_interop::status_report::StatusReport; use fj_math::{Aabb, Scalar}; -use crate::{file_dialog::show_file_dialog, graphics::DrawConfig}; +use crate::graphics::DrawConfig; /// Event that are passed between the event_loop and gui pub enum GuiEvent { @@ -115,7 +116,7 @@ impl Gui { line_drawing_available: bool, ) { loop { - let event = self + let gui_event = self .event_rx .try_recv() .map_err(|err| { @@ -125,12 +126,12 @@ impl Gui { }) .ok(); - let event = match event { + let gui_event = match gui_event { Some(gui_event) => gui_event, None => break, }; - match event { + match gui_event { GuiEvent::AskModel => self.state.has_model = false, _ => {} } @@ -301,7 +302,7 @@ impl Gui { "No model selected please choose a model to view.", ); if ui - .button(egui::RichText::new("Pick a file")) + .button(egui::RichText::new("Pick a model")) .clicked() { let model_dir = show_file_dialog(); @@ -354,6 +355,12 @@ impl Gui { } } +fn show_file_dialog() -> Option { + FileDialog::new() + .set_directory(current_dir().unwrap_or_else(|_| PathBuf::from("/"))) + .pick_folder() +} + impl std::fmt::Debug for Gui { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("Gui {}") diff --git a/crates/fj-viewer/src/lib.rs b/crates/fj-viewer/src/lib.rs index 81d728862..236c0f2c9 100644 --- a/crates/fj-viewer/src/lib.rs +++ b/crates/fj-viewer/src/lib.rs @@ -15,7 +15,6 @@ #![warn(missing_docs)] mod camera; -mod file_dialog; mod graphics; mod gui; mod input; diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index 3c0229637..1af68a361 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -32,7 +32,6 @@ pub fn run( invert_zoom: bool, ) -> Result<(), Error> { let (send_gui, gui_event_rx) = crossbeam_channel::bounded::(5); - let (gui_event_tx, recv_gui) = crossbeam_channel::bounded::(5); if model.is_none() { @@ -49,10 +48,7 @@ pub fn run( let mut viewer = block_on(Viewer::new(&window, gui_event_rx, gui_event_tx))?; - let mut events = match host { - Some(ref host) => Some(host.events()), - None => None, - }; + let mut events = host.as_ref().map(|host| host.events()); let mut held_mouse_button = None; @@ -81,12 +77,18 @@ pub fn run( GuiEvent::LoadModel(model_path) => { let model = Model::new(model_path, Parameters::empty()).unwrap(); - host = - Some(Host::from_model(Some(model)).unwrap().unwrap()); - events = match host { - Some(ref host) => Some(host.events()), - None => None, - }; + match Host::from_model(Some(model)).unwrap() { + Ok(new_host) => { + host = Some(new_host); + events = host.as_ref().map(|host| host.events()); + } + Err(_) => { + status.update_status("Error creating host."); + send_gui + .send(GuiEvent::AskModel) + .expect("Channel is disconnected"); + } + } } _ => {} } @@ -105,11 +107,8 @@ pub fn run( }); let event = match event { - Some(event) => match event { - Some(status_update) => status_update, - None => break, - }, - None => break, + Some(Some(status_update)) => status_update, + _ => break, }; match event { diff --git a/crates/fj-window/src/window.rs b/crates/fj-window/src/window.rs index 7b676ef01..25d709d39 100644 --- a/crates/fj-window/src/window.rs +++ b/crates/fj-window/src/window.rs @@ -1,10 +1,7 @@ //! CAD viewer utility windowing abstraction use fj_viewer::{Screen, ScreenSize}; -use winit::{ - event_loop::EventLoop, - window::{Fullscreen, WindowBuilder}, -}; +use winit::{event_loop::EventLoop, window::WindowBuilder}; /// Window abstraction providing details such as the width or height and easing initialization. pub struct Window(winit::window::Window); @@ -15,7 +12,6 @@ impl Window { let window = WindowBuilder::new() .with_title("Fornjot") .with_maximized(true) - .with_fullscreen(Some(Fullscreen::Borderless(None))) .with_decorations(true) .with_transparent(false) .build(event_loop)?; From 281f599796df2d20880781093fd1d4efe33a56b4 Mon Sep 17 00:00:00 2001 From: erenoku Date: Sat, 29 Oct 2022 17:05:24 +0300 Subject: [PATCH 4/6] Minor fixes --- Cargo.lock | 543 ++++++++++++++++------ crates/fj-app/src/main.rs | 2 +- crates/fj-host/src/host.rs | 25 +- crates/fj-viewer/Cargo.toml | 6 +- crates/fj-viewer/src/graphics/renderer.rs | 8 +- crates/fj-viewer/src/gui.rs | 30 +- crates/fj-viewer/src/lib.rs | 2 +- crates/fj-viewer/src/viewer.rs | 12 +- crates/fj-window/src/run.rs | 146 +++--- 9 files changed, 504 insertions(+), 270 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a05b146c..c64ffdee1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,10 +132,90 @@ dependencies = [ ] [[package]] -name = "async-trait" -version = "0.1.58" +name = "ashpd" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "6dcc8ed0b5211687437636d8c95f6a608f4281d142101b3b5d314b38bfadd40f" +dependencies = [ + "enumflags2", + "futures", + "rand", + "serde", + "serde_repr", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61" +dependencies = [ + "event-listener", + "futures-core", + "parking_lot", +] + +[[package]] +name = "async-channel" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-io" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-recursion" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" dependencies = [ "proc-macro2", "quote", @@ -143,15 +223,20 @@ dependencies = [ ] [[package]] -name = "atk-sys" -version = "0.15.1" +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -306,14 +391,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] -name = "cairo-sys-rs" -version = "0.15.1" +name = "cache-padded" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" -dependencies = [ - "libc", - "system-deps", -] +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "calloop" @@ -322,7 +403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a22a6a8f622f797120d452c630b0ab12e1331a1a753e2039ce7868d4ac77b4ee" dependencies = [ "log", - "nix", + "nix 0.24.2", "slotmap", "thiserror", "vec_map", @@ -366,15 +447,6 @@ version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -[[package]] -name = "cfg-expr" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" -dependencies = [ - "smallvec", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -515,6 +587,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "concurrent-queue" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +dependencies = [ + "cache-padded", +] + [[package]] name = "copyless" version = "0.1.5" @@ -781,12 +862,43 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -889,6 +1001,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enumflags2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.9.1" @@ -917,6 +1050,12 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "expat-sys" version = "2.1.6" @@ -1274,6 +1413,21 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.25" @@ -1324,36 +1478,6 @@ dependencies = [ "byteorder 1.4.3", ] -[[package]] -name = "gdk-pixbuf-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gdk-sys" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps", -] - [[package]] name = "getrandom" version = "0.2.8" @@ -1373,29 +1497,6 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -[[package]] -name = "gio-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", -] - -[[package]] -name = "glib-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" -dependencies = [ - "libc", - "system-deps", -] - [[package]] name = "glow" version = "0.11.2" @@ -1447,17 +1548,6 @@ dependencies = [ "xi-unicode", ] -[[package]] -name = "gobject-sys" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - [[package]] name = "gpu-alloc" version = "0.5.3" @@ -1497,24 +1587,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "gtk-sys" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", -] - [[package]] name = "h2" version = "0.3.15" @@ -1558,6 +1630,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hexf-parse" version = "0.2.1" @@ -2125,6 +2203,19 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nix" version = "0.24.2" @@ -2421,6 +2512,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-stream" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_pipe" version = "0.9.2" @@ -2462,16 +2563,10 @@ dependencies = [ ] [[package]] -name = "pango-sys" -version = "0.15.10" +name = "parking" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" @@ -2612,6 +2707,26 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -2795,6 +2910,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.6.0" @@ -2898,18 +3024,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" dependencies = [ + "ashpd", "block", "dispatch", - "glib-sys", - "gobject-sys", - "gtk-sys", "js-sys", - "lazy_static", "log", "objc", "objc-foundation", "objc_id", + "pollster", "raw-window-handle 0.5.0", + "urlencoding", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3121,6 +3246,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3154,6 +3290,21 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sharded-slab" version = "0.1.4" @@ -3233,7 +3384,7 @@ dependencies = [ "lazy_static", "log", "memmap2", - "nix", + "nix 0.24.2", "pkg-config", "wayland-client", "wayland-cursor", @@ -3347,19 +3498,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "system-deps" -version = "6.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - [[package]] name = "tempfile" version = "3.3.0" @@ -3679,6 +3817,16 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] + [[package]] name = "uncased" version = "0.9.7" @@ -3748,6 +3896,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + [[package]] name = "valuable" version = "0.1.0" @@ -3766,18 +3920,18 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "version-compare" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" - [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "walkdir" version = "2.3.2" @@ -3886,7 +4040,7 @@ dependencies = [ "bitflags", "downcast-rs", "libc", - "nix", + "nix 0.24.2", "scoped-tls", "wayland-commons", "wayland-scanner", @@ -3899,7 +4053,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" dependencies = [ - "nix", + "nix 0.24.2", "once_cell", "smallvec", "wayland-sys", @@ -3911,7 +4065,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" dependencies = [ - "nix", + "nix 0.24.2", "wayland-client", "xcursor", ] @@ -3960,6 +4114,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + [[package]] name = "wgpu" version = "0.13.1" @@ -4339,6 +4502,70 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zbus" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8f1a037b2c4a67d9654dc7bdfa8ff2e80555bbefdd3c1833c1d1b27c963a6b" +dependencies = [ + "async-broadcast", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-recursion", + "async-task", + "async-trait", + "byteorder 1.4.3", + "derivative", + "dirs", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "lazy_static", + "nix 0.23.1", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8fb5186d1c87ae88cf234974c240671238b4a679158ad3b94ec465237349a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "zbus_names" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a408fd8a352695690f53906dc7fd036be924ec51ea5e05666ff42685ed0af5" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zeroize" version = "1.5.7" @@ -4356,3 +4583,29 @@ dependencies = [ "crossbeam-utils", "flate2", ] + +[[package]] +name = "zvariant" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794fb7f59af4105697b0449ba31731ee5dbb3e773a17dbdf3d36206ea1b1644" +dependencies = [ + "byteorder 1.4.3", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd58d4b6c8e26d3dd2149c8c40c6613ef6451b9885ff1296d1ac86c388351a54" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index 7ee52ec66..e8ab235a5 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -70,7 +70,7 @@ fn main() -> anyhow::Result<()> { fn no_model_error() -> anyhow::Error { anyhow!( - "You must specify a model to start Fornjot.\n\ + "You must specify a model to start Fornjot in export only mode.\n\ - Pass a model as a command-line argument. See `fj-app --help`.\n\ - Specify a default model in the configuration file." ) diff --git a/crates/fj-host/src/host.rs b/crates/fj-host/src/host.rs index 615ec1a68..6c3b71b02 100644 --- a/crates/fj-host/src/host.rs +++ b/crates/fj-host/src/host.rs @@ -13,21 +13,18 @@ impl Host { /// /// This is only useful, if you want to continuously watch the model for /// changes. If you don't just keep using `Model`. - pub fn from_model(model: Option) -> Option> { - if let Some(model) = model { - let watch_path = model.watch_path(); - let evaluator = Evaluator::from_model(model); - let _watcher = match Watcher::watch_model(&watch_path, &evaluator) { - Ok(_watcher) => _watcher, - Err(e) => return Some(Err(e)), - }; + pub fn from_model(model: Model) -> Result { + let watch_path = model.watch_path(); + let evaluator = Evaluator::from_model(model); + let _watcher = match Watcher::watch_model(&watch_path, &evaluator) { + Ok(_watcher) => _watcher, + Err(e) => return Err(e), + }; - return Some(Ok(Self { - evaluator, - _watcher, - })); - } - None + return Ok(Self { + evaluator, + _watcher, + }); } /// Access a channel with evaluation events diff --git a/crates/fj-viewer/Cargo.toml b/crates/fj-viewer/Cargo.toml index 6639ca4aa..58b8b6e2f 100644 --- a/crates/fj-viewer/Cargo.toml +++ b/crates/fj-viewer/Cargo.toml @@ -18,11 +18,15 @@ egui-wgpu = "0.19.0" fj-interop.workspace = true fj-math.workspace = true raw-window-handle = "0.4.3" -rfd = "0.10.0" thiserror = "1.0.35" tracing = "0.1.37" wgpu_glyph = "0.17.0" +[dependencies.rfd] +version = "0.10.0" +default_features = false +features = ["xdg-portal"] + [dependencies.wgpu] version = "0.13.1" features = ["webgl"] diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index eb63ba059..d69d2cc28 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -1,4 +1,4 @@ -use std::{io, mem::size_of}; +use std::{io, mem::size_of, path::PathBuf}; use crossbeam_channel::{Receiver, Sender}; use thiserror::Error; @@ -8,7 +8,7 @@ use wgpu_glyph::ab_glyph::InvalidFont; use crate::{ camera::Camera, - gui::{Gui, GuiEvent}, + gui::Gui, screen::{Screen, ScreenSize}, }; @@ -159,8 +159,8 @@ impl Renderer { pub(crate) fn init_gui( &self, - event_rx: Receiver, - event_tx: Sender, + event_rx: Receiver<()>, + event_tx: Sender, ) -> Gui { Gui::new(&self.device, self.surface_config.format, event_rx, event_tx) } diff --git a/crates/fj-viewer/src/gui.rs b/crates/fj-viewer/src/gui.rs index 739ef719a..8fac3a024 100644 --- a/crates/fj-viewer/src/gui.rs +++ b/crates/fj-viewer/src/gui.rs @@ -24,12 +24,6 @@ use fj_math::{Aabb, Scalar}; use crate::graphics::DrawConfig; -/// Event that are passed between the event_loop and gui -pub enum GuiEvent { - AskModel, - LoadModel(PathBuf), -} - struct GuiState { has_model: bool, } @@ -45,8 +39,8 @@ pub struct Gui { context: egui::Context, render_pass: egui_wgpu::renderer::RenderPass, options: Options, - event_rx: Receiver, - event_tx: Sender, + event_rx: Receiver<()>, + event_tx: Sender, state: GuiState, } @@ -54,8 +48,8 @@ impl Gui { pub(crate) fn new( device: &wgpu::Device, texture_format: wgpu::TextureFormat, - event_rx: Receiver, - event_tx: Sender, + event_rx: Receiver<()>, + event_tx: Sender, ) -> Self { // The implementation of the integration with `egui` is likely to need // to change "significantly" depending on what architecture approach is @@ -126,15 +120,10 @@ impl Gui { }) .ok(); - let gui_event = match gui_event { - Some(gui_event) => gui_event, + match gui_event { + Some(_) => self.state.has_model = false, None => break, }; - - match gui_event { - GuiEvent::AskModel => self.state.has_model = false, - _ => {} - } } self.context.set_pixels_per_point(pixels_per_point); @@ -298,9 +287,10 @@ impl Gui { .anchor(egui::Align2::CENTER_CENTER, [0_f32, -5_f32]) .show(&self.context, |ui| { ui.vertical_centered(|ui| { - ui.label( + ui.label(egui::RichText::new( "No model selected please choose a model to view.", - ); + ).color(egui::Color32::BLACK) + .background_color(egui::Color32::WHITE)); if ui .button(egui::RichText::new("Pick a model")) .clicked() @@ -308,7 +298,7 @@ impl Gui { let model_dir = show_file_dialog(); if let Some(model_dir) = model_dir { self.event_tx - .send(GuiEvent::LoadModel(model_dir)) + .send(model_dir) .expect("Channel is disconnected"); self.state.has_model = true; diff --git a/crates/fj-viewer/src/lib.rs b/crates/fj-viewer/src/lib.rs index 236c0f2c9..eea0499fb 100644 --- a/crates/fj-viewer/src/lib.rs +++ b/crates/fj-viewer/src/lib.rs @@ -24,7 +24,7 @@ mod viewer; pub use self::{ camera::Camera, graphics::{DrawConfig, Renderer, RendererInitError}, - gui::{Gui, GuiEvent}, + gui::Gui, input::{InputEvent, InputHandler}, screen::{NormalizedScreenPosition, Screen, ScreenSize}, viewer::Viewer, diff --git a/crates/fj-viewer/src/viewer.rs b/crates/fj-viewer/src/viewer.rs index 81419067b..c0520084f 100644 --- a/crates/fj-viewer/src/viewer.rs +++ b/crates/fj-viewer/src/viewer.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use fj_interop::{ processed_shape::ProcessedShape, status_report::StatusReport, }; @@ -7,10 +9,8 @@ use tracing::warn; use crossbeam_channel::{Receiver, Sender}; use crate::{ - camera::FocusPoint, - gui::{Gui, GuiEvent}, - Camera, DrawConfig, InputEvent, InputHandler, NormalizedScreenPosition, - Renderer, RendererInitError, Screen, ScreenSize, + camera::FocusPoint, gui::Gui, Camera, DrawConfig, InputEvent, InputHandler, + NormalizedScreenPosition, Renderer, RendererInitError, Screen, ScreenSize, }; /// The Fornjot model viewer @@ -44,8 +44,8 @@ impl Viewer { /// Construct a new instance of `Viewer` pub async fn new( screen: &impl Screen, - event_rx: Receiver, - event_tx: Sender, + event_rx: Receiver<()>, + event_tx: Sender, ) -> Result { let renderer = Renderer::new(screen).await?; let gui = renderer.init_gui(event_rx, event_tx); diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index 1af68a361..ab6a1508b 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -3,13 +3,13 @@ //! Provides the functionality to create a window and perform basic viewing //! with programmed models. -use std::error; +use std::{error, path::PathBuf}; use fj_host::{Host, Model, ModelEvent, Parameters}; use fj_interop::status_report::StatusReport; use fj_operations::shape_processor::ShapeProcessor; use fj_viewer::{ - GuiEvent, InputEvent, NormalizedScreenPosition, RendererInitError, Screen, + InputEvent, NormalizedScreenPosition, RendererInitError, Screen, ScreenSize, Viewer, }; use futures::executor::block_on; @@ -31,29 +31,27 @@ pub fn run( shape_processor: ShapeProcessor, invert_zoom: bool, ) -> Result<(), Error> { - let (send_gui, gui_event_rx) = crossbeam_channel::bounded::(5); - let (gui_event_tx, recv_gui) = crossbeam_channel::bounded::(5); - - if model.is_none() { - send_gui - .send(GuiEvent::AskModel) - .expect("Channel is disconnected"); - } + let (send_gui, gui_event_rx) = crossbeam_channel::bounded::<()>(1); + let (gui_event_tx, recv_gui) = crossbeam_channel::bounded::(1); let mut status = StatusReport::new(); - let mut host = Host::from_model(model).transpose()?; let event_loop = EventLoop::new(); let window = Window::new(&event_loop)?; let mut viewer = block_on(Viewer::new(&window, gui_event_rx, gui_event_tx))?; - let mut events = host.as_ref().map(|host| host.events()); - let mut held_mouse_button = None; let mut egui_winit_state = egui_winit::State::new(&event_loop); + let mut host = None; + if let Some(model) = model { + host = Some(Host::from_model(model)?); + } else { + send_gui.send(()).expect("Channel is disconnected"); + } + // Only handle resize events once every frame. This filters out spurious // resize events that can lead to wgpu warnings. See this issue for some // context: @@ -72,93 +70,85 @@ pub fn run( }) .ok(); - if let Some(gui_event) = gui_event { - match gui_event { - GuiEvent::LoadModel(model_path) => { - let model = - Model::new(model_path, Parameters::empty()).unwrap(); - match Host::from_model(Some(model)).unwrap() { - Ok(new_host) => { - host = Some(new_host); - events = host.as_ref().map(|host| host.events()); - } - Err(_) => { - status.update_status("Error creating host."); - send_gui - .send(GuiEvent::AskModel) - .expect("Channel is disconnected"); - } - } + if let Some(model_path) = gui_event { + let model = Model::new(model_path, Parameters::empty()).unwrap(); + match Host::from_model(model) { + Ok(new_host) => { + host = Some(new_host); + } + Err(_) => { + status.update_status("Error creating host."); + send_gui.send(()).expect("Channel is disconnected"); } - _ => {} } } - loop { - let event = events.as_ref().map(|events| { - events + if let Some(host) = &host { + loop { + let events = host.events(); + let event = events .try_recv() .map_err(|err| { if err.is_disconnected() { panic!("Expected channel to never disconnect"); } }) - .ok() - }); + .ok(); - let event = match event { - Some(Some(status_update)) => status_update, - _ => break, - }; + let event = match event { + Some(status_update) => status_update, + _ => break, + }; - match event { - ModelEvent::StatusUpdate(status_update) => { - status.update_status(&status_update) - } - ModelEvent::Evaluation(evaluation) => { - status.update_status(&format!( - "Model compiled successfully in {}!", - evaluation.compile_time - )); - - match shape_processor.process(&evaluation.shape) { - Ok(shape) => { - viewer.handle_shape_update(shape); - } - Err(err) => { - // Can be cleaned up, once `Report` is stable: - // https://doc.rust-lang.org/std/error/struct.Report.html + match event { + ModelEvent::StatusUpdate(status_update) => { + status.update_status(&status_update) + } + ModelEvent::Evaluation(evaluation) => { + status.update_status(&format!( + "Model compiled successfully in {}!", + evaluation.compile_time + )); + + match shape_processor.process(&evaluation.shape) { + Ok(shape) => { + viewer.handle_shape_update(shape); + } + Err(err) => { + // Can be cleaned up, once `Report` is stable: + // https://doc.rust-lang.org/std/error/struct.Report.html - println!("Shape processing error: {}", err); + println!("Shape processing error: {}", err); - let mut current_err = &err as &dyn error::Error; - while let Some(err) = current_err.source() { - println!(); - println!("Caused by:"); - println!(" {}", err); + let mut current_err = &err as &dyn error::Error; + while let Some(err) = current_err.source() { + println!(); + println!("Caused by:"); + println!(" {}", err); - current_err = err; + current_err = err; + } } } } - } - ModelEvent::Error(err) => { - // Can be cleaned up, once `Report` is stable: - // https://doc.rust-lang.org/std/error/struct.Report.html + ModelEvent::Error(err) => { + // Can be cleaned up, once `Report` is stable: + // https://doc.rust-lang.org/std/error/struct.Report.html - println!("Error receiving updated shape: {}", err); + println!("Error receiving updated shape: {}", err); - let mut current_err = &err as &dyn error::Error; - while let Some(err) = current_err.source() { - println!(); - println!("Caused by:"); - println!(" {}", err); + let mut current_err = &err as &dyn error::Error; + while let Some(err) = current_err.source() { + println!(); + println!("Caused by:"); + println!(" {}", err); - current_err = err; - } + current_err = err; + } - *control_flow = ControlFlow::Exit; - return; + *control_flow = ControlFlow::Exit; + return; + } } } } From 8b1c6fc5ad5e4cf8401fa0b7500f59b13edc14ab Mon Sep 17 00:00:00 2001 From: erenoku Date: Sat, 29 Oct 2022 17:47:52 +0300 Subject: [PATCH 5/6] Fix clippy warning --- crates/fj-host/src/host.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-host/src/host.rs b/crates/fj-host/src/host.rs index 6c3b71b02..948946468 100644 --- a/crates/fj-host/src/host.rs +++ b/crates/fj-host/src/host.rs @@ -21,10 +21,10 @@ impl Host { Err(e) => return Err(e), }; - return Ok(Self { + Ok(Self { evaluator, _watcher, - }); + }) } /// Access a channel with evaluation events From e564acbb7ac23c313fa6acfc7cca155edc9cbe46 Mon Sep 17 00:00:00 2001 From: erenoku Date: Sat, 29 Oct 2022 18:20:21 +0300 Subject: [PATCH 6/6] Fix build on wasm32 --- crates/fj-viewer/src/gui.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/crates/fj-viewer/src/gui.rs b/crates/fj-viewer/src/gui.rs index 3e8c1f4a9..6c1fad6d3 100644 --- a/crates/fj-viewer/src/gui.rs +++ b/crates/fj-viewer/src/gui.rs @@ -14,9 +14,14 @@ //! //! -use std::{env::current_dir, path::PathBuf}; +use std::path::PathBuf; + +#[cfg(not(target_arch = "wasm32"))] +use std::env::current_dir; use crossbeam_channel::{Receiver, Sender}; + +#[cfg(not(target_arch = "wasm32"))] use rfd::FileDialog; use fj_interop::status_report::StatusReport; @@ -348,9 +353,13 @@ impl Gui { } fn show_file_dialog() -> Option { - FileDialog::new() + #[cfg(not(target_arch = "wasm32"))] + return FileDialog::new() .set_directory(current_dir().unwrap_or_else(|_| PathBuf::from("/"))) - .pick_folder() + .pick_folder(); + + #[cfg(target_arch = "wasm32")] + todo!("Picking folders does not work on wasm32") } impl std::fmt::Debug for Gui {