@@ -10,34 +10,62 @@ use graphene_core::raster::image::ImageFrame;
1010use graphene_core:: raster:: BlendMode ;
1111use graphene_core:: text:: { Font , TypesettingConfig } ;
1212use graphene_core:: vector:: style:: Gradient ;
13- use graphene_core:: vector:: PointId ;
1413use graphene_core:: Color ;
14+ use graphene_std:: vector:: { ManipulatorPointId , PointId , SegmentId , VectorModificationType } ;
1515
1616use glam:: DVec2 ;
1717use std:: collections:: VecDeque ;
1818
19- pub fn merge_layers ( document : & DocumentMessageHandler , current_layer : LayerNodeIdentifier , other_layer : LayerNodeIdentifier , responses : & mut VecDeque < Message > ) {
19+ /// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists.
20+ pub fn find_spline ( document : & DocumentMessageHandler , layer : LayerNodeIdentifier ) -> Option < NodeId > {
21+ document
22+ . network_interface
23+ . upstream_flow_back_from_nodes ( [ layer. to_node ( ) ] . to_vec ( ) , & [ ] , FlowType :: HorizontalFlow )
24+ . map ( |node_id| ( document. network_interface . reference ( & node_id, & [ ] ) . unwrap ( ) , node_id) )
25+ . take_while ( |( reference, _) | reference. as_ref ( ) . is_some_and ( |node_ref| node_ref != "Path" ) )
26+ . find ( |( reference, _) | reference. as_ref ( ) . is_some_and ( |node_ref| node_ref == "Spline" ) )
27+ . map ( |node| node. 1 )
28+ }
29+
30+ /// Merge `second_layer` to the `first_layer`.
31+ pub fn merge_layers ( document : & DocumentMessageHandler , first_layer : LayerNodeIdentifier , second_layer : LayerNodeIdentifier , responses : & mut VecDeque < Message > ) {
32+ if first_layer == second_layer {
33+ return ;
34+ }
2035 // Calculate the downstream transforms in order to bring the other vector data into the same layer space
21- let current_transform = document. metadata ( ) . downstream_transform_to_document ( current_layer ) ;
22- let other_transform = document. metadata ( ) . downstream_transform_to_document ( other_layer ) ;
36+ let first_layer_transform = document. metadata ( ) . downstream_transform_to_document ( first_layer ) ;
37+ let second_layer_transform = document. metadata ( ) . downstream_transform_to_document ( second_layer ) ;
2338
2439 // Represents the change in position that would occur if the other layer was moved below the current layer
25- let transform_delta = current_transform * other_transform . inverse ( ) ;
40+ let transform_delta = first_layer_transform * second_layer_transform . inverse ( ) ;
2641 let offset = transform_delta. inverse ( ) ;
2742 responses. add ( GraphOperationMessage :: TransformChange {
28- layer : other_layer ,
43+ layer : second_layer ,
2944 transform : offset,
3045 transform_in : TransformIn :: Local ,
3146 skip_rerender : false ,
3247 } ) ;
3348
34- // Move the other layer below the current layer for positioning purposes
35- let current_layer_parent = current_layer. parent ( document. metadata ( ) ) . unwrap ( ) ;
36- let current_layer_index = current_layer_parent. children ( document. metadata ( ) ) . position ( |child| child == current_layer) . unwrap ( ) ;
49+ let mut current_and_other_layer_is_spline = false ;
50+
51+ match ( find_spline ( document, first_layer) , find_spline ( document, second_layer) ) {
52+ ( Some ( current_layer_spline) , Some ( other_layer_spline) ) => {
53+ responses. add ( NodeGraphMessage :: DeleteNodes {
54+ node_ids : [ current_layer_spline, other_layer_spline] . to_vec ( ) ,
55+ delete_children : false ,
56+ } ) ;
57+ current_and_other_layer_is_spline = true ;
58+ }
59+ _ => { }
60+ }
61+
62+ // Move the `second_layer` below the `first_layer` for positioning purposes
63+ let first_layer_parent = first_layer. parent ( document. metadata ( ) ) . unwrap ( ) ;
64+ let first_layer_index = first_layer_parent. children ( document. metadata ( ) ) . position ( |child| child == first_layer) . unwrap ( ) ;
3765 responses. add ( NodeGraphMessage :: MoveLayerToStack {
38- layer : other_layer ,
39- parent : current_layer_parent ,
40- insert_index : current_layer_index + 1 ,
66+ layer : second_layer ,
67+ parent : first_layer_parent ,
68+ insert_index : first_layer_index + 1 ,
4169 } ) ;
4270
4371 // Merge the inputs of the two layers
@@ -55,14 +83,14 @@ pub fn merge_layers(document: &DocumentMessageHandler, current_layer: LayerNodeI
5583 } ) ;
5684 responses. add ( NodeGraphMessage :: MoveNodeToChainStart {
5785 node_id : merge_node_id,
58- parent : current_layer ,
86+ parent : first_layer ,
5987 } ) ;
6088 responses. add ( NodeGraphMessage :: ConnectUpstreamOutputToInput {
61- downstream_input : InputConnector :: node ( other_layer . to_node ( ) , 1 ) ,
89+ downstream_input : InputConnector :: node ( second_layer . to_node ( ) , 1 ) ,
6290 input_connector : InputConnector :: node ( merge_node_id, 1 ) ,
6391 } ) ;
6492 responses. add ( NodeGraphMessage :: DeleteNodes {
65- node_ids : vec ! [ other_layer . to_node( ) ] ,
93+ node_ids : vec ! [ second_layer . to_node( ) ] ,
6694 delete_children : false ,
6795 } ) ;
6896
@@ -77,7 +105,7 @@ pub fn merge_layers(document: &DocumentMessageHandler, current_layer: LayerNodeI
77105 } ) ;
78106 responses. add ( NodeGraphMessage :: MoveNodeToChainStart {
79107 node_id : flatten_node_id,
80- parent : current_layer ,
108+ parent : first_layer ,
81109 } ) ;
82110
83111 // Add a path node after the flatten node
@@ -91,9 +119,25 @@ pub fn merge_layers(document: &DocumentMessageHandler, current_layer: LayerNodeI
91119 } ) ;
92120 responses. add ( NodeGraphMessage :: MoveNodeToChainStart {
93121 node_id : path_node_id,
94- parent : current_layer ,
122+ parent : first_layer ,
95123 } ) ;
96124
125+ // Add a Spline node after the Path node if both the layers we are merging is spline.
126+ if current_and_other_layer_is_spline {
127+ let spline_node_id = NodeId :: new ( ) ;
128+ let spline_node = document_node_definitions:: resolve_document_node_type ( "Spline" )
129+ . expect ( "Failed to create Spline node" )
130+ . default_node_template ( ) ;
131+ responses. add ( NodeGraphMessage :: InsertNode {
132+ node_id : spline_node_id,
133+ node_template : spline_node,
134+ } ) ;
135+ responses. add ( NodeGraphMessage :: MoveNodeToChainStart {
136+ node_id : spline_node_id,
137+ parent : first_layer,
138+ } ) ;
139+ }
140+
97141 // Add a transform node to ensure correct tooling modifications
98142 let transform_node_id = NodeId :: new ( ) ;
99143 let transform_node = document_node_definitions:: resolve_document_node_type ( "Transform" )
@@ -105,14 +149,57 @@ pub fn merge_layers(document: &DocumentMessageHandler, current_layer: LayerNodeI
105149 } ) ;
106150 responses. add ( NodeGraphMessage :: MoveNodeToChainStart {
107151 node_id : transform_node_id,
108- parent : current_layer ,
152+ parent : first_layer ,
109153 } ) ;
110154
111155 responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
112156 responses. add ( Message :: StartBuffer ) ;
113157 responses. add ( PenToolMessage :: RecalculateLatestPointsPosition ) ;
114158}
115159
160+ /// Merge the `first_endpoint` with `second_endpoint`.
161+ pub fn merge_points ( document : & DocumentMessageHandler , layer : LayerNodeIdentifier , first_endpoint : PointId , second_endpont : PointId , responses : & mut VecDeque < Message > ) {
162+ let transform = document. metadata ( ) . transform_to_document ( layer) ;
163+ let Some ( vector_data) = document. network_interface . compute_modified_vector ( layer) else { return } ;
164+
165+ let segment = vector_data. segment_bezier_iter ( ) . find ( |( _, _, start, end) | * end == second_endpont || * start == second_endpont) ;
166+ let Some ( ( segment, _, mut segment_start_point, mut segment_end_point) ) = segment else {
167+ log:: error!( "Could not get the segment for second_endpoint." ) ;
168+ return ;
169+ } ;
170+
171+ let mut handles = [ None ; 2 ] ;
172+ if let Some ( handle_position) = ManipulatorPointId :: PrimaryHandle ( segment) . get_position ( & vector_data) {
173+ let anchor_position = ManipulatorPointId :: Anchor ( segment_start_point) . get_position ( & vector_data) . unwrap ( ) ;
174+ let handle_position = transform. transform_point2 ( handle_position) ;
175+ let anchor_position = transform. transform_point2 ( anchor_position) ;
176+ let anchor_to_handle = handle_position - anchor_position;
177+ handles[ 0 ] = Some ( anchor_to_handle) ;
178+ }
179+ if let Some ( handle_position) = ManipulatorPointId :: EndHandle ( segment) . get_position ( & vector_data) {
180+ let anchor_position = ManipulatorPointId :: Anchor ( segment_end_point) . get_position ( & vector_data) . unwrap ( ) ;
181+ let handle_position = transform. transform_point2 ( handle_position) ;
182+ let anchor_position = transform. transform_point2 ( anchor_position) ;
183+ let anchor_to_handle = handle_position - anchor_position;
184+ handles[ 1 ] = Some ( anchor_to_handle) ;
185+ }
186+
187+ if segment_start_point == second_endpont {
188+ core:: mem:: swap ( & mut segment_start_point, & mut segment_end_point) ;
189+ handles. reverse ( ) ;
190+ }
191+
192+ let modification_type = VectorModificationType :: RemovePoint { id : second_endpont } ;
193+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
194+ let modification_type = VectorModificationType :: RemoveSegment { id : segment } ;
195+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
196+
197+ let points = [ segment_start_point, first_endpoint] ;
198+ let id = SegmentId :: generate ( ) ;
199+ let modification_type = VectorModificationType :: InsertSegment { id, points, handles } ;
200+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
201+ }
202+
116203/// Create a new vector layer.
117204pub fn new_vector_layer ( subpaths : Vec < Subpath < PointId > > , id : NodeId , parent : LayerNodeIdentifier , responses : & mut VecDeque < Message > ) -> LayerNodeIdentifier {
118205 let insert_index = 0 ;
0 commit comments