@@ -1525,96 +1525,87 @@ async fn jitter_points(_: impl Ctx, vector_data: VectorDataTable, #[default(5.)]
1525
1525
}
1526
1526
1527
1527
#[ 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
+
1529
1532
let time = time. clamp ( 0. , 1. ) ;
1530
1533
1534
+ let mut result_table = VectorDataTable :: default ( ) ;
1535
+
1536
+ // Lerp styles
1531
1537
let source_alpha_blending = source. one_instance_ref ( ) . alpha_blending ;
1532
1538
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) ;
1533
1541
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 ;
1539
1545
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) {
1550
1550
source_path. apply_transform ( source_transform) ;
1551
1551
target_path. apply_transform ( target_transform) ;
1552
1552
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 } ) ;
1563
1557
}
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 } ) ;
1567
1561
}
1568
1562
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) ) ;
1586
1572
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) ) ;
1592
1576
}
1593
1577
1594
- result . one_instance_mut ( ) . instance . append_subpath ( source_path, true ) ;
1578
+ result_table . one_instance_mut ( ) . instance . append_subpath ( source_path. clone ( ) , true ) ;
1595
1579
}
1596
1580
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
+
1598
1587
for mut source_path in source_paths {
1599
1588
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 ( ) ;
1601
1590
for group in source_path. manipulator_groups_mut ( ) {
1602
1591
group. anchor = group. anchor . lerp ( end, time) ;
1603
1592
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) ) ;
1605
1594
}
1595
+ result_table. one_instance_mut ( ) . instance . append_subpath ( source_path, true ) ;
1606
1596
}
1607
1597
for mut target_path in target_paths {
1608
1598
target_path. apply_transform ( target_transform) ;
1609
1599
let start = target_path. manipulator_groups ( ) . first ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
1610
1600
for group in target_path. manipulator_groups_mut ( ) {
1611
1601
group. anchor = start. lerp ( group. anchor , time) ;
1612
1602
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) ) ;
1614
1604
}
1605
+ result_table. one_instance_mut ( ) . instance . append_subpath ( target_path, true ) ;
1615
1606
}
1616
1607
1617
- result
1608
+ result_table
1618
1609
}
1619
1610
1620
1611
fn bevel_algorithm ( mut vector_data : VectorData , vector_data_transform : DAffine2 , distance : f64 ) -> VectorData {
@@ -1978,7 +1969,7 @@ mod test {
1978
1969
async fn morph ( ) {
1979
1970
let source = Subpath :: new_rect ( DVec2 :: ZERO , DVec2 :: ONE * 100. ) ;
1980
1971
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 ;
1982
1973
let sample_points = sample_points. instance_ref_iter ( ) . next ( ) . unwrap ( ) . instance ;
1983
1974
assert_eq ! (
1984
1975
& sample_points. point_domain. positions( ) [ ..4 ] ,
0 commit comments