mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 13:38:12 +08:00
Migrate demo artwork and fix all failing CI tests (#1459)
* Initial work on fixing tests * Fix formatting * Remove dead code to satisfy rustc warnings * Insert into an artboard * Load updated artwork in editor * Remove popup when importing image * Fix up demo art * Change transform app[lication method * Reduce number of enums called BlendMode * Finalize the demo artwork upgrade * Code review pass --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Keavon Chambers
parent
719c96ecd8
commit
8a1cf3ad5d
@@ -14,18 +14,24 @@ use glam::{DAffine2, DVec2};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
/// Create a new vector layer from a vector of [`bezier_rs::Subpath`].
|
||||
pub fn new_vector_layer(subpaths: Vec<Subpath<ManipulatorGroupId>>, layer_path: Vec<LayerId>, responses: &mut VecDeque<Message>) {
|
||||
let id = *layer_path.last().unwrap();
|
||||
responses.add(GraphOperationMessage::NewVectorLayer { id, subpaths });
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![id] })
|
||||
pub fn new_vector_layer(subpaths: Vec<Subpath<ManipulatorGroupId>>, id: NodeId, parent: LayerNodeIdentifier, responses: &mut VecDeque<Message>) -> LayerNodeIdentifier {
|
||||
let insert_index = -1;
|
||||
responses.add(GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index });
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![id] });
|
||||
|
||||
LayerNodeIdentifier::new_unchecked(id)
|
||||
}
|
||||
|
||||
/// Create a new bitmap layer from an [`graphene_core::raster::ImageFrame<Color>`]
|
||||
pub fn new_image_layer(image_frame: ImageFrame<Color>, layer_path: Vec<LayerId>, responses: &mut VecDeque<Message>) {
|
||||
pub fn new_image_layer(image_frame: ImageFrame<Color>, id: NodeId, parent: LayerNodeIdentifier, responses: &mut VecDeque<Message>) -> LayerNodeIdentifier {
|
||||
let insert_index = -1;
|
||||
responses.add(GraphOperationMessage::NewBitmapLayer {
|
||||
id: *layer_path.last().unwrap(),
|
||||
id,
|
||||
image_frame,
|
||||
parent,
|
||||
insert_index,
|
||||
});
|
||||
LayerNodeIdentifier::new_unchecked(id)
|
||||
}
|
||||
|
||||
/// Create a legacy node graph frame TODO: remove
|
||||
@@ -41,10 +47,10 @@ pub fn new_custom_layer(network: NodeNetwork, layer_path: Vec<LayerId>, response
|
||||
}
|
||||
|
||||
/// Batch set all of the manipulator groups to mirror on a specific layer
|
||||
pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer_path: &[u64], mirror_angle: bool, responses: &mut VecDeque<Message>) {
|
||||
pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer: LayerNodeIdentifier, mirror_angle: bool, responses: &mut VecDeque<Message>) {
|
||||
for manipulator_group in manipulator_groups {
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_owned(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorHandleMirroring {
|
||||
id: manipulator_group.id,
|
||||
mirror_angle,
|
||||
|
||||
@@ -3,15 +3,15 @@ use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
|
||||
use crate::messages::prelude::*;
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::layers::style::RenderData;
|
||||
use document_legacy::LayerId;
|
||||
|
||||
use glam::{DAffine2, DVec2, Vec2Swizzles};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Resize {
|
||||
drag_start: ViewportPosition,
|
||||
pub path: Option<Vec<LayerId>>,
|
||||
pub layer: Option<LayerNodeIdentifier>,
|
||||
snap_manager: SnapManager,
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ impl Resize {
|
||||
lock_ratio: Key,
|
||||
skip_rerender: bool,
|
||||
) -> Option<Message> {
|
||||
let Some(path) = &self.path else {
|
||||
let Some(layer) = self.layer else {
|
||||
return None;
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ impl Resize {
|
||||
|
||||
Some(
|
||||
GraphOperationMessage::TransformSet {
|
||||
layer: path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
transform: DAffine2::from_scale_angle_translation(size, 0., start),
|
||||
transform_in: TransformIn::Viewport,
|
||||
skip_rerender,
|
||||
@@ -74,6 +74,6 @@ impl Resize {
|
||||
|
||||
pub fn cleanup(&mut self, responses: &mut VecDeque<Message>) {
|
||||
self.snap_manager.cleanup(responses);
|
||||
self.path = None;
|
||||
self.layer = None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::resize::Resize;
|
||||
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -205,24 +206,21 @@ impl Fsm for EllipseToolFsmState {
|
||||
shape_data.start(responses, document, input, render_data);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
// Create a new layer path for this shape
|
||||
let layer_path = document.get_path_for_new_layer();
|
||||
shape_data.path = Some(layer_path.clone());
|
||||
|
||||
// Create a new ellipse vector shape
|
||||
let subpath = bezier_rs::Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE);
|
||||
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);
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
|
||||
graph_modification_utils::set_manipulator_mirror_angle(&manipulator_groups, layer, true, responses);
|
||||
shape_data.layer = Some(layer);
|
||||
|
||||
let fill_color = tool_options.fill.active_color();
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path,
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ 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 document_legacy::LayerId;
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -179,7 +180,7 @@ struct FreehandToolData {
|
||||
last_point: DVec2,
|
||||
dragged: bool,
|
||||
weight: f64,
|
||||
layer_path: Option<Vec<LayerId>>,
|
||||
layer: Option<LayerNodeIdentifier>,
|
||||
}
|
||||
|
||||
impl Fsm for FreehandToolFsmState {
|
||||
@@ -200,7 +201,6 @@ impl Fsm for FreehandToolFsmState {
|
||||
(FreehandToolFsmState::Ready, FreehandToolMessage::DragStart) => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
tool_data.layer_path = Some(document.get_path_for_new_layer());
|
||||
|
||||
let pos = transform.inverse().transform_point2(input.mouse.position);
|
||||
|
||||
@@ -209,7 +209,20 @@ impl Fsm for FreehandToolFsmState {
|
||||
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
add_polyline([pos], tool_data, tool_options.stroke.active_color(), tool_options.fill.active_color(), responses);
|
||||
let subpath = bezier_rs::Subpath::from_anchors([pos], false);
|
||||
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
|
||||
tool_data.layer = Some(layer);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight),
|
||||
});
|
||||
|
||||
FreehandToolFsmState::Drawing
|
||||
}
|
||||
@@ -217,10 +230,10 @@ impl Fsm for FreehandToolFsmState {
|
||||
let pos = transform.inverse().transform_point2(input.mouse.position);
|
||||
|
||||
if tool_data.last_point != pos {
|
||||
if let Some(layer) = tool_data.layer_path.clone() {
|
||||
if let Some(layer) = tool_data.layer.clone() {
|
||||
let manipulator_group = ManipulatorGroup::new_anchor(pos);
|
||||
let modification = VectorDataModification::AddEndManipulatorGroup { subpath_index: 0, manipulator_group };
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification });
|
||||
responses.add(GraphOperationMessage::Vector { layer: layer.to_path(), modification });
|
||||
tool_data.dragged = true;
|
||||
tool_data.last_point = pos;
|
||||
}
|
||||
@@ -235,7 +248,7 @@ impl Fsm for FreehandToolFsmState {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
}
|
||||
|
||||
tool_data.layer_path = None;
|
||||
tool_data.layer = None;
|
||||
|
||||
FreehandToolFsmState::Ready
|
||||
}
|
||||
@@ -263,20 +276,3 @@ impl Fsm for FreehandToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
let layer_path = data.layer_path.clone().unwrap();
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path,
|
||||
stroke: Stroke::new(stroke_color, data.weight),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::messages::portfolio::document::node_graph::{self, IMAGINATE_NODE};
|
||||
use crate::messages::tool::common_functionality::path_outline::PathOutline;
|
||||
use crate::messages::tool::common_functionality::resize::Resize;
|
||||
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::Operation;
|
||||
|
||||
use glam::DAffine2;
|
||||
@@ -127,7 +128,7 @@ impl Fsm for ImaginateToolFsmState {
|
||||
|
||||
shape_data.start(responses, document, input, render_data);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
shape_data.path = Some(document.get_path_for_new_layer());
|
||||
shape_data.layer = Some(LayerNodeIdentifier::new(generate_uuid(), document.network()));
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
|
||||
use graph_craft::document::*;
|
||||
@@ -163,7 +164,7 @@ impl Fsm for ImaginateToolFsmState {
|
||||
|
||||
// Add a layer with a frame to the document
|
||||
responses.add(Operation::AddFrame {
|
||||
path: shape_data.path.clone().unwrap(),
|
||||
path: shape_data.layer.unwrap().to_path(),
|
||||
insert_index: -1,
|
||||
transform: DAffine2::ZERO.to_cols_array(),
|
||||
network,
|
||||
@@ -179,8 +180,8 @@ impl Fsm for ImaginateToolFsmState {
|
||||
state
|
||||
}
|
||||
(ImaginateToolFsmState::Drawing, ImaginateToolMessage::DragStop) => {
|
||||
if let Some(layer_path) = &shape_data.path {
|
||||
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer_path.to_vec() });
|
||||
if let Some(layer) = &shape_data.layer {
|
||||
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer.to_path() });
|
||||
}
|
||||
|
||||
input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses);
|
||||
|
||||
@@ -4,7 +4,8 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
|
||||
use document_legacy::LayerId;
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::Stroke;
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -155,7 +156,7 @@ struct LineToolData {
|
||||
drag_current: DVec2,
|
||||
angle: f64,
|
||||
weight: f64,
|
||||
path: Option<Vec<LayerId>>,
|
||||
layer: Option<LayerNodeIdentifier>,
|
||||
snap_manager: SnapManager,
|
||||
}
|
||||
|
||||
@@ -186,13 +187,13 @@ impl Fsm for LineToolFsmState {
|
||||
let subpath = bezier_rs::Subpath::new_line(DVec2::ZERO, DVec2::X);
|
||||
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
let layer_path = document.get_path_for_new_layer();
|
||||
tool_data.path = Some(layer_path.clone());
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path,
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
|
||||
});
|
||||
tool_data.layer = Some(layer);
|
||||
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
@@ -210,13 +211,13 @@ impl Fsm for LineToolFsmState {
|
||||
(LineToolFsmState::Drawing, LineToolMessage::DragStop) => {
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
input.mouse.finish_transaction(tool_data.drag_start, responses);
|
||||
tool_data.path = None;
|
||||
tool_data.layer = None;
|
||||
LineToolFsmState::Ready
|
||||
}
|
||||
(LineToolFsmState::Drawing, LineToolMessage::Abort) => {
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
tool_data.path = None;
|
||||
tool_data.layer = None;
|
||||
LineToolFsmState::Ready
|
||||
}
|
||||
(_, LineToolMessage::WorkingColorChanged) => {
|
||||
@@ -283,7 +284,7 @@ fn generate_transform(tool_data: &mut LineToolData, document_to_viewport: DAffin
|
||||
}
|
||||
|
||||
GraphOperationMessage::TransformSet {
|
||||
layer: tool_data.path.clone().unwrap(),
|
||||
layer: tool_data.layer.unwrap().to_path(),
|
||||
transform: glam::DAffine2::from_scale_angle_translation(DVec2::new(line_length, 1.), angle, start),
|
||||
transform_in: TransformIn::Viewport,
|
||||
skip_rerender: false,
|
||||
|
||||
@@ -7,8 +7,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils::get_s
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::LayerId;
|
||||
use graphene_core::uuid::ManipulatorGroupId;
|
||||
use graphene_core::uuid::{generate_uuid, ManipulatorGroupId};
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::vector::{ManipulatorPointId, SelectedType};
|
||||
use graphene_core::Color;
|
||||
@@ -200,7 +199,7 @@ struct ModifierState {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct PenToolData {
|
||||
weight: f64,
|
||||
path: Option<Vec<LayerId>>,
|
||||
layer: Option<LayerNodeIdentifier>,
|
||||
subpath_index: usize,
|
||||
snap_manager: SnapManager,
|
||||
should_mirror: bool,
|
||||
@@ -209,13 +208,13 @@ struct PenToolData {
|
||||
angle: f64,
|
||||
}
|
||||
impl PenToolData {
|
||||
fn extend_subpath(&mut self, layer: &[LayerId], subpath_index: usize, from_start: bool, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
self.path = Some(layer.to_vec());
|
||||
fn extend_subpath(&mut self, layer: LayerNodeIdentifier, subpath_index: usize, from_start: bool, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
self.layer = Some(layer);
|
||||
self.from_start = from_start;
|
||||
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 {
|
||||
let Some(subpaths) = get_subpaths(layer, &document.document_legacy) else {
|
||||
return;
|
||||
};
|
||||
let manipulator_groups = subpaths[subpath_index].manipulator_groups();
|
||||
@@ -224,7 +223,7 @@ impl PenToolData {
|
||||
};
|
||||
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorHandleMirroring {
|
||||
id: last_handle.id,
|
||||
mirror_angle: false,
|
||||
@@ -241,32 +240,31 @@ impl PenToolData {
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
let parent = document.new_layer_parent();
|
||||
// Deselect layers because we are now creating a new layer
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
|
||||
let layer_path = document.get_path_for_new_layer();
|
||||
|
||||
// Get the position and set properties
|
||||
let transform = document.metadata().document_to_viewport * document.document_legacy.multiply_transforms(&layer_path[..layer_path.len() - 1]).unwrap_or_default();
|
||||
let transform = document.metadata().document_to_viewport * document.metadata().transform_to_viewport(parent);
|
||||
let snapped_position = self.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
let start_position = transform.inverse().transform_point2(snapped_position);
|
||||
self.weight = line_weight;
|
||||
|
||||
// Create the initial shape with a `bez_path` (only contains a moveto initially)
|
||||
let subpath = bezier_rs::Subpath::new(vec![bezier_rs::ManipulatorGroup::new(start_position, Some(start_position), Some(start_position))], false);
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), parent, responses);
|
||||
self.layer = Some(layer);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(stroke_color, line_weight),
|
||||
});
|
||||
|
||||
self.path = Some(layer_path);
|
||||
self.from_start = false;
|
||||
self.subpath_index = 0;
|
||||
}
|
||||
@@ -275,8 +273,8 @@ impl PenToolData {
|
||||
/// If you place the anchor on top of the previous anchor then you break the mirror
|
||||
fn check_break(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<()> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
let layer = self.layer?;
|
||||
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
|
||||
|
||||
// Get the last manipulator group and the one previous to that
|
||||
let mut manipulator_groups = subpath.manipulator_groups().iter();
|
||||
@@ -297,21 +295,21 @@ impl PenToolData {
|
||||
}
|
||||
// Remove the point that has just been placed
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
|
||||
});
|
||||
|
||||
// Move the in handle of the previous anchor to on top of the previous position
|
||||
let point = ManipulatorPointId::new(previous_manipulator_group.id, outwards_handle);
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position: previous_anchor },
|
||||
});
|
||||
|
||||
// Stop the handles on the last point from mirroring
|
||||
let id = previous_manipulator_group.id;
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false },
|
||||
});
|
||||
|
||||
@@ -321,8 +319,8 @@ impl PenToolData {
|
||||
|
||||
fn finish_placing_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
let layer = self.layer?;
|
||||
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
|
||||
|
||||
// Get the last manipulator group and the one previous to that
|
||||
let mut manipulator_groups = subpath.manipulator_groups().iter();
|
||||
@@ -352,33 +350,33 @@ impl PenToolData {
|
||||
// Move the in handle of the first point to where the user has placed it
|
||||
let point = ManipulatorPointId::new(first_manipulator_group.id, inwards_handle);
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position: last_in },
|
||||
});
|
||||
|
||||
// Stop the handles on the first point from mirroring
|
||||
let id = first_manipulator_group.id;
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false },
|
||||
});
|
||||
|
||||
// Remove the point that has just been placed
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
|
||||
});
|
||||
|
||||
// Push a close path node
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetClosed { index: 0, closed: true },
|
||||
});
|
||||
|
||||
responses.add(DocumentMessage::CommitTransaction);
|
||||
|
||||
// Clean up tool data
|
||||
self.path = None;
|
||||
self.layer = None;
|
||||
self.snap_manager.cleanup(responses);
|
||||
|
||||
// Return to ready state
|
||||
@@ -386,7 +384,7 @@ impl PenToolData {
|
||||
}
|
||||
// Add a new manipulator for the next anchor that we will place
|
||||
if let Some(out_handle) = outwards_handle.get_position(last_manipulator_group) {
|
||||
responses.add(add_manipulator_group(&self.path, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle)));
|
||||
responses.add(add_manipulator_group(&self.layer, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle)));
|
||||
}
|
||||
|
||||
Some(PenToolFsmState::PlacingAnchor)
|
||||
@@ -394,8 +392,7 @@ impl PenToolData {
|
||||
|
||||
fn drag_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, mouse: DVec2, modifiers: ModifierState, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
let subpath = &get_subpaths(self.layer?, &document.document_legacy)?[self.subpath_index];
|
||||
|
||||
// Get the last manipulator group
|
||||
let manipulator_groups = subpath.manipulator_groups();
|
||||
@@ -419,7 +416,7 @@ impl PenToolData {
|
||||
// Update points on current segment (to show preview of new handle)
|
||||
let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle);
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: self.layer?.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
|
||||
});
|
||||
|
||||
@@ -430,7 +427,7 @@ impl PenToolData {
|
||||
let pos = last_anchor - (pos - last_anchor);
|
||||
let point = ManipulatorPointId::new(last_manipulator_group.id, inwards_handle);
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: self.layer?.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
|
||||
});
|
||||
}
|
||||
@@ -438,7 +435,7 @@ impl PenToolData {
|
||||
// Update the mirror status of the currently modifying point
|
||||
let id = last_manipulator_group.id;
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: self.layer?.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: should_mirror },
|
||||
});
|
||||
|
||||
@@ -447,8 +444,8 @@ impl PenToolData {
|
||||
|
||||
fn place_anchor(&mut self, document: &DocumentMessageHandler, transform: DAffine2, mouse: DVec2, modifiers: ModifierState, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
let layer = self.layer?;
|
||||
let subpath = &get_subpaths(layer, &document.document_legacy)?[self.subpath_index];
|
||||
|
||||
// Get the last manipulator group and the one previous to that
|
||||
let mut manipulator_groups = subpath.manipulator_groups().iter();
|
||||
@@ -483,7 +480,7 @@ impl PenToolData {
|
||||
for manipulator_type in [SelectedType::Anchor, SelectedType::InHandle, SelectedType::OutHandle] {
|
||||
let point = ManipulatorPointId::new(last_manipulator_group.id, manipulator_type);
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: layer.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
|
||||
});
|
||||
}
|
||||
@@ -492,8 +489,7 @@ impl PenToolData {
|
||||
|
||||
fn finish_transaction(&mut self, fsm: PenToolFsmState, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) -> Option<DocumentMessage> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
let subpath = &get_subpaths(self.layer?, &document.document_legacy)?[self.subpath_index];
|
||||
|
||||
// Abort if only one manipulator group has been placed
|
||||
if fsm == PenToolFsmState::PlacingAnchor && subpath.len() < 3 {
|
||||
@@ -516,9 +512,8 @@ impl PenToolData {
|
||||
// Clean up if there are two or more manipulators
|
||||
// Remove the unplaced anchor if in anchor placing mode
|
||||
if fsm == PenToolFsmState::PlacingAnchor {
|
||||
let layer_path = layer_path.clone();
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: self.layer?.to_path(),
|
||||
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
|
||||
});
|
||||
last_manipulator_group = previous_manipulator_group;
|
||||
@@ -528,7 +523,7 @@ impl PenToolData {
|
||||
let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle);
|
||||
let position = last_manipulator_group.anchor;
|
||||
responses.add(GraphOperationMessage::Vector {
|
||||
layer: layer_path.to_vec(),
|
||||
layer: self.layer?.to_path(),
|
||||
modification: VectorDataModification::SetManipulatorPosition { point, position },
|
||||
});
|
||||
|
||||
@@ -551,13 +546,13 @@ impl Fsm for PenToolFsmState {
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
let mut transform = tool_data.path.as_ref().and_then(|path| document.document_legacy.multiply_transforms(path).ok()).unwrap_or_default();
|
||||
let mut transform = tool_data.layer.map(|layer| document.metadata().transform_to_viewport(layer)).unwrap_or_default();
|
||||
|
||||
if !transform.inverse().is_finite() {
|
||||
let parent_transform = tool_data
|
||||
.path
|
||||
.as_ref()
|
||||
.and_then(|layer_path| document.document_legacy.multiply_transforms(&layer_path[..layer_path.len() - 1]).ok());
|
||||
.layer
|
||||
.and_then(|layer| layer.parent(document.metadata()))
|
||||
.map(|layer| document.metadata().transform_to_viewport(layer));
|
||||
|
||||
transform = parent_transform.unwrap_or(DAffine2::IDENTITY);
|
||||
}
|
||||
@@ -566,8 +561,6 @@ impl Fsm for PenToolFsmState {
|
||||
transform = DAffine2::IDENTITY;
|
||||
}
|
||||
|
||||
transform = document.metadata().document_to_viewport * transform;
|
||||
|
||||
let ToolMessage::Pen(event) = event else {
|
||||
return self;
|
||||
};
|
||||
@@ -661,7 +654,7 @@ impl Fsm for PenToolFsmState {
|
||||
let message = tool_data.finish_transaction(self, document, responses).unwrap_or(DocumentMessage::AbortTransaction);
|
||||
responses.add(message);
|
||||
|
||||
tool_data.path = None;
|
||||
tool_data.layer = None;
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
|
||||
PenToolFsmState::Ready
|
||||
@@ -721,10 +714,11 @@ fn compute_snapped_angle(cached_angle: &mut f64, lock_angle: bool, snap_angle: b
|
||||
}
|
||||
|
||||
/// Pushes a [ManipulatorGroup] to the current layer via a [GraphOperationMessage].
|
||||
fn add_manipulator_group(layer_path: &Option<Vec<LayerId>>, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup<ManipulatorGroupId>) -> Message {
|
||||
let Some(layer) = layer_path.clone() else {
|
||||
fn add_manipulator_group(layer: &Option<LayerNodeIdentifier>, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup<ManipulatorGroupId>) -> Message {
|
||||
let Some(layer) = layer else {
|
||||
return Message::NoOp;
|
||||
};
|
||||
let layer = layer.to_path();
|
||||
let modification = if from_start {
|
||||
VectorDataModification::AddStartManipulatorGroup { subpath_index: 0, manipulator_group }
|
||||
} else {
|
||||
@@ -734,16 +728,14 @@ fn add_manipulator_group(layer_path: &Option<Vec<LayerId>>, from_start: bool, ma
|
||||
}
|
||||
|
||||
/// Determines if a path should be extended. Returns the path and if it is extending from the start, if applicable.
|
||||
fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64) -> Option<(&[LayerId], usize, bool)> {
|
||||
fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64) -> Option<(LayerNodeIdentifier, usize, bool)> {
|
||||
let mut best = None;
|
||||
let mut best_distance_squared = tolerance * tolerance;
|
||||
|
||||
for layer_path in document.selected_layers() {
|
||||
let Ok(viewspace) = document.document_legacy.generate_transform_relative_to_viewport(layer_path) else {
|
||||
continue;
|
||||
};
|
||||
for layer in document.metadata().selected_layers() {
|
||||
let viewspace = document.metadata().transform_to_viewport(layer);
|
||||
|
||||
let subpaths = get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?;
|
||||
let subpaths = get_subpaths(layer, &document.document_legacy)?;
|
||||
for (subpath_index, subpath) in subpaths.iter().enumerate() {
|
||||
if subpath.closed() {
|
||||
continue;
|
||||
@@ -755,7 +747,7 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64)
|
||||
let distance_squared = viewspace.transform_point2(manipulator_group.anchor).distance_squared(pos);
|
||||
|
||||
if distance_squared < best_distance_squared {
|
||||
best = Some((layer_path, subpath_index, from_start));
|
||||
best = Some((layer, subpath_index, from_start));
|
||||
best_distance_squared = distance_squared;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::resize::Resize;
|
||||
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -244,23 +245,22 @@ impl Fsm for PolygonToolFsmState {
|
||||
(PolygonToolFsmState::Ready, PolygonToolMessage::DragStart) => {
|
||||
polygon_data.start(responses, document, input, render_data);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
let layer_path = document.get_path_for_new_layer();
|
||||
polygon_data.path = Some(layer_path.clone());
|
||||
|
||||
let subpath = match tool_options.primitive_shape_type {
|
||||
PrimitiveShapeType::Polygon => bezier_rs::Subpath::new_regular_polygon(DVec2::ZERO, tool_options.vertices as u64, 1.),
|
||||
PrimitiveShapeType::Star => bezier_rs::Subpath::new_star_polygon(DVec2::ZERO, tool_options.vertices as u64, 1., 0.5),
|
||||
};
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
|
||||
polygon_data.layer = Some(layer);
|
||||
|
||||
let fill_color = tool_options.fill.active_color();
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path,
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::resize::Resize;
|
||||
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -216,19 +217,19 @@ impl Fsm for RectangleToolFsmState {
|
||||
|
||||
let subpath = bezier_rs::Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
|
||||
|
||||
let layer_path = document.get_path_for_new_layer();
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
shape_data.path = Some(layer_path.clone());
|
||||
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
|
||||
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
|
||||
shape_data.layer = Some(layer);
|
||||
|
||||
let fill_color = tool_options.fill.active_color();
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer_path.clone(),
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer_path,
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
|
||||
use document_legacy::LayerId;
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use graphene_core::uuid::generate_uuid;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
@@ -185,7 +186,7 @@ struct SplineToolData {
|
||||
points: Vec<DVec2>,
|
||||
next_point: DVec2,
|
||||
weight: f64,
|
||||
path: Option<Vec<LayerId>>,
|
||||
layer: Option<LayerNodeIdentifier>,
|
||||
snap_manager: SnapManager,
|
||||
}
|
||||
|
||||
@@ -215,7 +216,6 @@ impl Fsm for SplineToolFsmState {
|
||||
(SplineToolFsmState::Ready, SplineToolMessage::DragStart) => {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
tool_data.path = Some(document.get_path_for_new_layer());
|
||||
|
||||
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true);
|
||||
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
|
||||
@@ -228,7 +228,18 @@ impl Fsm for SplineToolFsmState {
|
||||
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
add_spline(tool_data, tool_options.fill.active_color(), tool_options.stroke.active_color(), responses);
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![], generate_uuid(), document.new_layer_parent(), responses);
|
||||
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: layer.to_path(),
|
||||
fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
layer: layer.to_path(),
|
||||
stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight),
|
||||
});
|
||||
tool_data.layer = Some(layer);
|
||||
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
@@ -264,7 +275,7 @@ impl Fsm for SplineToolFsmState {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
}
|
||||
|
||||
tool_data.path = None;
|
||||
tool_data.layer = None;
|
||||
tool_data.points.clear();
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
|
||||
@@ -298,23 +309,6 @@ impl Fsm for SplineToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
|
||||
});
|
||||
|
||||
responses.add(GraphOperationMessage::StrokeSet {
|
||||
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 {
|
||||
@@ -323,12 +317,12 @@ fn update_spline(tool_data: &SplineToolData, show_preview: bool, responses: &mut
|
||||
|
||||
let subpath = bezier_rs::Subpath::new_cubic_spline(points);
|
||||
|
||||
let Some(layer) = tool_data.path.clone() else {
|
||||
let Some(layer) = tool_data.layer.clone() else {
|
||||
return;
|
||||
};
|
||||
|
||||
graph_modification_utils::set_manipulator_mirror_angle(subpath.manipulator_groups(), &layer, true, responses);
|
||||
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 });
|
||||
responses.add(GraphOperationMessage::Vector { layer: layer.to_path(), modification });
|
||||
}
|
||||
|
||||
@@ -290,6 +290,8 @@ impl TextToolData {
|
||||
text: String::new(),
|
||||
font: editing_text.font.clone(),
|
||||
size: editing_text.font_size,
|
||||
parent: LayerNodeIdentifier::ROOT,
|
||||
insert_index: -1,
|
||||
});
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
layer: self.layer.to_path(),
|
||||
|
||||
Reference in New Issue
Block a user