use crate::drawings::domain::Drawing;
use crate::tokens::DESIGN_TOKENS;
use egui::{Color32, Pos2, Rect, Stroke, epaint::StrokeKind};
impl Drawing {
pub(crate) fn render_rotated_rect(&self, painter: &egui::Painter) {
if self.points.len() < 2 {
return;
}
let p1 = self.points[0];
let p2 = self.points[1];
let color = Color32::from_rgba_unmultiplied(
self.color[0],
self.color[1],
self.color[2],
self.color[3],
);
let rect = Rect::from_two_pos(p1, p2);
painter.rect_stroke(
rect,
0.0,
Stroke::new(self.stroke_width, color),
StrokeKind::Inside,
);
}
pub(crate) fn render_double_curve(&self, painter: &egui::Painter) {
if self.points.len() < 2 {
return;
}
let p1 = self.points[0];
let p2 = self.points[1];
let color = Color32::from_rgba_unmultiplied(
self.color[0],
self.color[1],
self.color[2],
self.color[3],
);
let segments = 32;
let mut prev = p1;
for i in 1..=segments {
let t = i as f32 / segments as f32;
let x = p1.x + (p2.x - p1.x) * t;
let offset = ((t * std::f32::consts::PI * 2.0).sin()) * 20.0;
let y = p1.y + (p2.y - p1.y) * t + offset;
let point = Pos2::new(x, y);
painter.line_segment([prev, point], Stroke::new(self.stroke_width, color));
prev = point;
}
}
pub(crate) fn render_brush(&self, painter: &egui::Painter) {
let color = Color32::from_rgba_unmultiplied(
self.color[0],
self.color[1],
self.color[2],
self.color[3],
);
for (i, &point) in self.points.iter().enumerate() {
if i > 0 {
painter.line_segment(
[self.points[i - 1], point],
Stroke::new(self.stroke_width * 2.0, color),
);
}
}
}
pub(crate) fn render_highlighter(&self, painter: &egui::Painter) {
let color =
Color32::from_rgba_unmultiplied(self.color[0], self.color[1], self.color[2], 100);
for (i, &point) in self.points.iter().enumerate() {
if i > 0 {
painter.line_segment(
[self.points[i - 1], point],
Stroke::new(self.stroke_width * 8.0, color),
);
}
}
}
pub(crate) fn render_path(&self, painter: &egui::Painter) {
if self.points.is_empty() {
return;
}
let color = Color32::from_rgba_unmultiplied(
self.color[0],
self.color[1],
self.color[2],
self.color[3],
);
let stroke = Stroke::new(self.stroke_width, color);
for (i, &point) in self.points.iter().enumerate() {
if i > 0 {
painter.line_segment([self.points[i - 1], point], stroke);
}
painter.circle_filled(point, DESIGN_TOKENS.rounding.sm, color);
}
if !self.points.is_empty() {
painter.circle_filled(self.points[0], DESIGN_TOKENS.rounding.md, color);
}
}
pub(crate) fn render_curve(&self, painter: &egui::Painter) {
if self.points.len() < 2 {
return;
}
let p0 = self.points[0];
let p2 = self.points[self.points.len() - 1];
let p1 = if self.points.len() >= 3 {
self.points[1]
} else {
let mid_x = (p0.x + p2.x) / 2.0;
let mid_y = (p0.y + p2.y) / 2.0;
let dx = p2.x - p0.x;
let dy = p2.y - p0.y;
Pos2::new(mid_x - dy * 0.3, mid_y + dx * 0.3)
};
let color = Color32::from_rgba_unmultiplied(
self.color[0],
self.color[1],
self.color[2],
self.color[3],
);
let stroke = Stroke::new(self.stroke_width, color);
let segments = 32;
let mut prev_point: Option<Pos2> = None;
for i in 0..=segments {
let t = i as f32 / segments as f32;
let point = Self::quadratic_bezier(p0, p1, p2, t);
if let Some(prev) = prev_point {
painter.line_segment([prev, point], stroke);
}
prev_point = Some(point);
}
painter.circle_filled(p0, DESIGN_TOKENS.rounding.md, color);
painter.circle_filled(p2, DESIGN_TOKENS.rounding.md, color);
painter.circle_filled(
p1,
DESIGN_TOKENS.rounding.sm,
Color32::from_rgba_unmultiplied(self.color[0], self.color[1], self.color[2], 128),
);
}
}