From df056b7b2cb012a3a45f4e1326b7e781403db586 Mon Sep 17 00:00:00 2001 From: TQ Hirsch Date: Thu, 3 Jul 2025 09:00:37 +0200 Subject: [PATCH] Factored out crates for web version --- Cargo.lock | 24 ++++++- Cargo.toml | 21 +++---- mandelia_native/Cargo.toml | 10 +++ mandelia_native/src/main.rs | 17 +++++ mandelia_renderer/Cargo.toml | 12 ++++ {src => mandelia_renderer/src}/lib.rs | 7 +-- {src => mandelia_renderer/src}/transform.rs | 1 - mandelia_ui/Cargo.toml | 11 ++++ src/main.rs => mandelia_ui/src/lib.rs | 69 ++++++++------------- 9 files changed, 105 insertions(+), 67 deletions(-) create mode 100644 mandelia_native/Cargo.toml create mode 100644 mandelia_native/src/main.rs create mode 100644 mandelia_renderer/Cargo.toml rename {src => mandelia_renderer/src}/lib.rs (94%) rename {src => mandelia_renderer/src}/transform.rs (99%) create mode 100644 mandelia_ui/Cargo.toml rename src/main.rs => mandelia_ui/src/lib.rs (74%) diff --git a/Cargo.lock b/Cargo.lock index 596faee..5e129be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1980,19 +1980,37 @@ dependencies = [ ] [[package]] -name = "mandelia" +name = "mandelia_native" +version = "0.1.0" +dependencies = [ + "eframe", + "egui", + "mandelia_ui", +] + +[[package]] +name = "mandelia_renderer" version = "0.1.0" dependencies = [ "anyhow", "clap", - "eframe", - "egui", "image", "nalgebra", "num", "rayon", ] +[[package]] +name = "mandelia_ui" +version = "0.1.0" +dependencies = [ + "anyhow", + "eframe", + "egui", + "image", + "mandelia_renderer", +] + [[package]] name = "matrixmultiply" version = "0.3.10" diff --git a/Cargo.toml b/Cargo.toml index 1b8e591..a9ce8c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,7 @@ -[package] -name = "mandelia" -version = "0.1.0" -edition = "2024" - -[dependencies] -image = { version = "0.25.6", features = ["png"] } -rayon = "1.10.0" -num = "0.4.3" -nalgebra = "0.33.2" -anyhow = "1.0.98" -clap = { version = "4.5.40", features = ["derive"] } -egui = "0.31" -eframe = { version = "0.31", features = ["wayland", "glow"] } +[workspace] +resolver = "3" +members = [ + "mandelia_renderer", + "mandelia_native", + "mandelia_ui" +] diff --git a/mandelia_native/Cargo.toml b/mandelia_native/Cargo.toml new file mode 100644 index 0000000..810851f --- /dev/null +++ b/mandelia_native/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "mandelia_native" +version = "0.1.0" +edition = "2024" + +[dependencies] +mandelia_ui = { path = "../mandelia_ui" } +eframe = { version = "0.31", features = ["wayland", "glow"] } +egui = "0.31" + diff --git a/mandelia_native/src/main.rs b/mandelia_native/src/main.rs new file mode 100644 index 0000000..5a5ae13 --- /dev/null +++ b/mandelia_native/src/main.rs @@ -0,0 +1,17 @@ +fn main() -> eframe::Result { + // mandelia::main() + + let options = eframe::NativeOptions { + ..eframe::NativeOptions::default() + }; + + eframe::run_native( + "Mandelia", + options, + Box::new(|cc| { + Ok(Box::new(mandelia_ui::App::new(cc))) + }) + ) +} + +// this is backend-independent diff --git a/mandelia_renderer/Cargo.toml b/mandelia_renderer/Cargo.toml new file mode 100644 index 0000000..ff9d86a --- /dev/null +++ b/mandelia_renderer/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "mandelia_renderer" +version = "0.1.0" +edition = "2024" + +[dependencies] +image = { version = "0.25.6", features = ["png"] } +rayon = "1.10.0" +num = "0.4.3" +nalgebra = "0.33.2" +anyhow = "1.0.98" +clap = { version = "4.5.40", features = ["derive"] } diff --git a/src/lib.rs b/mandelia_renderer/src/lib.rs similarity index 94% rename from src/lib.rs rename to mandelia_renderer/src/lib.rs index e9cefa4..95601ee 100644 --- a/src/lib.rs +++ b/mandelia_renderer/src/lib.rs @@ -1,10 +1,8 @@ //#![feature(portable_simd)] +use clap::Parser; +use image::{ImageBuffer, Rgb}; use std::path::PathBuf; -use clap::{Arg, Parser}; -use image::{GrayImage, ImageBuffer, Luma, Rgb}; -use image::buffer::ConvertBuffer; -use rayon::iter::ParallelIterator; pub mod transform; @@ -60,7 +58,6 @@ impl Config { const ESCAPE: Float = 2.; const ESCAPE2: Float = ESCAPE * ESCAPE; - let mut base = base; let result = std::iter::successors(Some(base), |i| Some(*i * *i + delta)) .take(self.maxiter) diff --git a/src/transform.rs b/mandelia_renderer/src/transform.rs similarity index 99% rename from src/transform.rs rename to mandelia_renderer/src/transform.rs index 11edc5b..ff89b1c 100644 --- a/src/transform.rs +++ b/mandelia_renderer/src/transform.rs @@ -114,7 +114,6 @@ pub fn transform_to_coords(mat: &MTransform) -> super::Transform { } pub fn parse_transforms<'a>(transforms: impl Iterator>) ->anyhow::Result { - use super::Point; let mat = transforms .map(|s| parse_step(s.as_ref()) .ok_or_else(|| anyhow::anyhow!("Invalid step: {:?}", s.as_ref()))) diff --git a/mandelia_ui/Cargo.toml b/mandelia_ui/Cargo.toml new file mode 100644 index 0000000..eb300c6 --- /dev/null +++ b/mandelia_ui/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mandelia_ui" +version = "0.1.0" +edition = "2024" + +[dependencies] +mandelia_renderer = {path = "../mandelia_renderer"} +anyhow = "1.0.98" +egui = "0.31" +eframe = { version = "0.31" } +image = "0.25.6" \ No newline at end of file diff --git a/src/main.rs b/mandelia_ui/src/lib.rs similarity index 74% rename from src/main.rs rename to mandelia_ui/src/lib.rs index 49fdffb..3a1ac15 100644 --- a/src/main.rs +++ b/mandelia_ui/src/lib.rs @@ -1,44 +1,26 @@ -// extern crate mandelia; -use eframe::{CreationContext, Frame, Result}; +use eframe::{CreationContext, Frame}; use egui::Context; -use egui::load::SizedTexture; use image::EncodableLayout; -use mandelia::Float; -fn main() -> eframe::Result { - // mandelia::main() +use mandelia_renderer::Float; - let options = eframe::NativeOptions { - ..eframe::NativeOptions::default() - }; - - eframe::run_native( - "Mandelia", - options, - Box::new(|cc| { - Ok(Box::new(App::new(cc))) - }) - ) -} - -// this is backend-independent pub struct App { - tx_mat: nalgebra::Matrix5, - transform: mandelia::Transform, + tx_mat: mandelia_renderer::transform::MTransform, + transform: mandelia_renderer::Transform, texture: egui::TextureHandle, last_render: RenderData, } #[derive(Copy, Clone, PartialEq, Debug, Default)] struct RenderData { - transform: mandelia::Transform, + transform: mandelia_renderer::Transform, render_size: [usize; 2], } impl App { - fn new(cc: &CreationContext) -> Self { + pub fn new(cc: &CreationContext) -> Self { let mut result = Self { transform: Default::default(), - tx_mat: nalgebra::Matrix5::identity(), + tx_mat: mandelia_renderer::transform::MTransform::identity(), texture: cc.egui_ctx.load_texture("rendering", egui::ColorImage::example(), egui::TextureOptions::LINEAR), last_render: Default::default(), }; @@ -47,12 +29,12 @@ impl App { } pub fn reset_transform(&mut self) { - self.tx_mat = nalgebra::Matrix5::identity(); + self.tx_mat = mandelia_renderer::transform::MTransform::identity(); self.update_transform(); } fn update_transform(&mut self) { - use mandelia::Point; + use mandelia_renderer::Point; let mat = &self.tx_mat; let bx = Point::new(mat[(0,0)], mat[(0,1)]); let by = Point::new(mat[(1,0)], mat[(1,1)]); @@ -69,12 +51,12 @@ impl App { ] } - fn add_transform(&mut self, xf: mandelia::transform::Type) { - self.tx_mat = mandelia::transform::MTransform::from(xf) * self.tx_mat; + fn add_transform(&mut self, xf: mandelia_renderer::transform::Type) { + self.tx_mat = mandelia_renderer::transform::MTransform::from(xf) * self.tx_mat; self.update_transform(); } - fn mk_adjuster(&mut self, ui: &mut egui::Ui, label: &str, key_dec: egui::Key, key_inc: egui::Key, mut action: impl Fn(Float) -> mandelia::transform::Type) { + fn mk_adjuster(&mut self, ui: &mut egui::Ui, label: &str, key_dec: egui::Key, key_inc: egui::Key, action: impl Fn(Float) -> mandelia_renderer::transform::Type) { let (dn, up) = ui.ctx().input(|is| (is.key_pressed(key_dec), is.key_pressed(key_inc))); if ui.button(format!("- ({})", key_dec.symbol_or_name())).clicked() || dn { self.add_transform(action(-1.)); @@ -94,7 +76,7 @@ impl App { }; if self.last_render != new_rdata { self.last_render = new_rdata; - let config = mandelia::Config { + let config = mandelia_renderer::Config { transform: self.transform, width: size[0] as u32, height: size[1] as u32, @@ -111,26 +93,26 @@ impl App { } // transform functions -fn mk_translation(axis: u8) -> impl Fn(Float) -> mandelia::transform::Type { - move |amt| mandelia::transform::Type::Translation(axis, amt / 100.) +fn mk_translation(axis: u8) -> impl Fn(Float) -> mandelia_renderer::transform::Type { + move |amt| mandelia_renderer::transform::Type::Translation(axis, amt / 100.) } -fn mk_rotation(a0: u8, a1: u8) -> impl Fn(Float) -> mandelia::transform::Type { - move |amt| mandelia::transform::Type::Rotation(a0, a1, amt) +fn mk_rotation(a0: u8, a1: u8) -> impl Fn(Float) -> mandelia_renderer::transform::Type { + move |amt| mandelia_renderer::transform::Type::Rotation(a0, a1, amt) } -fn mk_scale(scale: Float) -> mandelia::transform::Type { - mandelia::transform::Type::Scale(1. + scale / 4.) +fn mk_scale(scale: Float) -> mandelia_renderer::transform::Type { + mandelia_renderer::transform::Type::Scale(1. + scale / 4.) } -enum JumpMode { +pub enum JumpMode { Mandelbrot, Julia, Origin, } impl eframe::App for App { - fn update(&mut self, ctx: &Context, frame: &mut Frame) { + fn update(&mut self, ctx: &Context, _frame: &mut Frame) { if let Some(jump_mode) = ctx.input(|is| { if is.key_pressed(egui::Key::Num0) { Some(JumpMode::Origin) @@ -142,7 +124,7 @@ impl eframe::App for App { None } }) { - use mandelia::transform::Type; + use mandelia_renderer::transform::Type; match jump_mode { JumpMode::Mandelbrot => { self.reset_transform(); @@ -160,7 +142,6 @@ impl eframe::App for App { } }; egui::SidePanel::left("nav").show(ctx, |ui| { - use mandelia::transform::Type; use egui::Key; egui::Grid::new("nav_grid") .num_columns(3) @@ -169,9 +150,9 @@ impl eframe::App for App { self.mk_adjuster(ui, "base y", Key::S, Key::W, mk_translation(1)); self.mk_adjuster(ui, "delta x", Key::J, Key::L, mk_translation(2)); self.mk_adjuster(ui, "delta y", Key::K, Key::I, mk_translation(3)); - + self.mk_adjuster(ui, "scale", Key::OpenBracket, Key::CloseBracket, mk_scale); - + self.mk_adjuster(ui, "xy", Key::Q, Key::E, mk_rotation(0, 1)); self.mk_adjuster(ui, "XY", Key::U, Key::O, mk_rotation(2, 3)); self.mk_adjuster(ui, "xX", Key::F, Key::G, mk_rotation(0, 2)); @@ -185,7 +166,7 @@ impl eframe::App for App { let size = base_size * ui.pixels_per_point(); let size = [size.x as usize, size.y as usize]; self.update_texture(size); - ui.add(egui::Image::from_texture(SizedTexture::new(&self.texture, base_size))); + ui.add(egui::Image::from_texture(egui::load::SizedTexture::new(&self.texture, base_size))); }); } } \ No newline at end of file