
* Move all interior mutability from Context to CtxRef and make it a handle * Rename `CtxRef` to `Context` * The old `Context` is now `ContextImpl` and is non-pub * Add benchmark Painter::rect Co-authored-by: Daniel Keller <dklr433@gmail.com>
98 lines
2.7 KiB
Rust
98 lines
2.7 KiB
Rust
use egui::*;
|
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
#[cfg_attr(feature = "serde", serde(default))]
|
|
pub struct Painting {
|
|
/// in 0-1 normalized coordinates
|
|
lines: Vec<Vec<Pos2>>,
|
|
stroke: Stroke,
|
|
}
|
|
|
|
impl Default for Painting {
|
|
fn default() -> Self {
|
|
Self {
|
|
lines: Default::default(),
|
|
stroke: Stroke::new(1.0, Color32::LIGHT_BLUE),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Painting {
|
|
pub fn ui_control(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
|
ui.horizontal(|ui| {
|
|
egui::stroke_ui(ui, &mut self.stroke, "Stroke");
|
|
ui.separator();
|
|
if ui.button("Clear Painting").clicked() {
|
|
self.lines.clear();
|
|
}
|
|
})
|
|
.response
|
|
}
|
|
|
|
pub fn ui_content(&mut self, ui: &mut Ui) -> egui::Response {
|
|
let (mut response, painter) =
|
|
ui.allocate_painter(ui.available_size_before_wrap(), Sense::drag());
|
|
|
|
let to_screen = emath::RectTransform::from_to(
|
|
Rect::from_min_size(Pos2::ZERO, response.rect.square_proportions()),
|
|
response.rect,
|
|
);
|
|
let from_screen = to_screen.inverse();
|
|
|
|
if self.lines.is_empty() {
|
|
self.lines.push(vec![]);
|
|
}
|
|
|
|
let current_line = self.lines.last_mut().unwrap();
|
|
|
|
if let Some(pointer_pos) = response.interact_pointer_pos() {
|
|
let canvas_pos = from_screen * pointer_pos;
|
|
if current_line.last() != Some(&canvas_pos) {
|
|
current_line.push(canvas_pos);
|
|
response.mark_changed();
|
|
}
|
|
} else if !current_line.is_empty() {
|
|
self.lines.push(vec![]);
|
|
response.mark_changed();
|
|
}
|
|
|
|
let mut shapes = vec![];
|
|
for line in &self.lines {
|
|
if line.len() >= 2 {
|
|
let points: Vec<Pos2> = line.iter().map(|p| to_screen * *p).collect();
|
|
shapes.push(egui::Shape::line(points, self.stroke));
|
|
}
|
|
}
|
|
painter.extend(shapes);
|
|
|
|
response
|
|
}
|
|
}
|
|
|
|
impl super::Demo for Painting {
|
|
fn name(&self) -> &'static str {
|
|
"🖊 Painting"
|
|
}
|
|
|
|
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
|
use super::View as _;
|
|
Window::new(self.name())
|
|
.open(open)
|
|
.default_size(vec2(512.0, 512.0))
|
|
.vscroll(false)
|
|
.show(ctx, |ui| self.ui(ui));
|
|
}
|
|
}
|
|
|
|
impl super::View for Painting {
|
|
fn ui(&mut self, ui: &mut Ui) {
|
|
ui.vertical_centered(|ui| {
|
|
ui.add(crate::__egui_github_link_file!());
|
|
});
|
|
self.ui_control(ui);
|
|
ui.label("Paint with your mouse/touch!");
|
|
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
|
self.ui_content(ui);
|
|
});
|
|
}
|
|
}
|