From 33c6f45a35acf145a6244828a8f58cd9f45f3c9f Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Wed, 11 Jun 2025 00:57:28 +0300 Subject: [PATCH] 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` 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` 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` and `Pointer` event names use a different verb tense than all of our other observer events such as `Pointer` or `Pointer`. 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` and `With` 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` to `Pointer` - Rename `Pointer` to `Pointer` - Rename `Depressed` to `Pressed` - Rename `IsHovered` to `Hovered` - Rename `IsDirectlyHovered` to `DirectlyHovered` --- crates/bevy_core_widgets/src/core_button.rs | 42 ++++++------- crates/bevy_dev_tools/src/picking_debug.rs | 4 +- crates/bevy_picking/src/events.rs | 22 +++---- crates/bevy_picking/src/hover.rs | 60 +++++++++---------- crates/bevy_picking/src/lib.rs | 6 +- crates/bevy_ui/src/interaction_states.rs | 6 +- crates/bevy_ui/src/lib.rs | 6 +- examples/picking/mesh_picking.rs | 8 +-- examples/picking/sprite_picking.rs | 12 ++-- examples/ui/core_widgets.rs | 36 +++++------ examples/ui/core_widgets_observers.rs | 44 +++++++------- examples/ui/scroll.rs | 2 +- examples/usages/context_menu.rs | 8 +-- .../migration-guides/rename_pointer_events.md | 6 ++ .../release-notes/headless-widgets.md | 6 +- 15 files changed, 136 insertions(+), 132 deletions(-) create mode 100644 release-content/migration-guides/rename_pointer_events.md diff --git a/crates/bevy_core_widgets/src/core_button.rs b/crates/bevy_core_widgets/src/core_button.rs index 23f5c28380..bf88c27143 100644 --- a/crates/bevy_core_widgets/src/core_button.rs +++ b/crates/bevy_core_widgets/src/core_button.rs @@ -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>, - mut q_state: Query<(&CoreButton, Has, Has)>, + mut q_state: Query<(&CoreButton, Has, Has)>, 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>, - mut q_state: Query<(Entity, Has, Has), With>, + mut trigger: Trigger>, + mut q_state: Query<(Entity, Has, Has), With>, focus: Option>, focus_visible: Option>, 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>, - mut q_state: Query<(Entity, Has, Has), With>, + mut trigger: Trigger>, + mut q_state: Query<(Entity, Has, Has), With>, 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::(); + if !disabled && pressed { + commands.entity(button).remove::(); } } } fn button_on_pointer_drag_end( mut trigger: Trigger>, - mut q_state: Query<(Entity, Has, Has), With>, + mut q_state: Query<(Entity, Has, Has), With>, 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::(); + if !disabled && pressed { + commands.entity(button).remove::(); } } } fn button_on_pointer_cancel( mut trigger: Trigger>, - mut q_state: Query<(Entity, Has, Has), With>, + mut q_state: Query<(Entity, Has, Has), With>, 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::(); + if !disabled && pressed { + commands.entity(button).remove::(); } } } diff --git a/crates/bevy_dev_tools/src/picking_debug.rs b/crates/bevy_dev_tools/src/picking_debug.rs index 79c1c8fff4..d11818dc6a 100644 --- a/crates/bevy_dev_tools/src/picking_debug.rs +++ b/crates/bevy_dev_tools/src/picking_debug.rs @@ -94,8 +94,8 @@ impl Plugin for DebugPickingPlugin { log_event_debug::.run_if(DebugPickingMode::is_noisy), log_pointer_event_debug::, log_pointer_event_debug::, - log_pointer_event_debug::, - log_pointer_event_debug::, + log_pointer_event_debug::, + log_pointer_event_debug::, log_pointer_event_debug::, log_pointer_event_trace::.run_if(DebugPickingMode::is_noisy), log_pointer_event_debug::, diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index 72c0f06c46..f9083433be 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -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>, click_events: EventWriter<'w, Pointer>, - pressed_events: EventWriter<'w, Pointer>, + pressed_events: EventWriter<'w, Pointer>, drag_drop_events: EventWriter<'w, Pointer>, drag_end_events: EventWriter<'w, Pointer>, drag_enter_events: EventWriter<'w, Pointer>, @@ -412,7 +412,7 @@ pub struct PickingEventWriters<'w> { move_events: EventWriter<'w, Pointer>, out_events: EventWriter<'w, Pointer>, over_events: EventWriter<'w, Pointer>, - released_events: EventWriter<'w, Pointer>, + released_events: EventWriter<'w, Pointer>, } /// 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(), }, diff --git a/crates/bevy_picking/src/hover.rs b/crates/bevy_picking/src/hover.rs index 529cb94e8c..dbb6ee942e 100644 --- a/crates/bevy_picking/src/hover.rs +++ b/crates/bevy_picking/src/hover.rs @@ -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>, - 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>, - 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::().unwrap(); + // Check to insure that the hovered entity has the Hovered component set to true + let hover = world.entity(hovered_entity).get_ref::().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::().unwrap(); + let hover = world.entity(hovered_entity).get_ref::().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::().unwrap(); + let hover = world.entity(hovered_entity).get_ref::().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::() + .get_ref::() .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::() + .get_ref::() .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::() + .get_ref::() .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::() + .get_ref::() .unwrap(); assert!(!hover.get()); assert!(hover.is_changed()); diff --git a/crates/bevy_picking/src/lib.rs b/crates/bevy_picking/src/lib.rs index fde5801b42..6a7576f132 100644 --- a/crates/bevy_picking/src/lib.rs +++ b/crates/bevy_picking/src/lib.rs @@ -393,7 +393,7 @@ impl Plugin for PickingPlugin { .register_type::() .register_type::() .register_type::() - .register_type::() + .register_type::() .register_type::() .register_type::() .register_type::() @@ -416,7 +416,7 @@ impl Plugin for InteractionPlugin { .init_resource::() .add_event::>() .add_event::>() - .add_event::>() + .add_event::>() .add_event::>() .add_event::>() .add_event::>() @@ -427,7 +427,7 @@ impl Plugin for InteractionPlugin { .add_event::>() .add_event::>() .add_event::>() - .add_event::>() + .add_event::>() .add_event::>() .add_systems( PreUpdate, diff --git a/crates/bevy_ui/src/interaction_states.rs b/crates/bevy_ui/src/interaction_states.rs index eed4864258..f91cdaee59 100644 --- a/crates/bevy_ui/src/interaction_states.rs +++ b/crates/bevy_ui/src/interaction_states.rs @@ -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, mut world: DeferredWorld) { +pub(crate) fn on_insert_is_checked(trigger: Trigger, mut world: DeferredWorld) { let mut entity = world.entity_mut(trigger.target().unwrap()); let checked = entity.get::().unwrap().get(); if let Some(mut accessibility) = entity.get_mut::() { @@ -66,7 +66,7 @@ pub(crate) fn on_insert_checked(trigger: Trigger, mut world: } } -pub(crate) fn on_remove_checked(trigger: Trigger, mut world: DeferredWorld) { +pub(crate) fn on_remove_is_checked(trigger: Trigger, mut world: DeferredWorld) { let mut entity = world.entity_mut(trigger.target().unwrap()); if let Some(mut accessibility) = entity.get_mut::() { accessibility.set_toggled(accesskit::Toggled::False); diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 6edfad0967..ac70897d06 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -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, diff --git a/examples/picking/mesh_picking.rs b/examples/picking/mesh_picking.rs index 4c247aa62a..c9023f48b8 100644 --- a/examples/picking/mesh_picking.rs +++ b/examples/picking/mesh_picking.rs @@ -91,8 +91,8 @@ fn setup_scene( )) .observe(update_material_on::>(hover_matl.clone())) .observe(update_material_on::>(white_matl.clone())) - .observe(update_material_on::>(pressed_matl.clone())) - .observe(update_material_on::>(hover_matl.clone())) + .observe(update_material_on::>(pressed_matl.clone())) + .observe(update_material_on::>(hover_matl.clone())) .observe(rotate_on_drag); } @@ -114,8 +114,8 @@ fn setup_scene( )) .observe(update_material_on::>(hover_matl.clone())) .observe(update_material_on::>(white_matl.clone())) - .observe(update_material_on::>(pressed_matl.clone())) - .observe(update_material_on::>(hover_matl.clone())) + .observe(update_material_on::>(pressed_matl.clone())) + .observe(update_material_on::>(hover_matl.clone())) .observe(rotate_on_drag); } diff --git a/examples/picking/sprite_picking.rs b/examples/picking/sprite_picking.rs index 99403e9192..cf7308671e 100644 --- a/examples/picking/sprite_picking.rs +++ b/examples/picking/sprite_picking.rs @@ -63,8 +63,8 @@ fn setup(mut commands: Commands, asset_server: Res) { )) .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))) .observe(recolor_on::>(Color::BLACK)) - .observe(recolor_on::>(Color::srgb(1.0, 1.0, 0.0))) - .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))); + .observe(recolor_on::>(Color::srgb(1.0, 1.0, 0.0))) + .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))); commands .spawn(( @@ -83,8 +83,8 @@ fn setup(mut commands: Commands, asset_server: Res) { )) .observe(recolor_on::>(Color::srgb(0.0, 1.0, 0.0))) .observe(recolor_on::>(Color::srgb(1.0, 0.0, 0.0))) - .observe(recolor_on::>(Color::srgb(0.0, 0.0, 1.0))) - .observe(recolor_on::>(Color::srgb(0.0, 1.0, 0.0))); + .observe(recolor_on::>(Color::srgb(0.0, 0.0, 1.0))) + .observe(recolor_on::>(Color::srgb(0.0, 1.0, 0.0))); } }); } @@ -145,8 +145,8 @@ fn setup_atlas( )) .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))) .observe(recolor_on::>(Color::srgb(1.0, 1.0, 1.0))) - .observe(recolor_on::>(Color::srgb(1.0, 1.0, 0.0))) - .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))); + .observe(recolor_on::>(Color::srgb(1.0, 1.0, 0.0))) + .observe(recolor_on::>(Color::srgb(0.0, 1.0, 1.0))); } // An observer listener that changes the target entity's color. diff --git a/examples/ui/core_widgets.rs b/examples/ui/core_widgets.rs index 69a45f3e50..594f43efd8 100644 --- a/examples/ui/core_widgets.rs +++ b/examples/ui/core_widgets.rs @@ -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, - &IsHovered, + Has, + &Hovered, Has, &mut BackgroundColor, &mut BorderColor, @@ -47,8 +47,8 @@ fn update_button_style( ), ( Or<( - Changed, - Changed, + Changed, + Changed, Added, )>, With, @@ -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, - &IsHovered, + Has, + &Hovered, Has, &mut BackgroundColor, &mut BorderColor, @@ -82,19 +82,19 @@ fn update_button_style2( ), With, >, - mut removed_depressed: RemovedComponents, + mut removed_depressed: RemovedComponents, mut removed_disabled: RemovedComponents, 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, diff --git a/examples/ui/core_widgets_observers.rs b/examples/ui/core_widgets_observers.rs index 55dc2d36b1..206c596e2c 100644 --- a/examples/ui/core_widgets_observers.rs +++ b/examples/ui/core_widgets_observers.rs @@ -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, + trigger: Trigger, mut buttons: Query< ( - &IsHovered, + &Hovered, Has, &mut BackgroundColor, &mut BorderColor, @@ -67,10 +67,10 @@ fn on_add_pressed( } fn on_remove_pressed( - trigger: Trigger, + trigger: Trigger, mut buttons: Query< ( - &IsHovered, + &Hovered, Has, &mut BackgroundColor, &mut BorderColor, @@ -99,8 +99,8 @@ fn on_add_disabled( trigger: Trigger, mut buttons: Query< ( - Has, - &IsHovered, + Has, + &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, mut buttons: Query< ( - Has, - &IsHovered, + Has, + &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, + trigger: Trigger, mut buttons: Query< ( - Has, - &IsHovered, + Has, + &Hovered, Has, &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, diff --git a/examples/ui/scroll.rs b/examples/ui/scroll.rs index 535e351c16..a3a443b991 100644 --- a/examples/ui/scroll.rs +++ b/examples/ui/scroll.rs @@ -89,7 +89,7 @@ fn setup(mut commands: Commands, asset_server: Res) { ..default() }) .observe(| - trigger: Trigger>, + trigger: Trigger>, mut commands: Commands | { if trigger.event().button == PointerButton::Primary { diff --git a/examples/usages/context_menu.rs b/examples/usages/context_menu.rs index ea595be877..d315f8badb 100644 --- a/examples/usages/context_menu.rs +++ b/examples/usages/context_menu.rs @@ -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>, mut commands: Commands| { + |_: Trigger>, mut commands: Commands| { commands.trigger(CloseContextMenus); }, ); @@ -108,11 +108,11 @@ fn on_trigger_menu(trigger: Trigger, mut commands: Commands) { ], )) .observe( - |trigger: Trigger>, + |trigger: Trigger>, menu_items: Query<&ContextMenuItem>, mut clear_col: ResMut, mut commands: Commands| { - // Note that we want to know the target of the `Pointer` event (Button) here. + // Note that we want to know the target of the `Pointer` 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>, mut commands: Commands| { + |mut trigger: Trigger>, 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); diff --git a/release-content/migration-guides/rename_pointer_events.md b/release-content/migration-guides/rename_pointer_events.md new file mode 100644 index 0000000000..38e9b07821 --- /dev/null +++ b/release-content/migration-guides/rename_pointer_events.md @@ -0,0 +1,6 @@ +--- +title: Rename `Pointer` and `Pointer` to `Pointer` and `Pointer` +pull_requests: [19179] +--- + +The `Pointer` and `Pointer` events have been renamed to `Pointer` and `Pointer` 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. diff --git a/release-content/release-notes/headless-widgets.md b/release-content/release-notes/headless-widgets.md index a71e7aad2b..5d39ffe755 100644 --- a/release-content/release-notes/headless-widgets.md +++ b/release-content/release-notes/headless-widgets.md @@ -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