Skip to content

Implement fill tool #254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/web/src/components/panels/Document.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
<Separator :type="SeparatorType.Section" :direction="SeparatorDirection.Vertical" />

<ShelfItem :icon="'TextTool'" title="Text Tool (T)" :active="activeTool === 'Text'" @click="'tool not implemented' || selectTool('Text')" />
<ShelfItem :icon="'FillTool'" title="Fill Tool (F)" :active="activeTool === 'Fill'" @click="'tool not implemented' || selectTool('Fill')" />
<ShelfItem :icon="'FillTool'" title="Fill Tool (F)" :active="activeTool === 'Fill'" @click="selectTool('Fill')" />
<ShelfItem :icon="'GradientTool'" title="Gradient Tool (H)" :active="activeTool === 'Gradient'" @click="'tool not implemented' || selectTool('Gradient')" />

<Separator :type="SeparatorType.Section" :direction="SeparatorDirection.Vertical" />
Expand Down
16 changes: 16 additions & 0 deletions core/document/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,16 @@ impl Document {
Ok(())
}

fn mark_as_dirty(&mut self, path: &[LayerId]) -> Result<(), DocumentError> {
let mut root = &mut self.root;
root.cache_dirty = true;
for id in path {
root = root.as_folder_mut()?.layer_mut(*id).ok_or(DocumentError::LayerNotFound)?;
root.cache_dirty = true;
}
Ok(())
}

/// Mutate the document by applying the `operation` to it. If the operation necessitates a
/// reaction from the frontend, responses may be returned.
pub fn handle_operation(&mut self, operation: Operation) -> Result<Option<Vec<DocumentResponse>>, DocumentError> {
Expand Down Expand Up @@ -361,6 +371,12 @@ impl Document {
let path = path.as_slice()[..path.len() - 1].to_vec();
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path }])
}
Operation::FillLayer { path, color } => {
let layer = self.layer_mut(path).unwrap();
layer.style.set_fill(layers::style::Fill::new(*color));
self.mark_as_dirty(path)?;
Some(vec![DocumentResponse::DocumentChanged])
}
};
if !matches!(
operation,
Expand Down
2 changes: 0 additions & 2 deletions core/document/src/layers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ use crate::LayerId;
pub use folder::Folder;
use serde::{Deserialize, Serialize};

pub const SELECTION_TOLERANCE: f64 = 5.0;

pub trait LayerData {
fn render(&mut self, svg: &mut String, transform: glam::DAffine2, style: style::PathStyle);
fn to_kurbo_path(&self, transform: glam::DAffine2, style: style::PathStyle) -> BezPath;
Expand Down
18 changes: 18 additions & 0 deletions core/document/src/layers/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ impl PathStyle {
pub fn new(stroke: Option<Stroke>, fill: Option<Fill>) -> Self {
Self { stroke, fill }
}
pub fn fill(&self) -> Option<Fill> {
self.fill
}
pub fn stroke(&self) -> Option<Stroke> {
self.stroke
}
pub fn set_fill(&mut self, fill: Fill) {
self.fill = Some(fill);
}
pub fn set_stroke(&mut self, stroke: Stroke) {
self.stroke = Some(stroke);
}
pub fn clear_fill(&mut self) {
self.fill = None;
}
pub fn clear_stroke(&mut self) {
self.stroke = None;
}
pub fn render(&self) -> String {
format!(
"{}{}",
Expand Down
5 changes: 5 additions & 0 deletions core/document/src/operation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
color::Color,
layers::{style, Layer},
LayerId,
};
Expand Down Expand Up @@ -71,4 +72,8 @@ pub enum Operation {
ToggleVisibility {
path: Vec<LayerId>,
},
FillLayer {
path: Vec<LayerId>,
color: Color,
},
}
2 changes: 2 additions & 0 deletions core/editor/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ pub const WHEEL_ZOOM_RATE: f64 = 1. / 600.;
pub const MOUSE_ZOOM_RATE: f64 = 1. / 400.;

pub const ROTATE_SNAP_INTERVAL: f64 = 15.;

pub const SELECTION_TOLERANCE: f64 = 5.0;
3 changes: 3 additions & 0 deletions core/editor/src/input/input_mapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,10 @@ impl Default for Mapping {
entry! {action=PenMessage::Confirm, key_down=Rmb},
entry! {action=PenMessage::Confirm, key_down=KeyEscape},
entry! {action=PenMessage::Confirm, key_down=KeyEnter},
// Fill
entry! {action=FillMessage::MouseDown, key_down=Lmb},
// Tool Actions
entry! {action=ToolMessage::SelectTool(ToolType::Fill), key_down=KeyF},
entry! {action=ToolMessage::SelectTool(ToolType::Rectangle), key_down=KeyM},
entry! {action=ToolMessage::SelectTool(ToolType::Ellipse), key_down=KeyE},
entry! {action=ToolMessage::SelectTool(ToolType::Select), key_down=KeyV},
Expand Down
1 change: 1 addition & 0 deletions core/editor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub mod message_prelude {
pub use super::tool::tool_messages::*;
pub use super::tool::tools::crop::{CropMessage, CropMessageDiscriminant};
pub use super::tool::tools::eyedropper::{EyedropperMessage, EyedropperMessageDiscriminant};
pub use super::tool::tools::fill::{FillMessage, FillMessageDiscriminant};
pub use super::tool::tools::line::{LineMessage, LineMessageDiscriminant};
pub use super::tool::tools::navigate::{NavigateMessage, NavigateMessageDiscriminant};
pub use super::tool::tools::path::{PathMessage, PathMessageDiscriminant};
Expand Down
1 change: 1 addition & 0 deletions core/editor/src/tool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl Default for ToolFsmState {
Line => line::Line,
Shape => shape::Shape,
Ellipse => ellipse::Ellipse,
Fill => fill::Fill,
},
},
document_tool_data: DocumentToolData {
Expand Down
3 changes: 3 additions & 0 deletions core/editor/src/tool/tool_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub enum ToolMessage {
SwapColors,
ResetColors,
#[child]
Fill(FillMessage),
#[child]
Rectangle(RectangleMessage),
#[child]
Ellipse(EllipseMessage),
Expand Down Expand Up @@ -89,6 +91,7 @@ impl MessageHandler<ToolMessage, (&SvgDocument, &InputPreprocessor)> for ToolMes
}
message => {
let tool_type = match message {
Fill(_) => ToolType::Fill,
Rectangle(_) => ToolType::Rectangle,
Ellipse(_) => ToolType::Ellipse,
Shape(_) => ToolType::Shape,
Expand Down
43 changes: 43 additions & 0 deletions core/editor/src/tool/tools/fill.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::consts::SELECTION_TOLERANCE;
use crate::message_prelude::*;
use crate::tool::ToolActionHandlerData;
use document_core::Operation;
use glam::DVec2;

#[derive(Default)]
pub struct Fill;

#[impl_message(Message, ToolMessage, Fill)]
#[derive(PartialEq, Clone, Debug)]
pub enum FillMessage {
MouseDown,
}

impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Fill {
fn process_action(&mut self, _action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
let mouse_pos = data.2.mouse.position;
let (x, y) = (mouse_pos.x as f64, mouse_pos.y as f64);
let (point_1, point_2) = (
DVec2::new(x - SELECTION_TOLERANCE, y - SELECTION_TOLERANCE),
DVec2::new(x + SELECTION_TOLERANCE, y + SELECTION_TOLERANCE),
);

let quad = [
DVec2::new(point_1.x, point_1.y),
DVec2::new(point_2.x, point_1.y),
DVec2::new(point_2.x, point_2.y),
DVec2::new(point_1.x, point_2.y),
];

if let Some(path) = data.0.intersects_quad_root(quad).last() {
responses.push_back(
Operation::FillLayer {
path: path.to_vec(),
color: data.1.primary_color,
}
.into(),
);
}
}
advertise_actions!(FillMessageDiscriminant; MouseDown);
}
1 change: 1 addition & 0 deletions core/editor/src/tool/tools/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// already implemented
pub mod ellipse;
pub mod fill;
pub mod line;
pub mod pen;
pub mod rectangle;
Expand Down
4 changes: 2 additions & 2 deletions core/editor/src/tool/tools/select.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use document_core::color::Color;
use document_core::layers::style;
use document_core::layers::style::Fill;
use document_core::layers::style::Stroke;
use document_core::layers::{style, SELECTION_TOLERANCE};
use document_core::Operation;
use glam::{DAffine2, DVec2};

use crate::input::{mouse::ViewportPosition, InputPreprocessor};
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
use crate::{message_prelude::*, SvgDocument};
use crate::{consts::SELECTION_TOLERANCE, message_prelude::*, SvgDocument};

#[derive(Default)]
pub struct Select {
Expand Down