Add a stroke width option to the Line Tool (#355)
* Add a stroke width option to the Line Tool * Fix title case for line options * Add px unit to line stroke width * Add stroke width to pen tool * Rename stroke width to weight * Change number input width to min-width * Remove the word "stroke" from "stroke weight"
This commit is contained in:
parent
0a7c6df222
commit
44f244fb5f
|
|
@ -5,6 +5,8 @@ pub enum ToolOptions {
|
||||||
Select { append_mode: SelectAppendMode },
|
Select { append_mode: SelectAppendMode },
|
||||||
Ellipse,
|
Ellipse,
|
||||||
Shape { shape_type: ShapeType },
|
Shape { shape_type: ShapeType },
|
||||||
|
Line { weight: u32 },
|
||||||
|
Pen { weight: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::consts::LINE_ROTATE_SNAP_ANGLE;
|
use crate::consts::LINE_ROTATE_SNAP_ANGLE;
|
||||||
use crate::input::keyboard::Key;
|
use crate::input::keyboard::Key;
|
||||||
use crate::input::{mouse::ViewportPosition, InputPreprocessor};
|
use crate::input::{mouse::ViewportPosition, InputPreprocessor};
|
||||||
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
|
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData, ToolOptions, ToolType};
|
||||||
use crate::{document::DocumentMessageHandler, message_prelude::*};
|
use crate::{document::DocumentMessageHandler, message_prelude::*};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphene::{layers::style, Operation};
|
use graphene::{layers::style, Operation};
|
||||||
|
|
@ -50,6 +50,7 @@ struct LineToolData {
|
||||||
drag_start: ViewportPosition,
|
drag_start: ViewportPosition,
|
||||||
drag_current: ViewportPosition,
|
drag_current: ViewportPosition,
|
||||||
angle: f64,
|
angle: f64,
|
||||||
|
weight: u32,
|
||||||
path: Option<Vec<LayerId>>,
|
path: Option<Vec<LayerId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,12 +76,17 @@ impl Fsm for LineToolFsmState {
|
||||||
data.path = Some(vec![generate_uuid()]);
|
data.path = Some(vec![generate_uuid()]);
|
||||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||||
|
|
||||||
|
data.weight = match tool_data.tool_options.get(&ToolType::Line) {
|
||||||
|
Some(&ToolOptions::Line { weight }) => weight,
|
||||||
|
_ => 5,
|
||||||
|
};
|
||||||
|
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
Operation::AddLine {
|
Operation::AddLine {
|
||||||
path: data.path.clone().unwrap(),
|
path: data.path.clone().unwrap(),
|
||||||
insert_index: -1,
|
insert_index: -1,
|
||||||
transform: DAffine2::ZERO.to_cols_array(),
|
transform: DAffine2::ZERO.to_cols_array(),
|
||||||
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, 5.)), None),
|
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, data.weight as f32)), None),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::input::InputPreprocessor;
|
use crate::input::InputPreprocessor;
|
||||||
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
|
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData, ToolOptions, ToolType};
|
||||||
use crate::{document::DocumentMessageHandler, message_prelude::*};
|
use crate::{document::DocumentMessageHandler, message_prelude::*};
|
||||||
use glam::DAffine2;
|
use glam::DAffine2;
|
||||||
use graphene::{layers::style, Operation};
|
use graphene::{layers::style, Operation};
|
||||||
|
|
@ -49,6 +49,7 @@ impl Default for PenToolFsmState {
|
||||||
struct PenToolData {
|
struct PenToolData {
|
||||||
points: Vec<DAffine2>,
|
points: Vec<DAffine2>,
|
||||||
next_point: DAffine2,
|
next_point: DAffine2,
|
||||||
|
weight: u32,
|
||||||
path: Option<Vec<LayerId>>,
|
path: Option<Vec<LayerId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,6 +80,11 @@ impl Fsm for PenToolFsmState {
|
||||||
data.points.push(pos);
|
data.points.push(pos);
|
||||||
data.next_point = pos;
|
data.next_point = pos;
|
||||||
|
|
||||||
|
data.weight = match tool_data.tool_options.get(&ToolType::Pen) {
|
||||||
|
Some(&ToolOptions::Pen { weight }) => weight,
|
||||||
|
_ => 5,
|
||||||
|
};
|
||||||
|
|
||||||
Dragging
|
Dragging
|
||||||
}
|
}
|
||||||
(Dragging, DragStop) => {
|
(Dragging, DragStop) => {
|
||||||
|
|
@ -140,7 +146,7 @@ fn make_operation(data: &PenToolData, tool_data: &DocumentToolData, show_preview
|
||||||
insert_index: -1,
|
insert_index: -1,
|
||||||
transform: DAffine2::IDENTITY.to_cols_array(),
|
transform: DAffine2::IDENTITY.to_cols_array(),
|
||||||
points,
|
points,
|
||||||
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, 5.)), Some(style::Fill::none())),
|
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, data.weight as f32)), Some(style::Fill::none())),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.number-input {
|
.number-input {
|
||||||
width: 80px;
|
min-width: 80px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
@ -38,7 +38,8 @@
|
||||||
|
|
||||||
input {
|
input {
|
||||||
flex: 1 1 100%;
|
flex: 1 1 100%;
|
||||||
width: 100%;
|
width: 0;
|
||||||
|
min-width: 30px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
margin: 0 8px;
|
margin: 0 8px;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
async setToolOptions(newValue: number) {
|
async setShapeOptions(newValue: number) {
|
||||||
// TODO: Each value-input widget (i.e. not a button) should map to a field in an options struct,
|
// TODO: Each value-input widget (i.e. not a button) should map to a field in an options struct,
|
||||||
// and updating a widget should send the whole updated struct to the backend.
|
// and updating a widget should send the whole updated struct to the backend.
|
||||||
// Later, it could send a single-field update to the backend.
|
// Later, it could send a single-field update to the backend.
|
||||||
|
|
@ -50,6 +50,14 @@ export default defineComponent({
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
(await wasm).set_tool_options(this.$props.activeTool || "", { Shape: { shape_type: { Polygon: { vertices: newValue } } } });
|
(await wasm).set_tool_options(this.$props.activeTool || "", { Shape: { shape_type: { Polygon: { vertices: newValue } } } });
|
||||||
},
|
},
|
||||||
|
async setLineOptions(newValue: number) {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
(await wasm).set_tool_options(this.$props.activeTool || "", { Line: { weight: newValue } });
|
||||||
|
},
|
||||||
|
async setPenOptions(newValue: number) {
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
(await wasm).set_tool_options(this.$props.activeTool || "", { Pen: { weight: newValue } });
|
||||||
|
},
|
||||||
async sendToolMessage(message: string | object) {
|
async sendToolMessage(message: string | object) {
|
||||||
(await wasm).send_tool_message(this.$props.activeTool || "", message);
|
(await wasm).send_tool_message(this.$props.activeTool || "", message);
|
||||||
},
|
},
|
||||||
|
|
@ -126,7 +134,9 @@ export default defineComponent({
|
||||||
props: {},
|
props: {},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
Shape: [{ kind: "NumberInput", callback: this.setToolOptions, props: { value: 6, min: 3, isInteger: true, label: "Sides" } }],
|
Shape: [{ kind: "NumberInput", callback: this.setShapeOptions, props: { value: 6, min: 3, isInteger: true, label: "Sides" } }],
|
||||||
|
Line: [{ kind: "NumberInput", callback: this.setLineOptions, props: { value: 5, min: 1, isInteger: true, unit: " px", label: "Weight" } }],
|
||||||
|
Pen: [{ kind: "NumberInput", callback: this.setPenOptions, props: { value: 5, min: 1, isInteger: true, unit: " px", label: "Weight" } }],
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue