egui: implement painting of shapes

This commit is contained in:
Mikolaj Wielgus 2024-02-21 16:29:58 +00:00
parent f10f7b7ab4
commit 08c03a0e77
2 changed files with 101 additions and 5 deletions

View File

@ -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. /// Deserialize/Serialize is needed to persist app state between restarts.
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)] #[serde(default)]
@ -57,11 +64,43 @@ impl eframe::App for App {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
egui::Frame::canvas(ui.style()).show(ui, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| {
let (rect, response) = ui.ctx().request_repaint();
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)); let desired_size = ui.available_width() * egui::vec2(1.0, 0.5);
ui.painter() let (_id, viewport_rect) = ui.allocate_space(desired_size);
.line_segment([[10.0, 10.0].into(), [30.0, 30.0].into()], stroke);
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));
}) })
}); });
} }

View File

@ -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<Pos2> = 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) {
//
}
}