@@ -28,6 +28,9 @@ pub struct DocumentMetadata {
2828 pub first_element_source_ids : HashMap < NodeId , Option < NodeId > > ,
2929 pub structure : HashMap < LayerNodeIdentifier , NodeRelations > ,
3030 pub click_targets : HashMap < LayerNodeIdentifier , Vec < Arc < ClickTarget > > > ,
31+ /// Source-geometry outlines for hover/selection overlays, separate from `click_targets` so
32+ /// nodes with an `editor:click_target` override still outline the precise geometry.
33+ pub outlines : HashMap < LayerNodeIdentifier , Vec < Arc < ClickTarget > > > ,
3134 pub clip_targets : HashSet < NodeId > ,
3235 pub vector_modify : HashMap < NodeId , Vector > ,
3336 /// Vector data keyed by layer ID, used as fallback when no Path node exists.
@@ -154,17 +157,23 @@ impl DocumentMetadata {
154157// ===============================
155158
156159impl DocumentMetadata {
160+ /// Outline targets if present, otherwise click targets. Used for bounding boxes and outline
161+ /// drawing so layers with an `editor:click_target` override report precise geometry bounds.
162+ fn visual_targets ( & self , layer : LayerNodeIdentifier ) -> Option < & [ Arc < ClickTarget > ] > {
163+ self . outlines . get ( & layer) . or_else ( || self . click_targets . get ( & layer) ) . map ( |v| v. as_slice ( ) )
164+ }
165+
157166 /// Get the bounding box of the click target of the specified layer in the specified transform space
158167 pub fn bounding_box_with_transform ( & self , layer : LayerNodeIdentifier , transform : DAffine2 ) -> Option < [ DVec2 ; 2 ] > {
159- self . click_targets ( layer) ?
168+ self . visual_targets ( layer) ?
160169 . iter ( )
161170 . filter_map ( |click_target| click_target. bounding_box_with_transform ( transform) )
162171 . reduce ( Quad :: combine_bounds)
163172 }
164173
165174 /// Get the loose bounding box of the click target of the specified layer in the specified transform space
166175 pub fn loose_bounding_box_with_transform ( & self , layer : LayerNodeIdentifier , transform : DAffine2 ) -> Option < [ DVec2 ; 2 ] > {
167- self . click_targets ( layer) ?
176+ self . visual_targets ( layer) ?
168177 . iter ( )
169178 . filter_map ( |click_target| match click_target. target_type ( ) {
170179 ClickTargetType :: Subpath ( subpath) => subpath. loose_bounding_box_with_transform ( transform) ,
@@ -210,18 +219,14 @@ impl DocumentMetadata {
210219 }
211220
212221 pub fn layer_outline ( & self , layer : LayerNodeIdentifier ) -> impl Iterator < Item = & subpath:: Subpath < PointId > > {
213- static EMPTY : Vec < Arc < ClickTarget > > = Vec :: new ( ) ;
214- let click_targets = self . click_targets . get ( & layer) . unwrap_or ( & EMPTY ) ;
215- click_targets. iter ( ) . filter_map ( |target| match target. target_type ( ) {
222+ self . visual_targets ( layer) . unwrap_or ( & [ ] ) . iter ( ) . filter_map ( |target| match target. target_type ( ) {
216223 ClickTargetType :: Subpath ( subpath) => Some ( subpath) ,
217224 _ => None ,
218225 } )
219226 }
220227
221228 pub fn layer_with_free_points_outline ( & self , layer : LayerNodeIdentifier ) -> impl Iterator < Item = & ClickTargetType > {
222- static EMPTY : Vec < Arc < ClickTarget > > = Vec :: new ( ) ;
223- let click_targets = self . click_targets . get ( & layer) . unwrap_or ( & EMPTY ) ;
224- click_targets. iter ( ) . map ( |target| target. target_type ( ) )
229+ self . visual_targets ( layer) . unwrap_or ( & [ ] ) . iter ( ) . map ( |target| target. target_type ( ) )
225230 }
226231
227232 pub fn is_clip ( & self , node : NodeId ) -> bool {
0 commit comments