@@ -1708,6 +1708,132 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
17081708 document. network_interface . set_input ( & InputConnector :: node ( * node_id, 1 ) , old_inputs[ 2 ] . clone ( ) , network_path) ;
17091709 }
17101710
1711+ // Migrate old Arrow node from (start, end, shaft_width, head_width, head_length) to (arrow_to, shaft_width, head_width, head_length) with a Transform node for positioning
1712+ if reference == DefinitionIdentifier :: ProtoNode ( graphene_std:: vector_nodes:: arrow:: IDENTIFIER ) && inputs_count == 6 {
1713+ // Read old start and end values
1714+ let start = match node. inputs . get ( 1 ) ? {
1715+ NodeInput :: Value { tagged_value, .. } => {
1716+ if let TaggedValue :: DVec2 ( v) = * tagged_value. clone ( ) . into_inner ( ) {
1717+ v
1718+ } else {
1719+ DVec2 :: ZERO
1720+ }
1721+ }
1722+ _ => DVec2 :: ZERO ,
1723+ } ;
1724+ let end = match node. inputs . get ( 2 ) ? {
1725+ NodeInput :: Value { tagged_value, .. } => {
1726+ if let TaggedValue :: DVec2 ( v) = * tagged_value. clone ( ) . into_inner ( ) {
1727+ v
1728+ } else {
1729+ DVec2 :: new ( 100. , 0. )
1730+ }
1731+ }
1732+ _ => DVec2 :: new ( 100. , 0. ) ,
1733+ } ;
1734+
1735+ // Replace inputs with the new node definition (primary + arrow_to + shaft_width + head_width + head_length)
1736+ let mut node_template = resolve_document_node_type ( & reference) ?. default_node_template ( ) ;
1737+ let old_inputs = document. network_interface . replace_inputs ( node_id, network_path, & mut node_template) ?;
1738+
1739+ // Preserve primary input connection
1740+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 0 ) , old_inputs[ 0 ] . clone ( ) , network_path) ;
1741+ // Set arrow_to = end - start
1742+ document
1743+ . network_interface
1744+ . set_input ( & InputConnector :: node ( * node_id, 1 ) , NodeInput :: value ( TaggedValue :: DVec2 ( end - start) , false ) , network_path) ;
1745+ // Preserve shaft_width, head_width, head_length (shifted from indices 3,4,5 to 2,3,4)
1746+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 2 ) , old_inputs[ 3 ] . clone ( ) , network_path) ;
1747+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 3 ) , old_inputs[ 4 ] . clone ( ) , network_path) ;
1748+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 4 ) , old_inputs[ 5 ] . clone ( ) , network_path) ;
1749+
1750+ // Find downstream connection to insert Transform node
1751+ let downstream = document
1752+ . network_interface
1753+ . outward_wires ( network_path)
1754+ . and_then ( |wires| wires. get ( & OutputConnector :: node ( * node_id, 0 ) ) )
1755+ . and_then ( |connections| connections. first ( ) . cloned ( ) ) ;
1756+
1757+ if let Some ( downstream_input) = downstream {
1758+ // Create a Transform node with translation = start
1759+ let Some ( transform_node_type) = resolve_network_node_type ( "Transform" ) else {
1760+ log:: error!( "Transform node definition not found during Arrow migration" ) ;
1761+ return None ;
1762+ } ;
1763+ let mut transform_template = transform_node_type. default_node_template ( ) ;
1764+ transform_template. document_node . inputs [ 1 ] = NodeInput :: value ( TaggedValue :: DVec2 ( start) , false ) ;
1765+
1766+ let transform_id = NodeId :: new ( ) ;
1767+
1768+ // Position the Transform node to the right of the Arrow node
1769+ let arrow_position = document. network_interface . position ( node_id, network_path) . unwrap_or_default ( ) ;
1770+ document. network_interface . insert_node ( transform_id, transform_template, network_path) ;
1771+ document. network_interface . shift_absolute_node_position ( & transform_id, arrow_position + IVec2 :: new ( 7 , 0 ) , network_path) ;
1772+ document. network_interface . insert_node_between ( & transform_id, & downstream_input, 0 , network_path) ;
1773+ }
1774+ }
1775+
1776+ // Migrate old Line node from (start, end) to (line_to) with a Transform node for positioning
1777+ if reference == DefinitionIdentifier :: ProtoNode ( graphene_std:: vector:: generator_nodes:: line:: IDENTIFIER ) && inputs_count == 3 {
1778+ // Read old start and end values
1779+ let start = match node. inputs . get ( 1 ) ? {
1780+ NodeInput :: Value { tagged_value, .. } => {
1781+ if let TaggedValue :: DVec2 ( v) = * tagged_value. clone ( ) . into_inner ( ) {
1782+ v
1783+ } else {
1784+ DVec2 :: ZERO
1785+ }
1786+ }
1787+ _ => DVec2 :: ZERO ,
1788+ } ;
1789+ let end = match node. inputs . get ( 2 ) ? {
1790+ NodeInput :: Value { tagged_value, .. } => {
1791+ if let TaggedValue :: DVec2 ( v) = * tagged_value. clone ( ) . into_inner ( ) {
1792+ v
1793+ } else {
1794+ DVec2 :: new ( 100. , 100. )
1795+ }
1796+ }
1797+ _ => DVec2 :: new ( 100. , 100. ) ,
1798+ } ;
1799+
1800+ // Replace inputs with the new node definition (primary + line_to)
1801+ let mut node_template = resolve_document_node_type ( & reference) ?. default_node_template ( ) ;
1802+ let old_inputs = document. network_interface . replace_inputs ( node_id, network_path, & mut node_template) ?;
1803+
1804+ // Preserve primary input connection
1805+ document. network_interface . set_input ( & InputConnector :: node ( * node_id, 0 ) , old_inputs[ 0 ] . clone ( ) , network_path) ;
1806+ // Set line_to = end - start
1807+ document
1808+ . network_interface
1809+ . set_input ( & InputConnector :: node ( * node_id, 1 ) , NodeInput :: value ( TaggedValue :: DVec2 ( end - start) , false ) , network_path) ;
1810+
1811+ // Find downstream connection to insert Transform node
1812+ let downstream = document
1813+ . network_interface
1814+ . outward_wires ( network_path)
1815+ . and_then ( |wires| wires. get ( & OutputConnector :: node ( * node_id, 0 ) ) )
1816+ . and_then ( |connections| connections. first ( ) . cloned ( ) ) ;
1817+
1818+ if let Some ( downstream_input) = downstream {
1819+ // Create a Transform node with translation = start
1820+ let Some ( transform_node_type) = resolve_network_node_type ( "Transform" ) else {
1821+ log:: error!( "Transform node definition not found during Line migration" ) ;
1822+ return None ;
1823+ } ;
1824+ let mut transform_template = transform_node_type. default_node_template ( ) ;
1825+ transform_template. document_node . inputs [ 1 ] = NodeInput :: value ( TaggedValue :: DVec2 ( start) , false ) ;
1826+
1827+ let transform_id = NodeId :: new ( ) ;
1828+
1829+ // Position the Transform node to the right of the Line node
1830+ let line_position = document. network_interface . position ( node_id, network_path) . unwrap_or_default ( ) ;
1831+ document. network_interface . insert_node ( transform_id, transform_template, network_path) ;
1832+ document. network_interface . shift_absolute_node_position ( & transform_id, line_position + IVec2 :: new ( 7 , 0 ) , network_path) ;
1833+ document. network_interface . insert_node_between ( & transform_id, & downstream_input, 0 , network_path) ;
1834+ }
1835+ }
1836+
17111837 // Add context features to nodes that don't have them (fine-grained context caching migration)
17121838 if node. context_features == graphene_std:: ContextDependencies :: default ( )
17131839 && let Some ( reference) = document. network_interface . reference ( node_id, network_path) . clone ( )
0 commit comments