@@ -342,33 +342,42 @@ async fn mirror<I: 'n + Send>(
342
342
#[ implementations( VectorDataTable , GraphicGroupTable ) ] instance : Instances < I > ,
343
343
#[ default( 0. , 0. ) ] center : DVec2 ,
344
344
#[ range( ( -90. , 90. ) ) ] angle : Angle ,
345
+ #[ default( true ) ] keep_original : bool ,
345
346
) -> GraphicGroupTable
346
347
where
347
348
Instances < I > : GraphicElementRendered ,
348
349
{
349
350
let mut result_table = GraphicGroupTable :: default ( ) ;
350
- let Some ( bounding_box ) = instance . bounding_box ( DAffine2 :: IDENTITY ) else { return result_table } ;
351
+
351
352
// The mirror center is based on the bounding box for now
353
+ let Some ( bounding_box) = instance. bounding_box ( DAffine2 :: IDENTITY ) else { return result_table } ;
352
354
let mirror_center = ( bounding_box[ 0 ] + bounding_box[ 1 ] ) / 2. + center;
353
- // Normalize direction vector
355
+
356
+ // Normalize the direction vector
354
357
let normal = DVec2 :: from_angle ( angle. to_radians ( ) ) ;
355
- // Create reflection matrix
358
+
359
+ // Create the reflection matrix
356
360
let reflection = DAffine2 :: from_mat2_translation (
357
361
glam:: DMat2 :: from_cols (
358
362
DVec2 :: new ( 1. - 2. * normal. x * normal. x , -2. * normal. y * normal. x ) ,
359
363
DVec2 :: new ( -2. * normal. x * normal. y , 1. - 2. * normal. y * normal. y ) ,
360
364
) ,
361
365
DVec2 :: ZERO ,
362
366
) ;
367
+
363
368
// Apply reflection around the center point
364
369
let modification = DAffine2 :: from_translation ( mirror_center) * reflection * DAffine2 :: from_translation ( -mirror_center) ;
365
- // Add original instance to result
366
- let original_element = instance. to_graphic_element ( ) . clone ( ) ;
367
- result_table. push ( original_element) ;
370
+
371
+ // Add original instance depending on the keep_original flag
372
+ if keep_original {
373
+ result_table. push ( instance. to_graphic_element ( ) ) ;
374
+ }
375
+
368
376
// Create and add mirrored instance
369
- let mut mirrored_element = instance. to_graphic_element ( ) . clone ( ) ;
377
+ let mut mirrored_element = instance. to_graphic_element ( ) ;
370
378
mirrored_element. new_ids_from_hash ( None ) ;
371
- // Finally, apply the transformation to the mirrored instance
379
+
380
+ // Apply the transformation to the mirrored instance
372
381
let mirrored_instance = result_table. push ( mirrored_element) ;
373
382
* mirrored_instance. transform = modification;
374
383
@@ -393,6 +402,7 @@ async fn round_corners(
393
402
let source_transform = source. transform ( ) ;
394
403
let source_transform_inverse = source_transform. inverse ( ) ;
395
404
let source = source. one_instance ( ) . instance ;
405
+ let upstream_graphics_group = source. upstream_graphic_group . clone ( ) ;
396
406
397
407
// Flip the roundness to help with user intuition
398
408
let roundness = 1. - roundness;
@@ -402,11 +412,14 @@ async fn round_corners(
402
412
let mut result = VectorData :: empty ( ) ;
403
413
result. style = source. style . clone ( ) ;
404
414
415
+ // Grab the initial point ID as a stable starting point
416
+ let mut initial_point_id = source. point_domain . ids ( ) . first ( ) . copied ( ) . unwrap_or ( PointId :: generate ( ) ) ;
417
+
405
418
for mut subpath in source. stroke_bezier_paths ( ) {
406
419
subpath. apply_transform ( source_transform) ;
407
420
421
+ // End if not enough points for corner rounding
408
422
if subpath. manipulator_groups ( ) . len ( ) < 3 {
409
- // Not enough points for corner rounding
410
423
result. append_subpath ( subpath, false ) ;
411
424
continue ;
412
425
}
@@ -450,28 +463,30 @@ async fn round_corners(
450
463
let p1 = curr - dir1 * distance_along_edge;
451
464
let p2 = curr + dir2 * distance_along_edge;
452
465
453
- // Add first point with out handle
466
+ // Add first point (coming into the rounded corner)
454
467
new_groups. push ( ManipulatorGroup {
455
468
anchor : p1,
456
469
in_handle : None ,
457
470
out_handle : Some ( curr - dir1 * distance_along_edge * roundness) ,
458
- id : PointId :: generate ( ) ,
471
+ id : initial_point_id . next_id ( ) ,
459
472
} ) ;
460
473
461
- // Add second point with in handle
474
+ // Add second point (coming out of the rounded corner)
462
475
new_groups. push ( ManipulatorGroup {
463
476
anchor : p2,
464
477
in_handle : Some ( curr + dir2 * distance_along_edge * roundness) ,
465
478
out_handle : None ,
466
- id : PointId :: generate ( ) ,
479
+ id : initial_point_id . next_id ( ) ,
467
480
} ) ;
468
481
}
469
482
483
+ // One subpath for each shape
470
484
let mut rounded_subpath = Subpath :: new ( new_groups, is_closed) ;
471
485
rounded_subpath. apply_transform ( source_transform_inverse) ;
472
486
result. append_subpath ( rounded_subpath, false ) ;
473
487
}
474
488
489
+ result. upstream_graphic_group = upstream_graphics_group;
475
490
let mut result_table = VectorDataTable :: new ( result) ;
476
491
* result_table. transform_mut ( ) = source_transform;
477
492
result_table
0 commit comments