From 08c03a0e77612ef850e51e8499fe5cc7569decd4 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 21 Feb 2024 16:29:58 +0000 Subject: [PATCH] egui: implement painting of shapes --- src/bin/topola-egui/app.rs | 49 ++++++++++++++++++++++++++--- src/bin/topola-egui/painter.rs | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 51ed5cc..5d7f480 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -1,3 +1,10 @@ +use topola::{ + layout::geometry::shape::{BendShape, DotShape, SegShape, Shape}, + math::Circle, +}; + +use crate::painter::Painter; + /// Deserialize/Serialize is needed to persist app state between restarts. #[derive(serde::Deserialize, serde::Serialize)] #[serde(default)] @@ -57,11 +64,43 @@ impl eframe::App for App { egui::CentralPanel::default().show(ctx, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| { - let (rect, response) = - ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag()); - let stroke = egui::Stroke::new(10.0, egui::Color32::from_white_alpha(255)); - ui.painter() - .line_segment([[10.0, 10.0].into(), [30.0, 30.0].into()], stroke); + ui.ctx().request_repaint(); + + let desired_size = ui.available_width() * egui::vec2(1.0, 0.5); + let (_id, viewport_rect) = ui.allocate_space(desired_size); + + let transform = egui::emath::RectTransform::from_to( + egui::Rect::from_x_y_ranges(0.0..=1000.0, 0.0..=500.0), + viewport_rect, + ); + let mut painter = Painter::new(ui, transform); + + let dot_shape = Shape::Dot(DotShape { + c: Circle { + pos: [50.0, 100.0].into(), + r: 10.0, + }, + }); + + let seg_shape = Shape::Seg(SegShape { + from: [200.0, 25.0].into(), + to: [300.0, 300.0].into(), + width: 5.0, + }); + + let bend_shape = Shape::Bend(BendShape { + from: [100.0, 100.0].into(), + to: [160.0, 160.0].into(), + c: Circle { + pos: [130.0, 130.0].into(), + r: 30.0, + }, + width: 12.0, + }); + + painter.paint_shape(&dot_shape, egui::Color32::from_rgb(255, 0, 0)); + painter.paint_shape(&seg_shape, egui::Color32::from_rgb(128, 128, 128)); + painter.paint_shape(&bend_shape, egui::Color32::from_rgb(255, 255, 0)); }) }); } diff --git a/src/bin/topola-egui/painter.rs b/src/bin/topola-egui/painter.rs index 8b13789..6f88469 100644 --- a/src/bin/topola-egui/painter.rs +++ b/src/bin/topola-egui/painter.rs @@ -1 +1,58 @@ +use egui::{emath::RectTransform, epaint, Color32, Pos2, Ui}; +use geo::Point; +use topola::layout::geometry::shape::Shape; +pub struct Painter<'a> { + ui: &'a mut egui::Ui, + transform: RectTransform, +} + +impl<'a> Painter<'a> { + pub fn new(ui: &'a mut Ui, transform: RectTransform) -> Self { + Self { ui, transform } + } + + pub fn paint_shape(&mut self, shape: &Shape, color: Color32) { + let epaint_shape = match shape { + Shape::Dot(dot) => epaint::Shape::circle_filled( + self.transform + .transform_pos([dot.c.pos.x() as f32, dot.c.pos.y() as f32].into()), + dot.c.r as f32, + color, + ), + Shape::Seg(seg) => epaint::Shape::line_segment( + [ + self.transform + .transform_pos([seg.from.x() as f32, seg.from.y() as f32].into()), + self.transform + .transform_pos([seg.to.x() as f32, seg.to.y() as f32].into()), + ], + egui::Stroke::new(seg.width as f32, color), + ), + Shape::Bend(bend) => { + let delta_from = bend.from - bend.c.pos; + let delta_to = bend.to - bend.c.pos; + + let angle_from = delta_from.y().atan2(delta_from.x()); + let angle_to = delta_to.y().atan2(delta_to.x()); + let mut points: Vec = vec![]; + + let angle_step = (angle_to - angle_from) / 100.0; + + for i in 0..100 { + let x = bend.c.pos.x() + bend.c.r * (angle_from + i as f64 * angle_step).cos(); + let y = bend.c.pos.y() + bend.c.r * (angle_from + i as f64 * angle_step).sin(); + points.push(self.transform.transform_pos([x as f32, y as f32].into())); + } + + epaint::Shape::line(points, egui::Stroke::new(bend.width as f32, color)) + } + }; + + self.ui.painter().add(epaint_shape); + } + + pub fn paint_edge(&mut self, from: Point, to: Point, color: Color32) { + // + } +}