@@ -1525,96 +1525,87 @@ async fn jitter_points(_: impl Ctx, vector_data: VectorDataTable, #[default(5.)]
15251525}
15261526
15271527#[ node_macro:: node( category( "Vector" ) , path( graphene_core:: vector) ) ]
1528- async fn morph ( _: impl Ctx , source : VectorDataTable , #[ expose] target : VectorDataTable , #[ default( 0.5 ) ] time : Fraction , #[ min( 0. ) ] start_index : IntegerCount ) -> VectorDataTable {
1528+ async fn morph ( _: impl Ctx , source : VectorDataTable , #[ expose] target : VectorDataTable , #[ default( 0.5 ) ] time : Fraction ) -> VectorDataTable {
1529+ let mut source = source;
1530+ let mut target = target;
1531+
15291532 let time = time. clamp ( 0. , 1. ) ;
15301533
1534+ let mut result_table = VectorDataTable :: default ( ) ;
1535+
1536+ // Lerp styles
15311537 let source_alpha_blending = source. one_instance_ref ( ) . alpha_blending ;
15321538 let target_alpha_blending = target. one_instance_ref ( ) . alpha_blending ;
1539+ * result_table. one_instance_mut ( ) . alpha_blending = if time < 0.5 { * source_alpha_blending } else { * target_alpha_blending } ;
1540+ result_table. one_instance_mut ( ) . instance . style = source. one_instance_ref ( ) . instance . style . lerp ( & target. one_instance_ref ( ) . instance . style , time) ;
15331541
1534- let source_transform = source. transform ( ) ;
1535- let target_transform = target. transform ( ) ;
1536-
1537- let source = source. one_instance_ref ( ) . instance ;
1538- let target = target. one_instance_ref ( ) . instance ;
1542+ // Before and after transforms
1543+ let source_transform = * source. one_instance_ref ( ) . transform ;
1544+ let target_transform = * target. one_instance_ref ( ) . transform ;
15391545
1540- let mut result = VectorDataTable :: default ( ) ;
1541-
1542- // Lerp styles
1543- * result. one_instance_mut ( ) . alpha_blending = if time < 0.5 { * source_alpha_blending } else { * target_alpha_blending } ;
1544- result. one_instance_mut ( ) . instance . style = source. style . lerp ( & target. style , time) ;
1545-
1546- let mut source_paths = source. stroke_bezier_paths ( ) ;
1547- let mut target_paths = target. stroke_bezier_paths ( ) ;
1548- for ( mut source_path, mut target_path) in ( & mut source_paths) . zip ( & mut target_paths) {
1549- // Deal with mismatched transforms
1546+ // Before and after paths
1547+ let source_paths = source. one_instance_mut ( ) . instance . stroke_bezier_paths ( ) ;
1548+ let target_paths = target. one_instance_mut ( ) . instance . stroke_bezier_paths ( ) ;
1549+ for ( mut source_path, mut target_path) in source_paths. zip ( target_paths) {
15501550 source_path. apply_transform ( source_transform) ;
15511551 target_path. apply_transform ( target_transform) ;
15521552
1553- // Deal with mismatched start index
1554- for _ in 0 ..start_index {
1555- let first = target_path. remove_manipulator_group ( 0 ) ;
1556- target_path. push_manipulator_group ( first) ;
1557- }
1558-
1559- // Deal with mismatched closed state
1560- if source_path. closed ( ) && !target_path. closed ( ) {
1561- source_path. set_closed ( false ) ;
1562- source_path. push_manipulator_group ( source_path. manipulator_groups ( ) [ 0 ] . flip ( ) ) ;
1553+ // Align point counts by inserting mid‐segment points until their counts match
1554+ while source_path. manipulator_groups ( ) . len ( ) < target_path. manipulator_groups ( ) . len ( ) {
1555+ let last = source_path. len ( ) - 1 ;
1556+ source_path. insert ( SubpathTValue :: Parametric { segment_index : last, t : 0.5 } ) ;
15631557 }
1564- if !source_path . closed ( ) && target_path . closed ( ) {
1565- target_path. set_closed ( false ) ;
1566- target_path. push_manipulator_group ( target_path . manipulator_groups ( ) [ 0 ] . flip ( ) ) ;
1558+ while target_path . manipulator_groups ( ) . len ( ) < source_path . manipulator_groups ( ) . len ( ) {
1559+ let last = target_path. len ( ) - 1 ;
1560+ target_path. insert ( SubpathTValue :: Parametric { segment_index : last , t : 0.5 } ) ;
15671561 }
15681562
1569- // Mismatched subpath items
1570- ' outer: loop {
1571- for segment_index in ( 0 ..( source_path. len ( ) - 1 ) ) . rev ( ) {
1572- if target_path. len ( ) <= source_path. len ( ) {
1573- break ' outer;
1574- }
1575- source_path. insert ( SubpathTValue :: Parametric { segment_index, t : 0.5 } )
1576- }
1577- }
1578- ' outer: loop {
1579- for segment_index in ( 0 ..( target_path. len ( ) - 1 ) ) . rev ( ) {
1580- if source_path. len ( ) <= target_path. len ( ) {
1581- break ' outer;
1582- }
1583- target_path. insert ( SubpathTValue :: Parametric { segment_index, t : 0.5 } )
1584- }
1585- }
1563+ // Interpolate anchors and handles
1564+ for ( source_manipulators, target_manipulators) in source_path. manipulator_groups_mut ( ) . iter_mut ( ) . zip ( target_path. manipulator_groups ( ) ) {
1565+ let source_anchor = source_manipulators. anchor ;
1566+ let target_anchor = target_manipulators. anchor ;
1567+ source_manipulators. anchor = source_anchor. lerp ( target_anchor, time) ;
1568+
1569+ let source_in_handle = source_manipulators. in_handle . unwrap_or ( source_anchor) ;
1570+ let target_in_handle = target_manipulators. in_handle . unwrap_or ( target_anchor) ;
1571+ source_manipulators. in_handle = Some ( source_in_handle. lerp ( target_in_handle, time) ) ;
15861572
1587- // Lerp points
1588- for ( manipulator, target) in source_path. manipulator_groups_mut ( ) . iter_mut ( ) . zip ( target_path. manipulator_groups ( ) ) {
1589- manipulator. in_handle = Some ( manipulator. in_handle . unwrap_or ( manipulator. anchor ) . lerp ( target. in_handle . unwrap_or ( target. anchor ) , time) ) ;
1590- manipulator. out_handle = Some ( manipulator. out_handle . unwrap_or ( manipulator. anchor ) . lerp ( target. out_handle . unwrap_or ( target. anchor ) , time) ) ;
1591- manipulator. anchor = manipulator. anchor . lerp ( target. anchor , time) ;
1573+ let source_out_handle = source_manipulators. out_handle . unwrap_or ( source_anchor) ;
1574+ let target_out_handle = target_manipulators. out_handle . unwrap_or ( target_anchor) ;
1575+ source_manipulators. out_handle = Some ( source_out_handle. lerp ( target_out_handle, time) ) ;
15921576 }
15931577
1594- result . one_instance_mut ( ) . instance . append_subpath ( source_path, true ) ;
1578+ result_table . one_instance_mut ( ) . instance . append_subpath ( source_path. clone ( ) , true ) ;
15951579 }
15961580
1597- // Mismatched subpath count
1581+ // Deal with unmatched extra paths by collapsing them
1582+ let source_paths_count = source. one_instance_ref ( ) . instance . stroke_bezier_paths ( ) . count ( ) ;
1583+ let target_paths_count = target. one_instance_ref ( ) . instance . stroke_bezier_paths ( ) . count ( ) ;
1584+ let source_paths = source. one_instance_mut ( ) . instance . stroke_bezier_paths ( ) . skip ( target_paths_count) ;
1585+ let target_paths = target. one_instance_mut ( ) . instance . stroke_bezier_paths ( ) . skip ( source_paths_count) ;
1586+
15981587 for mut source_path in source_paths {
15991588 source_path. apply_transform ( source_transform) ;
1600- let end = source_path. manipulator_groups ( ) . first ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
1589+ let end = source_path. manipulator_groups ( ) . last ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
16011590 for group in source_path. manipulator_groups_mut ( ) {
16021591 group. anchor = group. anchor . lerp ( end, time) ;
16031592 group. in_handle = group. in_handle . map ( |handle| handle. lerp ( end, time) ) ;
1604- group. out_handle = group. in_handle . map ( |handle| handle. lerp ( end, time) ) ;
1593+ group. out_handle = group. out_handle . map ( |handle| handle. lerp ( end, time) ) ;
16051594 }
1595+ result_table. one_instance_mut ( ) . instance . append_subpath ( source_path, true ) ;
16061596 }
16071597 for mut target_path in target_paths {
16081598 target_path. apply_transform ( target_transform) ;
16091599 let start = target_path. manipulator_groups ( ) . first ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
16101600 for group in target_path. manipulator_groups_mut ( ) {
16111601 group. anchor = start. lerp ( group. anchor , time) ;
16121602 group. in_handle = group. in_handle . map ( |handle| start. lerp ( handle, time) ) ;
1613- group. out_handle = group. in_handle . map ( |handle| start. lerp ( handle, time) ) ;
1603+ group. out_handle = group. out_handle . map ( |handle| start. lerp ( handle, time) ) ;
16141604 }
1605+ result_table. one_instance_mut ( ) . instance . append_subpath ( target_path, true ) ;
16151606 }
16161607
1617- result
1608+ result_table
16181609}
16191610
16201611fn bevel_algorithm ( mut vector_data : VectorData , vector_data_transform : DAffine2 , distance : f64 ) -> VectorData {
@@ -1978,7 +1969,7 @@ mod test {
19781969 async fn morph ( ) {
19791970 let source = Subpath :: new_rect ( DVec2 :: ZERO , DVec2 :: ONE * 100. ) ;
19801971 let target = Subpath :: new_ellipse ( DVec2 :: NEG_ONE * 100. , DVec2 :: ZERO ) ;
1981- let sample_points = super :: morph ( Footprint :: default ( ) , vector_node ( source) , vector_node ( target) , 0.5 , 0 ) . await ;
1972+ let sample_points = super :: morph ( Footprint :: default ( ) , vector_node ( source) , vector_node ( target) , 0.5 ) . await ;
19821973 let sample_points = sample_points. instance_ref_iter ( ) . next ( ) . unwrap ( ) . instance ;
19831974 assert_eq ! (
19841975 & sample_points. point_domain. positions( ) [ ..4 ] ,
0 commit comments