@@ -2,12 +2,14 @@ use super::graph_modification_utils::{self, merge_layers};
22use super :: snapping:: { SnapCache , SnapCandidatePoint , SnapData , SnapManager , SnappedPoint } ;
33use super :: utility_functions:: calculate_segment_angle;
44use crate :: consts:: HANDLE_LENGTH_FACTOR ;
5+ use crate :: messages:: portfolio:: document:: overlays:: utility_functions:: selected_segments;
56use crate :: messages:: portfolio:: document:: utility_types:: document_metadata:: { DocumentMetadata , LayerNodeIdentifier } ;
67use crate :: messages:: portfolio:: document:: utility_types:: misc:: { PathSnapSource , SnapSource } ;
78use crate :: messages:: portfolio:: document:: utility_types:: network_interface:: NodeNetworkInterface ;
89use crate :: messages:: prelude:: * ;
910use 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 } ;
1113use bezier_rs:: { Bezier , BezierHandles , Subpath , TValue } ;
1214use glam:: { DAffine2 , DVec2 } ;
1315use graphene_core:: transform:: Transform ;
@@ -421,12 +423,20 @@ impl ShapeState {
421423
422424 /// Select/deselect the first point within the selection threshold.
423425 /// 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 > > {
425435 if self . selected_shape_state . is_empty ( ) {
426436 return None ;
427437 }
428438
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 ) {
430440 let vector_data = network_interface. compute_modified_vector ( layer) ?;
431441 let point_position = manipulator_point_id. get_position ( & vector_data) ?;
432442
@@ -467,7 +477,14 @@ impl ShapeState {
467477 None
468478 }
469479
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 > ) > {
471488 if self . selected_shape_state . is_empty ( ) {
472489 return None ;
473490 }
@@ -476,6 +493,13 @@ impl ShapeState {
476493 let vector_data = network_interface. compute_modified_vector ( layer) ?;
477494 let point_position = manipulator_point_id. get_position ( & vector_data) ?;
478495
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+
479503 let selected_shape_state = self . selected_shape_state . get ( & layer) ?;
480504 let already_selected = selected_shape_state. is_selected ( manipulator_point_id) ;
481505
@@ -1320,6 +1344,42 @@ impl ShapeState {
13201344 None
13211345 }
13221346
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+
13231383 // TODO Use quadtree or some equivalent spatial acceleration structure to improve this to O(log(n))
13241384 /// Find the closest manipulator, manipulator point, and distance so we can select path elements.
13251385 /// Brute force comparison to determine which manipulator (handle or anchor) we want to select taking O(n) time.
@@ -1623,7 +1683,17 @@ impl ShapeState {
16231683 false
16241684 }
16251685
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+
16271697 for ( & layer, state) in & mut self . selected_shape_state {
16281698 if selection_change == SelectionChange :: Clear {
16291699 state. clear_points ( )
@@ -1666,13 +1736,17 @@ impl ShapeState {
16661736 } ;
16671737
16681738 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+ }
16761750 }
16771751 }
16781752 }
0 commit comments