Rename some pointer events and components (#19574)
# Objective #19366 implemented core button widgets, which included the `Depressed` state component. `Depressed` was chosen instead of `Pressed` to avoid conflict with the `Pointer<Pressed>` event, but it is problematic and awkward in many ways: - Using the word "depressed" for such a high-traffic type is not great due to the obvious connection to "depressed" as in depression. - "Depressed" is not what I would search for if I was looking for a component like this, and I'm not aware of any other engine or UI framework using the term. - `Depressed` is not a very natural pair to the `Pointer<Pressed>` event. - It might be because I'm not a native English speaker, but I have very rarely heard someone say "a button is depressed". Seeing it, my mind initially goes from "depression??" to "oh, de-pressed, meaning released" and definitely not "is pressed", even though that *is* also a valid meaning for it. A related problem is that the current `Pointer<Pressed>` and `Pointer<Released>` event names use a different verb tense than all of our other observer events such as `Pointer<Click>` or `Pointer<DragStart>`. By fixing this and renaming `Pressed` (and `Released`), we can then use `Pressed` instead of `Depressed` for the state component. Additionally, the `IsHovered` and `IsDirectlyHovered` components added in #19366 use an inconsistent naming; the other similar components don't use an `Is` prefix. It also makes query filters like `Has<IsHovered>` and `With<IsHovered>` a bit more awkward. This is partially related to Cart's [picking concept proposal](https://gist.github.com/cart/756e48a149db2838028be600defbd24a?permalink_comment_id=5598154). ## Solution - Rename `Pointer<Pressed>` to `Pointer<Press>` - Rename `Pointer<Released>` to `Pointer<Release>` - Rename `Depressed` to `Pressed` - Rename `IsHovered` to `Hovered` - Rename `IsDirectlyHovered` to `DirectlyHovered`
This commit is contained in:
parent
27b64c3bf1
commit
33c6f45a35
@ -12,8 +12,8 @@ use bevy_ecs::{
|
||||
};
|
||||
use bevy_input::keyboard::{KeyCode, KeyboardInput};
|
||||
use bevy_input_focus::{FocusedInput, InputFocus, InputFocusVisible};
|
||||
use bevy_picking::events::{Cancel, Click, DragEnd, Pointer, Pressed, Released};
|
||||
use bevy_ui::{Depressed, InteractionDisabled};
|
||||
use bevy_picking::events::{Cancel, Click, DragEnd, Pointer, Press, Release};
|
||||
use bevy_ui::{InteractionDisabled, Pressed};
|
||||
|
||||
/// Headless button widget. This widget maintains a "pressed" state, which is used to
|
||||
/// indicate whether the button is currently being pressed by the user. It emits a `ButtonClicked`
|
||||
@ -49,7 +49,7 @@ fn button_on_key_event(
|
||||
|
||||
fn button_on_pointer_click(
|
||||
mut trigger: Trigger<Pointer<Click>>,
|
||||
mut q_state: Query<(&CoreButton, Has<Depressed>, Has<InteractionDisabled>)>,
|
||||
mut q_state: Query<(&CoreButton, Has<Pressed>, Has<InteractionDisabled>)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok((bstate, pressed, disabled)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
@ -63,17 +63,17 @@ fn button_on_pointer_click(
|
||||
}
|
||||
|
||||
fn button_on_pointer_down(
|
||||
mut trigger: Trigger<Pointer<Pressed>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Depressed>), With<CoreButton>>,
|
||||
mut trigger: Trigger<Pointer<Press>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Pressed>), With<CoreButton>>,
|
||||
focus: Option<ResMut<InputFocus>>,
|
||||
focus_visible: Option<ResMut<InputFocusVisible>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok((button, disabled, depressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
if let Ok((button, disabled, pressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
trigger.propagate(false);
|
||||
if !disabled {
|
||||
if !depressed {
|
||||
commands.entity(button).insert(Depressed);
|
||||
if !pressed {
|
||||
commands.entity(button).insert(Pressed);
|
||||
}
|
||||
// Clicking on a button makes it the focused input,
|
||||
// and hides the focus ring if it was visible.
|
||||
@ -88,40 +88,40 @@ fn button_on_pointer_down(
|
||||
}
|
||||
|
||||
fn button_on_pointer_up(
|
||||
mut trigger: Trigger<Pointer<Released>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Depressed>), With<CoreButton>>,
|
||||
mut trigger: Trigger<Pointer<Release>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Pressed>), With<CoreButton>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok((button, disabled, depressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
if let Ok((button, disabled, pressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
trigger.propagate(false);
|
||||
if !disabled && depressed {
|
||||
commands.entity(button).remove::<Depressed>();
|
||||
if !disabled && pressed {
|
||||
commands.entity(button).remove::<Pressed>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn button_on_pointer_drag_end(
|
||||
mut trigger: Trigger<Pointer<DragEnd>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Depressed>), With<CoreButton>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Pressed>), With<CoreButton>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok((button, disabled, depressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
if let Ok((button, disabled, pressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
trigger.propagate(false);
|
||||
if !disabled && depressed {
|
||||
commands.entity(button).remove::<Depressed>();
|
||||
if !disabled && pressed {
|
||||
commands.entity(button).remove::<Pressed>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn button_on_pointer_cancel(
|
||||
mut trigger: Trigger<Pointer<Cancel>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Depressed>), With<CoreButton>>,
|
||||
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Pressed>), With<CoreButton>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok((button, disabled, depressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
if let Ok((button, disabled, pressed)) = q_state.get_mut(trigger.target().unwrap()) {
|
||||
trigger.propagate(false);
|
||||
if !disabled && depressed {
|
||||
commands.entity(button).remove::<Depressed>();
|
||||
if !disabled && pressed {
|
||||
commands.entity(button).remove::<Pressed>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ impl Plugin for DebugPickingPlugin {
|
||||
log_event_debug::<pointer::PointerInput>.run_if(DebugPickingMode::is_noisy),
|
||||
log_pointer_event_debug::<Over>,
|
||||
log_pointer_event_debug::<Out>,
|
||||
log_pointer_event_debug::<Pressed>,
|
||||
log_pointer_event_debug::<Released>,
|
||||
log_pointer_event_debug::<Press>,
|
||||
log_pointer_event_debug::<Release>,
|
||||
log_pointer_event_debug::<Click>,
|
||||
log_pointer_event_trace::<Move>.run_if(DebugPickingMode::is_noisy),
|
||||
log_pointer_event_debug::<DragStart>,
|
||||
|
@ -31,7 +31,7 @@
|
||||
//!
|
||||
//! The events this module defines fall into a few broad categories:
|
||||
//! + Hovering and movement: [`Over`], [`Move`], and [`Out`].
|
||||
//! + Clicking and pressing: [`Pressed`], [`Released`], and [`Click`].
|
||||
//! + Clicking and pressing: [`Press`], [`Release`], and [`Click`].
|
||||
//! + Dragging and dropping: [`DragStart`], [`Drag`], [`DragEnd`], [`DragEnter`], [`DragOver`], [`DragDrop`], [`DragLeave`].
|
||||
//!
|
||||
//! When received by an observer, these events will always be wrapped by the [`Pointer`] type, which contains
|
||||
@ -171,7 +171,7 @@ pub struct Out {
|
||||
/// Fires when a pointer button is pressed over the `target` entity.
|
||||
#[derive(Clone, PartialEq, Debug, Reflect)]
|
||||
#[reflect(Clone, PartialEq)]
|
||||
pub struct Pressed {
|
||||
pub struct Press {
|
||||
/// Pointer button pressed to trigger this event.
|
||||
pub button: PointerButton,
|
||||
/// Information about the picking intersection.
|
||||
@ -181,7 +181,7 @@ pub struct Pressed {
|
||||
/// Fires when a pointer button is released over the `target` entity.
|
||||
#[derive(Clone, PartialEq, Debug, Reflect)]
|
||||
#[reflect(Clone, PartialEq)]
|
||||
pub struct Released {
|
||||
pub struct Release {
|
||||
/// Pointer button lifted to trigger this event.
|
||||
pub button: PointerButton,
|
||||
/// Information about the picking intersection.
|
||||
@ -400,7 +400,7 @@ impl PointerState {
|
||||
pub struct PickingEventWriters<'w> {
|
||||
cancel_events: EventWriter<'w, Pointer<Cancel>>,
|
||||
click_events: EventWriter<'w, Pointer<Click>>,
|
||||
pressed_events: EventWriter<'w, Pointer<Pressed>>,
|
||||
pressed_events: EventWriter<'w, Pointer<Press>>,
|
||||
drag_drop_events: EventWriter<'w, Pointer<DragDrop>>,
|
||||
drag_end_events: EventWriter<'w, Pointer<DragEnd>>,
|
||||
drag_enter_events: EventWriter<'w, Pointer<DragEnter>>,
|
||||
@ -412,7 +412,7 @@ pub struct PickingEventWriters<'w> {
|
||||
move_events: EventWriter<'w, Pointer<Move>>,
|
||||
out_events: EventWriter<'w, Pointer<Out>>,
|
||||
over_events: EventWriter<'w, Pointer<Over>>,
|
||||
released_events: EventWriter<'w, Pointer<Released>>,
|
||||
released_events: EventWriter<'w, Pointer<Release>>,
|
||||
}
|
||||
|
||||
/// Dispatches interaction events to the target entities.
|
||||
@ -422,7 +422,7 @@ pub struct PickingEventWriters<'w> {
|
||||
/// + [`DragEnter`] → [`Over`].
|
||||
/// + Any number of any of the following:
|
||||
/// + For each movement: [`DragStart`] → [`Drag`] → [`DragOver`] → [`Move`].
|
||||
/// + For each button press: [`Pressed`] or [`Click`] → [`Released`] → [`DragDrop`] → [`DragEnd`] → [`DragLeave`].
|
||||
/// + For each button press: [`Press`] or [`Click`] → [`Release`] → [`DragDrop`] → [`DragEnd`] → [`DragLeave`].
|
||||
/// + For each pointer cancellation: [`Cancel`].
|
||||
///
|
||||
/// Additionally, across multiple frames, the following are also strictly
|
||||
@ -430,7 +430,7 @@ pub struct PickingEventWriters<'w> {
|
||||
/// + When a pointer moves over the target:
|
||||
/// [`Over`], [`Move`], [`Out`].
|
||||
/// + When a pointer presses buttons on the target:
|
||||
/// [`Pressed`], [`Click`], [`Released`].
|
||||
/// [`Press`], [`Click`], [`Release`].
|
||||
/// + When a pointer drags the target:
|
||||
/// [`DragStart`], [`Drag`], [`DragEnd`].
|
||||
/// + When a pointer drags something over the target:
|
||||
@ -452,7 +452,7 @@ pub struct PickingEventWriters<'w> {
|
||||
/// In the context of UI, this is especially problematic. Additional hierarchy-aware
|
||||
/// events will be added in a future release.
|
||||
///
|
||||
/// Both [`Click`] and [`Released`] target the entity hovered in the *previous frame*,
|
||||
/// Both [`Click`] and [`Release`] target the entity hovered in the *previous frame*,
|
||||
/// rather than the current frame. This is because touch pointers hover nothing
|
||||
/// on the frame they are released. The end effect is that these two events can
|
||||
/// be received sequentially after an [`Out`] event (but always on the same frame
|
||||
@ -609,7 +609,7 @@ pub fn pointer_events(
|
||||
pointer_id,
|
||||
location.clone(),
|
||||
hovered_entity,
|
||||
Pressed {
|
||||
Press {
|
||||
button,
|
||||
hit: hit.clone(),
|
||||
},
|
||||
@ -646,12 +646,12 @@ pub fn pointer_events(
|
||||
commands.trigger_targets(click_event.clone(), hovered_entity);
|
||||
event_writers.click_events.write(click_event);
|
||||
}
|
||||
// Always send the Released event
|
||||
// Always send the Release event
|
||||
let released_event = Pointer::new(
|
||||
pointer_id,
|
||||
location.clone(),
|
||||
hovered_entity,
|
||||
Released {
|
||||
Release {
|
||||
button,
|
||||
hit: hit.clone(),
|
||||
},
|
||||
|
@ -296,14 +296,14 @@ fn merge_interaction_states(
|
||||
/// Typically, a simple hoverable entity or widget will have this component added to it. More
|
||||
/// complex widgets can have this component added to each hoverable part.
|
||||
///
|
||||
/// The computational cost of keeping the `IsHovered` components up to date is relatively cheap, and
|
||||
/// linear in the number of entities that have the [`IsHovered`] component inserted.
|
||||
/// The computational cost of keeping the `Hovered` components up to date is relatively cheap, and
|
||||
/// linear in the number of entities that have the [`Hovered`] component inserted.
|
||||
#[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)]
|
||||
#[reflect(Component, Default, PartialEq, Debug, Clone)]
|
||||
#[component(immutable)]
|
||||
pub struct IsHovered(pub bool);
|
||||
pub struct Hovered(pub bool);
|
||||
|
||||
impl IsHovered {
|
||||
impl Hovered {
|
||||
/// Get whether the entity is currently hovered.
|
||||
pub fn get(&self) -> bool {
|
||||
self.0
|
||||
@ -314,24 +314,24 @@ impl IsHovered {
|
||||
/// is directly hovering over an entity. Users should insert this component on an entity to indicate
|
||||
/// interest in knowing about hover state changes.
|
||||
///
|
||||
/// This is similar to [`IsHovered`] component, except that it does not include descendants in the
|
||||
/// This is similar to [`Hovered`] component, except that it does not include descendants in the
|
||||
/// hover state.
|
||||
#[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)]
|
||||
#[reflect(Component, Default, PartialEq, Debug, Clone)]
|
||||
#[component(immutable)]
|
||||
pub struct IsDirectlyHovered(pub bool);
|
||||
pub struct DirectlyHovered(pub bool);
|
||||
|
||||
impl IsDirectlyHovered {
|
||||
impl DirectlyHovered {
|
||||
/// Get whether the entity is currently hovered.
|
||||
pub fn get(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Uses [`HoverMap`] changes to update [`IsHovered`] components.
|
||||
/// Uses [`HoverMap`] changes to update [`Hovered`] components.
|
||||
pub fn update_is_hovered(
|
||||
hover_map: Option<Res<HoverMap>>,
|
||||
mut hovers: Query<(Entity, &IsHovered)>,
|
||||
mut hovers: Query<(Entity, &Hovered)>,
|
||||
parent_query: Query<&ChildOf>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
@ -343,11 +343,11 @@ pub fn update_is_hovered(
|
||||
return;
|
||||
}
|
||||
|
||||
// Algorithm: for each entity having a `IsHovered` component, we want to know if the current
|
||||
// Algorithm: for each entity having a `Hovered` component, we want to know if the current
|
||||
// entry in the hover map is "within" (that is, in the set of descenants of) that entity. Rather
|
||||
// than doing an expensive breadth-first traversal of children, instead start with the hovermap
|
||||
// entry and search upwards. We can make this even cheaper by building a set of ancestors for
|
||||
// the hovermap entry, and then testing each `IsHovered` entity against that set.
|
||||
// the hovermap entry, and then testing each `Hovered` entity against that set.
|
||||
|
||||
// A set which contains the hovered for the current pointer entity and its ancestors. The
|
||||
// capacity is based on the likely tree depth of the hierarchy, which is typically greater for
|
||||
@ -365,15 +365,15 @@ pub fn update_is_hovered(
|
||||
for (entity, hoverable) in hovers.iter_mut() {
|
||||
let is_hovering = hover_ancestors.contains(&entity);
|
||||
if hoverable.0 != is_hovering {
|
||||
commands.entity(entity).insert(IsHovered(is_hovering));
|
||||
commands.entity(entity).insert(Hovered(is_hovering));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Uses [`HoverMap`] changes to update [`IsDirectlyHovered`] components.
|
||||
/// Uses [`HoverMap`] changes to update [`DirectlyHovered`] components.
|
||||
pub fn update_is_directly_hovered(
|
||||
hover_map: Option<Res<HoverMap>>,
|
||||
hovers: Query<(Entity, &IsDirectlyHovered)>,
|
||||
hovers: Query<(Entity, &DirectlyHovered)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
// Don't do any work if there's no hover map.
|
||||
@ -389,16 +389,14 @@ pub fn update_is_directly_hovered(
|
||||
for (entity, hoverable) in hovers.iter() {
|
||||
let is_hovering = map.contains_key(&entity);
|
||||
if hoverable.0 != is_hovering {
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(IsDirectlyHovered(is_hovering));
|
||||
commands.entity(entity).insert(DirectlyHovered(is_hovering));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No hovered entity, reset all hovers.
|
||||
for (entity, hoverable) in hovers.iter() {
|
||||
if hoverable.0 {
|
||||
commands.entity(entity).insert(IsDirectlyHovered(false));
|
||||
commands.entity(entity).insert(DirectlyHovered(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -417,7 +415,7 @@ mod tests {
|
||||
|
||||
// Setup entities
|
||||
let hovered_child = world.spawn_empty().id();
|
||||
let hovered_entity = world.spawn(IsHovered(false)).add_child(hovered_child).id();
|
||||
let hovered_entity = world.spawn(Hovered(false)).add_child(hovered_child).id();
|
||||
|
||||
// Setup hover map with hovered_entity hovered by mouse
|
||||
let mut hover_map = HoverMap::default();
|
||||
@ -437,8 +435,8 @@ mod tests {
|
||||
// Run the system
|
||||
assert!(world.run_system_cached(update_is_hovered).is_ok());
|
||||
|
||||
// Check to insure that the hovered entity has the IsHovered component set to true
|
||||
let hover = world.entity(hovered_entity).get_ref::<IsHovered>().unwrap();
|
||||
// Check to insure that the hovered entity has the Hovered component set to true
|
||||
let hover = world.entity(hovered_entity).get_ref::<Hovered>().unwrap();
|
||||
assert!(hover.get());
|
||||
assert!(hover.is_changed());
|
||||
|
||||
@ -446,7 +444,7 @@ mod tests {
|
||||
world.increment_change_tick();
|
||||
|
||||
assert!(world.run_system_cached(update_is_hovered).is_ok());
|
||||
let hover = world.entity(hovered_entity).get_ref::<IsHovered>().unwrap();
|
||||
let hover = world.entity(hovered_entity).get_ref::<Hovered>().unwrap();
|
||||
assert!(hover.get());
|
||||
|
||||
// Should not be changed
|
||||
@ -458,7 +456,7 @@ mod tests {
|
||||
world.increment_change_tick();
|
||||
|
||||
assert!(world.run_system_cached(update_is_hovered).is_ok());
|
||||
let hover = world.entity(hovered_entity).get_ref::<IsHovered>().unwrap();
|
||||
let hover = world.entity(hovered_entity).get_ref::<Hovered>().unwrap();
|
||||
assert!(!hover.get());
|
||||
assert!(hover.is_changed());
|
||||
}
|
||||
@ -469,7 +467,7 @@ mod tests {
|
||||
let camera = world.spawn(Camera::default()).id();
|
||||
|
||||
// Setup entities
|
||||
let hovered_entity = world.spawn(IsDirectlyHovered(false)).id();
|
||||
let hovered_entity = world.spawn(DirectlyHovered(false)).id();
|
||||
|
||||
// Setup hover map with hovered_entity hovered by mouse
|
||||
let mut hover_map = HoverMap::default();
|
||||
@ -489,10 +487,10 @@ mod tests {
|
||||
// Run the system
|
||||
assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
|
||||
|
||||
// Check to insure that the hovered entity has the IsDirectlyHovered component set to true
|
||||
// Check to insure that the hovered entity has the DirectlyHovered component set to true
|
||||
let hover = world
|
||||
.entity(hovered_entity)
|
||||
.get_ref::<IsDirectlyHovered>()
|
||||
.get_ref::<DirectlyHovered>()
|
||||
.unwrap();
|
||||
assert!(hover.get());
|
||||
assert!(hover.is_changed());
|
||||
@ -503,7 +501,7 @@ mod tests {
|
||||
assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
|
||||
let hover = world
|
||||
.entity(hovered_entity)
|
||||
.get_ref::<IsDirectlyHovered>()
|
||||
.get_ref::<DirectlyHovered>()
|
||||
.unwrap();
|
||||
assert!(hover.get());
|
||||
|
||||
@ -518,7 +516,7 @@ mod tests {
|
||||
assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
|
||||
let hover = world
|
||||
.entity(hovered_entity)
|
||||
.get_ref::<IsDirectlyHovered>()
|
||||
.get_ref::<DirectlyHovered>()
|
||||
.unwrap();
|
||||
assert!(!hover.get());
|
||||
assert!(hover.is_changed());
|
||||
@ -532,7 +530,7 @@ mod tests {
|
||||
// Setup entities
|
||||
let hovered_child = world.spawn_empty().id();
|
||||
let hovered_entity = world
|
||||
.spawn(IsDirectlyHovered(false))
|
||||
.spawn(DirectlyHovered(false))
|
||||
.add_child(hovered_child)
|
||||
.id();
|
||||
|
||||
@ -554,10 +552,10 @@ mod tests {
|
||||
// Run the system
|
||||
assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
|
||||
|
||||
// Check to insure that the IsDirectlyHovered component is still false
|
||||
// Check to insure that the DirectlyHovered component is still false
|
||||
let hover = world
|
||||
.entity(hovered_entity)
|
||||
.get_ref::<IsDirectlyHovered>()
|
||||
.get_ref::<DirectlyHovered>()
|
||||
.unwrap();
|
||||
assert!(!hover.get());
|
||||
assert!(hover.is_changed());
|
||||
|
@ -393,7 +393,7 @@ impl Plugin for PickingPlugin {
|
||||
.register_type::<Self>()
|
||||
.register_type::<Pickable>()
|
||||
.register_type::<hover::PickingInteraction>()
|
||||
.register_type::<hover::IsHovered>()
|
||||
.register_type::<hover::Hovered>()
|
||||
.register_type::<pointer::PointerId>()
|
||||
.register_type::<pointer::PointerLocation>()
|
||||
.register_type::<pointer::PointerPress>()
|
||||
@ -416,7 +416,7 @@ impl Plugin for InteractionPlugin {
|
||||
.init_resource::<PointerState>()
|
||||
.add_event::<Pointer<Cancel>>()
|
||||
.add_event::<Pointer<Click>>()
|
||||
.add_event::<Pointer<Pressed>>()
|
||||
.add_event::<Pointer<Press>>()
|
||||
.add_event::<Pointer<DragDrop>>()
|
||||
.add_event::<Pointer<DragEnd>>()
|
||||
.add_event::<Pointer<DragEnter>>()
|
||||
@ -427,7 +427,7 @@ impl Plugin for InteractionPlugin {
|
||||
.add_event::<Pointer<Move>>()
|
||||
.add_event::<Pointer<Out>>()
|
||||
.add_event::<Pointer<Over>>()
|
||||
.add_event::<Pointer<Released>>()
|
||||
.add_event::<Pointer<Release>>()
|
||||
.add_event::<Pointer<Scroll>>()
|
||||
.add_systems(
|
||||
PreUpdate,
|
||||
|
@ -41,7 +41,7 @@ pub(crate) fn on_remove_disabled(
|
||||
/// Component that indicates whether a button or widget is currently in a pressed or "held down"
|
||||
/// state.
|
||||
#[derive(Component, Default, Debug)]
|
||||
pub struct Depressed;
|
||||
pub struct Pressed;
|
||||
|
||||
/// Component that indicates whether a checkbox or radio button is in a checked state.
|
||||
#[derive(Component, Default, Debug)]
|
||||
@ -55,7 +55,7 @@ impl Checked {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn on_insert_checked(trigger: Trigger<OnInsert, Checked>, mut world: DeferredWorld) {
|
||||
pub(crate) fn on_insert_is_checked(trigger: Trigger<OnInsert, Checked>, mut world: DeferredWorld) {
|
||||
let mut entity = world.entity_mut(trigger.target().unwrap());
|
||||
let checked = entity.get::<Checked>().unwrap().get();
|
||||
if let Some(mut accessibility) = entity.get_mut::<AccessibilityNode>() {
|
||||
@ -66,7 +66,7 @@ pub(crate) fn on_insert_checked(trigger: Trigger<OnInsert, Checked>, mut world:
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn on_remove_checked(trigger: Trigger<OnRemove, Checked>, mut world: DeferredWorld) {
|
||||
pub(crate) fn on_remove_is_checked(trigger: Trigger<OnRemove, Checked>, mut world: DeferredWorld) {
|
||||
let mut entity = world.entity_mut(trigger.target().unwrap());
|
||||
if let Some(mut accessibility) = entity.get_mut::<AccessibilityNode>() {
|
||||
accessibility.set_toggled(accesskit::Toggled::False);
|
||||
|
@ -39,7 +39,7 @@ mod ui_node;
|
||||
pub use focus::*;
|
||||
pub use geometry::*;
|
||||
pub use gradients::*;
|
||||
pub use interaction_states::{Checked, Depressed, InteractionDisabled};
|
||||
pub use interaction_states::{Checked, InteractionDisabled, Pressed};
|
||||
pub use layout::*;
|
||||
pub use measurement::*;
|
||||
pub use render::*;
|
||||
@ -323,8 +323,8 @@ fn build_text_interop(app: &mut App) {
|
||||
|
||||
app.add_observer(interaction_states::on_add_disabled)
|
||||
.add_observer(interaction_states::on_remove_disabled)
|
||||
.add_observer(interaction_states::on_insert_checked)
|
||||
.add_observer(interaction_states::on_remove_checked);
|
||||
.add_observer(interaction_states::on_insert_is_checked)
|
||||
.add_observer(interaction_states::on_remove_is_checked);
|
||||
|
||||
app.configure_sets(
|
||||
PostUpdate,
|
||||
|
@ -91,8 +91,8 @@ fn setup_scene(
|
||||
))
|
||||
.observe(update_material_on::<Pointer<Over>>(hover_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Out>>(white_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Pressed>>(pressed_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Released>>(hover_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Press>>(pressed_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Release>>(hover_matl.clone()))
|
||||
.observe(rotate_on_drag);
|
||||
}
|
||||
|
||||
@ -114,8 +114,8 @@ fn setup_scene(
|
||||
))
|
||||
.observe(update_material_on::<Pointer<Over>>(hover_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Out>>(white_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Pressed>>(pressed_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Released>>(hover_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Press>>(pressed_matl.clone()))
|
||||
.observe(update_material_on::<Pointer<Release>>(hover_matl.clone()))
|
||||
.observe(rotate_on_drag);
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
))
|
||||
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 1.0)))
|
||||
.observe(recolor_on::<Pointer<Out>>(Color::BLACK))
|
||||
.observe(recolor_on::<Pointer<Pressed>>(Color::srgb(1.0, 1.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Released>>(Color::srgb(0.0, 1.0, 1.0)));
|
||||
.observe(recolor_on::<Pointer<Press>>(Color::srgb(1.0, 1.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Release>>(Color::srgb(0.0, 1.0, 1.0)));
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
@ -83,8 +83,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
))
|
||||
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Out>>(Color::srgb(1.0, 0.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Pressed>>(Color::srgb(0.0, 0.0, 1.0)))
|
||||
.observe(recolor_on::<Pointer<Released>>(Color::srgb(0.0, 1.0, 0.0)));
|
||||
.observe(recolor_on::<Pointer<Press>>(Color::srgb(0.0, 0.0, 1.0)))
|
||||
.observe(recolor_on::<Pointer<Release>>(Color::srgb(0.0, 1.0, 0.0)));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -145,8 +145,8 @@ fn setup_atlas(
|
||||
))
|
||||
.observe(recolor_on::<Pointer<Over>>(Color::srgb(0.0, 1.0, 1.0)))
|
||||
.observe(recolor_on::<Pointer<Out>>(Color::srgb(1.0, 1.0, 1.0)))
|
||||
.observe(recolor_on::<Pointer<Pressed>>(Color::srgb(1.0, 1.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Released>>(Color::srgb(0.0, 1.0, 1.0)));
|
||||
.observe(recolor_on::<Pointer<Press>>(Color::srgb(1.0, 1.0, 0.0)))
|
||||
.observe(recolor_on::<Pointer<Release>>(Color::srgb(0.0, 1.0, 1.0)));
|
||||
}
|
||||
|
||||
// An observer listener that changes the target entity's color.
|
||||
|
@ -8,9 +8,9 @@ use bevy::{
|
||||
tab_navigation::{TabGroup, TabIndex},
|
||||
InputDispatchPlugin,
|
||||
},
|
||||
picking::hover::IsHovered,
|
||||
picking::hover::Hovered,
|
||||
prelude::*,
|
||||
ui::{Depressed, InteractionDisabled},
|
||||
ui::{InteractionDisabled, Pressed},
|
||||
winit::WinitSettings,
|
||||
};
|
||||
|
||||
@ -38,8 +38,8 @@ struct DemoButton;
|
||||
fn update_button_style(
|
||||
mut buttons: Query<
|
||||
(
|
||||
Has<Depressed>,
|
||||
&IsHovered,
|
||||
Has<Pressed>,
|
||||
&Hovered,
|
||||
Has<InteractionDisabled>,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
@ -47,8 +47,8 @@ fn update_button_style(
|
||||
),
|
||||
(
|
||||
Or<(
|
||||
Changed<Depressed>,
|
||||
Changed<IsHovered>,
|
||||
Changed<Pressed>,
|
||||
Changed<Hovered>,
|
||||
Added<InteractionDisabled>,
|
||||
)>,
|
||||
With<DemoButton>,
|
||||
@ -56,12 +56,12 @@ fn update_button_style(
|
||||
>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
) {
|
||||
for (depressed, hovered, disabled, mut color, mut border_color, children) in &mut buttons {
|
||||
for (pressed, hovered, disabled, mut color, mut border_color, children) in &mut buttons {
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
set_button_style(
|
||||
disabled,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -73,8 +73,8 @@ fn update_button_style(
|
||||
fn update_button_style2(
|
||||
mut buttons: Query<
|
||||
(
|
||||
Has<Depressed>,
|
||||
&IsHovered,
|
||||
Has<Pressed>,
|
||||
&Hovered,
|
||||
Has<InteractionDisabled>,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
@ -82,19 +82,19 @@ fn update_button_style2(
|
||||
),
|
||||
With<DemoButton>,
|
||||
>,
|
||||
mut removed_depressed: RemovedComponents<Depressed>,
|
||||
mut removed_depressed: RemovedComponents<Pressed>,
|
||||
mut removed_disabled: RemovedComponents<InteractionDisabled>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
) {
|
||||
removed_depressed.read().for_each(|entity| {
|
||||
if let Ok((depressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
if let Ok((pressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
buttons.get_mut(entity)
|
||||
{
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
set_button_style(
|
||||
disabled,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -102,14 +102,14 @@ fn update_button_style2(
|
||||
}
|
||||
});
|
||||
removed_disabled.read().for_each(|entity| {
|
||||
if let Ok((depressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
if let Ok((pressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
buttons.get_mut(entity)
|
||||
{
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
set_button_style(
|
||||
disabled,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -121,12 +121,12 @@ fn update_button_style2(
|
||||
fn set_button_style(
|
||||
disabled: bool,
|
||||
hovered: bool,
|
||||
depressed: bool,
|
||||
pressed: bool,
|
||||
color: &mut BackgroundColor,
|
||||
border_color: &mut BorderColor,
|
||||
text: &mut Text,
|
||||
) {
|
||||
match (disabled, hovered, depressed) {
|
||||
match (disabled, hovered, pressed) {
|
||||
// Disabled button
|
||||
(true, _, _) => {
|
||||
**text = "Disabled".to_string();
|
||||
@ -192,7 +192,7 @@ fn button(asset_server: &AssetServer, on_click: SystemId) -> impl Bundle {
|
||||
CoreButton {
|
||||
on_click: Some(on_click),
|
||||
},
|
||||
IsHovered::default(),
|
||||
Hovered::default(),
|
||||
TabIndex(0),
|
||||
BorderColor::all(Color::BLACK),
|
||||
BorderRadius::MAX,
|
||||
|
@ -8,9 +8,9 @@ use bevy::{
|
||||
tab_navigation::{TabGroup, TabIndex},
|
||||
InputDispatchPlugin,
|
||||
},
|
||||
picking::hover::IsHovered,
|
||||
picking::hover::Hovered,
|
||||
prelude::*,
|
||||
ui::{Depressed, InteractionDisabled},
|
||||
ui::{InteractionDisabled, Pressed},
|
||||
winit::WinitSettings,
|
||||
};
|
||||
|
||||
@ -38,10 +38,10 @@ const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
|
||||
struct DemoButton;
|
||||
|
||||
fn on_add_pressed(
|
||||
trigger: Trigger<OnAdd, Depressed>,
|
||||
trigger: Trigger<OnAdd, Pressed>,
|
||||
mut buttons: Query<
|
||||
(
|
||||
&IsHovered,
|
||||
&Hovered,
|
||||
Has<InteractionDisabled>,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
@ -67,10 +67,10 @@ fn on_add_pressed(
|
||||
}
|
||||
|
||||
fn on_remove_pressed(
|
||||
trigger: Trigger<OnRemove, Depressed>,
|
||||
trigger: Trigger<OnRemove, Pressed>,
|
||||
mut buttons: Query<
|
||||
(
|
||||
&IsHovered,
|
||||
&Hovered,
|
||||
Has<InteractionDisabled>,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
@ -99,8 +99,8 @@ fn on_add_disabled(
|
||||
trigger: Trigger<OnAdd, InteractionDisabled>,
|
||||
mut buttons: Query<
|
||||
(
|
||||
Has<Depressed>,
|
||||
&IsHovered,
|
||||
Has<Pressed>,
|
||||
&Hovered,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
&Children,
|
||||
@ -109,14 +109,14 @@ fn on_add_disabled(
|
||||
>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
) {
|
||||
if let Ok((depressed, hovered, mut color, mut border_color, children)) =
|
||||
if let Ok((pressed, hovered, mut color, mut border_color, children)) =
|
||||
buttons.get_mut(trigger.target().unwrap())
|
||||
{
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
set_button_style(
|
||||
true,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -128,8 +128,8 @@ fn on_remove_disabled(
|
||||
trigger: Trigger<OnRemove, InteractionDisabled>,
|
||||
mut buttons: Query<
|
||||
(
|
||||
Has<Depressed>,
|
||||
&IsHovered,
|
||||
Has<Pressed>,
|
||||
&Hovered,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
&Children,
|
||||
@ -138,14 +138,14 @@ fn on_remove_disabled(
|
||||
>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
) {
|
||||
if let Ok((depressed, hovered, mut color, mut border_color, children)) =
|
||||
if let Ok((pressed, hovered, mut color, mut border_color, children)) =
|
||||
buttons.get_mut(trigger.target().unwrap())
|
||||
{
|
||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||
set_button_style(
|
||||
false,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -154,11 +154,11 @@ fn on_remove_disabled(
|
||||
}
|
||||
|
||||
fn on_change_hover(
|
||||
trigger: Trigger<OnInsert, IsHovered>,
|
||||
trigger: Trigger<OnInsert, Hovered>,
|
||||
mut buttons: Query<
|
||||
(
|
||||
Has<Depressed>,
|
||||
&IsHovered,
|
||||
Has<Pressed>,
|
||||
&Hovered,
|
||||
Has<InteractionDisabled>,
|
||||
&mut BackgroundColor,
|
||||
&mut BorderColor,
|
||||
@ -168,7 +168,7 @@ fn on_change_hover(
|
||||
>,
|
||||
mut text_query: Query<&mut Text>,
|
||||
) {
|
||||
if let Ok((depressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
if let Ok((pressed, hovered, disabled, mut color, mut border_color, children)) =
|
||||
buttons.get_mut(trigger.target().unwrap())
|
||||
{
|
||||
if children.is_empty() {
|
||||
@ -180,7 +180,7 @@ fn on_change_hover(
|
||||
set_button_style(
|
||||
disabled,
|
||||
hovered.get(),
|
||||
depressed,
|
||||
pressed,
|
||||
&mut color,
|
||||
&mut border_color,
|
||||
&mut text,
|
||||
@ -191,12 +191,12 @@ fn on_change_hover(
|
||||
fn set_button_style(
|
||||
disabled: bool,
|
||||
hovered: bool,
|
||||
depressed: bool,
|
||||
pressed: bool,
|
||||
color: &mut BackgroundColor,
|
||||
border_color: &mut BorderColor,
|
||||
text: &mut Text,
|
||||
) {
|
||||
match (disabled, hovered, depressed) {
|
||||
match (disabled, hovered, pressed) {
|
||||
// Disabled button
|
||||
(true, _, _) => {
|
||||
**text = "Disabled".to_string();
|
||||
@ -262,7 +262,7 @@ fn button(asset_server: &AssetServer, on_click: SystemId) -> impl Bundle {
|
||||
CoreButton {
|
||||
on_click: Some(on_click),
|
||||
},
|
||||
IsHovered::default(),
|
||||
Hovered::default(),
|
||||
TabIndex(0),
|
||||
BorderColor::all(Color::BLACK),
|
||||
BorderRadius::MAX,
|
||||
|
@ -89,7 +89,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
..default()
|
||||
})
|
||||
.observe(|
|
||||
trigger: Trigger<Pointer<Pressed>>,
|
||||
trigger: Trigger<Pointer<Press>>,
|
||||
mut commands: Commands
|
||||
| {
|
||||
if trigger.event().button == PointerButton::Primary {
|
||||
|
@ -62,7 +62,7 @@ fn setup(mut commands: Commands) {
|
||||
|
||||
commands.spawn(background_and_button()).observe(
|
||||
// any click bubbling up here should lead to closing any open menu
|
||||
|_: Trigger<Pointer<Pressed>>, mut commands: Commands| {
|
||||
|_: Trigger<Pointer<Press>>, mut commands: Commands| {
|
||||
commands.trigger(CloseContextMenus);
|
||||
},
|
||||
);
|
||||
@ -108,11 +108,11 @@ fn on_trigger_menu(trigger: Trigger<OpenContextMenu>, mut commands: Commands) {
|
||||
],
|
||||
))
|
||||
.observe(
|
||||
|trigger: Trigger<Pointer<Pressed>>,
|
||||
|trigger: Trigger<Pointer<Press>>,
|
||||
menu_items: Query<&ContextMenuItem>,
|
||||
mut clear_col: ResMut<ClearColor>,
|
||||
mut commands: Commands| {
|
||||
// Note that we want to know the target of the `Pointer<Pressed>` event (Button) here.
|
||||
// Note that we want to know the target of the `Pointer<Press>` event (Button) here.
|
||||
// Not to be confused with the trigger `target`
|
||||
let target = trigger.event().target;
|
||||
|
||||
@ -184,7 +184,7 @@ fn background_and_button() -> impl Bundle + use<> {
|
||||
)],
|
||||
))
|
||||
.observe(
|
||||
|mut trigger: Trigger<Pointer<Pressed>>, mut commands: Commands| {
|
||||
|mut trigger: Trigger<Pointer<Press>>, mut commands: Commands| {
|
||||
// by default this event would bubble up further leading to the `CloseContextMenus`
|
||||
// event being triggered and undoing the opening of one here right away.
|
||||
trigger.propagate(false);
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Rename `Pointer<Pressed>` and `Pointer<Released>` to `Pointer<Press>` and `Pointer<Release>`
|
||||
pull_requests: [19179]
|
||||
---
|
||||
|
||||
The `Pointer<Pressed>` and `Pointer<Released>` events have been renamed to `Pointer<Press>` and `Pointer<Release>` for improved consistency. `Pressed` is now a marker component indicating that a button or other UI node is in a pressed or "held down" state.
|
@ -44,12 +44,12 @@ These components include:
|
||||
- `InteractionDisabled` - a boolean component used to indicate that a component should be
|
||||
"grayed out" and non-interactive. Note that these disabled widgets are still visible and can
|
||||
have keyboard focus (otherwise the user would have no way to discover them).
|
||||
- `IsHovered` is a simple boolean component that allows detection of whether the widget is being
|
||||
- `Hovered` is a simple boolean component that allows detection of whether the widget is being
|
||||
hovered using regular Bevy change detection.
|
||||
- `Checked` is a boolean component that stores the checked state of a checkbox or radio button.
|
||||
- `Depressed` is used for a button-like widget, and will be true while the button is held down.
|
||||
- `Pressed` is used for a button-like widget, and will be true while the button is held down.
|
||||
|
||||
The combination of `IsHovered` and `ButtonPressed` fulfills the same purpose as the old
|
||||
The combination of `Hovered` and `Pressed` fulfills the same purpose as the old
|
||||
`Interaction` component, except that now we can also represent "roll-off" behavior (the state where
|
||||
you click on a button and then, while holding the mouse down, move the pointer out of the button's
|
||||
bounds). It also provides additional flexibility in cases where a widget has multiple hoverable
|
||||
|
Loading…
Reference in New Issue
Block a user