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:
Joona Aalto 2025-06-11 00:57:28 +03:00 committed by GitHub
parent 27b64c3bf1
commit 33c6f45a35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 136 additions and 132 deletions

View File

@ -12,8 +12,8 @@ use bevy_ecs::{
}; };
use bevy_input::keyboard::{KeyCode, KeyboardInput}; use bevy_input::keyboard::{KeyCode, KeyboardInput};
use bevy_input_focus::{FocusedInput, InputFocus, InputFocusVisible}; use bevy_input_focus::{FocusedInput, InputFocus, InputFocusVisible};
use bevy_picking::events::{Cancel, Click, DragEnd, Pointer, Pressed, Released}; use bevy_picking::events::{Cancel, Click, DragEnd, Pointer, Press, Release};
use bevy_ui::{Depressed, InteractionDisabled}; use bevy_ui::{InteractionDisabled, Pressed};
/// Headless button widget. This widget maintains a "pressed" state, which is used to /// 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` /// 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( fn button_on_pointer_click(
mut trigger: Trigger<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, mut commands: Commands,
) { ) {
if let Ok((bstate, pressed, disabled)) = q_state.get_mut(trigger.target().unwrap()) { 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( fn button_on_pointer_down(
mut trigger: Trigger<Pointer<Pressed>>, mut trigger: Trigger<Pointer<Press>>,
mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Depressed>), With<CoreButton>>, mut q_state: Query<(Entity, Has<InteractionDisabled>, Has<Pressed>), With<CoreButton>>,
focus: Option<ResMut<InputFocus>>, focus: Option<ResMut<InputFocus>>,
focus_visible: Option<ResMut<InputFocusVisible>>, focus_visible: Option<ResMut<InputFocusVisible>>,
mut commands: Commands, 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); trigger.propagate(false);
if !disabled { if !disabled {
if !depressed { if !pressed {
commands.entity(button).insert(Depressed); commands.entity(button).insert(Pressed);
} }
// Clicking on a button makes it the focused input, // Clicking on a button makes it the focused input,
// and hides the focus ring if it was visible. // and hides the focus ring if it was visible.
@ -88,40 +88,40 @@ fn button_on_pointer_down(
} }
fn button_on_pointer_up( fn button_on_pointer_up(
mut trigger: Trigger<Pointer<Released>>, mut trigger: Trigger<Pointer<Release>>,
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, 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); trigger.propagate(false);
if !disabled && depressed { if !disabled && pressed {
commands.entity(button).remove::<Depressed>(); commands.entity(button).remove::<Pressed>();
} }
} }
} }
fn button_on_pointer_drag_end( fn button_on_pointer_drag_end(
mut trigger: Trigger<Pointer<DragEnd>>, 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, 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); trigger.propagate(false);
if !disabled && depressed { if !disabled && pressed {
commands.entity(button).remove::<Depressed>(); commands.entity(button).remove::<Pressed>();
} }
} }
} }
fn button_on_pointer_cancel( fn button_on_pointer_cancel(
mut trigger: Trigger<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, 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); trigger.propagate(false);
if !disabled && depressed { if !disabled && pressed {
commands.entity(button).remove::<Depressed>(); commands.entity(button).remove::<Pressed>();
} }
} }
} }

View File

@ -94,8 +94,8 @@ impl Plugin for DebugPickingPlugin {
log_event_debug::<pointer::PointerInput>.run_if(DebugPickingMode::is_noisy), log_event_debug::<pointer::PointerInput>.run_if(DebugPickingMode::is_noisy),
log_pointer_event_debug::<Over>, log_pointer_event_debug::<Over>,
log_pointer_event_debug::<Out>, log_pointer_event_debug::<Out>,
log_pointer_event_debug::<Pressed>, log_pointer_event_debug::<Press>,
log_pointer_event_debug::<Released>, log_pointer_event_debug::<Release>,
log_pointer_event_debug::<Click>, log_pointer_event_debug::<Click>,
log_pointer_event_trace::<Move>.run_if(DebugPickingMode::is_noisy), log_pointer_event_trace::<Move>.run_if(DebugPickingMode::is_noisy),
log_pointer_event_debug::<DragStart>, log_pointer_event_debug::<DragStart>,

View File

@ -31,7 +31,7 @@
//! //!
//! The events this module defines fall into a few broad categories: //! The events this module defines fall into a few broad categories:
//! + Hovering and movement: [`Over`], [`Move`], and [`Out`]. //! + 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`]. //! + 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 //! 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. /// Fires when a pointer button is pressed over the `target` entity.
#[derive(Clone, PartialEq, Debug, Reflect)] #[derive(Clone, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)] #[reflect(Clone, PartialEq)]
pub struct Pressed { pub struct Press {
/// Pointer button pressed to trigger this event. /// Pointer button pressed to trigger this event.
pub button: PointerButton, pub button: PointerButton,
/// Information about the picking intersection. /// Information about the picking intersection.
@ -181,7 +181,7 @@ pub struct Pressed {
/// Fires when a pointer button is released over the `target` entity. /// Fires when a pointer button is released over the `target` entity.
#[derive(Clone, PartialEq, Debug, Reflect)] #[derive(Clone, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)] #[reflect(Clone, PartialEq)]
pub struct Released { pub struct Release {
/// Pointer button lifted to trigger this event. /// Pointer button lifted to trigger this event.
pub button: PointerButton, pub button: PointerButton,
/// Information about the picking intersection. /// Information about the picking intersection.
@ -400,7 +400,7 @@ impl PointerState {
pub struct PickingEventWriters<'w> { pub struct PickingEventWriters<'w> {
cancel_events: EventWriter<'w, Pointer<Cancel>>, cancel_events: EventWriter<'w, Pointer<Cancel>>,
click_events: EventWriter<'w, Pointer<Click>>, 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_drop_events: EventWriter<'w, Pointer<DragDrop>>,
drag_end_events: EventWriter<'w, Pointer<DragEnd>>, drag_end_events: EventWriter<'w, Pointer<DragEnd>>,
drag_enter_events: EventWriter<'w, Pointer<DragEnter>>, drag_enter_events: EventWriter<'w, Pointer<DragEnter>>,
@ -412,7 +412,7 @@ pub struct PickingEventWriters<'w> {
move_events: EventWriter<'w, Pointer<Move>>, move_events: EventWriter<'w, Pointer<Move>>,
out_events: EventWriter<'w, Pointer<Out>>, out_events: EventWriter<'w, Pointer<Out>>,
over_events: EventWriter<'w, Pointer<Over>>, 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. /// Dispatches interaction events to the target entities.
@ -422,7 +422,7 @@ pub struct PickingEventWriters<'w> {
/// + [`DragEnter`] → [`Over`]. /// + [`DragEnter`] → [`Over`].
/// + Any number of any of the following: /// + Any number of any of the following:
/// + For each movement: [`DragStart`] → [`Drag`] → [`DragOver`] → [`Move`]. /// + 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`]. /// + For each pointer cancellation: [`Cancel`].
/// ///
/// Additionally, across multiple frames, the following are also strictly /// Additionally, across multiple frames, the following are also strictly
@ -430,7 +430,7 @@ pub struct PickingEventWriters<'w> {
/// + When a pointer moves over the target: /// + When a pointer moves over the target:
/// [`Over`], [`Move`], [`Out`]. /// [`Over`], [`Move`], [`Out`].
/// + When a pointer presses buttons on the target: /// + When a pointer presses buttons on the target:
/// [`Pressed`], [`Click`], [`Released`]. /// [`Press`], [`Click`], [`Release`].
/// + When a pointer drags the target: /// + When a pointer drags the target:
/// [`DragStart`], [`Drag`], [`DragEnd`]. /// [`DragStart`], [`Drag`], [`DragEnd`].
/// + When a pointer drags something over the target: /// + 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 /// In the context of UI, this is especially problematic. Additional hierarchy-aware
/// events will be added in a future release. /// 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 /// 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 /// 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 /// be received sequentially after an [`Out`] event (but always on the same frame
@ -609,7 +609,7 @@ pub fn pointer_events(
pointer_id, pointer_id,
location.clone(), location.clone(),
hovered_entity, hovered_entity,
Pressed { Press {
button, button,
hit: hit.clone(), hit: hit.clone(),
}, },
@ -646,12 +646,12 @@ pub fn pointer_events(
commands.trigger_targets(click_event.clone(), hovered_entity); commands.trigger_targets(click_event.clone(), hovered_entity);
event_writers.click_events.write(click_event); event_writers.click_events.write(click_event);
} }
// Always send the Released event // Always send the Release event
let released_event = Pointer::new( let released_event = Pointer::new(
pointer_id, pointer_id,
location.clone(), location.clone(),
hovered_entity, hovered_entity,
Released { Release {
button, button,
hit: hit.clone(), hit: hit.clone(),
}, },

View File

@ -296,14 +296,14 @@ fn merge_interaction_states(
/// Typically, a simple hoverable entity or widget will have this component added to it. More /// 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. /// 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 /// The computational cost of keeping the `Hovered` components up to date is relatively cheap, and
/// linear in the number of entities that have the [`IsHovered`] component inserted. /// linear in the number of entities that have the [`Hovered`] component inserted.
#[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)] #[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)]
#[reflect(Component, Default, PartialEq, Debug, Clone)] #[reflect(Component, Default, PartialEq, Debug, Clone)]
#[component(immutable)] #[component(immutable)]
pub struct IsHovered(pub bool); pub struct Hovered(pub bool);
impl IsHovered { impl Hovered {
/// Get whether the entity is currently hovered. /// Get whether the entity is currently hovered.
pub fn get(&self) -> bool { pub fn get(&self) -> bool {
self.0 self.0
@ -314,24 +314,24 @@ impl IsHovered {
/// is directly hovering over an entity. Users should insert this component on an entity to indicate /// is directly hovering over an entity. Users should insert this component on an entity to indicate
/// interest in knowing about hover state changes. /// 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. /// hover state.
#[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)] #[derive(Component, Copy, Clone, Default, Eq, PartialEq, Debug, Reflect)]
#[reflect(Component, Default, PartialEq, Debug, Clone)] #[reflect(Component, Default, PartialEq, Debug, Clone)]
#[component(immutable)] #[component(immutable)]
pub struct IsDirectlyHovered(pub bool); pub struct DirectlyHovered(pub bool);
impl IsDirectlyHovered { impl DirectlyHovered {
/// Get whether the entity is currently hovered. /// Get whether the entity is currently hovered.
pub fn get(&self) -> bool { pub fn get(&self) -> bool {
self.0 self.0
} }
} }
/// Uses [`HoverMap`] changes to update [`IsHovered`] components. /// Uses [`HoverMap`] changes to update [`Hovered`] components.
pub fn update_is_hovered( pub fn update_is_hovered(
hover_map: Option<Res<HoverMap>>, hover_map: Option<Res<HoverMap>>,
mut hovers: Query<(Entity, &IsHovered)>, mut hovers: Query<(Entity, &Hovered)>,
parent_query: Query<&ChildOf>, parent_query: Query<&ChildOf>,
mut commands: Commands, mut commands: Commands,
) { ) {
@ -343,11 +343,11 @@ pub fn update_is_hovered(
return; 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 // 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 // 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 // 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 // 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 // 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() { for (entity, hoverable) in hovers.iter_mut() {
let is_hovering = hover_ancestors.contains(&entity); let is_hovering = hover_ancestors.contains(&entity);
if hoverable.0 != is_hovering { 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( pub fn update_is_directly_hovered(
hover_map: Option<Res<HoverMap>>, hover_map: Option<Res<HoverMap>>,
hovers: Query<(Entity, &IsDirectlyHovered)>, hovers: Query<(Entity, &DirectlyHovered)>,
mut commands: Commands, mut commands: Commands,
) { ) {
// Don't do any work if there's no hover map. // 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() { for (entity, hoverable) in hovers.iter() {
let is_hovering = map.contains_key(&entity); let is_hovering = map.contains_key(&entity);
if hoverable.0 != is_hovering { if hoverable.0 != is_hovering {
commands commands.entity(entity).insert(DirectlyHovered(is_hovering));
.entity(entity)
.insert(IsDirectlyHovered(is_hovering));
} }
} }
} else { } else {
// No hovered entity, reset all hovers. // No hovered entity, reset all hovers.
for (entity, hoverable) in hovers.iter() { for (entity, hoverable) in hovers.iter() {
if hoverable.0 { if hoverable.0 {
commands.entity(entity).insert(IsDirectlyHovered(false)); commands.entity(entity).insert(DirectlyHovered(false));
} }
} }
} }
@ -417,7 +415,7 @@ mod tests {
// Setup entities // Setup entities
let hovered_child = world.spawn_empty().id(); 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 // Setup hover map with hovered_entity hovered by mouse
let mut hover_map = HoverMap::default(); let mut hover_map = HoverMap::default();
@ -437,8 +435,8 @@ mod tests {
// Run the system // Run the system
assert!(world.run_system_cached(update_is_hovered).is_ok()); assert!(world.run_system_cached(update_is_hovered).is_ok());
// Check to insure that the hovered entity has the IsHovered component set to true // Check to insure that the hovered entity has the Hovered component set to true
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.get());
assert!(hover.is_changed()); assert!(hover.is_changed());
@ -446,7 +444,7 @@ mod tests {
world.increment_change_tick(); world.increment_change_tick();
assert!(world.run_system_cached(update_is_hovered).is_ok()); 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.get());
// Should not be changed // Should not be changed
@ -458,7 +456,7 @@ mod tests {
world.increment_change_tick(); world.increment_change_tick();
assert!(world.run_system_cached(update_is_hovered).is_ok()); 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.get());
assert!(hover.is_changed()); assert!(hover.is_changed());
} }
@ -469,7 +467,7 @@ mod tests {
let camera = world.spawn(Camera::default()).id(); let camera = world.spawn(Camera::default()).id();
// Setup entities // 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 // Setup hover map with hovered_entity hovered by mouse
let mut hover_map = HoverMap::default(); let mut hover_map = HoverMap::default();
@ -489,10 +487,10 @@ mod tests {
// Run the system // Run the system
assert!(world.run_system_cached(update_is_directly_hovered).is_ok()); 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 let hover = world
.entity(hovered_entity) .entity(hovered_entity)
.get_ref::<IsDirectlyHovered>() .get_ref::<DirectlyHovered>()
.unwrap(); .unwrap();
assert!(hover.get()); assert!(hover.get());
assert!(hover.is_changed()); assert!(hover.is_changed());
@ -503,7 +501,7 @@ mod tests {
assert!(world.run_system_cached(update_is_directly_hovered).is_ok()); assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
let hover = world let hover = world
.entity(hovered_entity) .entity(hovered_entity)
.get_ref::<IsDirectlyHovered>() .get_ref::<DirectlyHovered>()
.unwrap(); .unwrap();
assert!(hover.get()); assert!(hover.get());
@ -518,7 +516,7 @@ mod tests {
assert!(world.run_system_cached(update_is_directly_hovered).is_ok()); assert!(world.run_system_cached(update_is_directly_hovered).is_ok());
let hover = world let hover = world
.entity(hovered_entity) .entity(hovered_entity)
.get_ref::<IsDirectlyHovered>() .get_ref::<DirectlyHovered>()
.unwrap(); .unwrap();
assert!(!hover.get()); assert!(!hover.get());
assert!(hover.is_changed()); assert!(hover.is_changed());
@ -532,7 +530,7 @@ mod tests {
// Setup entities // Setup entities
let hovered_child = world.spawn_empty().id(); let hovered_child = world.spawn_empty().id();
let hovered_entity = world let hovered_entity = world
.spawn(IsDirectlyHovered(false)) .spawn(DirectlyHovered(false))
.add_child(hovered_child) .add_child(hovered_child)
.id(); .id();
@ -554,10 +552,10 @@ mod tests {
// Run the system // Run the system
assert!(world.run_system_cached(update_is_directly_hovered).is_ok()); 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 let hover = world
.entity(hovered_entity) .entity(hovered_entity)
.get_ref::<IsDirectlyHovered>() .get_ref::<DirectlyHovered>()
.unwrap(); .unwrap();
assert!(!hover.get()); assert!(!hover.get());
assert!(hover.is_changed()); assert!(hover.is_changed());

View File

@ -393,7 +393,7 @@ impl Plugin for PickingPlugin {
.register_type::<Self>() .register_type::<Self>()
.register_type::<Pickable>() .register_type::<Pickable>()
.register_type::<hover::PickingInteraction>() .register_type::<hover::PickingInteraction>()
.register_type::<hover::IsHovered>() .register_type::<hover::Hovered>()
.register_type::<pointer::PointerId>() .register_type::<pointer::PointerId>()
.register_type::<pointer::PointerLocation>() .register_type::<pointer::PointerLocation>()
.register_type::<pointer::PointerPress>() .register_type::<pointer::PointerPress>()
@ -416,7 +416,7 @@ impl Plugin for InteractionPlugin {
.init_resource::<PointerState>() .init_resource::<PointerState>()
.add_event::<Pointer<Cancel>>() .add_event::<Pointer<Cancel>>()
.add_event::<Pointer<Click>>() .add_event::<Pointer<Click>>()
.add_event::<Pointer<Pressed>>() .add_event::<Pointer<Press>>()
.add_event::<Pointer<DragDrop>>() .add_event::<Pointer<DragDrop>>()
.add_event::<Pointer<DragEnd>>() .add_event::<Pointer<DragEnd>>()
.add_event::<Pointer<DragEnter>>() .add_event::<Pointer<DragEnter>>()
@ -427,7 +427,7 @@ impl Plugin for InteractionPlugin {
.add_event::<Pointer<Move>>() .add_event::<Pointer<Move>>()
.add_event::<Pointer<Out>>() .add_event::<Pointer<Out>>()
.add_event::<Pointer<Over>>() .add_event::<Pointer<Over>>()
.add_event::<Pointer<Released>>() .add_event::<Pointer<Release>>()
.add_event::<Pointer<Scroll>>() .add_event::<Pointer<Scroll>>()
.add_systems( .add_systems(
PreUpdate, PreUpdate,

View File

@ -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" /// Component that indicates whether a button or widget is currently in a pressed or "held down"
/// state. /// state.
#[derive(Component, Default, Debug)] #[derive(Component, Default, Debug)]
pub struct Depressed; pub struct Pressed;
/// Component that indicates whether a checkbox or radio button is in a checked state. /// Component that indicates whether a checkbox or radio button is in a checked state.
#[derive(Component, Default, Debug)] #[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 mut entity = world.entity_mut(trigger.target().unwrap());
let checked = entity.get::<Checked>().unwrap().get(); let checked = entity.get::<Checked>().unwrap().get();
if let Some(mut accessibility) = entity.get_mut::<AccessibilityNode>() { 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()); let mut entity = world.entity_mut(trigger.target().unwrap());
if let Some(mut accessibility) = entity.get_mut::<AccessibilityNode>() { if let Some(mut accessibility) = entity.get_mut::<AccessibilityNode>() {
accessibility.set_toggled(accesskit::Toggled::False); accessibility.set_toggled(accesskit::Toggled::False);

View File

@ -39,7 +39,7 @@ mod ui_node;
pub use focus::*; pub use focus::*;
pub use geometry::*; pub use geometry::*;
pub use gradients::*; pub use gradients::*;
pub use interaction_states::{Checked, Depressed, InteractionDisabled}; pub use interaction_states::{Checked, InteractionDisabled, Pressed};
pub use layout::*; pub use layout::*;
pub use measurement::*; pub use measurement::*;
pub use render::*; pub use render::*;
@ -323,8 +323,8 @@ fn build_text_interop(app: &mut App) {
app.add_observer(interaction_states::on_add_disabled) app.add_observer(interaction_states::on_add_disabled)
.add_observer(interaction_states::on_remove_disabled) .add_observer(interaction_states::on_remove_disabled)
.add_observer(interaction_states::on_insert_checked) .add_observer(interaction_states::on_insert_is_checked)
.add_observer(interaction_states::on_remove_checked); .add_observer(interaction_states::on_remove_is_checked);
app.configure_sets( app.configure_sets(
PostUpdate, PostUpdate,

View File

@ -91,8 +91,8 @@ fn setup_scene(
)) ))
.observe(update_material_on::<Pointer<Over>>(hover_matl.clone())) .observe(update_material_on::<Pointer<Over>>(hover_matl.clone()))
.observe(update_material_on::<Pointer<Out>>(white_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<Press>>(pressed_matl.clone()))
.observe(update_material_on::<Pointer<Released>>(hover_matl.clone())) .observe(update_material_on::<Pointer<Release>>(hover_matl.clone()))
.observe(rotate_on_drag); .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<Over>>(hover_matl.clone()))
.observe(update_material_on::<Pointer<Out>>(white_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<Press>>(pressed_matl.clone()))
.observe(update_material_on::<Pointer<Released>>(hover_matl.clone())) .observe(update_material_on::<Pointer<Release>>(hover_matl.clone()))
.observe(rotate_on_drag); .observe(rotate_on_drag);
} }

View File

@ -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<Over>>(Color::srgb(0.0, 1.0, 1.0)))
.observe(recolor_on::<Pointer<Out>>(Color::BLACK)) .observe(recolor_on::<Pointer<Out>>(Color::BLACK))
.observe(recolor_on::<Pointer<Pressed>>(Color::srgb(1.0, 1.0, 0.0))) .observe(recolor_on::<Pointer<Press>>(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<Release>>(Color::srgb(0.0, 1.0, 1.0)));
commands commands
.spawn(( .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<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<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<Press>>(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<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<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<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<Press>>(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<Release>>(Color::srgb(0.0, 1.0, 1.0)));
} }
// An observer listener that changes the target entity's color. // An observer listener that changes the target entity's color.

View File

@ -8,9 +8,9 @@ use bevy::{
tab_navigation::{TabGroup, TabIndex}, tab_navigation::{TabGroup, TabIndex},
InputDispatchPlugin, InputDispatchPlugin,
}, },
picking::hover::IsHovered, picking::hover::Hovered,
prelude::*, prelude::*,
ui::{Depressed, InteractionDisabled}, ui::{InteractionDisabled, Pressed},
winit::WinitSettings, winit::WinitSettings,
}; };
@ -38,8 +38,8 @@ struct DemoButton;
fn update_button_style( fn update_button_style(
mut buttons: Query< mut buttons: Query<
( (
Has<Depressed>, Has<Pressed>,
&IsHovered, &Hovered,
Has<InteractionDisabled>, Has<InteractionDisabled>,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
@ -47,8 +47,8 @@ fn update_button_style(
), ),
( (
Or<( Or<(
Changed<Depressed>, Changed<Pressed>,
Changed<IsHovered>, Changed<Hovered>,
Added<InteractionDisabled>, Added<InteractionDisabled>,
)>, )>,
With<DemoButton>, With<DemoButton>,
@ -56,12 +56,12 @@ fn update_button_style(
>, >,
mut text_query: Query<&mut Text>, 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(); let mut text = text_query.get_mut(children[0]).unwrap();
set_button_style( set_button_style(
disabled, disabled,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -73,8 +73,8 @@ fn update_button_style(
fn update_button_style2( fn update_button_style2(
mut buttons: Query< mut buttons: Query<
( (
Has<Depressed>, Has<Pressed>,
&IsHovered, &Hovered,
Has<InteractionDisabled>, Has<InteractionDisabled>,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
@ -82,19 +82,19 @@ fn update_button_style2(
), ),
With<DemoButton>, With<DemoButton>,
>, >,
mut removed_depressed: RemovedComponents<Depressed>, mut removed_depressed: RemovedComponents<Pressed>,
mut removed_disabled: RemovedComponents<InteractionDisabled>, mut removed_disabled: RemovedComponents<InteractionDisabled>,
mut text_query: Query<&mut Text>, mut text_query: Query<&mut Text>,
) { ) {
removed_depressed.read().for_each(|entity| { 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) buttons.get_mut(entity)
{ {
let mut text = text_query.get_mut(children[0]).unwrap(); let mut text = text_query.get_mut(children[0]).unwrap();
set_button_style( set_button_style(
disabled, disabled,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -102,14 +102,14 @@ fn update_button_style2(
} }
}); });
removed_disabled.read().for_each(|entity| { 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) buttons.get_mut(entity)
{ {
let mut text = text_query.get_mut(children[0]).unwrap(); let mut text = text_query.get_mut(children[0]).unwrap();
set_button_style( set_button_style(
disabled, disabled,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -121,12 +121,12 @@ fn update_button_style2(
fn set_button_style( fn set_button_style(
disabled: bool, disabled: bool,
hovered: bool, hovered: bool,
depressed: bool, pressed: bool,
color: &mut BackgroundColor, color: &mut BackgroundColor,
border_color: &mut BorderColor, border_color: &mut BorderColor,
text: &mut Text, text: &mut Text,
) { ) {
match (disabled, hovered, depressed) { match (disabled, hovered, pressed) {
// Disabled button // Disabled button
(true, _, _) => { (true, _, _) => {
**text = "Disabled".to_string(); **text = "Disabled".to_string();
@ -192,7 +192,7 @@ fn button(asset_server: &AssetServer, on_click: SystemId) -> impl Bundle {
CoreButton { CoreButton {
on_click: Some(on_click), on_click: Some(on_click),
}, },
IsHovered::default(), Hovered::default(),
TabIndex(0), TabIndex(0),
BorderColor::all(Color::BLACK), BorderColor::all(Color::BLACK),
BorderRadius::MAX, BorderRadius::MAX,

View File

@ -8,9 +8,9 @@ use bevy::{
tab_navigation::{TabGroup, TabIndex}, tab_navigation::{TabGroup, TabIndex},
InputDispatchPlugin, InputDispatchPlugin,
}, },
picking::hover::IsHovered, picking::hover::Hovered,
prelude::*, prelude::*,
ui::{Depressed, InteractionDisabled}, ui::{InteractionDisabled, Pressed},
winit::WinitSettings, winit::WinitSettings,
}; };
@ -38,10 +38,10 @@ const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
struct DemoButton; struct DemoButton;
fn on_add_pressed( fn on_add_pressed(
trigger: Trigger<OnAdd, Depressed>, trigger: Trigger<OnAdd, Pressed>,
mut buttons: Query< mut buttons: Query<
( (
&IsHovered, &Hovered,
Has<InteractionDisabled>, Has<InteractionDisabled>,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
@ -67,10 +67,10 @@ fn on_add_pressed(
} }
fn on_remove_pressed( fn on_remove_pressed(
trigger: Trigger<OnRemove, Depressed>, trigger: Trigger<OnRemove, Pressed>,
mut buttons: Query< mut buttons: Query<
( (
&IsHovered, &Hovered,
Has<InteractionDisabled>, Has<InteractionDisabled>,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
@ -99,8 +99,8 @@ fn on_add_disabled(
trigger: Trigger<OnAdd, InteractionDisabled>, trigger: Trigger<OnAdd, InteractionDisabled>,
mut buttons: Query< mut buttons: Query<
( (
Has<Depressed>, Has<Pressed>,
&IsHovered, &Hovered,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
&Children, &Children,
@ -109,14 +109,14 @@ fn on_add_disabled(
>, >,
mut text_query: Query<&mut Text>, 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()) buttons.get_mut(trigger.target().unwrap())
{ {
let mut text = text_query.get_mut(children[0]).unwrap(); let mut text = text_query.get_mut(children[0]).unwrap();
set_button_style( set_button_style(
true, true,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -128,8 +128,8 @@ fn on_remove_disabled(
trigger: Trigger<OnRemove, InteractionDisabled>, trigger: Trigger<OnRemove, InteractionDisabled>,
mut buttons: Query< mut buttons: Query<
( (
Has<Depressed>, Has<Pressed>,
&IsHovered, &Hovered,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
&Children, &Children,
@ -138,14 +138,14 @@ fn on_remove_disabled(
>, >,
mut text_query: Query<&mut Text>, 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()) buttons.get_mut(trigger.target().unwrap())
{ {
let mut text = text_query.get_mut(children[0]).unwrap(); let mut text = text_query.get_mut(children[0]).unwrap();
set_button_style( set_button_style(
false, false,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -154,11 +154,11 @@ fn on_remove_disabled(
} }
fn on_change_hover( fn on_change_hover(
trigger: Trigger<OnInsert, IsHovered>, trigger: Trigger<OnInsert, Hovered>,
mut buttons: Query< mut buttons: Query<
( (
Has<Depressed>, Has<Pressed>,
&IsHovered, &Hovered,
Has<InteractionDisabled>, Has<InteractionDisabled>,
&mut BackgroundColor, &mut BackgroundColor,
&mut BorderColor, &mut BorderColor,
@ -168,7 +168,7 @@ fn on_change_hover(
>, >,
mut text_query: Query<&mut Text>, 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()) buttons.get_mut(trigger.target().unwrap())
{ {
if children.is_empty() { if children.is_empty() {
@ -180,7 +180,7 @@ fn on_change_hover(
set_button_style( set_button_style(
disabled, disabled,
hovered.get(), hovered.get(),
depressed, pressed,
&mut color, &mut color,
&mut border_color, &mut border_color,
&mut text, &mut text,
@ -191,12 +191,12 @@ fn on_change_hover(
fn set_button_style( fn set_button_style(
disabled: bool, disabled: bool,
hovered: bool, hovered: bool,
depressed: bool, pressed: bool,
color: &mut BackgroundColor, color: &mut BackgroundColor,
border_color: &mut BorderColor, border_color: &mut BorderColor,
text: &mut Text, text: &mut Text,
) { ) {
match (disabled, hovered, depressed) { match (disabled, hovered, pressed) {
// Disabled button // Disabled button
(true, _, _) => { (true, _, _) => {
**text = "Disabled".to_string(); **text = "Disabled".to_string();
@ -262,7 +262,7 @@ fn button(asset_server: &AssetServer, on_click: SystemId) -> impl Bundle {
CoreButton { CoreButton {
on_click: Some(on_click), on_click: Some(on_click),
}, },
IsHovered::default(), Hovered::default(),
TabIndex(0), TabIndex(0),
BorderColor::all(Color::BLACK), BorderColor::all(Color::BLACK),
BorderRadius::MAX, BorderRadius::MAX,

View File

@ -89,7 +89,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
..default() ..default()
}) })
.observe(| .observe(|
trigger: Trigger<Pointer<Pressed>>, trigger: Trigger<Pointer<Press>>,
mut commands: Commands mut commands: Commands
| { | {
if trigger.event().button == PointerButton::Primary { if trigger.event().button == PointerButton::Primary {

View File

@ -62,7 +62,7 @@ fn setup(mut commands: Commands) {
commands.spawn(background_and_button()).observe( commands.spawn(background_and_button()).observe(
// any click bubbling up here should lead to closing any open menu // 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); commands.trigger(CloseContextMenus);
}, },
); );
@ -108,11 +108,11 @@ fn on_trigger_menu(trigger: Trigger<OpenContextMenu>, mut commands: Commands) {
], ],
)) ))
.observe( .observe(
|trigger: Trigger<Pointer<Pressed>>, |trigger: Trigger<Pointer<Press>>,
menu_items: Query<&ContextMenuItem>, menu_items: Query<&ContextMenuItem>,
mut clear_col: ResMut<ClearColor>, mut clear_col: ResMut<ClearColor>,
mut commands: Commands| { 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` // Not to be confused with the trigger `target`
let target = trigger.event().target; let target = trigger.event().target;
@ -184,7 +184,7 @@ fn background_and_button() -> impl Bundle + use<> {
)], )],
)) ))
.observe( .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` // by default this event would bubble up further leading to the `CloseContextMenus`
// event being triggered and undoing the opening of one here right away. // event being triggered and undoing the opening of one here right away.
trigger.propagate(false); trigger.propagate(false);

View File

@ -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.

View File

@ -44,12 +44,12 @@ These components include:
- `InteractionDisabled` - a boolean component used to indicate that a component should be - `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 "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). 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. hovered using regular Bevy change detection.
- `Checked` is a boolean component that stores the checked state of a checkbox or radio button. - `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 `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 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 bounds). It also provides additional flexibility in cases where a widget has multiple hoverable