@@ -3,7 +3,7 @@ use super::document::utility_types::network_interface;
3
3
use super :: spreadsheet:: SpreadsheetMessageHandler ;
4
4
use super :: utility_types:: { PanelType , PersistentData } ;
5
5
use crate :: application:: generate_uuid;
6
- use crate :: consts:: DEFAULT_DOCUMENT_NAME ;
6
+ use crate :: consts:: { DEFAULT_DOCUMENT_NAME , DEFAULT_STROKE_WIDTH } ;
7
7
use crate :: messages:: animation:: TimingInformation ;
8
8
use crate :: messages:: debug:: utility_types:: MessageLoggingVerbosity ;
9
9
use crate :: messages:: dialog:: simple_dialogs;
@@ -12,6 +12,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
12
12
use crate :: messages:: portfolio:: document:: DocumentMessageContext ;
13
13
use crate :: messages:: portfolio:: document:: graph_operation:: utility_types:: TransformIn ;
14
14
use crate :: messages:: portfolio:: document:: node_graph:: document_node_definitions;
15
+ use crate :: messages:: portfolio:: document:: node_graph:: document_node_definitions:: resolve_document_node_type;
15
16
use crate :: messages:: portfolio:: document:: utility_types:: clipboards:: { Clipboard , CopyBufferEntry , INTERNAL_CLIPBOARD_COUNT } ;
16
17
use crate :: messages:: portfolio:: document:: utility_types:: network_interface:: OutputConnector ;
17
18
use crate :: messages:: portfolio:: document:: utility_types:: nodes:: SelectedNodes ;
@@ -21,11 +22,14 @@ use crate::messages::prelude::*;
21
22
use crate :: messages:: tool:: common_functionality:: graph_modification_utils;
22
23
use crate :: messages:: tool:: utility_types:: { HintData , HintGroup , ToolType } ;
23
24
use crate :: node_graph_executor:: { ExportConfig , NodeGraphExecutor } ;
25
+ use bezier_rs:: BezierHandles ;
24
26
use glam:: { DAffine2 , DVec2 } ;
25
27
use graph_craft:: document:: NodeId ;
26
28
use graph_craft:: document:: value:: TaggedValue ;
29
+ use graphene_std:: Color ;
27
30
use graphene_std:: renderer:: Quad ;
28
31
use graphene_std:: text:: Font ;
32
+ use graphene_std:: vector:: { HandleId , PointId , SegmentId , VectorData , VectorModificationType } ;
29
33
use std:: vec;
30
34
31
35
#[ derive( ExtractField ) ]
@@ -576,6 +580,99 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
576
580
}
577
581
}
578
582
}
583
+ // Custom paste implementation for Path tool
584
+ PortfolioMessage :: PasteSerializedVector { data } => {
585
+ // If using Path tool then send the operation to Path tool
586
+ if * current_tool == ToolType :: Path {
587
+ responses. add ( PathToolMessage :: Paste { data } ) ;
588
+ return ;
589
+ }
590
+
591
+ // If not using Path tool, create new layers and add paths into those
592
+ if let Some ( document) = self . active_document ( ) {
593
+ let Ok ( data) = serde_json:: from_str :: < Vec < ( LayerNodeIdentifier , VectorData , DAffine2 ) > > ( & data) else {
594
+ return ;
595
+ } ;
596
+
597
+ let mut layers = Vec :: new ( ) ;
598
+
599
+ for ( _, new_vector, transform) in data {
600
+ let Some ( node_type) = resolve_document_node_type ( "Path" ) else {
601
+ error ! ( "Path node does not exist" ) ;
602
+ continue ;
603
+ } ;
604
+ let nodes = vec ! [ ( NodeId ( 0 ) , node_type. default_node_template( ) ) ] ;
605
+
606
+ let parent = document. new_layer_parent ( false ) ;
607
+
608
+ let layer = graph_modification_utils:: new_custom ( NodeId :: new ( ) , nodes, parent, responses) ;
609
+ layers. push ( layer) ;
610
+
611
+ // Adding the transform back into the layer
612
+ responses. add ( GraphOperationMessage :: TransformSet {
613
+ layer,
614
+ transform,
615
+ transform_in : TransformIn :: Local ,
616
+ skip_rerender : false ,
617
+ } ) ;
618
+
619
+ // Add default fill and stroke to the layer
620
+ let fill_color = Color :: WHITE ;
621
+ let stroke_color = Color :: BLACK ;
622
+
623
+ let fill = graphene_std:: vector:: style:: Fill :: solid ( fill_color. to_gamma_srgb ( ) ) ;
624
+ responses. add ( GraphOperationMessage :: FillSet { layer, fill } ) ;
625
+
626
+ let stroke = graphene_std:: vector:: style:: Stroke :: new ( Some ( stroke_color. to_gamma_srgb ( ) ) , DEFAULT_STROKE_WIDTH ) ;
627
+ responses. add ( GraphOperationMessage :: StrokeSet { layer, stroke } ) ;
628
+
629
+ // Create new point ids and add those into the existing vector data
630
+ let mut points_map = HashMap :: new ( ) ;
631
+ for ( point, position) in new_vector. point_domain . iter ( ) {
632
+ let new_point_id = PointId :: generate ( ) ;
633
+ points_map. insert ( point, new_point_id) ;
634
+ let modification_type = VectorModificationType :: InsertPoint { id : new_point_id, position } ;
635
+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
636
+ }
637
+
638
+ // Create new segment ids and add the segments into the existing vector data
639
+ let mut segments_map = HashMap :: new ( ) ;
640
+ for ( segment_id, bezier, start, end) in new_vector. segment_bezier_iter ( ) {
641
+ let new_segment_id = SegmentId :: generate ( ) ;
642
+
643
+ segments_map. insert ( segment_id, new_segment_id) ;
644
+
645
+ let handles = match bezier. handles {
646
+ BezierHandles :: Linear => [ None , None ] ,
647
+ BezierHandles :: Quadratic { handle } => [ Some ( handle - bezier. start ) , None ] ,
648
+ BezierHandles :: Cubic { handle_start, handle_end } => [ Some ( handle_start - bezier. start ) , Some ( handle_end - bezier. end ) ] ,
649
+ } ;
650
+
651
+ let points = [ points_map[ & start] , points_map[ & end] ] ;
652
+ let modification_type = VectorModificationType :: InsertSegment { id : new_segment_id, points, handles } ;
653
+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
654
+ }
655
+
656
+ // Set G1 continuity
657
+ for handles in new_vector. colinear_manipulators {
658
+ let to_new_handle = |handle : HandleId | -> HandleId {
659
+ HandleId {
660
+ ty : handle. ty ,
661
+ segment : segments_map[ & handle. segment ] ,
662
+ }
663
+ } ;
664
+ let new_handles = [ to_new_handle ( handles[ 0 ] ) , to_new_handle ( handles[ 1 ] ) ] ;
665
+ let modification_type = VectorModificationType :: SetG1Continuous { handles : new_handles, enabled : true } ;
666
+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
667
+ }
668
+ }
669
+
670
+ responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
671
+ responses. add ( Message :: Defer ( DeferMessage :: AfterGraphRun {
672
+ messages : vec ! [ PortfolioMessage :: CenterPastedLayers { layers } . into( ) ] ,
673
+ } ) ) ;
674
+ }
675
+ }
579
676
PortfolioMessage :: CenterPastedLayers { layers } => {
580
677
if let Some ( document) = self . active_document_mut ( ) {
581
678
let viewport_bounds_quad_pixels = Quad :: from_box ( [ DVec2 :: ZERO , ipp. viewport_bounds . size ( ) ] ) ;
0 commit comments