@@ -2,12 +2,12 @@ use crate::{CalculatedClip, Node};
2
2
use bevy_core:: FloatOrd ;
3
3
use bevy_ecs:: {
4
4
entity:: Entity ,
5
- prelude:: Component ,
5
+ prelude:: { Component , Mut } ,
6
6
reflect:: ReflectComponent ,
7
7
system:: { Local , Query , Res , Resource } ,
8
8
} ;
9
9
use bevy_input:: { mouse:: MouseButton , touch:: Touches , Input } ;
10
- use bevy_math:: Vec2 ;
10
+ use bevy_math:: { Vec2 , Vec3 } ;
11
11
use bevy_reflect:: { Reflect , ReflectDeserialize } ;
12
12
use bevy_transform:: components:: GlobalTransform ;
13
13
use bevy_window:: Windows ;
@@ -118,31 +118,13 @@ fn focus_ui<Cursor: CursorResource>(
118
118
Some ( cursor_position) => cursor_position,
119
119
} ;
120
120
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
-
127
121
let mut moused_over_z_sorted_nodes = node_query
128
122
. iter_mut ( )
129
123
. filter_map (
130
124
|( entity, node, global_transform, interaction, focus_policy, clip) | {
131
125
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 ) ;
144
126
145
- if contains_cursor {
127
+ if contains_cursor ( & cursor_position , node , position , clip ) {
146
128
Some ( ( entity, focus_policy, interaction, FloatOrd ( position. z ) ) )
147
129
} else {
148
130
None
@@ -153,25 +135,30 @@ fn focus_ui<Cursor: CursorResource>(
153
135
154
136
moused_over_z_sorted_nodes. sort_by_key ( |( _, _, _, z) | -* z) ;
155
137
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
+ }
167
145
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 ) ;
174
159
}
160
+
161
+ ( min. x ..max. x ) . contains ( & cursor_position. x ) && ( min. y ..max. y ) . contains ( & cursor_position. y )
175
162
}
176
163
177
164
fn reset_interactions (
@@ -209,6 +196,38 @@ fn reset_interactions(
209
196
}
210
197
}
211
198
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
+
212
231
trait CursorResource : Resource {
213
232
fn get_cursor_position ( & self ) -> Option < Vec2 > ;
214
233
}
0 commit comments