Fix freehand and spline tool
This commit is contained in:
parent
76d7b6256d
commit
6173662a40
|
|
@ -94,4 +94,5 @@ pub enum VectorDataModification {
|
|||
SetManipulatorHandleMirroring { id: ManipulatorGroupId, mirror_angle: bool },
|
||||
SetManipulatorPosition { point: ManipulatorPointId, position: DVec2 },
|
||||
ToggleManipulatorHandleMirroring { id: ManipulatorGroupId },
|
||||
UpdateSubpaths { subpaths: Vec<Subpath<ManipulatorGroupId>> },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,6 +378,11 @@ impl<'a> ModifyInputsContext<'a> {
|
|||
}
|
||||
|
||||
fn delete_layer(&mut self, id: NodeId) {
|
||||
if !self.network.nodes.contains_key(&id) {
|
||||
warn!("Deleting layer node that does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
let mut new_input = None;
|
||||
let post_node = self.outwards_links.get(&id).and_then(|links| links.first().copied());
|
||||
let mut delete_nodes = vec![id];
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ impl<'a> VectorModificationState<'a> {
|
|||
VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle } => self.set_mirror(id, mirror_angle),
|
||||
VectorDataModification::SetManipulatorPosition { point, position } => self.set_position(point, position),
|
||||
VectorDataModification::ToggleManipulatorHandleMirroring { id } => self.toggle_mirror(id),
|
||||
VectorDataModification::UpdateSubpaths { subpaths } => *self.subpaths = subpaths,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ impl PortfolioMessageHandler {
|
|||
}
|
||||
|
||||
pub fn poll_node_graph_evaluation(&mut self, responses: &mut VecDeque<Message>) {
|
||||
let Some(active_document) = self.active_document_id.and_then(|id| self.documents.get_mut(&id)) else {
|
||||
let Some(active_document) = self.active_document_id.and_then(|id| self.documents.get_mut(&id)) else {
|
||||
warn!("Polling node graph with no document");
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub fn new_custom_layer(network: NodeNetwork, layer_path: Vec<LayerId>, response
|
|||
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
|
||||
}
|
||||
|
||||
pub fn set_manipulator_mirror_angle(manipulator_groups: &Vec<ManipulatorGroup<ManipulatorGroupId>>, layer_path: &[u64], mirror_angle: bool, responses: &mut VecDeque<Message>) {
|
||||
pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer_path: &[u64], mirror_angle: bool, responses: &mut VecDeque<Message>) {
|
||||
for manipulator_group in manipulator_groups {
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_owned(),
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ impl ShapeState {
|
|||
|
||||
// Sets the selected points to all points for the corresponding intersection
|
||||
pub fn select_all_anchors(&mut self, document: &Document, layer: LayerNodeIdentifier) {
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { return };
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { return };
|
||||
let Some(state) = self.selected_shape_state.get_mut(&layer) else { return };
|
||||
for manipulator in get_manipulator_groups(subpaths) {
|
||||
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor))
|
||||
|
|
@ -375,7 +375,7 @@ impl ShapeState {
|
|||
continue;
|
||||
}
|
||||
|
||||
let Some(group) =get_manipulator_from_id(subpaths,point.group) else { continue };
|
||||
let Some(group) = get_manipulator_from_id(subpaths, point.group) else { continue };
|
||||
|
||||
let mut move_point = |point: ManipulatorPointId| {
|
||||
let Some(previous_position) = point.manipulator_type.get_position(group) else { return };
|
||||
|
|
@ -430,7 +430,7 @@ impl ShapeState {
|
|||
/// Delete selected and mirrored handles with zero length when the drag stops.
|
||||
pub fn delete_selected_handles_with_zero_length(&self, document: &Document, opposing_handle_lengths: &Option<OpposingHandleLengths>, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { continue };
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { continue };
|
||||
let Some(mirror_angle) = get_mirror_handles(layer, document) else { continue };
|
||||
|
||||
let opposing_handle_lengths = opposing_handle_lengths.as_ref().and_then(|lengths| lengths.get(&layer));
|
||||
|
|
@ -443,7 +443,7 @@ impl ShapeState {
|
|||
continue;
|
||||
}
|
||||
|
||||
let Some(group) = get_manipulator_from_id(subpaths,point.group) else { continue };
|
||||
let Some(group) = get_manipulator_from_id(subpaths, point.group) else { continue };
|
||||
|
||||
let anchor_position = transform.transform_point2(group.anchor);
|
||||
|
||||
|
|
@ -521,7 +521,7 @@ impl ShapeState {
|
|||
/// Reset the opposing handle lengths.
|
||||
pub fn reset_opposing_handle_lengths(&self, document: &Document, opposing_handle_lengths: &OpposingHandleLengths, responses: &mut VecDeque<Message>) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { continue };
|
||||
let Some(subpaths) = get_subpaths(layer, document) else { continue };
|
||||
let Some(mirror_angle) = get_mirror_handles(layer, document) else { continue };
|
||||
let Some(opposing_handle_lengths) = opposing_handle_lengths.get(&layer) else { continue };
|
||||
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ impl LayoutHolder for BrushTool {
|
|||
|
||||
impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for BrushTool {
|
||||
fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque<Message>, tool_data: &mut ToolActionHandlerData<'a>) {
|
||||
let ToolMessage::Brush(BrushToolMessage::UpdateOptions(action)) = message else{
|
||||
let ToolMessage::Brush(BrushToolMessage::UpdateOptions(action)) = message else {
|
||||
self.fsm_state.process_event(message, &mut self.data, tool_data, &self.options, responses, true);
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ impl LayoutHolder for EllipseTool {
|
|||
|
||||
impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for EllipseTool {
|
||||
fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque<Message>, tool_data: &mut ToolActionHandlerData<'a>) {
|
||||
let ToolMessage::Ellipse(EllipseToolMessage::UpdateOptions(action)) = message else{
|
||||
let ToolMessage::Ellipse(EllipseToolMessage::UpdateOptions(action)) = message else {
|
||||
self.fsm_state.process_event(message, &mut self.data, tool_data, &self.options, responses, true);
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ impl Fsm for EyedropperToolFsmState {
|
|||
fn transition(self, event: ToolMessage, _tool_data: &mut Self::ToolData, tool_action_data: &mut ToolActionHandlerData, _tool_options: &(), responses: &mut VecDeque<Message>) -> Self {
|
||||
let ToolActionHandlerData { global_tool_data, input, .. } = tool_action_data;
|
||||
|
||||
let ToolMessage::Eyedropper(event) = event else{
|
||||
let ToolMessage::Eyedropper(event) = event else {
|
||||
return self;
|
||||
};
|
||||
match (self, event) {
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ impl Fsm for FillToolFsmState {
|
|||
return self;
|
||||
};
|
||||
let Some((layer_identifier, _)) = document.document_legacy.metadata.click(input.mouse.position) else {
|
||||
return self;
|
||||
};
|
||||
return self;
|
||||
};
|
||||
let layer = layer_identifier.to_path();
|
||||
|
||||
let color = match event {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use super::tool_prelude::*;
|
||||
use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
||||
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
|
||||
|
|
@ -6,6 +7,7 @@ use document_legacy::LayerId;
|
|||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
use bezier_rs::ManipulatorGroup;
|
||||
use glam::DVec2;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -117,7 +119,7 @@ impl LayoutHolder for FreehandTool {
|
|||
|
||||
impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for FreehandTool {
|
||||
fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque<Message>, tool_data: &mut ToolActionHandlerData<'a>) {
|
||||
let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(action)) = message else{
|
||||
let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(action)) = message else {
|
||||
self.fsm_state.process_event(message, &mut self.data, tool_data, &self.options, responses, true);
|
||||
return;
|
||||
};
|
||||
|
|
@ -174,9 +176,10 @@ impl ToolTransition for FreehandTool {
|
|||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct FreehandToolData {
|
||||
points: Vec<DVec2>,
|
||||
last_point: DVec2,
|
||||
dragged: bool,
|
||||
weight: f64,
|
||||
path: Option<Vec<LayerId>>,
|
||||
layer_path: Option<Vec<LayerId>>,
|
||||
}
|
||||
|
||||
impl Fsm for FreehandToolFsmState {
|
||||
|
|
@ -197,40 +200,42 @@ impl Fsm for FreehandToolFsmState {
|
|||
(FreehandToolFsmState::Ready, FreehandToolMessage::DragStart) => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
tool_data.path = Some(document.get_path_for_new_layer());
|
||||
tool_data.layer_path = Some(document.get_path_for_new_layer());
|
||||
|
||||
let pos = transform.inverse().transform_point2(input.mouse.position);
|
||||
|
||||
tool_data.points.push(pos);
|
||||
tool_data.dragged = false;
|
||||
tool_data.last_point = pos;
|
||||
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
add_polyline(tool_data, tool_options.stroke.active_color(), tool_options.fill.active_color(), responses);
|
||||
add_polyline([pos], tool_data, tool_options.stroke.active_color(), tool_options.fill.active_color(), responses);
|
||||
|
||||
FreehandToolFsmState::Drawing
|
||||
}
|
||||
(FreehandToolFsmState::Drawing, FreehandToolMessage::PointerMove) => {
|
||||
let pos = transform.inverse().transform_point2(input.mouse.position);
|
||||
|
||||
if tool_data.points.last() != Some(&pos) {
|
||||
tool_data.points.push(pos);
|
||||
if tool_data.last_point != pos {
|
||||
if let Some(layer) = tool_data.layer_path.clone() {
|
||||
let manipulator_group = ManipulatorGroup::new_anchor(pos);
|
||||
let modification = VectorDataModification::AddEndManipulatorGroup { subpath_index: 0, manipulator_group };
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification });
|
||||
tool_data.dragged = true;
|
||||
tool_data.last_point = pos;
|
||||
}
|
||||
}
|
||||
|
||||
add_polyline(tool_data, tool_options.stroke.active_color(), tool_options.fill.active_color(), responses);
|
||||
|
||||
FreehandToolFsmState::Drawing
|
||||
}
|
||||
(FreehandToolFsmState::Drawing, FreehandToolMessage::DragStop | FreehandToolMessage::Abort) => {
|
||||
if tool_data.points.len() >= 2 {
|
||||
responses.add(remove_preview(tool_data));
|
||||
add_polyline(tool_data, tool_options.stroke.active_color(), tool_options.fill.active_color(), responses);
|
||||
if tool_data.dragged {
|
||||
responses.add(DocumentMessage::CommitTransaction);
|
||||
} else {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
}
|
||||
|
||||
tool_data.path = None;
|
||||
tool_data.points.clear();
|
||||
tool_data.layer_path = None;
|
||||
|
||||
FreehandToolFsmState::Ready
|
||||
}
|
||||
|
|
@ -259,14 +264,10 @@ impl Fsm for FreehandToolFsmState {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_preview(data: &FreehandToolData) -> Message {
|
||||
GraphOperationMessage::DeleteLayer { id: data.path.clone().unwrap()[0] }.into()
|
||||
}
|
||||
fn add_polyline(anchors: impl IntoIterator<Item = DVec2>, data: &FreehandToolData, stroke_color: Option<Color>, fill_color: Option<Color>, responses: &mut VecDeque<Message>) {
|
||||
let subpath = bezier_rs::Subpath::from_anchors(anchors, false);
|
||||
|
||||
fn add_polyline(data: &FreehandToolData, stroke_color: Option<Color>, fill_color: Option<Color>, responses: &mut VecDeque<Message>) {
|
||||
let subpath = bezier_rs::Subpath::from_anchors(data.points.iter().copied(), false);
|
||||
|
||||
let layer_path = data.path.clone().unwrap();
|
||||
let layer_path = data.layer_path.clone().unwrap();
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ impl Fsm for ImaginateToolFsmState {
|
|||
) -> Self {
|
||||
let shape_data = &mut tool_data.data;
|
||||
|
||||
let ToolMessage::Imaginate(event) = event else{
|
||||
let ToolMessage::Imaginate(event) = event else {
|
||||
return self;
|
||||
};
|
||||
match (self, event) {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ impl Fsm for NavigateToolFsmState {
|
|||
_tool_options: &Self::ToolOptions,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
let ToolMessage::Navigate(navigate) = message else{
|
||||
let ToolMessage::Navigate(navigate) = message else {
|
||||
return self;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,9 @@ impl PenToolData {
|
|||
self.subpath_index = subpath_index;
|
||||
|
||||
// Stop the handles on the first point from mirroring
|
||||
let Some(subpaths) = get_subpaths (LayerNodeIdentifier::from_path(layer, document.network()), &document.document_legacy) else { return };
|
||||
let Some(subpaths) = get_subpaths(LayerNodeIdentifier::from_path(layer, document.network()), &document.document_legacy) else {
|
||||
return;
|
||||
};
|
||||
let manipulator_groups = subpaths[subpath_index].manipulator_groups();
|
||||
let Some(last_handle) = (if from_start { manipulator_groups.first() } else { manipulator_groups.last() }) else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use super::tool_prelude::*;
|
||||
use crate::consts::DRAG_THRESHOLD;
|
||||
use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
||||
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
|
|
@ -192,22 +193,14 @@ impl Fsm for SplineToolFsmState {
|
|||
type ToolData = SplineToolData;
|
||||
type ToolOptions = SplineOptions;
|
||||
|
||||
fn transition(
|
||||
self,
|
||||
event: ToolMessage,
|
||||
tool_data: &mut Self::ToolData,
|
||||
ToolActionHandlerData {
|
||||
fn transition(self, event: ToolMessage, tool_data: &mut Self::ToolData, tool_action_data: &mut ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque<Message>) -> Self {
|
||||
let ToolActionHandlerData {
|
||||
document,
|
||||
global_tool_data,
|
||||
input,
|
||||
render_data,
|
||||
..
|
||||
}: &mut ToolActionHandlerData,
|
||||
tool_options: &Self::ToolOptions,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use SplineToolFsmState::*;
|
||||
use SplineToolMessage::*;
|
||||
} = tool_action_data;
|
||||
|
||||
let transform = document.document_legacy.metadata.document_to_viewport;
|
||||
|
||||
|
|
@ -215,11 +208,11 @@ impl Fsm for SplineToolFsmState {
|
|||
return self;
|
||||
};
|
||||
match (self, event) {
|
||||
(_, CanvasTransformed) => {
|
||||
(_, SplineToolMessage::CanvasTransformed) => {
|
||||
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true);
|
||||
self
|
||||
}
|
||||
(Ready, DragStart) => {
|
||||
(SplineToolFsmState::Ready, SplineToolMessage::DragStart) => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
tool_data.path = Some(document.get_path_for_new_layer());
|
||||
|
|
@ -235,11 +228,11 @@ impl Fsm for SplineToolFsmState {
|
|||
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
add_spline(tool_data, true, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
add_spline(tool_data, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
|
||||
Drawing
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
(Drawing, DragStop) => {
|
||||
(SplineToolFsmState::Drawing, SplineToolMessage::DragStop) => {
|
||||
let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
let pos = transform.inverse().transform_point2(snapped_position);
|
||||
|
||||
|
|
@ -250,25 +243,22 @@ impl Fsm for SplineToolFsmState {
|
|||
}
|
||||
}
|
||||
|
||||
responses.add(remove_preview(tool_data));
|
||||
add_spline(tool_data, true, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
update_spline(tool_data, true, responses);
|
||||
|
||||
Drawing
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
(Drawing, PointerMove) => {
|
||||
(SplineToolFsmState::Drawing, SplineToolMessage::PointerMove) => {
|
||||
let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
let pos = transform.inverse().transform_point2(snapped_position);
|
||||
tool_data.next_point = pos;
|
||||
|
||||
responses.add(remove_preview(tool_data));
|
||||
add_spline(tool_data, true, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
update_spline(tool_data, true, responses);
|
||||
|
||||
Drawing
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
(Drawing, Confirm) | (Drawing, Abort) => {
|
||||
(SplineToolFsmState::Drawing, SplineToolMessage::Confirm | SplineToolMessage::Abort) => {
|
||||
if tool_data.points.len() >= 2 {
|
||||
responses.add(remove_preview(tool_data));
|
||||
add_spline(tool_data, false, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
update_spline(tool_data, false, responses);
|
||||
responses.add(DocumentMessage::CommitTransaction);
|
||||
} else {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
|
|
@ -278,9 +268,9 @@ impl Fsm for SplineToolFsmState {
|
|||
tool_data.points.clear();
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
|
||||
Ready
|
||||
SplineToolFsmState::Ready
|
||||
}
|
||||
(_, WorkingColorChanged) => {
|
||||
(_, SplineToolMessage::WorkingColorChanged) => {
|
||||
responses.add(SplineToolMessage::UpdateOptions(SplineOptionsUpdate::WorkingColors(
|
||||
Some(global_tool_data.primary_color),
|
||||
Some(global_tool_data.secondary_color),
|
||||
|
|
@ -308,25 +298,11 @@ impl Fsm for SplineToolFsmState {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_preview(tool_data: &SplineToolData) -> Message {
|
||||
Operation::DeleteLayer {
|
||||
path: tool_data.path.clone().unwrap(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
fn add_spline(tool_data: &SplineToolData, show_preview: bool, fill_color: Option<Color>, stroke_color: Option<Color>, responses: &mut VecDeque<Message>) {
|
||||
let mut points = tool_data.points.clone();
|
||||
if show_preview {
|
||||
points.push(tool_data.next_point)
|
||||
}
|
||||
|
||||
let subpath = bezier_rs::Subpath::new_cubic_spline(points);
|
||||
|
||||
let layer_path = tool_data.path.clone().unwrap();
|
||||
let manipulator_groups = subpath.manipulator_groups().to_vec();
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
graph_modification_utils::set_manipulator_mirror_angle(&manipulator_groups, &layer_path, true, responses);
|
||||
fn add_spline(tool_data: &SplineToolData, fill_color: Option<Color>, stroke_color: Option<Color>, responses: &mut VecDeque<Message>) {
|
||||
let Some(layer_path) = tool_data.path.clone() else {
|
||||
return;
|
||||
};
|
||||
graph_modification_utils::new_vector_layer(vec![], layer_path.clone(), responses);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
|
|
@ -334,7 +310,25 @@ fn add_spline(tool_data: &SplineToolData, show_preview: bool, fill_color: Option
|
|||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer_path,
|
||||
stroke: Stroke::new(stroke_color, tool_data.weight),
|
||||
});
|
||||
}
|
||||
|
||||
fn update_spline(tool_data: &SplineToolData, show_preview: bool, responses: &mut VecDeque<Message>) {
|
||||
let mut points = tool_data.points.clone();
|
||||
if show_preview {
|
||||
points.push(tool_data.next_point)
|
||||
}
|
||||
|
||||
let subpath = bezier_rs::Subpath::new_cubic_spline(points);
|
||||
|
||||
let Some(layer) = tool_data.path.clone() else {
|
||||
return;
|
||||
};
|
||||
|
||||
graph_modification_utils::set_manipulator_mirror_angle(subpath.manipulator_groups(), &layer, true, responses);
|
||||
let subpaths = vec![subpath];
|
||||
let modification = VectorDataModification::UpdateSubpaths { subpaths };
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification });
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue