From 06aba51a8c712209139ae7127ec6ec48661f50e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Tue, 15 Dec 2020 10:36:16 +0100 Subject: [PATCH 1/2] do not check for focus until cursor position has been set --- crates/bevy_ui/src/focus.rs | 131 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/crates/bevy_ui/src/focus.rs b/crates/bevy_ui/src/focus.rs index 663b27b4c63db..e4576b9d89e70 100644 --- a/crates/bevy_ui/src/focus.rs +++ b/crates/bevy_ui/src/focus.rs @@ -35,7 +35,7 @@ impl Default for FocusPolicy { #[derive(Default)] pub struct State { cursor_moved_event_reader: EventReader, - cursor_position: Vec2, + cursor_position: Option, hovered_entity: Option, } @@ -53,92 +53,95 @@ pub fn ui_focus_system( )>, ) { if let Some(cursor_moved) = state.cursor_moved_event_reader.latest(&cursor_moved_events) { - state.cursor_position = cursor_moved.position; + state.cursor_position = Some(cursor_moved.position); } if let Some(touch) = touches_input.get_pressed(0) { - state.cursor_position = touch.position(); + state.cursor_position = Some(touch.position()); } - if mouse_button_input.just_released(MouseButton::Left) || touches_input.just_released(0) { - for (_entity, _node, _global_transform, interaction, _focus_policy) in node_query.iter_mut() - { - if let Some(mut interaction) = interaction { - if *interaction == Interaction::Clicked { - *interaction = Interaction::None; + if let Some(cursor_position) = state.cursor_position { + if mouse_button_input.just_released(MouseButton::Left) || touches_input.just_released(0) { + for (_entity, _node, _global_transform, interaction, _focus_policy) in + node_query.iter_mut() + { + if let Some(mut interaction) = interaction { + if *interaction == Interaction::Clicked { + *interaction = Interaction::None; + } } } } - } - let mouse_clicked = - mouse_button_input.just_pressed(MouseButton::Left) || touches_input.just_released(0); - let mut hovered_entity = None; + let mouse_clicked = + mouse_button_input.just_pressed(MouseButton::Left) || touches_input.just_released(0); + let mut hovered_entity = None; - { - let mut moused_over_z_sorted_nodes = node_query - .iter_mut() - .filter_map( - |(entity, node, global_transform, interaction, focus_policy)| { - let position = global_transform.translation; - let ui_position = position.truncate(); - let extents = node.size / 2.0; - let min = ui_position - extents; - let max = ui_position + extents; - // if the current cursor position is within the bounds of the node, consider it for clicking - if (min.x..max.x).contains(&state.cursor_position.x) - && (min.y..max.y).contains(&state.cursor_position.y) - { - Some((entity, focus_policy, interaction, FloatOrd(position.z))) - } else { - if let Some(mut interaction) = interaction { - if *interaction == Interaction::Hovered { - *interaction = Interaction::None; + { + let mut moused_over_z_sorted_nodes = node_query + .iter_mut() + .filter_map( + |(entity, node, global_transform, interaction, focus_policy)| { + let position = global_transform.translation; + let ui_position = position.truncate(); + let extents = node.size / 2.0; + let min = ui_position - extents; + let max = ui_position + extents; + // if the current cursor position is within the bounds of the node, consider it for clicking + if (min.x..max.x).contains(&cursor_position.x) + && (min.y..max.y).contains(&cursor_position.y) + { + Some((entity, focus_policy, interaction, FloatOrd(position.z))) + } else { + if let Some(mut interaction) = interaction { + if *interaction == Interaction::Hovered { + *interaction = Interaction::None; + } } + None } - None - } - }, - ) - .collect::>(); + }, + ) + .collect::>(); - moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z); - for (entity, focus_policy, interaction, _) in moused_over_z_sorted_nodes { - if let Some(mut interaction) = interaction { - if mouse_clicked { - // only consider nodes with ClickState "clickable" - if *interaction != Interaction::Clicked { - *interaction = Interaction::Clicked; + moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z); + for (entity, focus_policy, interaction, _) in moused_over_z_sorted_nodes { + if let Some(mut interaction) = interaction { + if mouse_clicked { + // only consider nodes with ClickState "clickable" + if *interaction != Interaction::Clicked { + *interaction = Interaction::Clicked; + } + } else if *interaction == Interaction::None { + *interaction = Interaction::Hovered; } - } else if *interaction == Interaction::None { - *interaction = Interaction::Hovered; } - } - hovered_entity = Some(entity); + hovered_entity = Some(entity); - match focus_policy.cloned().unwrap_or(FocusPolicy::Block) { - FocusPolicy::Block => { - break; + match focus_policy.cloned().unwrap_or(FocusPolicy::Block) { + FocusPolicy::Block => { + break; + } + FocusPolicy::Pass => { /* allow the next node to be hovered/clicked */ } } - 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 interaction) = - node_query.get_component_mut::(old_hovered_entity) - { - if *interaction == Interaction::Hovered { - *interaction = Interaction::None; + // 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 interaction) = + node_query.get_component_mut::(old_hovered_entity) + { + if *interaction == Interaction::Hovered { + *interaction = Interaction::None; + } } + state.hovered_entity = None; } - state.hovered_entity = None; } + state.hovered_entity = hovered_entity; } - state.hovered_entity = hovered_entity; } } From ccf0c4e767feff535e795e305cd2b302ffa5e962 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Tue, 22 Dec 2020 14:36:12 -0600 Subject: [PATCH 2/2] simplify focus cursor state --- crates/bevy_ui/src/focus.rs | 147 +++++++++++++++++------------------- 1 file changed, 71 insertions(+), 76 deletions(-) diff --git a/crates/bevy_ui/src/focus.rs b/crates/bevy_ui/src/focus.rs index e4576b9d89e70..814bed2baab2d 100644 --- a/crates/bevy_ui/src/focus.rs +++ b/crates/bevy_ui/src/focus.rs @@ -1,11 +1,9 @@ use crate::Node; -use bevy_app::{EventReader, Events}; use bevy_core::FloatOrd; use bevy_ecs::prelude::*; use bevy_input::{mouse::MouseButton, touch::Touches, Input}; -use bevy_math::Vec2; use bevy_transform::components::GlobalTransform; -use bevy_window::CursorMoved; +use bevy_window::Windows; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum Interaction { @@ -34,15 +32,13 @@ impl Default for FocusPolicy { #[derive(Default)] pub struct State { - cursor_moved_event_reader: EventReader, - cursor_position: Option, hovered_entity: Option, } pub fn ui_focus_system( mut state: Local, + windows: Res, mouse_button_input: Res>, - cursor_moved_events: Res>, touches_input: Res, mut node_query: Query<( Entity, @@ -52,96 +48,95 @@ pub fn ui_focus_system( Option<&FocusPolicy>, )>, ) { - if let Some(cursor_moved) = state.cursor_moved_event_reader.latest(&cursor_moved_events) { - state.cursor_position = Some(cursor_moved.position); - } - if let Some(touch) = touches_input.get_pressed(0) { - state.cursor_position = Some(touch.position()); - } + let cursor_position = if let Some(cursor_position) = windows + .get_primary() + .and_then(|window| window.cursor_position()) + { + cursor_position + } else { + return; + }; - if let Some(cursor_position) = state.cursor_position { - if mouse_button_input.just_released(MouseButton::Left) || touches_input.just_released(0) { - for (_entity, _node, _global_transform, interaction, _focus_policy) in - node_query.iter_mut() - { - if let Some(mut interaction) = interaction { - if *interaction == Interaction::Clicked { - *interaction = Interaction::None; - } + if mouse_button_input.just_released(MouseButton::Left) || touches_input.just_released(0) { + for (_entity, _node, _global_transform, interaction, _focus_policy) in node_query.iter_mut() + { + if let Some(mut interaction) = interaction { + if *interaction == Interaction::Clicked { + *interaction = Interaction::None; } } } + } - let mouse_clicked = - mouse_button_input.just_pressed(MouseButton::Left) || touches_input.just_released(0); - let mut hovered_entity = None; + let mouse_clicked = + mouse_button_input.just_pressed(MouseButton::Left) || touches_input.just_released(0); + let mut hovered_entity = None; - { - let mut moused_over_z_sorted_nodes = node_query - .iter_mut() - .filter_map( - |(entity, node, global_transform, interaction, focus_policy)| { - let position = global_transform.translation; - let ui_position = position.truncate(); - let extents = node.size / 2.0; - let min = ui_position - extents; - let max = ui_position + extents; - // if the current cursor position is within the bounds of the node, consider it for clicking - if (min.x..max.x).contains(&cursor_position.x) - && (min.y..max.y).contains(&cursor_position.y) - { - Some((entity, focus_policy, interaction, FloatOrd(position.z))) - } else { - if let Some(mut interaction) = interaction { - if *interaction == Interaction::Hovered { - *interaction = Interaction::None; - } + { + let mut moused_over_z_sorted_nodes = node_query + .iter_mut() + .filter_map( + |(entity, node, global_transform, interaction, focus_policy)| { + let position = global_transform.translation; + let ui_position = position.truncate(); + let extents = node.size / 2.0; + let min = ui_position - extents; + let max = ui_position + extents; + // if the current cursor position is within the bounds of the node, consider it for clicking + if (min.x..max.x).contains(&cursor_position.x) + && (min.y..max.y).contains(&cursor_position.y) + { + Some((entity, focus_policy, interaction, FloatOrd(position.z))) + } else { + if let Some(mut interaction) = interaction { + if *interaction == Interaction::Hovered { + *interaction = Interaction::None; } - None } - }, - ) - .collect::>(); + None + } + }, + ) + .collect::>(); - moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z); - for (entity, focus_policy, interaction, _) in moused_over_z_sorted_nodes { - if let Some(mut interaction) = interaction { - if mouse_clicked { - // only consider nodes with ClickState "clickable" - if *interaction != Interaction::Clicked { - *interaction = Interaction::Clicked; - } - } else if *interaction == Interaction::None { - *interaction = Interaction::Hovered; + moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z); + for (entity, focus_policy, interaction, _) in moused_over_z_sorted_nodes { + if let Some(mut interaction) = interaction { + if mouse_clicked { + // only consider nodes with ClickState "clickable" + if *interaction != Interaction::Clicked { + *interaction = Interaction::Clicked; } + } else if *interaction == Interaction::None { + *interaction = Interaction::Hovered; } + } - hovered_entity = Some(entity); + hovered_entity = Some(entity); - match focus_policy.cloned().unwrap_or(FocusPolicy::Block) { - FocusPolicy::Block => { - break; - } - FocusPolicy::Pass => { /* allow the next node to be hovered/clicked */ } + match focus_policy.cloned().unwrap_or(FocusPolicy::Block) { + FocusPolicy::Block => { + break; } + 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 interaction) = - node_query.get_component_mut::(old_hovered_entity) - { - if *interaction == Interaction::Hovered { - *interaction = Interaction::None; - } + // 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 interaction) = + node_query.get_component_mut::(old_hovered_entity) + { + if *interaction == Interaction::Hovered { + *interaction = Interaction::None; } - state.hovered_entity = None; } + state.hovered_entity = None; } - state.hovered_entity = hovered_entity; } + state.hovered_entity = hovered_entity; } }