@@ -2,12 +2,14 @@ use super::graph_modification_utils::{self, merge_layers};
2
2
use super :: snapping:: { SnapCache , SnapCandidatePoint , SnapData , SnapManager , SnappedPoint } ;
3
3
use super :: utility_functions:: calculate_segment_angle;
4
4
use crate :: consts:: HANDLE_LENGTH_FACTOR ;
5
+ use crate :: messages:: portfolio:: document:: overlays:: utility_functions:: selected_segments;
5
6
use crate :: messages:: portfolio:: document:: utility_types:: document_metadata:: { DocumentMetadata , LayerNodeIdentifier } ;
6
7
use crate :: messages:: portfolio:: document:: utility_types:: misc:: { PathSnapSource , SnapSource } ;
7
8
use crate :: messages:: portfolio:: document:: utility_types:: network_interface:: NodeNetworkInterface ;
8
9
use crate :: messages:: prelude:: * ;
9
10
use crate :: messages:: tool:: common_functionality:: snapping:: SnapTypeConfiguration ;
10
- use crate :: messages:: tool:: tool_messages:: path_tool:: PointSelectState ;
11
+ use crate :: messages:: tool:: common_functionality:: utility_functions:: is_visible_point;
12
+ use crate :: messages:: tool:: tool_messages:: path_tool:: { PathOverlayMode , PointSelectState } ;
11
13
use bezier_rs:: { Bezier , BezierHandles , Subpath , TValue } ;
12
14
use glam:: { DAffine2 , DVec2 } ;
13
15
use graphene_core:: transform:: Transform ;
@@ -421,12 +423,20 @@ impl ShapeState {
421
423
422
424
/// Select/deselect the first point within the selection threshold.
423
425
/// Returns a tuple of the points if found and the offset, or `None` otherwise.
424
- pub fn change_point_selection ( & mut self , network_interface : & NodeNetworkInterface , mouse_position : DVec2 , select_threshold : f64 , extend_selection : bool ) -> Option < Option < SelectedPointsInfo > > {
426
+ pub fn change_point_selection (
427
+ & mut self ,
428
+ network_interface : & NodeNetworkInterface ,
429
+ mouse_position : DVec2 ,
430
+ select_threshold : f64 ,
431
+ extend_selection : bool ,
432
+ path_overlay_mode : PathOverlayMode ,
433
+ frontier_handles_info : Option < HashMap < SegmentId , Vec < PointId > > > ,
434
+ ) -> Option < Option < SelectedPointsInfo > > {
425
435
if self . selected_shape_state . is_empty ( ) {
426
436
return None ;
427
437
}
428
438
429
- if let Some ( ( layer, manipulator_point_id) ) = self . find_nearest_point_indices ( network_interface, mouse_position, select_threshold) {
439
+ if let Some ( ( layer, manipulator_point_id) ) = self . find_nearest_visible_point_indices ( network_interface, mouse_position, select_threshold, path_overlay_mode , frontier_handles_info ) {
430
440
let vector_data = network_interface. compute_modified_vector ( layer) ?;
431
441
let point_position = manipulator_point_id. get_position ( & vector_data) ?;
432
442
@@ -467,7 +477,14 @@ impl ShapeState {
467
477
None
468
478
}
469
479
470
- pub fn get_point_selection_state ( & mut self , network_interface : & NodeNetworkInterface , mouse_position : DVec2 , select_threshold : f64 ) -> Option < ( bool , Option < SelectedPointsInfo > ) > {
480
+ pub fn get_point_selection_state (
481
+ & mut self ,
482
+ network_interface : & NodeNetworkInterface ,
483
+ mouse_position : DVec2 ,
484
+ select_threshold : f64 ,
485
+ path_overlay_mode : PathOverlayMode ,
486
+ frontier_handles_info : Option < HashMap < SegmentId , Vec < PointId > > > ,
487
+ ) -> Option < ( bool , Option < SelectedPointsInfo > ) > {
471
488
if self . selected_shape_state . is_empty ( ) {
472
489
return None ;
473
490
}
@@ -476,6 +493,13 @@ impl ShapeState {
476
493
let vector_data = network_interface. compute_modified_vector ( layer) ?;
477
494
let point_position = manipulator_point_id. get_position ( & vector_data) ?;
478
495
496
+ // Check if point is visible under current overlay mode or not
497
+ let selected_segments = selected_segments ( network_interface, self ) ;
498
+ let selected_points = self . selected_points ( ) . cloned ( ) . collect :: < HashSet < _ > > ( ) ;
499
+ if !is_visible_point ( manipulator_point_id, & vector_data, path_overlay_mode, frontier_handles_info, selected_segments, & selected_points) {
500
+ return None ;
501
+ }
502
+
479
503
let selected_shape_state = self . selected_shape_state . get ( & layer) ?;
480
504
let already_selected = selected_shape_state. is_selected ( manipulator_point_id) ;
481
505
@@ -1320,6 +1344,42 @@ impl ShapeState {
1320
1344
None
1321
1345
}
1322
1346
1347
+ pub fn find_nearest_visible_point_indices (
1348
+ & mut self ,
1349
+ network_interface : & NodeNetworkInterface ,
1350
+ mouse_position : DVec2 ,
1351
+ select_threshold : f64 ,
1352
+ path_overlay_mode : PathOverlayMode ,
1353
+ frontier_handles_info : Option < HashMap < SegmentId , Vec < PointId > > > ,
1354
+ ) -> Option < ( LayerNodeIdentifier , ManipulatorPointId ) > {
1355
+ if self . selected_shape_state . is_empty ( ) {
1356
+ return None ;
1357
+ }
1358
+
1359
+ let select_threshold_squared = select_threshold. powi ( 2 ) ;
1360
+
1361
+ // Find the closest control point among all elements of shapes_to_modify
1362
+ for & layer in self . selected_shape_state . keys ( ) {
1363
+ if let Some ( ( manipulator_point_id, distance_squared) ) = Self :: closest_point_in_layer ( network_interface, layer, mouse_position) {
1364
+ // Choose the first point under the threshold
1365
+ if distance_squared < select_threshold_squared {
1366
+ // Check if point is visible in current PathOverlayMode
1367
+ let vector_data = network_interface. compute_modified_vector ( layer) ?;
1368
+ let selected_segments = selected_segments ( network_interface, self ) ;
1369
+ let selected_points = self . selected_points ( ) . cloned ( ) . collect :: < HashSet < _ > > ( ) ;
1370
+
1371
+ if !is_visible_point ( manipulator_point_id, & vector_data, path_overlay_mode, frontier_handles_info, selected_segments, & selected_points) {
1372
+ return None ;
1373
+ }
1374
+
1375
+ return Some ( ( layer, manipulator_point_id) ) ;
1376
+ }
1377
+ }
1378
+ }
1379
+
1380
+ None
1381
+ }
1382
+
1323
1383
// TODO Use quadtree or some equivalent spatial acceleration structure to improve this to O(log(n))
1324
1384
/// Find the closest manipulator, manipulator point, and distance so we can select path elements.
1325
1385
/// Brute force comparison to determine which manipulator (handle or anchor) we want to select taking O(n) time.
@@ -1623,7 +1683,17 @@ impl ShapeState {
1623
1683
false
1624
1684
}
1625
1685
1626
- pub fn select_all_in_shape ( & mut self , network_interface : & NodeNetworkInterface , selection_shape : SelectionShape , selection_change : SelectionChange ) {
1686
+ pub fn select_all_in_shape (
1687
+ & mut self ,
1688
+ network_interface : & NodeNetworkInterface ,
1689
+ selection_shape : SelectionShape ,
1690
+ selection_change : SelectionChange ,
1691
+ path_overlay_mode : PathOverlayMode ,
1692
+ frontier_handles_info : Option < HashMap < SegmentId , Vec < PointId > > > ,
1693
+ ) {
1694
+ let selected_points = self . selected_points ( ) . cloned ( ) . collect :: < HashSet < _ > > ( ) ;
1695
+ let selected_segments = selected_segments ( network_interface, self ) ;
1696
+
1627
1697
for ( & layer, state) in & mut self . selected_shape_state {
1628
1698
if selection_change == SelectionChange :: Clear {
1629
1699
state. clear_points ( )
@@ -1666,13 +1736,17 @@ impl ShapeState {
1666
1736
} ;
1667
1737
1668
1738
if select {
1669
- match selection_change {
1670
- SelectionChange :: Shrink => state. deselect_point ( id) ,
1671
- _ => {
1672
- // Select only the handles which are of nonzero length
1673
- if let Some ( handle) = id. as_handle ( ) {
1674
- if handle. length ( & vector_data) > 0. {
1675
- state. select_point ( id)
1739
+ let is_visible_handle = is_visible_point ( id, & vector_data, path_overlay_mode, frontier_handles_info. clone ( ) , selected_segments. clone ( ) , & selected_points) ;
1740
+
1741
+ if is_visible_handle {
1742
+ match selection_change {
1743
+ SelectionChange :: Shrink => state. deselect_point ( id) ,
1744
+ _ => {
1745
+ // Select only the handles which are of nonzero length
1746
+ if let Some ( handle) = id. as_handle ( ) {
1747
+ if handle. length ( & vector_data) > 0. {
1748
+ state. select_point ( id)
1749
+ }
1676
1750
}
1677
1751
}
1678
1752
}
0 commit comments