@@ -2,12 +2,12 @@ use crate::{CalculatedClip, Node};
22use bevy_core:: FloatOrd ;
33use bevy_ecs:: {
44 entity:: Entity ,
5- prelude:: Component ,
5+ prelude:: { Component , Mut } ,
66 reflect:: ReflectComponent ,
77 system:: { Local , Query , Res , Resource } ,
88} ;
99use bevy_input:: { mouse:: MouseButton , touch:: Touches , Input } ;
10- use bevy_math:: Vec2 ;
10+ use bevy_math:: { Vec2 , Vec3 } ;
1111use bevy_reflect:: { Reflect , ReflectDeserialize } ;
1212use bevy_transform:: components:: GlobalTransform ;
1313use bevy_window:: Windows ;
@@ -118,31 +118,13 @@ fn focus_ui<Cursor: CursorResource>(
118118 Some ( cursor_position) => cursor_position,
119119 } ;
120120
121- let mouse_released =
122- mouse_button_input. just_released ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
123-
124- let mouse_clicked =
125- mouse_button_input. just_pressed ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
126-
127121 let mut moused_over_z_sorted_nodes = node_query
128122 . iter_mut ( )
129123 . filter_map (
130124 |( entity, node, global_transform, interaction, focus_policy, clip) | {
131125 let position = global_transform. translation ;
132- let ui_position = position. truncate ( ) ;
133- let extents = node. size / 2.0 ;
134- let mut min = ui_position - extents;
135- let mut max = ui_position + extents;
136- if let Some ( clip) = clip {
137- min = Vec2 :: max ( min, clip. clip . min ) ;
138- max = Vec2 :: min ( max, clip. clip . max ) ;
139- }
140- // if the current cursor position is within the bounds of the node, consider it for
141- // clicking
142- let contains_cursor = ( min. x ..max. x ) . contains ( & cursor_position. x )
143- && ( min. y ..max. y ) . contains ( & cursor_position. y ) ;
144126
145- if contains_cursor {
127+ if contains_cursor ( & cursor_position , node , position , clip ) {
146128 Some ( ( entity, focus_policy, interaction, FloatOrd ( position. z ) ) )
147129 } else {
148130 None
@@ -153,25 +135,30 @@ fn focus_ui<Cursor: CursorResource>(
153135
154136 moused_over_z_sorted_nodes. sort_by_key ( |( _, _, _, z) | -* z) ;
155137
156- // set Clicked or Hovered on top nodes
157- for ( entity, focus_policy, mut interaction, _) in moused_over_z_sorted_nodes {
158- if mouse_clicked {
159- // if the mouse was simultaneously released, reset this Interaction in the next frame
160- if * interaction != Interaction :: Clicked && mouse_released {
161- state. entities_to_reset . push ( entity) ;
162- }
163- * interaction = Interaction :: Clicked ;
164- } else if * interaction == Interaction :: None {
165- * interaction = Interaction :: Hovered ;
166- }
138+ set_top_nodes_as_clicked_or_hovered (
139+ moused_over_z_sorted_nodes,
140+ mouse_button_input,
141+ touches_input,
142+ state,
143+ )
144+ }
167145
168- match focus_policy. cloned ( ) . unwrap_or ( FocusPolicy :: Block ) {
169- FocusPolicy :: Block => {
170- break ;
171- }
172- FocusPolicy :: Pass => { /* allow the next node to be hovered/clicked */ }
173- }
146+ fn contains_cursor (
147+ cursor_position : & Vec2 ,
148+ node : & Node ,
149+ position : Vec3 ,
150+ clip : Option < & CalculatedClip > ,
151+ ) -> bool {
152+ let ui_position = position. truncate ( ) ;
153+ let extents = node. size / 2.0 ;
154+ let mut min = ui_position - extents;
155+ let mut max = ui_position + extents;
156+ if let Some ( clip) = clip {
157+ min = Vec2 :: max ( min, clip. clip . min ) ;
158+ max = Vec2 :: min ( max, clip. clip . max ) ;
174159 }
160+
161+ ( min. x ..max. x ) . contains ( & cursor_position. x ) && ( min. y ..max. y ) . contains ( & cursor_position. y )
175162}
176163
177164fn reset_interactions (
@@ -209,6 +196,38 @@ fn reset_interactions(
209196 }
210197}
211198
199+ fn set_top_nodes_as_clicked_or_hovered (
200+ moused_over_z_sorted_nodes : Vec < ( Entity , Option < & FocusPolicy > , Mut < Interaction > , FloatOrd ) > ,
201+ mouse_button_input : Res < Input < MouseButton > > ,
202+ touches_input : Res < Touches > ,
203+ mut state : Local < State > ,
204+ ) {
205+ let mouse_released =
206+ mouse_button_input. just_released ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
207+
208+ let mouse_clicked =
209+ mouse_button_input. just_pressed ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
210+
211+ for ( entity, focus_policy, mut interaction, _) in moused_over_z_sorted_nodes {
212+ if mouse_clicked {
213+ // if the mouse was simultaneously released, reset this Interaction in the next frame
214+ if * interaction != Interaction :: Clicked && mouse_released {
215+ state. entities_to_reset . push ( entity) ;
216+ }
217+ * interaction = Interaction :: Clicked ;
218+ } else if * interaction == Interaction :: None {
219+ * interaction = Interaction :: Hovered ;
220+ }
221+
222+ match focus_policy. cloned ( ) . unwrap_or ( FocusPolicy :: Block ) {
223+ FocusPolicy :: Block => {
224+ break ;
225+ }
226+ FocusPolicy :: Pass => { /* allow the next node to be hovered/clicked */ }
227+ }
228+ }
229+ }
230+
212231trait CursorResource : Resource {
213232 fn get_cursor_position ( & self ) -> Option < Vec2 > ;
214233}
0 commit comments