Conner Bondurant: 2 Implementation of selection box First attempt at selection logic 22 files changed, 326 insertions(+), 97 deletions(-)
I am going to consider this patch finalized thanks to an additional commit I have written removing the noise dependency and improving noise speed as a result. - Conner Bondurant
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~cbondurant/lipuma-devel/patches/36556/mbox | git am -3Learn more about email & git
--- Cargo.lock | 29 ------------- Cargo.toml | 2 - src/draw_tools/fractal_line_tool.rs | 14 +++--- src/draw_tools/mod.rs | 1 + src/draw_tools/selection_tool.rs | 65 ++++++++++++++++++++++++++++ src/draw_tools/tool.rs | 11 ++--- src/main.rs | 45 ++++++++++++------- src/render_objects/drawable.rs | 8 ++-- src/render_objects/fractal_line.rs | 12 ++--- src/render_objects/mod.rs | 1 + src/render_objects/render_object.rs | 2 +- src/render_objects/selection_rect.rs | 43 ++++++++++++++++++ src/widgets/graphics_data.rs | 5 ++- src/widgets/graphics_scene_widget.rs | 10 +++-- src/widgets/tool_selector.rs | 50 +++++++++++++++++++++ src/widgets/tool_selector_widget.rs | 0 16 files changed, 221 insertions(+), 77 deletions(-) create mode 100644 src/draw_tools/selection_tool.rs create mode 100644 src/render_objects/selection_rect.rs create mode 100644 src/widgets/tool_selector.rs create mode 100644 src/widgets/tool_selector_widget.rs diff --git a/Cargo.lock b/Cargo.lock index 3f7145c..0815524 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,33 +434,6 @@ dependencies = [ "wio", ] -[[package]] -name = "dyn-clonable" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" -dependencies = [ - "dyn-clonable-impl", - "dyn-clone", -] - -[[package]] -name = "dyn-clonable-impl" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dyn-clone" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" - [[package]] name = "either" version = "1.8.0" @@ -1466,8 +1439,6 @@ name = "rust-lipuma" version = "0.1.0" dependencies = [ "druid", - "dyn-clonable", - "dyn-clone", "noise", "rand 0.8.5", ] diff --git a/Cargo.toml b/Cargo.toml index 6b1fb47..7fc6609 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,5 @@ edition = "2021" [dependencies] druid = {version = "0.7.0", features = ["im", "svg", "image"]} -dyn-clonable = "0.9.0" -dyn-clone = "1.0.9" noise = "0.8.1" rand = "0.8.5" diff --git a/src/draw_tools/fractal_line_tool.rs b/src/draw_tools/fractal_line_tool.rs index c766594..f78679f 100644 --- a/src/draw_tools/fractal_line_tool.rs +++ b/src/draw_tools/fractal_line_tool.rs @@ -3,17 +3,17 @@ use noise::OpenSimplex; use rand::random; use std::rc::Rc; -use super::tool::Tool; use crate::render_objects::{fractal_line::FractalLine, RenderObject}; -use crate::widgets::graphics_data::GraphicsData; -#[derive(Data, Clone, PartialEq, Eq)] +use super::tool::Tool; + +#[derive(Data, Clone, PartialEq, Eq, Debug)] enum ToolState { Drawing, Standby, } -#[derive(Data, Clone)] +#[derive(Data, Debug, Clone)] pub struct FractalLineTool { preview: FractalLine, state: ToolState, @@ -94,15 +94,15 @@ impl FractalLineTool { } impl Tool for FractalLineTool { - fn enable(&mut self, _data: &mut GraphicsData) { + fn enable(&mut self, _data: &mut OrdSet<RenderObject>) { self.state = ToolState::Standby; } - fn disable(&mut self, data: &mut GraphicsData) { + fn disable(&mut self, data: &mut OrdSet<RenderObject>) { match self.state { ToolState::Drawing => { // get_preview always returns some when drawing - data.objects.insert(self.get_preview().unwrap()); + data.insert(self.get_preview().unwrap()); } ToolState::Standby => (), } diff --git a/src/draw_tools/mod.rs b/src/draw_tools/mod.rs index 033ef91..03c110c 100644 --- a/src/draw_tools/mod.rs +++ b/src/draw_tools/mod.rs @@ -1,2 +1,3 @@ pub mod fractal_line_tool; +pub mod selection_tool; pub mod tool; diff --git a/src/draw_tools/selection_tool.rs b/src/draw_tools/selection_tool.rs new file mode 100644 index 0000000..f12e6ec --- /dev/null +++ b/src/draw_tools/selection_tool.rs @@ -0,0 +1,65 @@ +use std::rc::Rc; + +use super::tool::Tool; +use druid::{im::OrdSet, Data, Event, Point, Rect}; + +use crate::render_objects::{selection_rect::SelectionRect, RenderObject}; + +#[derive(Data, Debug, Clone)] +pub struct SelectionTool { + start_coord: Point, + end_coord: Point, + is_active: bool, +} + +impl SelectionTool { + pub fn new() -> Self { + Self { + start_coord: Point::ZERO, + end_coord: Point::ZERO, + is_active: false, + } + } +} + +impl Tool for SelectionTool { + fn enable(&mut self, _data: &mut OrdSet<RenderObject>) { + () + } + + fn disable(&mut self, _data: &mut OrdSet<RenderObject>) { + () + } + + fn event( + &mut self, + event: &druid::Event, + _ctx: &mut druid::EventCtx, + data: OrdSet<RenderObject>, + ) -> OrdSet<RenderObject> { + match event { + Event::MouseDown(e) => { + self.is_active = true; + self.start_coord = e.pos; + } + Event::MouseUp(_) => self.is_active = false, + Event::MouseMove(e) => self.end_coord = e.pos, + _ => (), + } + data + } + + fn get_preview(&self) -> Option<RenderObject> { + if self.is_active { + Some(RenderObject::new( + u32::MAX, + Rc::new(Box::new(SelectionRect::new(Rect::from_points( + self.start_coord, + self.end_coord, + )))), + )) + } else { + None + } + } +} diff --git a/src/draw_tools/tool.rs b/src/draw_tools/tool.rs index bf11961..f052e8d 100644 --- a/src/draw_tools/tool.rs +++ b/src/draw_tools/tool.rs @@ -1,12 +1,9 @@ -use crate::{render_objects::RenderObject, GraphicsData}; +use crate::render_objects::RenderObject; use druid::{im::OrdSet, Event, EventCtx}; -use dyn_clonable::*; - -#[clonable] -pub trait Tool: Clone { - fn enable(&mut self, data: &mut GraphicsData); - fn disable(&mut self, data: &mut GraphicsData); +pub trait Tool { + fn enable(&mut self, data: &mut OrdSet<RenderObject>); + fn disable(&mut self, data: &mut OrdSet<RenderObject>); fn event( &mut self, event: &Event, diff --git a/src/main.rs b/src/main.rs index 94350fa..ce1093c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ +use std::sync::{Arc, Mutex}; + use draw_tools::fractal_line_tool::FractalLineTool; +use draw_tools::selection_tool::SelectionTool; +use draw_tools::tool::Tool; use druid::im::ordset; -use druid::widget::Flex; -use druid::{theme, AppLauncher, Color, PlatformError, Widget, WidgetExt, WindowDesc}; -use std::rc::Rc; +use druid::widget::{Button, Flex}; +use druid::{AppLauncher, PlatformError, Widget, WindowDesc}; mod draw_tools; mod render_objects; @@ -11,22 +14,32 @@ use widgets::{graphics_data::GraphicsData, graphics_scene_widget::*}; fn build_ui() -> impl Widget<GraphicsData> { let mut row = Flex::row(); + row.add_child( + Flex::column() + .with_child(Button::new("Fractal Line Tool").on_click( + |_ctx, data: &mut GraphicsData, _env| { + data.tool.lock().unwrap().disable(&mut data.objects); + data.tool = Arc::new(Mutex::new(FractalLineTool::new())); + data.tool.lock().unwrap().enable(&mut data.objects); + }, + )) + .with_child(Button::new("Selection Tool").on_click( + |_ctx, data: &mut GraphicsData, _env| { + data.tool.lock().unwrap().disable(&mut data.objects); + data.tool = Arc::new(Mutex::new(SelectionTool::new())); + data.tool.lock().unwrap().enable(&mut data.objects); + }, + )), + ); row.add_flex_child(GraphicsWidget::new(), 1.0); - row.debug_paint_layout() + row } fn main() -> Result<(), PlatformError> { - AppLauncher::with_window(WindowDesc::new(build_ui)) - .configure_env(|env, _| { - env.set( - theme::WINDOW_BACKGROUND_COLOR, - Color::rgba(0.0, 0.0, 0.0, 0.0), - ) - }) - .launch(GraphicsData { - objects: ordset![], - preview: None, - tool: Rc::new(Box::new(FractalLineTool::new())), - })?; + AppLauncher::with_window(WindowDesc::new(build_ui)).launch(GraphicsData { + objects: ordset![], + preview: None, + tool: Arc::new(Mutex::new(FractalLineTool::new())), + })?; Ok(()) } diff --git a/src/render_objects/drawable.rs b/src/render_objects/drawable.rs index 9407c74..ec3a2da 100644 --- a/src/render_objects/drawable.rs +++ b/src/render_objects/drawable.rs @@ -1,4 +1,6 @@ -use druid::{Affine, Rect}; +use druid::Rect; + +use super::RenderObject; pub trait Drawable { #[allow(non_snake_case)] @@ -9,7 +11,7 @@ pub trait Drawable { ctx: &mut druid::EventCtx, event: &druid::Event, env: &druid::Env, - sctx: &mut Affine, + sctx: &RenderObject, ); - fn paint(&self, ctx: &mut druid::PaintCtx, env: &druid::Env, sctx: &Affine); + fn paint(&self, ctx: &mut druid::PaintCtx, env: &druid::Env, sctx: &RenderObject); } diff --git a/src/render_objects/fractal_line.rs b/src/render_objects/fractal_line.rs index 89426fa..cef41bd 100644 --- a/src/render_objects/fractal_line.rs +++ b/src/render_objects/fractal_line.rs @@ -1,13 +1,13 @@ use druid::{ kurbo::{PathEl, Shape}, - Affine, Color, Data, Point, Rect, RenderContext, Vec2, + Color, Data, Point, Rect, RenderContext, Vec2, }; use noise::{NoiseFn, OpenSimplex}; use std::rc::Rc; -use super::drawable::Drawable; +use super::{drawable::Drawable, RenderObject}; -#[derive(Data, Clone)] +#[derive(Data, Clone, Debug)] pub struct FractalLine { pub start: Point, pub end: Point, @@ -85,7 +85,7 @@ impl Shape for FractalLine { } fn bounding_box(&self) -> Rect { - Rect::from_points(self.start, self.end).inflate(self.width, self.width * 1.5) + Rect::from_points(self.start, self.end).inflate(self.width * 1.5, self.width * 1.5) } } @@ -100,12 +100,12 @@ impl Drawable for FractalLine { ctx: &mut druid::EventCtx, event: &druid::Event, env: &druid::Env, - sctx: &mut Affine, + sctx: &RenderObject, ) { todo!() } - fn paint(&self, ctx: &mut druid::PaintCtx, _env: &druid::Env, _sctx: &Affine) { + fn paint(&self, ctx: &mut druid::PaintCtx, _env: &druid::Env, _sctx: &RenderObject) { ctx.stroke(self, &Color::BLACK, 1.0); } } diff --git a/src/render_objects/mod.rs b/src/render_objects/mod.rs index 04b766d..5babdd4 100644 --- a/src/render_objects/mod.rs +++ b/src/render_objects/mod.rs @@ -2,3 +2,4 @@ mod drawable; pub mod fractal_line; pub mod render_object; pub use render_object::RenderObject; +pub mod selection_rect; diff --git a/src/render_objects/render_object.rs b/src/render_objects/render_object.rs index 0780fd1..9c4d76d 100644 --- a/src/render_objects/render_object.rs +++ b/src/render_objects/render_object.rs @@ -59,7 +59,7 @@ impl RenderObject { newctx.transform(self.transform); //newctx.clip(self.drawable.AABB()); //newctx.fill(self.drawable.AABB(), &Color::WHITE); - self.drawable.paint(newctx, env, &self.transform); + self.drawable.paint(newctx, env, &self); }); } diff --git a/src/render_objects/selection_rect.rs b/src/render_objects/selection_rect.rs new file mode 100644 index 0000000..adebba1 --- /dev/null +++ b/src/render_objects/selection_rect.rs @@ -0,0 +1,43 @@ +use druid::{ + piet::{PaintBrush, StrokeStyle}, + Color, Rect, RenderContext, +}; + +use super::drawable::Drawable; + +const SELECTION_BRUSH: PaintBrush = PaintBrush::Color(Color::BLACK); + +pub struct SelectionRect { + rect: Rect, +} + +impl SelectionRect { + pub fn new(rect: Rect) -> Self { + Self { rect } + } +} + +impl Drawable for SelectionRect { + fn AABB(&self) -> Rect { + self.rect.inflate(1.0, 1.0) + } + + fn event( + &mut self, + _ctx: &mut druid::EventCtx, + _event: &druid::Event, + _env: &druid::Env, + _sctx: &super::RenderObject, + ) { + todo!() + } + + fn paint(&self, ctx: &mut druid::PaintCtx, env: &druid::Env, sctx: &super::RenderObject) { + ctx.stroke_styled( + self.rect, + &SELECTION_BRUSH, + 1.0, + &StrokeStyle::new().dash(vec![3.0, 3.0], 0.0), + ); + } +} diff --git a/src/widgets/graphics_data.rs b/src/widgets/graphics_data.rs index 1aebd51..a4ef689 100644 --- a/src/widgets/graphics_data.rs +++ b/src/widgets/graphics_data.rs @@ -1,12 +1,13 @@ +use std::sync::{Arc, Mutex}; + use crate::draw_tools::tool::Tool; use crate::render_objects::RenderObject; use druid::im::OrdSet; use druid::Data; -use std::rc::Rc; #[derive(Data, Clone)] pub struct GraphicsData { pub objects: OrdSet<RenderObject>, pub preview: Option<RenderObject>, - pub tool: Rc<Box<dyn Tool>>, + pub tool: Arc<Mutex<dyn Tool>>, } diff --git a/src/widgets/graphics_scene_widget.rs b/src/widgets/graphics_scene_widget.rs index 76cba53..1690364 100644 --- a/src/widgets/graphics_scene_widget.rs +++ b/src/widgets/graphics_scene_widget.rs @@ -34,8 +34,11 @@ impl Widget<GraphicsData> for GraphicsWidget { data: &mut GraphicsData, _env: &druid::Env, ) { - let muttool = Rc::make_mut(&mut data.tool); - data.objects = muttool.event(event, ctx, data.objects.clone()); + data.objects = data + .tool + .lock() + .unwrap() + .event(event, ctx, data.objects.clone()); if !ctx.is_handled() { #[allow(clippy::single_match)] // We expect to match other expressions later, but this is the only one that matters now @@ -47,8 +50,7 @@ impl Widget<GraphicsData> for GraphicsWidget { _ => (), } } - data.preview = muttool.get_preview(); - data.tool = Rc::new(muttool.clone()); + data.preview = data.tool.lock().unwrap().get_preview(); } fn lifecycle( diff --git a/src/widgets/tool_selector.rs b/src/widgets/tool_selector.rs new file mode 100644 index 0000000..4e72407 --- /dev/null +++ b/src/widgets/tool_selector.rs @@ -0,0 +1,50 @@ +use super::graphics_data::GraphicsData; +use druid::Widget; + +struct ToolSelector {} + +impl Widget<GraphicsData> for ToolSelector { + fn event( + &mut self, + ctx: &mut druid::EventCtx, + event: &druid::Event, + data: &mut GraphicsData, + env: &druid::Env, + ) { + todo!() + } + + fn lifecycle( + &mut self, + ctx: &mut druid::LifeCycleCtx, + event: &druid::LifeCycle, + data: &GraphicsData, + env: &druid::Env, + ) { + todo!() + } + + fn update( + &mut self, + ctx: &mut druid::UpdateCtx, + old_data: &GraphicsData, + data: &GraphicsData, + env: &druid::Env, + ) { + todo!() + } + + fn layout( + &mut self, + ctx: &mut druid::LayoutCtx, + bc: &druid::BoxConstraints, + data: &GraphicsData, + env: &druid::Env, + ) -> druid::Size { + todo!() + } + + fn paint(&mut self, ctx: &mut druid::PaintCtx, data: &GraphicsData, env: &druid::Env) { + todo!() + } +} diff --git a/src/widgets/tool_selector_widget.rs b/src/widgets/tool_selector_widget.rs new file mode 100644 index 0000000..e69de29 -- 2.34.1
--- src/draw_tools/fractal_line_tool.rs | 8 +++- src/draw_tools/selection_tool.rs | 62 +++++++++++++++++++++++----- src/render_objects/drawable.rs | 3 +- src/render_objects/fractal_line.rs | 26 ++++++++++-- src/render_objects/render_object.rs | 21 ++++++++-- src/render_objects/selection_rect.rs | 5 +++ 6 files changed, 105 insertions(+), 20 deletions(-) diff --git a/src/draw_tools/fractal_line_tool.rs b/src/draw_tools/fractal_line_tool.rs index f78679f..ea09f81 100644 --- a/src/draw_tools/fractal_line_tool.rs +++ b/src/draw_tools/fractal_line_tool.rs @@ -28,7 +28,9 @@ impl FractalLineTool { noise: Rc::new(OpenSimplex::new(0)), width: 10.0, density: 0.05, - samples: 1000, + samples: 500, + laurancity: 0.5, + octaves: 4, }, state: ToolState::Standby, } @@ -62,7 +64,9 @@ impl FractalLineTool { noise: Rc::new(OpenSimplex::new(random())), width: 10.0, density: 0.05, - samples: 1000, + samples: 500, + laurancity: 0.5, + octaves: 4, }; ctx.set_handled(); data diff --git a/src/draw_tools/selection_tool.rs b/src/draw_tools/selection_tool.rs index f12e6ec..b90be5f 100644 --- a/src/draw_tools/selection_tool.rs +++ b/src/draw_tools/selection_tool.rs @@ -5,11 +5,17 @@ use druid::{im::OrdSet, Data, Event, Point, Rect}; use crate::render_objects::{selection_rect::SelectionRect, RenderObject}; +#[derive(Data, Debug, Clone, PartialEq, Eq)] +enum SelectionState { + Active, + Inactive, +} + #[derive(Data, Debug, Clone)] pub struct SelectionTool { start_coord: Point, end_coord: Point, - is_active: bool, + state: SelectionState, } impl SelectionTool { @@ -17,9 +23,40 @@ impl SelectionTool { Self { start_coord: Point::ZERO, end_coord: Point::ZERO, - is_active: false, + state: SelectionState::Inactive, } } + + fn update_selected(&self, mut data: OrdSet<RenderObject>) -> OrdSet<RenderObject> { + let bound = Rect::from_points(self.start_coord, self.end_coord); + 'outer: for item in &data.clone() { + if !bound.intersect(item.drawable.AABB()).is_empty() { + for segment in item.drawable.fine_collision_shape(1.0) { + match segment { + druid::kurbo::PathEl::MoveTo(p) + | druid::kurbo::PathEl::LineTo(p) + | druid::kurbo::PathEl::QuadTo(_, p) + | druid::kurbo::PathEl::CurveTo(_, _, p) => { + if bound.contains(p) { + let mut new_item = item.clone(); + new_item.select(); + data.remove(item); + data.insert(new_item); + continue 'outer; + } + } + druid::kurbo::PathEl::ClosePath => todo!(), + } + } + } + + let mut new_item = item.clone(); + new_item.deselect(); + data.remove(item); + data.insert(new_item); + } + data + } } impl Tool for SelectionTool { @@ -39,27 +76,32 @@ impl Tool for SelectionTool { ) -> OrdSet<RenderObject> { match event { Event::MouseDown(e) => { - self.is_active = true; + self.state = SelectionState::Active; self.start_coord = e.pos; + self.end_coord = e.pos; + } + Event::MouseUp(_) => self.state = SelectionState::Inactive, + Event::MouseMove(e) => { + if let SelectionState::Active = self.state { + self.end_coord = e.pos; + return self.update_selected(data); + } } - Event::MouseUp(_) => self.is_active = false, - Event::MouseMove(e) => self.end_coord = e.pos, _ => (), } data } fn get_preview(&self) -> Option<RenderObject> { - if self.is_active { - Some(RenderObject::new( + match self.state { + SelectionState::Active => Some(RenderObject::new( u32::MAX, Rc::new(Box::new(SelectionRect::new(Rect::from_points( self.start_coord, self.end_coord, )))), - )) - } else { - None + )), + SelectionState::Inactive => None, } } } diff --git a/src/render_objects/drawable.rs b/src/render_objects/drawable.rs index ec3a2da..cd702a4 100644 --- a/src/render_objects/drawable.rs +++ b/src/render_objects/drawable.rs @@ -1,10 +1,11 @@ -use druid::Rect; +use druid::{kurbo::BezPath, Rect}; use super::RenderObject; pub trait Drawable { #[allow(non_snake_case)] fn AABB(&self) -> Rect; + fn fine_collision_shape(&self, tolerance: f64) -> BezPath; fn event( &mut self, diff --git a/src/render_objects/fractal_line.rs b/src/render_objects/fractal_line.rs index cef41bd..9f7e39c 100644 --- a/src/render_objects/fractal_line.rs +++ b/src/render_objects/fractal_line.rs @@ -1,5 +1,5 @@ use druid::{ - kurbo::{PathEl, Shape}, + kurbo::{BezPath, PathEl, Shape}, Color, Data, Point, Rect, RenderContext, Vec2, }; use noise::{NoiseFn, OpenSimplex}; @@ -15,6 +15,8 @@ pub struct FractalLine { pub width: f64, pub density: f64, pub samples: i32, + pub laurancity: f64, + pub octaves: i8, } impl FractalLinePathIter { @@ -57,7 +59,11 @@ impl Iterator for FractalLinePathIter { self.i += 1; let simplex_distance = self.real_length * index * self.line_data.density; - let simplex = self.line_data.noise.get([simplex_distance, 0.0]) * 3.0; + let mut simplex = 0.0; + for i in 0..self.line_data.octaves { + simplex += self.line_data.noise.get([simplex_distance * i as f64, 0.0]) + * 3.0 * self.line_data.laurancity.powi(i.into()); + } Some(druid::piet::kurbo::PathEl::LineTo( self.line_data.start.lerp(self.line_data.end, index) + self.perpendicular * self.line_data.width * Self::smooth_to_zero(index) * simplex, @@ -94,6 +100,10 @@ impl Drawable for FractalLine { self.bounding_box() } + fn fine_collision_shape(&self, tolerance: f64) -> BezPath { + self.to_path(tolerance) + } + #[allow(unused_variables)] fn event( &mut self, @@ -105,7 +115,15 @@ impl Drawable for FractalLine { todo!() } - fn paint(&self, ctx: &mut druid::PaintCtx, _env: &druid::Env, _sctx: &RenderObject) { - ctx.stroke(self, &Color::BLACK, 1.0); + fn paint(&self, ctx: &mut druid::PaintCtx, _env: &druid::Env, sctx: &RenderObject) { + ctx.stroke( + self, + if sctx.is_selected() { + &Color::RED + } else { + &Color::BLACK + }, + 1.0, + ); } } diff --git a/src/render_objects/render_object.rs b/src/render_objects/render_object.rs index 9c4d76d..9d394d2 100644 --- a/src/render_objects/render_object.rs +++ b/src/render_objects/render_object.rs @@ -10,6 +10,7 @@ use std::rc::Rc; pub struct RenderObject { pub z: u32, pub transform: Affine, + pub selected: bool, pub drawable: Rc<Box<dyn Drawable>>, } @@ -47,7 +48,10 @@ impl PartialOrd for RenderObject { impl PartialEq for RenderObject { fn eq(&self, other: &Self) -> bool { - self.z == other.z && Rc::ptr_eq(&self.drawable, &other.drawable) + self.z == other.z + && Rc::ptr_eq(&self.drawable, &other.drawable) + && self.selected == other.selected + && self.transform == other.transform } } @@ -57,8 +61,6 @@ impl RenderObject { pub fn paint(&self, ctx: &mut druid::PaintCtx, env: &druid::Env) { ctx.with_save(|newctx| { newctx.transform(self.transform); - //newctx.clip(self.drawable.AABB()); - //newctx.fill(self.drawable.AABB(), &Color::WHITE); self.drawable.paint(newctx, env, &self); }); } @@ -68,6 +70,7 @@ impl RenderObject { z, transform: Affine::new([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]), drawable, + selected: false, } } @@ -80,4 +83,16 @@ impl RenderObject { ctx.transform(self.transform); ctx.with_save(|new_ctx| new_ctx.stroke(self.drawable.AABB(), &Color::RED, 1.0)) } + + pub fn select(&mut self) { + self.selected = true; + } + + pub fn deselect(&mut self) { + self.selected = false; + } + + pub fn is_selected(&self) -> bool { + self.selected + } } diff --git a/src/render_objects/selection_rect.rs b/src/render_objects/selection_rect.rs index adebba1..b0affef 100644 --- a/src/render_objects/selection_rect.rs +++ b/src/render_objects/selection_rect.rs @@ -1,4 +1,5 @@ use druid::{ + kurbo::Shape, piet::{PaintBrush, StrokeStyle}, Color, Rect, RenderContext, }; @@ -22,6 +23,10 @@ impl Drawable for SelectionRect { self.rect.inflate(1.0, 1.0) } + fn fine_collision_shape(&self, tolerance: f64) -> druid::kurbo::BezPath { + self.AABB().to_path(tolerance) + } + fn event( &mut self, _ctx: &mut druid::EventCtx, -- 2.34.1
I am going to consider this patch finalized thanks to an additional commit I have written removing the noise dependency and improving noise speed as a result. - Conner Bondurant