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

View File

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

View File

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

View File

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