diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index cb8c4608c0..9e08e40c8d 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -154,6 +154,7 @@ impl<'a> ModifyInputsContext<'a> { } pub fn insert_vector(&mut self, subpaths: Vec>, layer: LayerNodeIdentifier, include_transform: bool, include_fill: bool, include_stroke: bool) { + let first_anchor = subpaths.first().and_then(|subpath| subpath.manipulator_groups().first().map(|group| group.anchor)); let vector = Table::new_from_element(Vector::from_subpaths(subpaths, true)); let shape = resolve_network_node_type("Path") @@ -164,7 +165,13 @@ impl<'a> ModifyInputsContext<'a> { self.network_interface.move_node_to_chain_start(&shape_id, layer, &[]); if include_transform { - let transform = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template(); + let mut transform = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template(); + if let Some(anchor) = first_anchor { + const TRANSLATION_INDEX: usize = 1; + if let Some(translation) = transform.document_node.inputs.get_mut(TRANSLATION_INDEX) { + *translation = NodeInput::value(TaggedValue::DVec2(anchor), false); + } + } let transform_id = NodeId::new(); self.network_interface.insert_node(transform_id, transform, &[]); self.network_interface.move_node_to_chain_start(&transform_id, layer, &[]); diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index a0d4cf1dbd..2f35cef188 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -243,6 +243,15 @@ pub fn new_svg_layer(svg: String, transform: glam::DAffine2, id: NodeId, parent: } pub fn new_custom(id: NodeId, nodes: Vec<(NodeId, NodeTemplate)>, parent: LayerNodeIdentifier, responses: &mut VecDeque) -> LayerNodeIdentifier { + let transform_node_id = NodeId::new(); + let mut nodes = nodes; + + // Insert a Transform node + let transform_node = crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_network_node_type("Transform") + .expect("Transform node does not exist") + .default_node_template(); + nodes.push((transform_node_id, transform_node)); + responses.add(GraphOperationMessage::NewCustomLayer { id, nodes, parent, insert_index: 0 }); responses.add(GraphOperationMessage::SetUpstreamToChain { layer: LayerNodeIdentifier::new_unchecked(id), diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index b3812b87cd..8c6980ad71 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -8,7 +8,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::utility_functions::should_extend; use glam::DVec2; -use graph_craft::document::NodeId; +use graph_craft::document::{NodeId, NodeInput}; use graphene_std::Color; use graphene_std::vector::VectorModificationType; use graphene_std::vector::{PointId, SegmentId}; @@ -285,9 +285,17 @@ impl Fsm for FreehandToolFsmState { let parent = document.new_layer_bounding_artboard(input, viewport); + let document_space_position = document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position); + let node_type = resolve_network_node_type("Path").expect("Path node does not exist"); - let node = node_type.default_node_template(); - let nodes = vec![(NodeId(0), node)]; + let mut transform_node = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template(); + if let Some(input) = transform_node.document_node.inputs.get_mut(0) { + *input = NodeInput::node(NodeId(1), 0); + } + if let Some(translation) = transform_node.document_node.inputs.get_mut(1) { + *translation = NodeInput::value(graph_craft::document::value::TaggedValue::DVec2(document_space_position), false); + } + let nodes = vec![(NodeId(0), transform_node), (NodeId(1), node_type.default_node_template())]; let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses); tool_options.stroke.apply_stroke(tool_data.weight, layer, responses); diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 25730b4751..532a8ef5b0 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -11,7 +11,8 @@ use crate::messages::tool::common_functionality::graph_modification_utils::{self use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration}; use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, closest_point, should_extend}; -use graph_craft::document::NodeId; +use graph_craft::document::value::TaggedValue; +use graph_craft::document::{NodeId, NodeInput}; use graphene_std::Color; use graphene_std::subpath::pathseg_points; use graphene_std::vector::misc::{HandleId, ManipulatorPointId, dvec2_to_point}; @@ -1283,7 +1284,15 @@ impl PenToolData { // New path layer let node_type = resolve_network_node_type("Path").expect("Path node does not exist"); - let nodes = vec![(NodeId(0), node_type.default_node_template())]; + let mut transform_node = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template(); + if let Some(input) = transform_node.document_node.inputs.get_mut(0) { + *input = NodeInput::node(NodeId(1), 0); + } + const TRANSLATION_INDEX: usize = 1; + if let Some(translation) = transform_node.document_node.inputs.get_mut(TRANSLATION_INDEX) { + *translation = NodeInput::value(TaggedValue::DVec2(snapped.snapped_point_document), false); + } + let nodes = vec![(NodeId(0), transform_node), (NodeId(1), node_type.default_node_template())]; let parent = document.new_layer_bounding_artboard(input, viewport); let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses); diff --git a/editor/src/messages/tool/tool_messages/shape_tool.rs b/editor/src/messages/tool/tool_messages/shape_tool.rs index 43895d0d70..e825ecabf7 100644 --- a/editor/src/messages/tool/tool_messages/shape_tool.rs +++ b/editor/src/messages/tool/tool_messages/shape_tool.rs @@ -21,7 +21,8 @@ use crate::messages::tool::common_functionality::shapes::{Ellipse, Line, Rectang use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapData, SnapTypeConfiguration}; use crate::messages::tool::common_functionality::transformation_cage::{BoundingBoxManager, EdgeBool}; use crate::messages::tool::common_functionality::utility_functions::{closest_point, resize_bounds, rotate_bounds, skew_bounds, transforming_transform_cage}; -use graph_craft::document::NodeId; +use graph_craft::document::value::TaggedValue; +use graph_craft::document::{NodeId, NodeInput}; use graphene_std::Color; use graphene_std::renderer::Quad; use graphene_std::vector::misc::{ArcType, GridType, SpiralType}; @@ -936,7 +937,17 @@ impl Fsm for ShapeToolFsmState { ShapeType::Line => Line::create_node(document, tool_data.data.drag_start), }; - let nodes = vec![(NodeId(0), node)]; + let mut transform_node = crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_network_node_type("Transform") + .expect("Transform node does not exist") + .default_node_template(); + if let Some(input) = transform_node.document_node.inputs.get_mut(0) { + *input = NodeInput::node(NodeId(1), 0); + } + const TRANSLATION_INDEX: usize = 1; + if let Some(translation) = transform_node.document_node.inputs.get_mut(TRANSLATION_INDEX) { + *translation = NodeInput::value(TaggedValue::DVec2(tool_data.data.drag_start), false); + } + let nodes = vec![(NodeId(0), transform_node), (NodeId(1), node)]; let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, document.new_layer_bounding_artboard(input, viewport), responses); let defered_responses = &mut VecDeque::new(); diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index 345b5a058e..0298b03948 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -10,6 +10,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils::{self, find_spline, merge_layers, merge_points}; use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapData, SnapManager, SnapTypeConfiguration, SnappedPoint}; use crate::messages::tool::common_functionality::utility_functions::{closest_point, should_extend}; +use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_std::Color; use graphene_std::vector::{PointId, SegmentId, VectorModificationType}; @@ -391,8 +392,17 @@ impl Fsm for SplineToolFsmState { let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist"); let path_node = path_node_type.default_node_template(); let spline_node_type = resolve_proto_node_type(graphene_std::vector::spline::IDENTIFIER).expect("Spline node does not exist"); - let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]); - let nodes = vec![(NodeId(1), path_node), (NodeId(0), spline_node)]; + let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(2), 0))]); + + let mut transform_node = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template(); + if let Some(input) = transform_node.document_node.inputs.get_mut(0) { + *input = NodeInput::node(NodeId(1), 0); + } + if let Some(translation) = transform_node.document_node.inputs.get_mut(1) { + *translation = NodeInput::value(TaggedValue::DVec2(snapped.snapped_point_document), false); + } + + let nodes = vec![(NodeId(0), transform_node), (NodeId(1), spline_node), (NodeId(2), path_node)]; let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses); tool_options.stroke.apply_stroke(tool_data.weight, layer, responses);