@@ -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 ;
@@ -104,31 +104,13 @@ fn focus_ui<Cursor: CursorResource>(
104
104
Some ( cursor_position) => cursor_position,
105
105
} ;
106
106
107
- let mouse_released =
108
- mouse_button_input. just_released ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
109
-
110
- let mouse_clicked =
111
- mouse_button_input. just_pressed ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
112
-
113
107
let mut moused_over_z_sorted_nodes = node_query
114
108
. iter_mut ( )
115
109
. filter_map (
116
110
|( entity, node, global_transform, interaction, focus_policy, clip) | {
117
111
let position = global_transform. translation ;
118
- let ui_position = position. truncate ( ) ;
119
- let extents = node. size / 2.0 ;
120
- let mut min = ui_position - extents;
121
- let mut max = ui_position + extents;
122
- if let Some ( clip) = clip {
123
- min = Vec2 :: max ( min, clip. clip . min ) ;
124
- max = Vec2 :: min ( max, clip. clip . max ) ;
125
- }
126
- // if the current cursor position is within the bounds of the node, consider it for
127
- // clicking
128
- let contains_cursor = ( min. x ..max. x ) . contains ( & cursor_position. x )
129
- && ( min. y ..max. y ) . contains ( & cursor_position. y ) ;
130
112
131
- if contains_cursor {
113
+ if contains_cursor ( & cursor_position , node , position , clip ) {
132
114
Some ( ( entity, focus_policy, interaction, FloatOrd ( position. z ) ) )
133
115
} else {
134
116
None
@@ -139,25 +121,30 @@ fn focus_ui<Cursor: CursorResource>(
139
121
140
122
moused_over_z_sorted_nodes. sort_by_key ( |( _, _, _, z) | -* z) ;
141
123
142
- // set Clicked or Hovered on top nodes
143
- for ( entity, focus_policy, mut interaction, _) in moused_over_z_sorted_nodes {
144
- if mouse_clicked {
145
- // if the mouse was simultaneously released, reset this Interaction in the next frame
146
- if * interaction != Interaction :: Clicked && mouse_released {
147
- state. entities_to_reset . push ( entity) ;
148
- }
149
- * interaction = Interaction :: Clicked ;
150
- } else if * interaction == Interaction :: None {
151
- * interaction = Interaction :: Hovered ;
152
- }
124
+ set_top_nodes_as_clicked_or_hovered (
125
+ moused_over_z_sorted_nodes,
126
+ mouse_button_input,
127
+ touches_input,
128
+ state,
129
+ )
130
+ }
153
131
154
- match focus_policy. cloned ( ) . unwrap_or ( FocusPolicy :: Block ) {
155
- FocusPolicy :: Block => {
156
- break ;
157
- }
158
- FocusPolicy :: Pass => { /* allow the next node to be hovered/clicked */ }
159
- }
132
+ fn contains_cursor (
133
+ cursor_position : & Vec2 ,
134
+ node : & Node ,
135
+ position : Vec3 ,
136
+ clip : Option < & CalculatedClip > ,
137
+ ) -> bool {
138
+ let ui_position = position. truncate ( ) ;
139
+ let extents = node. size / 2.0 ;
140
+ let mut min = ui_position - extents;
141
+ let mut max = ui_position + extents;
142
+ if let Some ( clip) = clip {
143
+ min = Vec2 :: max ( min, clip. clip . min ) ;
144
+ max = Vec2 :: min ( max, clip. clip . max ) ;
160
145
}
146
+
147
+ ( min. x ..max. x ) . contains ( & cursor_position. x ) && ( min. y ..max. y ) . contains ( & cursor_position. y )
161
148
}
162
149
163
150
fn reset_interactions (
@@ -188,6 +175,38 @@ fn reset_interactions(
188
175
}
189
176
}
190
177
178
+ fn set_top_nodes_as_clicked_or_hovered (
179
+ moused_over_z_sorted_nodes : Vec < ( Entity , Option < & FocusPolicy > , Mut < Interaction > , FloatOrd ) > ,
180
+ mouse_button_input : Res < Input < MouseButton > > ,
181
+ touches_input : Res < Touches > ,
182
+ mut state : Local < State > ,
183
+ ) {
184
+ let mouse_released =
185
+ mouse_button_input. just_released ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
186
+
187
+ let mouse_clicked =
188
+ mouse_button_input. just_pressed ( MouseButton :: Left ) || touches_input. just_released ( 0 ) ;
189
+
190
+ for ( entity, focus_policy, mut interaction, _) in moused_over_z_sorted_nodes {
191
+ if mouse_clicked {
192
+ // if the mouse was simultaneously released, reset this Interaction in the next frame
193
+ if * interaction != Interaction :: Clicked && mouse_released {
194
+ state. entities_to_reset . push ( entity) ;
195
+ }
196
+ * interaction = Interaction :: Clicked ;
197
+ } else if * interaction == Interaction :: None {
198
+ * interaction = Interaction :: Hovered ;
199
+ }
200
+
201
+ match focus_policy. cloned ( ) . unwrap_or ( FocusPolicy :: Block ) {
202
+ FocusPolicy :: Block => {
203
+ break ;
204
+ }
205
+ FocusPolicy :: Pass => { /* allow the next node to be hovered/clicked */ }
206
+ }
207
+ }
208
+ }
209
+
191
210
trait CursorResource : Resource {
192
211
fn get_cursor_position ( & self ) -> Option < Vec2 > ;
193
212
}
0 commit comments