ui: combine Click and Hover into Interaction

This commit is contained in:
Carter Anderson 2020-07-28 01:20:19 -07:00
parent 4a8c6c335a
commit 3d2a4f6c39
4 changed files with 45 additions and 92 deletions

View file

@ -2,7 +2,7 @@ use super::Node;
use crate::{
render::UI_PIPELINE_HANDLE,
widget::{Button, Text, Image},
Click, FocusPolicy, Hover, Style, CalculatedSize,
FocusPolicy, Interaction, Style, CalculatedSize,
};
use bevy_asset::Handle;
use bevy_ecs::Bundle;
@ -146,8 +146,7 @@ pub struct ButtonComponents {
pub node: Node,
pub button: Button,
pub style: Style,
pub click: Click,
pub hover: Hover,
pub interaction: Interaction,
pub focus_policy: FocusPolicy,
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
pub material: Handle<ColorMaterial>,
@ -180,8 +179,7 @@ impl Default for ButtonComponents {
..Default::default()
},
)]),
click: Default::default(),
hover: Default::default(),
interaction: Default::default(),
focus_policy: Default::default(),
node: Default::default(),
style: Default::default(),

View file

@ -8,26 +8,15 @@ use bevy_transform::components::Transform;
use bevy_window::CursorMoved;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Click {
Released,
Pressed,
}
impl Default for Click {
fn default() -> Self {
Click::Released
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Hover {
pub enum Interaction {
Clicked,
Hovered,
NotHovered,
None,
}
impl Default for Hover {
impl Default for Interaction {
fn default() -> Self {
Hover::NotHovered
Interaction::None
}
}
@ -58,8 +47,7 @@ pub fn ui_focus_system(
Entity,
&Node,
&Transform,
Option<&mut Click>,
Option<&mut Hover>,
Option<&mut Interaction>,
Option<&FocusPolicy>,
)>,
) {
@ -68,10 +56,10 @@ pub fn ui_focus_system(
}
if mouse_button_input.just_released(MouseButton::Left) {
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;
for (_entity, _node, _transform, interaction, _focus_policy) in &mut node_query.iter() {
if let Some(mut interaction) = interaction {
if *interaction == Interaction::Clicked {
*interaction = Interaction::None;
}
}
}
@ -84,7 +72,7 @@ pub fn ui_focus_system(
let mut query_iter = node_query.iter();
let mut moused_over_z_sorted_nodes = query_iter
.iter()
.filter_map(|(entity, node, transform, click, hover, focus_policy)| {
.filter_map(|(entity, node, transform, interaction, focus_policy)| {
let position = transform.value.w_axis();
let ui_position = position.truncate().truncate();
let extents = node.size / 2.0;
@ -94,11 +82,11 @@ 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((entity, focus_policy, click, hover, FloatOrd(position.z())))
Some((entity, focus_policy, interaction, FloatOrd(position.z())))
} else {
if let Some(mut hover) = hover {
if *hover == Hover::Hovered {
*hover = Hover::NotHovered;
if let Some(mut interaction) = interaction {
if *interaction == Interaction::Hovered {
*interaction = Interaction::None;
}
}
None
@ -106,24 +94,21 @@ pub fn ui_focus_system(
})
.collect::<Vec<_>>();
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 {
if *click == Click::Released {
*click = Click::Pressed;
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;
}
}
// only consider nodes with Hover "hoverable"
if let Some(mut hover) = hover {
if *hover == Hover::NotHovered {
*hover = Hover::Hovered;
}
hovered_entity = Some(entity);
}
hovered_entity = Some(entity);
match focus_policy.cloned().unwrap_or(FocusPolicy::Block) {
FocusPolicy::Block => {
break;
@ -137,9 +122,9 @@ pub fn ui_focus_system(
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;
if let Ok(mut interaction) = node_query.get_mut::<Interaction>(old_hovered_entity) {
if *interaction == Interaction::Hovered {
*interaction = Interaction::None;
}
}
state.hovered_entity = None;

View file

@ -20,7 +20,7 @@ pub mod prelude {
entity::*,
node::*,
widget::{Button, Text},
Anchors, Click, Hover, Margins,
Anchors, Interaction, Margins,
};
}

View file

@ -28,58 +28,28 @@ impl FromResources for ButtonMaterials {
fn button_system(
button_materials: Res<ButtonMaterials>,
mut click_query: Query<(
mut interaction_query: Query<(
&Button,
Mutated<Click>,
Option<&Hover>,
&mut Handle<ColorMaterial>,
&Children,
)>,
mut hover_query: Query<(
&Button,
Mutated<Hover>,
Option<&Click>,
Mutated<Interaction>,
&mut Handle<ColorMaterial>,
&Children,
)>,
text_query: Query<&mut Text>,
) {
for (_button, hover, click, mut material, children) in &mut hover_query.iter() {
for (_button, interaction, mut material, children) in &mut interaction_query.iter() {
let mut text = text_query.get_mut::<Text>(children[0]).unwrap();
match *hover {
Hover::Hovered => {
if let Some(Click::Released) = click {
text.value = "Hover".to_string();
*material = button_materials.hovered;
}
}
Hover::NotHovered => {
if let Some(Click::Pressed) = click {
text.value = "Press".to_string();
*material = button_materials.pressed;
} else {
text.value = "Button".to_string();
*material = button_materials.normal;
}
}
}
}
for (_button, click, hover, mut material, children) in &mut click_query.iter() {
let mut text = text_query.get_mut::<Text>(children[0]).unwrap();
match *click {
Click::Pressed => {
match *interaction {
Interaction::Clicked => {
text.value = "Press".to_string();
*material = button_materials.pressed;
}
Click::Released => {
if let Some(Hover::Hovered) = hover {
text.value = "Hover".to_string();
*material = button_materials.hovered;
} else {
text.value = "Button".to_string();
*material = button_materials.normal;
}
Interaction::Hovered => {
text.value = "Hover".to_string();
*material = button_materials.hovered;
}
Interaction::None => {
text.value = "Button".to_string();
*material = button_materials.normal;
}
}
}