From bc4cdbc861264c9e40bf9c5e3eeaba4f5d63d065 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Tue, 2 Aug 2022 16:06:41 -0700 Subject: [PATCH 1/8] Add status report struct --- crates/fj-interop/src/lib.rs | 1 + crates/fj-interop/src/status_report.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 crates/fj-interop/src/status_report.rs diff --git a/crates/fj-interop/src/lib.rs b/crates/fj-interop/src/lib.rs index 88d430744..7e8cfa384 100644 --- a/crates/fj-interop/src/lib.rs +++ b/crates/fj-interop/src/lib.rs @@ -17,3 +17,4 @@ pub mod debug; pub mod mesh; pub mod processed_shape; +pub mod status_report; diff --git a/crates/fj-interop/src/status_report.rs b/crates/fj-interop/src/status_report.rs new file mode 100644 index 000000000..a99bc6bf4 --- /dev/null +++ b/crates/fj-interop/src/status_report.rs @@ -0,0 +1,21 @@ +//! Struct to store and update status messages + +pub struct StatusReport { + status: String, +} + +impl StatusReport { + pub fn new() -> Self { + StatusReport { + status: String::new(), + } + } + + pub fn update_status(&mut self, status: &str) { + self.status = status.to_string(); + } + + pub fn status(&self) -> &str { + self.status.as_str() + } +} From 531d718456cb39e2a34976823b2e34d2ed3ae155 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Wed, 3 Aug 2022 16:51:26 -0700 Subject: [PATCH 2/8] First working version. TODO: Format error nicely --- Cargo.lock | 3 ++ crates/fj-app/Cargo.toml | 4 ++ crates/fj-app/src/main.rs | 6 ++- crates/fj-host/Cargo.toml | 4 ++ crates/fj-host/src/lib.rs | 44 ++++++++++++++----- crates/fj-interop/src/status_report.rs | 10 +++-- crates/fj-viewer/src/graphics/mod.rs | 1 + crates/fj-viewer/src/graphics/renderer.rs | 6 +++ .../fj-viewer/src/graphics/status_report.rs | 0 crates/fj-window/Cargo.toml | 4 ++ crates/fj-window/src/run.rs | 13 ++++-- models/star/src/lib.rs | 2 +- 12 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 crates/fj-viewer/src/graphics/status_report.rs diff --git a/Cargo.lock b/Cargo.lock index 6996f7c3b..2dec5f3af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -846,6 +846,7 @@ dependencies = [ "fj", "fj-export", "fj-host", + "fj-interop", "fj-kernel", "fj-math", "fj-operations", @@ -872,6 +873,7 @@ version = "0.10.0" dependencies = [ "cargo_metadata", "fj", + "fj-interop", "libloading", "notify", "thiserror", @@ -958,6 +960,7 @@ name = "fj-window" version = "0.10.0" dependencies = [ "fj-host", + "fj-interop", "fj-operations", "fj-viewer", "futures", diff --git a/crates/fj-app/Cargo.toml b/crates/fj-app/Cargo.toml index 0456a1967..4bd2cb1b4 100644 --- a/crates/fj-app/Cargo.toml +++ b/crates/fj-app/Cargo.toml @@ -65,3 +65,7 @@ features = ["derive"] [dependencies.tracing-subscriber] version = "0.3.15" features = ["env-filter", "fmt"] + +[dependencies.fj-interop] +version = "0.10.0" +path = "../fj-interop" diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index 6982fec48..845f30abb 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -20,6 +20,7 @@ use std::path::PathBuf; use anyhow::{anyhow, Context as _}; use fj_export::export; use fj_host::{Model, Parameters}; +use fj_interop::status_report::StatusReport; use fj_operations::shape_processor::ShapeProcessor; use fj_window::run::run; use tracing_subscriber::fmt::format; @@ -28,6 +29,7 @@ use tracing_subscriber::EnvFilter; use crate::{args::Args, config::Config}; fn main() -> anyhow::Result<()> { + let mut status = StatusReport::new(); // Respect `RUST_LOG`. If that's not defined or erroneous, log warnings and // above. // @@ -62,7 +64,7 @@ fn main() -> anyhow::Result<()> { }; if let Some(path) = args.export { - let shape = model.load_once(¶meters)?; + let shape = model.load_once(¶meters, &mut status)?; let shape = shape_processor.process(&shape)?; export(&shape.mesh, &path)?; @@ -71,7 +73,7 @@ fn main() -> anyhow::Result<()> { } let watcher = model.load_and_watch(parameters)?; - run(watcher, shape_processor)?; + run(watcher, shape_processor, status)?; Ok(()) } diff --git a/crates/fj-host/Cargo.toml b/crates/fj-host/Cargo.toml index 14cfa480a..10e21b967 100644 --- a/crates/fj-host/Cargo.toml +++ b/crates/fj-host/Cargo.toml @@ -24,3 +24,7 @@ cargo_metadata = "0.15.0" [dependencies.fj] version = "0.10.0" path = "../fj" + +[dependencies.fj-interop] +version = "0.10.0" +path = "../fj-interop" diff --git a/crates/fj-host/src/lib.rs b/crates/fj-host/src/lib.rs index ad644be93..6dc80e084 100644 --- a/crates/fj-host/src/lib.rs +++ b/crates/fj-host/src/lib.rs @@ -17,6 +17,7 @@ mod platform; +use fj_interop::status_report::StatusReport; use std::{ collections::{HashMap, HashSet}, ffi::OsStr, @@ -82,16 +83,37 @@ impl Model { pub fn load_once( &self, arguments: &Parameters, + status: &mut StatusReport, ) -> Result { let manifest_path = self.manifest_path.display().to_string(); - let status = Command::new("cargo") - .arg("build") - .args(["--manifest-path", &manifest_path]) - .status()?; + let mut command_root = Command::new("cargo"); - if !status.success() { - return Err(Error::Compile); + let command = command_root + .arg("build") + .args(["--manifest-path", &manifest_path]); + let exit_status = command.status()?; + + if !exit_status.success() { + status.update_status(&format!( + "Compile error: {:?}", + String::from_utf8( + command + .output() + .expect("Failed to get command output.") + .stderr + ) + .expect("Failed to read command output.") + )); + return Err(Error::Compile( + String::from_utf8( + command + .output() + .expect("Failed to get command output.") + .stderr, + ) + .expect("Failed to read command output"), + )); } // So, strictly speaking this is all unsound: @@ -260,16 +282,16 @@ impl Watcher { /// /// Returns `None`, if the model has not changed since the last time this /// method was called. - pub fn receive(&self) -> Option { + pub fn receive(&self, status: &mut StatusReport) -> Option { match self.channel.try_recv() { Ok(()) => { - let shape = match self.model.load_once(&self.parameters) { + let shape = match self.model.load_once(&self.parameters, status) + { Ok(shape) => shape, - Err(Error::Compile) => { + Err(Error::Compile(_)) => { // It would be better to display an error in the UI, // where the user can actually see it. Issue: // https://github.com/hannobraun/fornjot/issues/30 - println!("Error compiling model"); return None; } Err(err) => { @@ -334,7 +356,7 @@ impl DerefMut for Parameters { pub enum Error { /// Model failed to compile #[error("Error compiling model")] - Compile, + Compile(String), /// I/O error while loading the model #[error("I/O error while loading model")] diff --git a/crates/fj-interop/src/status_report.rs b/crates/fj-interop/src/status_report.rs index a99bc6bf4..cdbfddaff 100644 --- a/crates/fj-interop/src/status_report.rs +++ b/crates/fj-interop/src/status_report.rs @@ -6,9 +6,7 @@ pub struct StatusReport { impl StatusReport { pub fn new() -> Self { - StatusReport { - status: String::new(), - } + Self::default() } pub fn update_status(&mut self, status: &str) { @@ -18,4 +16,10 @@ impl StatusReport { pub fn status(&self) -> &str { self.status.as_str() } + + fn default() -> Self { + Self { + status: String::new(), + } + } } diff --git a/crates/fj-viewer/src/graphics/mod.rs b/crates/fj-viewer/src/graphics/mod.rs index ea0632c8d..15c4728bf 100644 --- a/crates/fj-viewer/src/graphics/mod.rs +++ b/crates/fj-viewer/src/graphics/mod.rs @@ -7,6 +7,7 @@ mod geometries; mod pipelines; mod renderer; mod shaders; +mod status_report; mod transform; mod uniforms; mod vertices; diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index cd2179e46..3e2dbcfbe 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 fj_interop::status_report::StatusReport; use fj_math::{Aabb, Point}; use thiserror::Error; use tracing::debug; @@ -304,6 +305,7 @@ impl Renderer { camera: &Camera, config: &mut DrawConfig, window: &egui_winit::winit::window::Window, + status: &mut StatusReport, ) -> Result<(), DrawError> { let aspect_ratio = self.surface_config.width as f64 / self.surface_config.height as f64; @@ -428,6 +430,10 @@ impl Renderer { egui::SidePanel::left("fj-left-panel").show(&self.egui.context, |ui| { ui.add_space(16.0); + ui.label(format!("Status Report:\n{}", status.status())); + + ui.add_space(16.0); + ui.group(|ui| { ui.checkbox(&mut config.draw_model, "Render model") .on_hover_text_at_pointer("Toggle with 1"); diff --git a/crates/fj-viewer/src/graphics/status_report.rs b/crates/fj-viewer/src/graphics/status_report.rs new file mode 100644 index 000000000..e69de29bb diff --git a/crates/fj-window/Cargo.toml b/crates/fj-window/Cargo.toml index 42b33fbf1..a60e1dee2 100644 --- a/crates/fj-window/Cargo.toml +++ b/crates/fj-window/Cargo.toml @@ -32,3 +32,7 @@ path = "../fj-operations" [dependencies.fj-viewer] version = "0.10.0" path = "../fj-viewer" + +[dependencies.fj-interop] +version = "0.10.0" +path = "../fj-interop" diff --git a/crates/fj-window/src/run.rs b/crates/fj-window/src/run.rs index 4264a48a4..310bf965c 100644 --- a/crates/fj-window/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -6,6 +6,7 @@ use std::error; use fj_host::Watcher; +use fj_interop::status_report::StatusReport; use fj_operations::shape_processor::ShapeProcessor; use fj_viewer::{ camera::Camera, @@ -30,6 +31,7 @@ use crate::window::{self, Window}; pub fn run( watcher: Watcher, shape_processor: ShapeProcessor, + mut status: StatusReport, ) -> Result<(), Error> { let event_loop = EventLoop::new(); let window = Window::new(&event_loop)?; @@ -49,7 +51,7 @@ pub fn run( event_loop.run(move |event, _, control_flow| { trace!("Handling event: {:?}", event); - if let Some(new_shape) = watcher.receive() { + if let Some(new_shape) = watcher.receive(&mut status) { match shape_processor.process(&new_shape) { Ok(new_shape) => { renderer.update_geometry( @@ -174,9 +176,12 @@ pub fn run( if let (Some(shape), Some(camera)) = (&shape, &mut camera) { camera.update_planes(&shape.aabb); - if let Err(err) = - renderer.draw(camera, &mut draw_config, window.window()) - { + if let Err(err) = renderer.draw( + camera, + &mut draw_config, + window.window(), + &mut status, + ) { warn!("Draw error: {}", err); } } diff --git a/models/star/src/lib.rs b/models/star/src/lib.rs index 3d1775680..27a8d3f70 100644 --- a/models/star/src/lib.rs +++ b/models/star/src/lib.rs @@ -13,7 +13,7 @@ pub fn model( fj::Angle::from_rad(2. * PI / num_vertices as f64 * i as f64); let radius = if i % 2 == 0 { r1 } else { r2 }; (angle, radius) - }); + }) // Now that we got that iterator prepared, generating the vertices is just a // bit of trigonometry. From 6082708fc938d7128c619aba82c98a9d5d11d4f7 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Thu, 4 Aug 2022 07:03:23 -0700 Subject: [PATCH 3/8] Add successfull compile message --- crates/fj-host/src/lib.rs | 16 +++++----------- models/star/src/lib.rs | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/crates/fj-host/src/lib.rs b/crates/fj-host/src/lib.rs index 6dc80e084..138595e5b 100644 --- a/crates/fj-host/src/lib.rs +++ b/crates/fj-host/src/lib.rs @@ -105,15 +105,9 @@ impl Model { ) .expect("Failed to read command output.") )); - return Err(Error::Compile( - String::from_utf8( - command - .output() - .expect("Failed to get command output.") - .stderr, - ) - .expect("Failed to read command output"), - )); + return Err(Error::Compile); + } else { + status.update_status("Model compiled successfully!"); } // So, strictly speaking this is all unsound: @@ -288,7 +282,7 @@ impl Watcher { let shape = match self.model.load_once(&self.parameters, status) { Ok(shape) => shape, - Err(Error::Compile(_)) => { + Err(Error::Compile) => { // It would be better to display an error in the UI, // where the user can actually see it. Issue: // https://github.com/hannobraun/fornjot/issues/30 @@ -356,7 +350,7 @@ impl DerefMut for Parameters { pub enum Error { /// Model failed to compile #[error("Error compiling model")] - Compile(String), + Compile, /// I/O error while loading the model #[error("I/O error while loading model")] diff --git a/models/star/src/lib.rs b/models/star/src/lib.rs index 27a8d3f70..3d1775680 100644 --- a/models/star/src/lib.rs +++ b/models/star/src/lib.rs @@ -13,7 +13,7 @@ pub fn model( fj::Angle::from_rad(2. * PI / num_vertices as f64 * i as f64); let radius = if i % 2 == 0 { r1 } else { r2 }; (angle, radius) - }) + }); // Now that we got that iterator prepared, generating the vertices is just a // bit of trigonometry. From 223a757bac24125be52305f843ac4820a7be7029 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Thu, 4 Aug 2022 08:24:11 -0700 Subject: [PATCH 4/8] Update docs --- crates/fj-host/src/lib.rs | 17 ++++------------- crates/fj-interop/src/status_report.rs | 14 +++++++------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/crates/fj-host/src/lib.rs b/crates/fj-host/src/lib.rs index 138595e5b..e76a3b9b2 100644 --- a/crates/fj-host/src/lib.rs +++ b/crates/fj-host/src/lib.rs @@ -94,20 +94,11 @@ impl Model { .args(["--manifest-path", &manifest_path]); let exit_status = command.status()?; - if !exit_status.success() { - status.update_status(&format!( - "Compile error: {:?}", - String::from_utf8( - command - .output() - .expect("Failed to get command output.") - .stderr - ) - .expect("Failed to read command output.") - )); - return Err(Error::Compile); - } else { + if exit_status.success() { status.update_status("Model compiled successfully!"); + } else { + status.update_status("Error compiling the model!"); + return Err(Error::Compile); } // So, strictly speaking this is all unsound: diff --git a/crates/fj-interop/src/status_report.rs b/crates/fj-interop/src/status_report.rs index cdbfddaff..d36150659 100644 --- a/crates/fj-interop/src/status_report.rs +++ b/crates/fj-interop/src/status_report.rs @@ -1,25 +1,25 @@ //! Struct to store and update status messages +/// Struct to store and update status messages pub struct StatusReport { status: String, } impl StatusReport { + /// Create a new ``StatusReport`` instance with a blank status pub fn new() -> Self { - Self::default() + Self { + status: String::new(), + } } + /// Update the status pub fn update_status(&mut self, status: &str) { self.status = status.to_string(); } + /// Get current status pub fn status(&self) -> &str { self.status.as_str() } - - fn default() -> Self { - Self { - status: String::new(), - } - } } From b367a5d66ff33fee7d4e1b0c0226e8327d5380d6 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Fri, 5 Aug 2022 07:16:38 -0700 Subject: [PATCH 5/8] Fix cargo fmt --- crates/fj-viewer/src/graphics/status_report.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 crates/fj-viewer/src/graphics/status_report.rs diff --git a/crates/fj-viewer/src/graphics/status_report.rs b/crates/fj-viewer/src/graphics/status_report.rs deleted file mode 100644 index e69de29bb..000000000 From ef196dd7108ce0c2d2bc400b6c000d95d8f02e23 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Fri, 5 Aug 2022 07:18:55 -0700 Subject: [PATCH 6/8] Fix error --- crates/fj-viewer/src/graphics/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/fj-viewer/src/graphics/mod.rs b/crates/fj-viewer/src/graphics/mod.rs index 15c4728bf..ea0632c8d 100644 --- a/crates/fj-viewer/src/graphics/mod.rs +++ b/crates/fj-viewer/src/graphics/mod.rs @@ -7,7 +7,6 @@ mod geometries; mod pipelines; mod renderer; mod shaders; -mod status_report; mod transform; mod uniforms; mod vertices; From 0992297bfcf88e168ddf928d22aa659443dc0559 Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Fri, 5 Aug 2022 07:24:50 -0700 Subject: [PATCH 7/8] Fix clippy suggestions --- crates/fj-interop/src/status_report.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/fj-interop/src/status_report.rs b/crates/fj-interop/src/status_report.rs index d36150659..80aa1ae5a 100644 --- a/crates/fj-interop/src/status_report.rs +++ b/crates/fj-interop/src/status_report.rs @@ -8,9 +8,7 @@ pub struct StatusReport { impl StatusReport { /// Create a new ``StatusReport`` instance with a blank status pub fn new() -> Self { - Self { - status: String::new(), - } + Self::default() } /// Update the status @@ -23,3 +21,9 @@ impl StatusReport { self.status.as_str() } } + +impl Default for StatusReport { + fn default() -> Self { + Self::new() + } +} From ec887632031141af459e3a9746cd8895eab4326c Mon Sep 17 00:00:00 2001 From: Devan Looches Date: Fri, 5 Aug 2022 07:27:17 -0700 Subject: [PATCH 8/8] Fix clippy without recursing new and default functions accidentally --- crates/fj-interop/src/status_report.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/fj-interop/src/status_report.rs b/crates/fj-interop/src/status_report.rs index 80aa1ae5a..7478fede1 100644 --- a/crates/fj-interop/src/status_report.rs +++ b/crates/fj-interop/src/status_report.rs @@ -8,7 +8,9 @@ pub struct StatusReport { impl StatusReport { /// Create a new ``StatusReport`` instance with a blank status pub fn new() -> Self { - Self::default() + Self { + status: String::new(), + } } /// Update the status