@@ -9,8 +9,11 @@ use glam::{DVec2, IVec2};
99use graph_craft:: document:: DocumentNode ;
1010use graph_craft:: document:: { DocumentNodeImplementation , NodeInput , value:: TaggedValue } ;
1111use graphene_std:: ProtoNodeIdentifier ;
12+ use graphene_std:: subpath:: Subpath ;
13+ use graphene_std:: table:: Table ;
1214use graphene_std:: text:: { TextAlign , TypesettingConfig } ;
1315use graphene_std:: uuid:: NodeId ;
16+ use graphene_std:: vector:: Vector ;
1417use graphene_std:: vector:: style:: { PaintOrder , StrokeAlign } ;
1518use std:: collections:: HashMap ;
1619use std:: f64:: consts:: PI ;
@@ -1055,6 +1058,82 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
10551058 document. network_interface . set_input ( & InputConnector :: node ( * node_id, 9 ) , old_inputs[ 4 ] . clone ( ) , network_path) ;
10561059 }
10571060
1061+ // Upgrade the old "Spline" node to the new "Spline" node
1062+ if reference == & DefinitionIdentifier :: ProtoNode ( graphene_std:: vector:: spline:: IDENTIFIER )
1063+ || reference == & DefinitionIdentifier :: ProtoNode ( ProtoNodeIdentifier :: new ( "graphene_core::vector::generator_nodes::SplineNode" ) )
1064+ || reference == & DefinitionIdentifier :: ProtoNode ( ProtoNodeIdentifier :: new ( "graphene_core::vector::SplineNode" ) )
1065+ || reference == & DefinitionIdentifier :: ProtoNode ( ProtoNodeIdentifier :: new ( "graphene_core::vector::SplinesFromPointsNode" ) )
1066+ {
1067+ // Retrieve the proto node identifier and verify it is the old "Spline" node, otherwise skip it if this is the new "Spline" node
1068+ let identifier = document
1069+ . network_interface
1070+ . implementation ( node_id, network_path)
1071+ . and_then ( |implementation| implementation. get_proto_node ( ) ) ;
1072+ if identifier. map ( |identifier| & identifier. name ) != Some ( & "graphene_core::vector::generator_nodes::SplineNode" . into ( ) ) {
1073+ return None ;
1074+ }
1075+
1076+ // Obtain the document node for the given node ID, extract the vector points, and create a Vector path from the list of points
1077+ let node = document. network_interface . document_node ( node_id, network_path) ?;
1078+ let Some ( TaggedValue :: VecDVec2 ( points) ) = node. inputs . get ( 1 ) . and_then ( |tagged_value| tagged_value. as_value ( ) ) else {
1079+ log:: error!( "The old Spline node's input at index 1 is not a TaggedValue::VecDVec2" ) ;
1080+ return None ;
1081+ } ;
1082+ let vector = Vector :: from_subpath ( Subpath :: from_anchors_linear ( points. to_vec ( ) , false ) ) ;
1083+
1084+ // Retrieve the output connectors linked to the "Spline" node's output connector
1085+ let Some ( spline_outputs) = document. network_interface . outward_wires ( network_path) ?. get ( & OutputConnector :: node ( * node_id, 0 ) ) . cloned ( ) else {
1086+ log:: error!( "Vec of InputConnector Spline node is connected to its output connector 0." ) ;
1087+ return None ;
1088+ } ;
1089+
1090+ // Get the node's current position in the graph
1091+ let Some ( node_position) = document. network_interface . position ( node_id, network_path) else {
1092+ log:: error!( "Could not get position of spline node." ) ;
1093+ return None ;
1094+ } ;
1095+
1096+ // Get the "Path" node definition and fill it in with the Vector path and default vector modification
1097+ let Some ( path_node_type) = resolve_document_node_type ( & DefinitionIdentifier :: Network ( "Path" . to_string ( ) ) ) else {
1098+ log:: error!( "Path node does not exist." ) ;
1099+ return None ;
1100+ } ;
1101+ let path_node = path_node_type. node_template_input_override ( [
1102+ Some ( NodeInput :: value ( TaggedValue :: Vector ( Table :: new_from_element ( vector) ) , true ) ) ,
1103+ Some ( NodeInput :: value ( TaggedValue :: VectorModification ( Default :: default ( ) ) , false ) ) ,
1104+ ] ) ;
1105+
1106+ // Get the "Spline" node definition and wire it up with the "Path" node as input
1107+ let Some ( spline_node_type) = resolve_document_node_type ( & DefinitionIdentifier :: ProtoNode ( graphene_std:: vector:: spline:: IDENTIFIER ) ) else {
1108+ log:: error!( "Spline node does not exist." ) ;
1109+ return None ;
1110+ } ;
1111+ let spline_node = spline_node_type. node_template_input_override ( [ Some ( NodeInput :: node ( NodeId ( 1 ) , 0 ) ) ] ) ;
1112+
1113+ // Create a new node group with the "Path" and "Spline" nodes and generate new node IDs for them
1114+ let nodes = vec ! [ ( NodeId ( 1 ) , path_node) , ( NodeId ( 0 ) , spline_node) ] ;
1115+ let new_ids = nodes. iter ( ) . map ( |( id, _) | ( * id, NodeId :: new ( ) ) ) . collect :: < HashMap < _ , _ > > ( ) ;
1116+ let new_spline_id = * new_ids. get ( & NodeId ( 0 ) ) ?;
1117+ let new_path_id = * new_ids. get ( & NodeId ( 1 ) ) ?;
1118+
1119+ // Remove the old "Spline" node from the document
1120+ document. network_interface . delete_nodes ( vec ! [ * node_id] , false , network_path) ;
1121+
1122+ // Insert the new "Path" and "Spline" nodes into the network interface with generated IDs
1123+ document. network_interface . insert_node_group ( nodes. clone ( ) , new_ids, network_path) ;
1124+
1125+ // Reposition the new "Spline" node to match the original "Spline" node's position
1126+ document. network_interface . shift_node ( & new_spline_id, node_position, network_path) ;
1127+
1128+ // Reposition the new "Path" node with an offset relative to the original "Spline" node's position
1129+ document. network_interface . shift_node ( & new_path_id, node_position + IVec2 :: new ( -7 , 0 ) , network_path) ;
1130+
1131+ // Redirect each output connection from the old node to the new "Spline" node's output connector
1132+ for input_connector in spline_outputs {
1133+ document. network_interface . set_input ( & input_connector, NodeInput :: node ( new_spline_id, 0 ) , network_path) ;
1134+ }
1135+ }
1136+
10581137 // Upgrade Text node to include line height and character spacing, which were previously hardcoded to 1, from https://github.com/GraphiteEditor/Graphite/pull/2016
10591138 if reference == & DefinitionIdentifier :: Network ( "Text" . to_string ( ) ) && inputs_count != 11 {
10601139 let mut template: NodeTemplate = resolve_document_node_type ( & reference) ?. default_node_template ( ) ;
@@ -1279,6 +1358,19 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
12791358 document. network_interface . set_input ( & InputConnector :: node ( * node_id, 2 ) , old_inputs[ 3 ] . clone ( ) , network_path) ;
12801359 }
12811360
1361+ if reference == & DefinitionIdentifier :: ProtoNode ( ProtoNodeIdentifier :: new ( "graphene_core::vector::GenerateHandlesNode" ) ) {
1362+ let mut node_template = resolve_document_node_type ( & DefinitionIdentifier :: ProtoNode ( graphene_std:: vector:: auto_tangents:: IDENTIFIER ) ) ?. default_node_template ( ) ;
1363+ document. network_interface . replace_implementation ( node_id, network_path, & mut node_template) ;
1364+
1365+ let old_inputs = document. network_interface . replace_inputs ( node_id, network_path, & mut node_template) ?;
1366+
1367+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 0 ) , old_inputs[ 0 ] . clone ( ) , network_path) ;
1368+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 1 ) , old_inputs[ 1 ] . clone ( ) , network_path) ;
1369+ document
1370+ . network_interface
1371+ . set_input ( & InputConnector :: node ( * node_id, 2 ) , NodeInput :: value ( TaggedValue :: Bool ( true ) , false ) , network_path) ;
1372+ }
1373+
12821374 if reference == & DefinitionIdentifier :: ProtoNode ( graphene_std:: vector:: merge_by_distance:: IDENTIFIER ) && inputs_count == 2 {
12831375 let mut node_template = resolve_document_node_type ( & reference) ?. default_node_template ( ) ;
12841376 document. network_interface . replace_implementation ( node_id, network_path, & mut node_template) ;
0 commit comments