---
src/draw_tools/fractal_line_tool.rs | 152 ++++++++++++++++++++++++++++
src/draw_tools/mod.rs | 2 +
src/draw_tools/tool.rs | 17 ++++
src/graphics_scene_widget.rs | 69 ++++---------
src/main.rs | 1 +
src/renderobject.rs | 8 ++
6 files changed, 199 insertions(+), 50 deletions(-)
create mode 100644 src/draw_tools/fractal_line_tool.rs
create mode 100644 src/draw_tools/mod.rs
create mode 100644 src/draw_tools/tool.rs
diff --git a/src/draw_tools/fractal_line_tool.rs b/src/draw_tools/fractal_line_tool.rs
new file mode 100644
index 0000000..944ea0a
--- /dev/null
+++ b/src/draw_tools/fractal_line_tool.rs
@@ -0,0 +1,152 @@
+use druid::{Data, Point};
+use noise::OpenSimplex;
+use rand::random;
+use std::rc::Rc;
+
+use super::tool::Tool;
+use crate::{fractal_line::FractalLine, renderobject::RenderObject};
+
+#[derive(Data, Clone, PartialEq, Eq)]
+enum ToolState {
+ Drawing,
+ Standby,
+}
+
+#[derive(Data, Clone)]
+pub struct FractalLineTool {
+ preview: FractalLine,
+ state: ToolState,
+}
+
+impl FractalLineTool {
+ pub fn new() -> Self {
+ Self {
+ preview: FractalLine {
+ start: Point::ZERO,
+ end: Point::ZERO,
+ noise: Rc::new(OpenSimplex::new(0)),
+ width: 10.0,
+ density: 0.05,
+ samples: 1000,
+ },
+ state: ToolState::Standby,
+ }
+ }
+}
+
+impl Tool for FractalLineTool {
+ fn enable(&mut self, _data: &mut crate::graphics_scene_widget::GraphicsData) {
+ self.state = ToolState::Standby;
+ }
+
+ fn disable(&mut self, data: &mut crate::graphics_scene_widget::GraphicsData) {
+ match self.state {
+ ToolState::Drawing => {
+ // get_preview always returns some when drawing
+ data.objects.insert(self.get_preview().unwrap());
+ }
+ ToolState::Standby => (),
+ }
+ }
+
+ fn on_mouse_move(
+ &mut self,
+ event: &druid::MouseEvent,
+ ctx: &mut druid::EventCtx,
+ data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ match self.state {
+ ToolState::Drawing => {
+ ctx.set_handled();
+ self.preview.end = event.pos;
+ }
+ ToolState::Standby => (),
+ }
+ }
+
+ fn on_mouse_down(
+ &mut self,
+ event: &druid::MouseEvent,
+ ctx: &mut druid::EventCtx,
+ data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ self.state = ToolState::Drawing;
+ self.preview = FractalLine {
+ start: event.pos,
+ end: event.pos,
+ noise: Rc::new(OpenSimplex::new(random())),
+ width: 10.0,
+ density: 0.05,
+ samples: 1000,
+ };
+ ctx.set_handled();
+ }
+
+ fn on_mouse_up(
+ &mut self,
+ event: &druid::MouseEvent,
+ ctx: &mut druid::EventCtx,
+ data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ match self.state {
+ ToolState::Drawing => {
+ self.preview.end = event.pos;
+ let mut obj = self.get_preview().unwrap();
+ obj.z = match data.objects.get_max() {
+ Some(obj) => obj.z + 1,
+ None => 0,
+ };
+ self.state = ToolState::Standby;
+ data.objects.insert(obj);
+ ctx.is_handled();
+ }
+ ToolState::Standby => (),
+ }
+ }
+
+ fn on_mouse_wheel(
+ &mut self,
+ event: &druid::MouseEvent,
+ ctx: &mut druid::EventCtx,
+ data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ ()
+ }
+
+ fn on_key_down(
+ &mut self,
+ _event: &druid::KeyEvent,
+ _ctx: &mut druid::EventCtx,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ ()
+ }
+
+ fn on_key_up(
+ &mut self,
+ _event: &druid::KeyEvent,
+ _ctx: &mut druid::EventCtx,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ ()
+ }
+
+ fn on_paste(
+ &mut self,
+ _event: &druid::Clipboard,
+ _ctx: &mut druid::EventCtx,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
+ ) {
+ ()
+ }
+
+ fn get_preview(&self) -> Option<crate::renderobject::RenderObject> {
+ match self.state {
+ ToolState::Drawing => Some(RenderObject::new(
+ u32::MAX,
+ Rc::new(Box::new(self.preview.clone())),
+ )),
+ ToolState::Standby => None,
+ }
+ }
+}
diff --git a/src/draw_tools/mod.rs b/src/draw_tools/mod.rs
new file mode 100644
index 0000000..033ef91
--- /dev/null
+++ b/src/draw_tools/mod.rs
@@ -0,0 +1,2 @@
+pub mod fractal_line_tool;
+pub mod tool;
diff --git a/src/draw_tools/tool.rs b/src/draw_tools/tool.rs
new file mode 100644
index 0000000..9aec10a
--- /dev/null
+++ b/src/draw_tools/tool.rs
@@ -0,0 +1,17 @@
+use crate::{renderobject::RenderObject, GraphicsData};
+use druid::{Clipboard, EventCtx, KeyEvent, MouseEvent};
+
+pub trait Tool {
+ fn enable(&mut self, data: &mut GraphicsData);
+ fn disable(&mut self, data: &mut GraphicsData);
+
+ fn on_mouse_move(&mut self, event: &MouseEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn on_mouse_down(&mut self, event: &MouseEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn on_mouse_up(&mut self, event: &MouseEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+
+ fn on_mouse_wheel(&mut self, event: &MouseEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn on_key_down(&mut self, event: &KeyEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn on_key_up(&mut self, event: &KeyEvent, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn on_paste(&mut self, event: &Clipboard, ctx: &mut EventCtx, data: &mut GraphicsData);
+ fn get_preview(&self) -> Option<RenderObject>;
+}
diff --git a/src/graphics_scene_widget.rs b/src/graphics_scene_widget.rs
index 7433c92..1fc6b26 100644
--- a/src/graphics_scene_widget.rs
+++ b/src/graphics_scene_widget.rs
@@ -10,8 +10,9 @@ use druid::{Data, Widget};
use noise::OpenSimplex;
+use crate::draw_tools::fractal_line_tool::FractalLineTool;
+use crate::draw_tools::tool::Tool;
use crate::drawable::Drawable;
-use crate::fractal_line::FractalLine;
use crate::renderobject::RenderObject;
#[derive(Data, Clone, Debug)]
@@ -20,7 +21,7 @@ pub struct Line(Point, Point, Rc<OpenSimplex>);
#[derive(Data, Clone)]
pub struct GraphicsData {
pub objects: OrdSet<RenderObject>,
- pub preview: Option<FractalLine>,
+ pub preview: Option<RenderObject>,
}
pub enum GraphicsEngineState {
@@ -32,6 +33,7 @@ pub struct GraphicsWidget {
pub state: GraphicsEngineState,
change_list: OrdSet<RenderObject>,
remove_list: Vector<RenderObject>,
+ current_tool: Rc<Box<dyn Tool>>,
}
impl GraphicsWidget {
@@ -40,6 +42,7 @@ impl GraphicsWidget {
state: GraphicsEngineState::Default,
change_list: OrdSet::new(),
remove_list: Vector::new(),
+ current_tool: Rc::new(Box::new(FractalLineTool::new())),
}
}
@@ -66,49 +69,22 @@ impl Widget<GraphicsData> for GraphicsWidget {
) {
match event {
druid::Event::WindowConnected => {}
- druid::Event::MouseDown(event) => match self.state {
- GraphicsEngineState::Default => {
- self.enter_state(GraphicsEngineState::Drawing);
- data.preview = Some(FractalLine {
- start: event.pos,
- end: event.pos,
- noise: Rc::new(OpenSimplex::new(rand::random())),
- width: 10.0,
- density: 0.05,
- samples: 1000,
- });
- }
- GraphicsEngineState::Drawing => (),
- },
- druid::Event::MouseUp(_) => match self.state {
- GraphicsEngineState::Default => (),
- GraphicsEngineState::Drawing => {
- data.objects.insert(RenderObject {
- transform: Affine::scale(1.0),
- drawable: Rc::new(Box::new(data.preview.take().unwrap())),
- z: match data.objects.get_max() {
- Some(v) => v.z + 1,
- None => 0,
- },
- });
-
- data.preview = None;
- self.enter_state(GraphicsEngineState::Default);
- }
- },
- druid::Event::MouseMove(event) => {
- if let GraphicsEngineState::Drawing = self.state {
- if let Some(preview) = &mut data.preview {
- preview.end = event.pos;
- }
- }
- }
+ druid::Event::MouseDown(event) => Rc::get_mut(&mut self.current_tool)
+ .unwrap()
+ .on_mouse_down(event, ctx, data),
+ druid::Event::MouseUp(event) => Rc::get_mut(&mut self.current_tool)
+ .unwrap()
+ .on_mouse_up(event, ctx, data),
+ druid::Event::MouseMove(event) => Rc::get_mut(&mut self.current_tool)
+ .unwrap()
+ .on_mouse_move(event, ctx, data),
druid::Event::WindowSize(_) => {
// Need to request full repaint to ensure everything draws correctly
ctx.request_paint();
}
_ => (),
}
+ data.preview = self.current_tool.get_preview();
}
fn lifecycle(
@@ -162,18 +138,11 @@ impl Widget<GraphicsData> for GraphicsWidget {
if let (Some(old), Some(new)) = (&old_data.preview, &data.preview) {
if !old.same(new) {
- self.change_list.insert(RenderObject {
- transform: Affine::scale(1.0),
- drawable: Rc::new(Box::new(new.clone())),
- z: match data.objects.get_max() {
- Some(v) => v.z + 1,
- None => 0,
- },
- });
+ self.change_list.insert(new.clone());
}
- ctx.request_paint_rect(old.AABB());
- ctx.request_paint_rect(new.AABB());
+ ctx.request_paint_rect(old.get_drawable().AABB());
+ ctx.request_paint_rect(new.get_drawable().AABB());
}
}
@@ -215,7 +184,7 @@ impl Widget<GraphicsData> for GraphicsWidget {
robj.paint(ctx, env);
}
if let Some(line) = &data.preview {
- line.paint(ctx, env, &Affine::rotate(0.0));
+ line.paint(ctx, env);
}
ctx.restore().unwrap();
self.change_list.clear();
diff --git a/src/main.rs b/src/main.rs
index 1418d97..9a77fd3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,7 @@ use druid::im::ordset;
use druid::{theme, AppLauncher, Color, PlatformError, Widget, WindowDesc};
mod bound;
+mod draw_tools;
mod drawable;
mod fractal_line;
mod graphics_scene_widget;
diff --git a/src/renderobject.rs b/src/renderobject.rs
index b2847d1..f3ba3d2 100644
--- a/src/renderobject.rs
+++ b/src/renderobject.rs
@@ -41,6 +41,14 @@ impl RenderObject {
});
}
+ pub fn new(z: u32, drawable: Rc<Box<dyn Drawable>>) -> Self {
+ Self {
+ z,
+ transform: Affine::new([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]),
+ drawable,
+ }
+ }
+
pub fn get_drawable(&self) -> Rc<Box<dyn Drawable>> {
Rc::clone(&self.drawable)
}
--
2.34.1
---
Had to add some more clippy suggestions I missed last time
src/draw_tools/fractal_line_tool.rs | 14 +++++---------
src/graphics_scene_widget.rs | 21 ---------------------
2 files changed, 5 insertions(+), 30 deletions(-)
diff --git a/src/draw_tools/fractal_line_tool.rs b/src/draw_tools/fractal_line_tool.rs
index 944ea0a..6948d8c 100644
--- a/src/draw_tools/fractal_line_tool.rs
+++ b/src/draw_tools/fractal_line_tool.rs
@@ -53,7 +53,7 @@ impl Tool for FractalLineTool {
&mut self,
event: &druid::MouseEvent,
ctx: &mut druid::EventCtx,
- data: &mut crate::graphics_scene_widget::GraphicsData,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
) {
match self.state {
ToolState::Drawing => {
@@ -68,7 +68,7 @@ impl Tool for FractalLineTool {
&mut self,
event: &druid::MouseEvent,
ctx: &mut druid::EventCtx,
- data: &mut crate::graphics_scene_widget::GraphicsData,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
) {
self.state = ToolState::Drawing;
self.preview = FractalLine {
@@ -106,11 +106,10 @@ impl Tool for FractalLineTool {
fn on_mouse_wheel(
&mut self,
- event: &druid::MouseEvent,
- ctx: &mut druid::EventCtx,
- data: &mut crate::graphics_scene_widget::GraphicsData,
+ _event: &druid::MouseEvent,
+ _ctx: &mut druid::EventCtx,
+ _data: &mut crate::graphics_scene_widget::GraphicsData,
) {
- ()
}
fn on_key_down(
@@ -119,7 +118,6 @@ impl Tool for FractalLineTool {
_ctx: &mut druid::EventCtx,
_data: &mut crate::graphics_scene_widget::GraphicsData,
) {
- ()
}
fn on_key_up(
@@ -128,7 +126,6 @@ impl Tool for FractalLineTool {
_ctx: &mut druid::EventCtx,
_data: &mut crate::graphics_scene_widget::GraphicsData,
) {
- ()
}
fn on_paste(
@@ -137,7 +134,6 @@ impl Tool for FractalLineTool {
_ctx: &mut druid::EventCtx,
_data: &mut crate::graphics_scene_widget::GraphicsData,
) {
- ()
}
fn get_preview(&self) -> Option<crate::renderobject::RenderObject> {
diff --git a/src/graphics_scene_widget.rs b/src/graphics_scene_widget.rs
index 1fc6b26..433d10f 100644
--- a/src/graphics_scene_widget.rs
+++ b/src/graphics_scene_widget.rs
@@ -2,7 +2,6 @@ use std::rc::Rc;
use druid::im::OrdSet;
use druid::im::Vector;
-use druid::Affine;
use druid::Color;
use druid::Point;
use druid::RenderContext;
@@ -12,7 +11,6 @@ use noise::OpenSimplex;
use crate::draw_tools::fractal_line_tool::FractalLineTool;
use crate::draw_tools::tool::Tool;
-use crate::drawable::Drawable;
use crate::renderobject::RenderObject;
#[derive(Data, Clone, Debug)]
@@ -24,13 +22,7 @@ pub struct GraphicsData {
pub preview: Option<RenderObject>,
}
-pub enum GraphicsEngineState {
- Default,
- Drawing,
-}
-
pub struct GraphicsWidget {
- pub state: GraphicsEngineState,
change_list: OrdSet<RenderObject>,
remove_list: Vector<RenderObject>,
current_tool: Rc<Box<dyn Tool>>,
@@ -39,24 +31,11 @@ pub struct GraphicsWidget {
impl GraphicsWidget {
pub fn new() -> Self {
Self {
- state: GraphicsEngineState::Default,
change_list: OrdSet::new(),
remove_list: Vector::new(),
current_tool: Rc::new(Box::new(FractalLineTool::new())),
}
}
-
- fn enter_state(&mut self, new_state: GraphicsEngineState) {
- self.exit_state();
- self.state = new_state;
- }
-
- fn exit_state(&self) {
- match self.state {
- GraphicsEngineState::Default => (),
- GraphicsEngineState::Drawing => (),
- }
- }
}
impl Widget<GraphicsData> for GraphicsWidget {
--
2.34.1