mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 05:03:47 +00:00
ui: only allow one thing to be hovered at a time
This commit is contained in:
parent
d8b3d078b4
commit
bd227859eb
1 changed files with 66 additions and 44 deletions
|
@ -47,6 +47,7 @@ impl Default for FocusPolicy {
|
|||
pub struct State {
|
||||
cursor_moved_event_reader: EventReader<CursorMoved>,
|
||||
cursor_position: Vec2,
|
||||
hovered_entity: Option<Entity>,
|
||||
}
|
||||
|
||||
pub fn ui_focus_system(
|
||||
|
@ -55,6 +56,7 @@ pub fn ui_focus_system(
|
|||
mouse_button_input: Res<Input<MouseButton>>,
|
||||
cursor_moved_events: Res<Events<CursorMoved>>,
|
||||
mut node_query: Query<(
|
||||
Entity,
|
||||
&Node,
|
||||
&Transform,
|
||||
Option<&mut Click>,
|
||||
|
@ -67,7 +69,7 @@ pub fn ui_focus_system(
|
|||
}
|
||||
|
||||
if mouse_button_input.just_released(MouseButton::Left) {
|
||||
for (_node, _transform, click, _hover, _focus_policy) in &mut node_query.iter() {
|
||||
for (_entity, _node, _transform, click, _hover, _focus_policy) in &mut node_query.iter() {
|
||||
if let Some(mut click) = click {
|
||||
if *click == Click::Pressed {
|
||||
*click = Click::Released;
|
||||
|
@ -78,11 +80,13 @@ pub fn ui_focus_system(
|
|||
|
||||
let mouse_clicked = mouse_button_input.just_pressed(MouseButton::Left);
|
||||
let window = windows.get_primary().unwrap();
|
||||
let mut hovered_entity = None;
|
||||
|
||||
{
|
||||
let mut query_iter = node_query.iter();
|
||||
let mut moused_over_z_sorted_nodes = query_iter
|
||||
.iter()
|
||||
.filter_map(|(node, transform, click, hover, focus_policy)| {
|
||||
.filter_map(|(entity, node, transform, click, hover, focus_policy)| {
|
||||
let position = transform.value.w_axis();
|
||||
// TODO: ui transform is currently in world space, so we need to move it to ui space. we should make these transforms ui space
|
||||
let ui_position = position.truncate().truncate()
|
||||
|
@ -94,7 +98,7 @@ pub fn ui_focus_system(
|
|||
if (min.x()..max.x()).contains(&state.cursor_position.x())
|
||||
&& (min.y()..max.y()).contains(&state.cursor_position.y())
|
||||
{
|
||||
Some((focus_policy, click, hover, FloatOrd(position.z())))
|
||||
Some((entity, focus_policy, click, hover, FloatOrd(position.z())))
|
||||
} else {
|
||||
if let Some(mut hover) = hover {
|
||||
if *hover == Hover::Hovered {
|
||||
|
@ -106,8 +110,8 @@ pub fn ui_focus_system(
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z);
|
||||
for (focus_policy, click, hover, _) in moused_over_z_sorted_nodes {
|
||||
moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, _, z)| -*z);
|
||||
for (entity, focus_policy, click, hover, _) in moused_over_z_sorted_nodes {
|
||||
if mouse_clicked {
|
||||
// only consider nodes with ClickState "clickable"
|
||||
if let Some(mut click) = click {
|
||||
|
@ -121,6 +125,8 @@ pub fn ui_focus_system(
|
|||
if *hover == Hover::NotHovered {
|
||||
*hover = Hover::Hovered;
|
||||
}
|
||||
|
||||
hovered_entity = Some(entity);
|
||||
}
|
||||
match focus_policy.cloned().unwrap_or(FocusPolicy::Block) {
|
||||
FocusPolicy::Block => {
|
||||
|
@ -129,4 +135,20 @@ pub fn ui_focus_system(
|
|||
FocusPolicy::Pass => { /* allow the next node to be hovered/clicked */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a new hovered entity, but an entity is currently hovered, unhover the old entity
|
||||
if let Some(new_hovered_entity) = hovered_entity {
|
||||
if let Some(old_hovered_entity) = state.hovered_entity {
|
||||
if new_hovered_entity != old_hovered_entity {
|
||||
if let Ok(mut hover) = node_query.get_mut(old_hovered_entity) {
|
||||
if *hover == Hover::Hovered {
|
||||
*hover = Hover::NotHovered;
|
||||
}
|
||||
}
|
||||
state.hovered_entity = None;
|
||||
}
|
||||
}
|
||||
state.hovered_entity = hovered_entity;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue