1- use std:: f64:: consts:: PI ;
1+ use std:: { collections :: HashMap , f64:: consts:: PI } ;
22
3+ use super :: DocumentMessageHandler ;
34use glam:: { DAffine2 , DVec2 } ;
45use graphene:: {
56 layers:: style:: { self , Stroke } ,
@@ -11,41 +12,40 @@ use crate::{
1112 message_prelude:: * ,
1213} ;
1314
14- use super :: DocumentMessageHandler ;
15-
1615#[ derive( Debug , Clone , Default ) ]
1716pub struct SnapHandler {
17+ enabled : bool ,
18+ document : DocumentMessageHandler ,
1819 snap_targets : Option < ( Vec < f64 > , Vec < f64 > ) > ,
20+ snappables : HashMap < Vec < LayerId > , Vec < Vec < LayerId > > > ,
21+ overlay_messages : Vec < Message > ,
22+
1923 overlay_paths : Vec < Vec < LayerId > > ,
2024}
2125
2226impl SnapHandler {
23- fn add_overlays ( & mut self , responses : & mut VecDeque < Message > , viewport_bounds : DVec2 ) {
24- fn add_overlay_line ( responses : & mut VecDeque < Message > , transform : DAffine2 ) -> Vec < LayerId > {
25- let layer_path = vec ! [ generate_uuid( ) ] ;
26-
27- let operation = Operation :: AddOverlayLine {
28- path : layer_path. clone ( ) ,
29- transform : transform. to_cols_array ( ) ,
30- style : style:: PathStyle :: new ( Some ( Stroke :: new ( COLOR_ACCENT , 1.0 ) ) , None ) ,
31- } ;
32- responses. push_back ( DocumentMessage :: Overlay ( operation. into ( ) ) . into ( ) ) ;
33-
34- layer_path
35- }
27+ fn add_overlay_line ( & mut self , transform : DAffine2 ) -> Vec < LayerId > {
28+ let layer_path = vec ! [ generate_uuid( ) ] ;
29+
30+ let operation = Operation :: AddOverlayLine {
31+ path : layer_path. clone ( ) ,
32+ transform : transform. to_cols_array ( ) ,
33+ style : style:: PathStyle :: new ( Some ( Stroke :: new ( COLOR_ACCENT , 1.0 ) ) , None ) ,
34+ } ;
35+ self . overlay_messages . push ( DocumentMessage :: Overlay ( operation. into ( ) ) . into ( ) ) ;
36+
37+ layer_path
38+ }
3639
40+ fn add_overlays ( & mut self , viewport_bounds : DVec2 ) {
3741 if let Some ( ( x_targets, y_targets) ) = & self . snap_targets {
3842 for x_target in x_targets {
39- self . overlay_paths . push ( add_overlay_line (
40- responses,
41- DAffine2 :: from_scale_angle_translation ( DVec2 :: new ( viewport_bounds. y , 1. ) , PI / 2. , DVec2 :: new ( x_target. round ( ) , 0. ) ) ,
42- ) ) ;
43+ self . overlay_paths
44+ . push ( self . add_overlay_line ( DAffine2 :: from_scale_angle_translation ( DVec2 :: new ( viewport_bounds. y , 1. ) , PI / 2. , DVec2 :: new ( x_target. round ( ) , 0. ) ) ) ) ;
4345 }
4446 for y_target in y_targets {
45- self . overlay_paths . push ( add_overlay_line (
46- responses,
47- DAffine2 :: from_scale_angle_translation ( DVec2 :: new ( viewport_bounds. x , 1. ) , 0. , DVec2 :: new ( 0. , y_target. round ( ) ) ) ,
48- ) ) ;
47+ self . overlay_paths
48+ . push ( self . add_overlay_line ( DAffine2 :: from_scale_angle_translation ( DVec2 :: new ( viewport_bounds. x , 1. ) , 0. , DVec2 :: new ( 0. , y_target. round ( ) ) ) ) ) ;
4949 }
5050 }
5151 }
@@ -58,29 +58,30 @@ impl SnapHandler {
5858
5959 /// Gets a list of snap targets for the X and Y axes in Viewport coords for the target layers (usually all layers or all non-selected layers.)
6060 /// This should be called at the start of a drag.
61- pub fn start_snap ( & mut self , responses : & mut VecDeque < Message > , viewport_bounds : DVec2 , document_message_handler : & DocumentMessageHandler , target_layers : Vec < Vec < LayerId > > ) {
62- if document_message_handler . snapping_enabled {
61+ pub fn start_snap ( & mut self , viewport_bounds : DVec2 , target_layers : Vec < Vec < LayerId > > ) {
62+ if self . document . snapping_enabled {
6363 // Could be made into sorted Vec or a HashSet for more performant lookups.
6464 self . snap_targets = Some (
6565 target_layers
6666 . iter ( )
67- . filter_map ( |path| document_message_handler . graphene_document . viewport_bounding_box ( path) . ok ( ) ?)
67+ . filter_map ( |path| self . document . graphene_document . viewport_bounding_box ( path) . ok ( ) ?)
6868 . flat_map ( |[ bound1, bound2] | [ bound1, bound2, ( ( bound1 + bound2) / 2. ) ] )
6969 . map ( |vec| vec. into ( ) )
7070 . unzip ( ) ,
7171 ) ;
72- self . add_overlays ( responses , viewport_bounds) ;
72+ self . add_overlays ( viewport_bounds) ;
7373 }
7474 }
7575
7676 /// Finds the closest snap from an array of layers to the specified snap targets in viewport coords.
7777 /// Returns 0 for each axis that there is no snap less than the snap tolerance.
78- pub fn snap_layers ( & self , document_message_handler : & DocumentMessageHandler , selected_layers : & [ Vec < LayerId > ] , mouse_delta : DVec2 ) -> DVec2 {
79- if document_message_handler . snapping_enabled {
78+ pub fn snap_layers ( & self , mouse_delta : DVec2 ) -> DVec2 {
79+ if self . enabled {
8080 if let Some ( ( targets_x, targets_y) ) = & self . snap_targets {
81- let ( snap_x, snap_y) : ( Vec < f64 > , Vec < f64 > ) = selected_layers
81+ let ( snap_x, snap_y) : ( Vec < f64 > , Vec < f64 > ) = self
82+ . snappables
8283 . iter ( )
83- . filter_map ( |path| document_message_handler . graphene_document . viewport_bounding_box ( path) . ok ( ) ?)
84+ . filter_map ( |( path, _ ) | self . document . graphene_document . viewport_bounding_box ( path) . ok ( ) ?)
8485 . flat_map ( |[ bound1, bound2] | [ bound1, bound2, ( bound1 + bound2) / 2. ] )
8586 . map ( |vec| vec. into ( ) )
8687 . unzip ( ) ;
@@ -112,8 +113,8 @@ impl SnapHandler {
112113 }
113114
114115 /// Handles snapping of a viewport position, returning another viewport position.
115- pub fn snap_position ( & self , document_message_handler : & DocumentMessageHandler , position_viewport : DVec2 ) -> DVec2 {
116- if document_message_handler . snapping_enabled {
116+ pub fn snap_position ( & self , position_viewport : DVec2 ) -> DVec2 {
117+ if self . document . snapping_enabled {
117118 if let Some ( ( targets_x, targets_y) ) = & self . snap_targets {
118119 // For each list of snap targets, find the shortest distance to move the point to that target.
119120 let closest_move = DVec2 :: new (
@@ -148,4 +149,18 @@ impl SnapHandler {
148149 self . remove_overlays ( responses) ;
149150 self . snap_targets = None ;
150151 }
152+
153+ // ---
154+ pub fn add_snappable ( & mut self , layer : Vec < LayerId > ) {
155+ self . snappables . insert ( layer, vec ! [ ] ) ;
156+ }
157+
158+ pub fn remove_snappable ( & mut self , layer : Vec < LayerId > ) {
159+ self . snappables . remove ( & layer) ;
160+ }
161+
162+ pub fn process_overlays ( & mut self , responses : & mut VecDeque < Message > ) {
163+ responses. extend ( self . overlay_messages . into_iter ( ) ) ;
164+ self . overlay_messages . clear ( ) ;
165+ }
151166}
0 commit comments