@@ -7,6 +7,7 @@ use crate::messages::debug::utility_types::MessageLoggingVerbosity;
7
7
use crate :: messages:: dialog:: simple_dialogs;
8
8
use crate :: messages:: frontend:: utility_types:: FrontendDocumentDetails ;
9
9
use crate :: messages:: layout:: utility_types:: widget_prelude:: * ;
10
+ use crate :: messages:: portfolio:: document:: graph_operation:: utility_types:: ModifyInputsContext ;
10
11
use crate :: messages:: portfolio:: document:: graph_operation:: utility_types:: TransformIn ;
11
12
use crate :: messages:: portfolio:: document:: node_graph:: document_node_definitions:: resolve_document_node_type;
12
13
use crate :: messages:: portfolio:: document:: utility_types:: clipboards:: { Clipboard , CopyBufferEntry , INTERNAL_CLIPBOARD_COUNT } ;
@@ -19,7 +20,7 @@ use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
19
20
use graphene_core:: renderer:: Quad ;
20
21
21
22
use bezier_rs:: Subpath ;
22
- use glam:: IVec2 ;
23
+ use glam:: { DAffine2 , DVec2 , IVec2 } ;
23
24
use graph_craft:: document:: value:: TaggedValue ;
24
25
use graph_craft:: document:: { DocumentNodeImplementation , NodeId , NodeInput } ;
25
26
use graphene_core:: text:: { Font , TypesettingConfig } ;
@@ -890,49 +891,69 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
890
891
if let Some ( document) = self . active_document ( ) {
891
892
if let Ok ( data) = serde_json:: from_str :: < Vec < CopyBufferEntry > > ( & data) {
892
893
let parent = document. new_layer_parent ( false ) ;
893
- let transform = document. metadata ( ) . document_to_viewport ;
894
-
895
- // Check parent bounds first since children will be pasted at same position
896
- if let Some ( parent_bounds) = document. metadata ( ) . bounding_box_document ( parent) {
897
- let viewport_bounds = Quad :: from_box_at_zero ( ipp. viewport_bounds . size ( ) ) ;
898
- let quad = transform * Quad :: from_box ( parent_bounds) ;
899
-
900
- // Calculate the translation needed to center the parent
901
- let translation = viewport_bounds. center ( ) - quad. center ( ) ;
902
- let centering_transform = quad
903
- . 0
904
- . into_iter ( )
905
- . all ( |point| !viewport_bounds. contains ( point) )
906
- . then_some ( glam:: DAffine2 :: from_translation ( translation. round ( ) ) ) ;
907
-
908
- let mut added_nodes = false ;
909
-
910
- for entry in data. into_iter ( ) . rev ( ) {
911
- if !added_nodes {
912
- responses. add ( DocumentMessage :: DeselectAllLayers ) ;
913
- responses. add ( DocumentMessage :: AddTransaction ) ;
914
- added_nodes = true ;
915
- }
894
+ let mut layers = Vec :: new ( ) ;
895
+
896
+ let mut added_nodes = false ;
897
+ for entry in data. into_iter ( ) . rev ( ) {
898
+ if !added_nodes {
899
+ responses. add ( DocumentMessage :: DeselectAllLayers ) ;
900
+ responses. add ( DocumentMessage :: AddTransaction ) ;
901
+ added_nodes = true ;
902
+ }
903
+
904
+ document. load_layer_resources ( responses) ;
905
+ let new_ids: HashMap < _ , _ > = entry. nodes . iter ( ) . map ( |( id, _) | ( * id, NodeId :: new ( ) ) ) . collect ( ) ;
906
+ let layer = LayerNodeIdentifier :: new_unchecked ( new_ids[ & NodeId ( 0 ) ] ) ;
907
+ responses. add ( NodeGraphMessage :: AddNodes { nodes : entry. nodes , new_ids } ) ;
908
+ responses. add ( NodeGraphMessage :: MoveLayerToStack { layer, parent, insert_index : 0 } ) ;
909
+ layers. push ( layer) ;
910
+ }
916
911
917
- document. load_layer_resources ( responses) ;
918
- let new_ids: HashMap < _ , _ > = entry. nodes . iter ( ) . map ( |( id, _) | ( * id, NodeId :: new ( ) ) ) . collect ( ) ;
919
- let layer = LayerNodeIdentifier :: new_unchecked ( new_ids[ & NodeId ( 0 ) ] ) ;
920
- responses. add ( NodeGraphMessage :: AddNodes { nodes : entry. nodes , new_ids } ) ;
921
- responses. add ( NodeGraphMessage :: MoveLayerToStack { layer, parent, insert_index : 0 } ) ;
922
-
923
- // Apply the same translation to all layers
924
- if let Some ( transform) = centering_transform {
925
- responses. add ( GraphOperationMessage :: TransformChange {
926
- layer,
927
- transform,
928
- transform_in : TransformIn :: Viewport ,
929
- skip_rerender : false ,
930
- } ) ;
912
+ responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
913
+ responses. add ( PortfolioMessage :: CenterPastedLayers { layers } ) ;
914
+ }
915
+ }
916
+ }
917
+ PortfolioMessage :: CenterPastedLayers { layers } => {
918
+ use crate :: messages:: portfolio:: document:: graph_operation:: transform_utils;
919
+ if let Some ( document) = self . active_document_mut ( ) {
920
+ let viewport_bounds = Quad :: from_box_at_zero ( ipp. viewport_bounds . size ( ) ) ;
921
+ let viewport_center = viewport_bounds. center ( ) ;
922
+
923
+ let mut positions = Vec :: new ( ) ;
924
+
925
+ for layer in & layers {
926
+ if let Some ( mut modify_inputs) = ModifyInputsContext :: new_with_layer ( * layer, & mut document. network_interface , responses) {
927
+ if let Some ( transform_node_id) = modify_inputs. existing_node_id ( "Transform" , true ) {
928
+ if let Some ( network) = modify_inputs. network_interface . network ( & [ ] ) {
929
+ if let Some ( node) = network. nodes . get ( & transform_node_id) {
930
+ let current_transform = transform_utils:: get_current_transform ( & node. inputs ) ;
931
+ positions. push ( ( * layer, current_transform. translation ) ) ;
932
+ }
931
933
}
932
934
}
933
- responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
934
935
}
935
936
}
937
+
938
+ if !positions. is_empty ( ) {
939
+ let mean_pos = positions. iter ( ) . fold ( glam:: DVec2 :: ZERO , |acc, ( _, pos) | acc + * pos) / positions. len ( ) as f64 ;
940
+ let mut transform = document. metadata ( ) . document_to_viewport ;
941
+
942
+ // Center each layer maintaining relative positions
943
+ for ( layer, pos) in positions {
944
+ let offset_from_center = pos - mean_pos;
945
+ let new_pos = viewport_center + transform. transform_vector2 ( offset_from_center) ;
946
+ transform. translation = new_pos;
947
+
948
+ responses. add ( GraphOperationMessage :: TransformSet {
949
+ layer,
950
+ transform,
951
+ transform_in : TransformIn :: Viewport ,
952
+ skip_rerender : false ,
953
+ } ) ;
954
+ }
955
+ responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
956
+ }
936
957
}
937
958
}
938
959
PortfolioMessage :: PasteImage {
0 commit comments