Rename PickingBehavior
to Pickable
(#17266)
# Objective PR #17225 allowed for sprite picking to be opt-in. After some discussion, it was agreed that `PickingBehavior` should be used to opt-in to sprite picking behavior for entities. This leads to `PickingBehavior` having two purposes: mark an entity for use in a backend, and describe how it should be picked. Discussion led to the name `Pickable`making more sense (also: this is what the component was named before upstreaming). A follow-up pass will be made after this PR to unify backends. ## Solution Replace all instances of `PickingBehavior` and `picking_behavior` with `Pickable` and `pickable`, respectively. ## Testing CI ## Migration Guide Change all instances of `PickingBehavior` to `Pickable`.
This commit is contained in:
parent
8ac1f8ccdc
commit
02bb151889
@ -293,7 +293,7 @@ pub fn debug_draw(
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.insert(TargetCamera(camera));
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
//! - The [`PointerHits`] events produced by a backend do **not** need to be sorted or filtered, all
|
||||
//! that is needed is an unordered list of entities and their [`HitData`].
|
||||
//!
|
||||
//! - Backends do not need to consider the [`PickingBehavior`](crate::PickingBehavior) component, though they may
|
||||
//! - Backends do not need to consider the [`Pickable`](crate::Pickable) component, though they may
|
||||
//! use it for optimization purposes. For example, a backend that traverses a spatial hierarchy
|
||||
//! may want to exit early if it intersects an entity that blocks lower entities from being
|
||||
//! picked.
|
||||
@ -42,7 +42,7 @@ pub mod prelude {
|
||||
pub use super::{ray::RayMap, HitData, PointerHits};
|
||||
pub use crate::{
|
||||
pointer::{PointerId, PointerLocation},
|
||||
PickSet, PickingBehavior,
|
||||
PickSet, Pickable,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ use std::collections::HashSet;
|
||||
use crate::{
|
||||
backend::{self, HitData},
|
||||
pointer::{PointerAction, PointerId, PointerInput, PointerInteraction, PointerPress},
|
||||
PickingBehavior,
|
||||
Pickable,
|
||||
};
|
||||
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
@ -43,8 +43,8 @@ type OverMap = HashMap<PointerId, LayerMap>;
|
||||
/// between it and the pointer block interactions.
|
||||
///
|
||||
/// For example, if a pointer is hitting a UI button and a 3d mesh, but the button is in front of
|
||||
/// the mesh, the UI button will be hovered, but the mesh will not. Unless, the [`PickingBehavior`]
|
||||
/// component is present with [`should_block_lower`](PickingBehavior::should_block_lower) set to `false`.
|
||||
/// the mesh, the UI button will be hovered, but the mesh will not. Unless, the [`Pickable`]
|
||||
/// component is present with [`should_block_lower`](Pickable::should_block_lower) set to `false`.
|
||||
///
|
||||
/// # Advanced Users
|
||||
///
|
||||
@ -64,7 +64,7 @@ pub struct PreviousHoverMap(pub HashMap<PointerId, HashMap<Entity, HitData>>);
|
||||
/// This is the final focusing step to determine which entity the pointer is hovering over.
|
||||
pub fn generate_hovermap(
|
||||
// Inputs
|
||||
picking_behavior: Query<&PickingBehavior>,
|
||||
pickable: Query<&Pickable>,
|
||||
pointers: Query<&PointerId>,
|
||||
mut under_pointer: EventReader<backend::PointerHits>,
|
||||
mut pointer_input: EventReader<PointerInput>,
|
||||
@ -81,7 +81,7 @@ pub fn generate_hovermap(
|
||||
&pointers,
|
||||
);
|
||||
build_over_map(&mut under_pointer, &mut over_map, &mut pointer_input);
|
||||
build_hover_map(&pointers, picking_behavior, &over_map, &mut hover_map);
|
||||
build_hover_map(&pointers, pickable, &over_map, &mut hover_map);
|
||||
}
|
||||
|
||||
/// Clear non-empty local maps, reusing allocated memory.
|
||||
@ -148,12 +148,12 @@ fn build_over_map(
|
||||
}
|
||||
}
|
||||
|
||||
/// Build an unsorted set of hovered entities, accounting for depth, layer, and [`PickingBehavior`]. Note
|
||||
/// that unlike the pointer map, this uses [`PickingBehavior`] to determine if lower entities receive hover
|
||||
/// Build an unsorted set of hovered entities, accounting for depth, layer, and [`Pickable`]. Note
|
||||
/// that unlike the pointer map, this uses [`Pickable`] to determine if lower entities receive hover
|
||||
/// focus. Often, only a single entity per pointer will be hovered.
|
||||
fn build_hover_map(
|
||||
pointers: &Query<&PointerId>,
|
||||
picking_behavior: Query<&PickingBehavior>,
|
||||
pickable: Query<&Pickable>,
|
||||
over_map: &Local<OverMap>,
|
||||
// Output
|
||||
hover_map: &mut HoverMap,
|
||||
@ -163,11 +163,11 @@ fn build_hover_map(
|
||||
if let Some(layer_map) = over_map.get(pointer_id) {
|
||||
// Note we reverse here to start from the highest layer first.
|
||||
for (entity, pick_data) in layer_map.values().rev().flatten() {
|
||||
if let Ok(picking_behavior) = picking_behavior.get(*entity) {
|
||||
if picking_behavior.is_hoverable {
|
||||
if let Ok(pickable) = pickable.get(*entity) {
|
||||
if pickable.is_hoverable {
|
||||
pointer_entity_set.insert(*entity, pick_data.clone());
|
||||
}
|
||||
if picking_behavior.should_block_lower {
|
||||
if pickable.should_block_lower {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -142,7 +142,7 @@
|
||||
//! just because a pointer is over an entity, it is not necessarily *hovering* that entity. Although
|
||||
//! multiple backends may be reporting that a pointer is hitting an entity, the hover system needs
|
||||
//! to determine which entities are actually being hovered by this pointer based on the pick depth,
|
||||
//! order of the backend, and the optional [`PickingBehavior`] component of the entity. In other
|
||||
//! order of the backend, and the optional [`Pickable`] component of the entity. In other
|
||||
//! words, if one entity is in front of another, usually only the topmost one will be hovered.
|
||||
//!
|
||||
//! #### Events ([`events`])
|
||||
@ -189,7 +189,7 @@ pub mod prelude {
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
events::*, input::PointerInputPlugin, pointer::PointerButton, DefaultPickingPlugins,
|
||||
InteractionPlugin, PickingBehavior, PickingPlugin,
|
||||
InteractionPlugin, Pickable, PickingPlugin,
|
||||
};
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ pub mod prelude {
|
||||
/// See the documentation on the fields for more details.
|
||||
#[derive(Component, Debug, Clone, Reflect, PartialEq, Eq)]
|
||||
#[reflect(Component, Default, Debug, PartialEq)]
|
||||
pub struct PickingBehavior {
|
||||
pub struct Pickable {
|
||||
/// Should this entity block entities below it from being picked?
|
||||
///
|
||||
/// This is useful if you want picking to continue hitting entities below this one. Normally,
|
||||
@ -221,7 +221,7 @@ pub struct PickingBehavior {
|
||||
/// element will be marked as hovered. However, if this field is set to `false`, both the UI
|
||||
/// element *and* the mesh will be marked as hovered.
|
||||
///
|
||||
/// Entities without the [`PickingBehavior`] component will block by default.
|
||||
/// Entities without the [`Pickable`] component will block by default.
|
||||
pub should_block_lower: bool,
|
||||
|
||||
/// If this is set to `false` and `should_block_lower` is set to true, this entity will block
|
||||
@ -236,11 +236,11 @@ pub struct PickingBehavior {
|
||||
/// components mark it as hovered. This can be combined with the other field
|
||||
/// [`Self::should_block_lower`], which is orthogonal to this one.
|
||||
///
|
||||
/// Entities without the [`PickingBehavior`] component are hoverable by default.
|
||||
/// Entities without the [`Pickable`] component are hoverable by default.
|
||||
pub is_hoverable: bool,
|
||||
}
|
||||
|
||||
impl PickingBehavior {
|
||||
impl Pickable {
|
||||
/// This entity will not block entities beneath it, nor will it emit events.
|
||||
///
|
||||
/// If a backend reports this entity as being hit, the picking plugin will completely ignore it.
|
||||
@ -250,7 +250,7 @@ impl PickingBehavior {
|
||||
};
|
||||
}
|
||||
|
||||
impl Default for PickingBehavior {
|
||||
impl Default for Pickable {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
should_block_lower: true,
|
||||
@ -391,7 +391,7 @@ impl Plugin for PickingPlugin {
|
||||
.chain(),
|
||||
)
|
||||
.register_type::<Self>()
|
||||
.register_type::<PickingBehavior>()
|
||||
.register_type::<Pickable>()
|
||||
.register_type::<pointer::PointerId>()
|
||||
.register_type::<pointer::PointerLocation>()
|
||||
.register_type::<pointer::PointerPress>()
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! A [mesh ray casting](ray_cast) backend for [`bevy_picking`](crate).
|
||||
//!
|
||||
//! By default, all meshes are pickable. Picking can be disabled for individual entities
|
||||
//! by adding [`PickingBehavior::IGNORE`].
|
||||
//! by adding [`Pickable::IGNORE`].
|
||||
//!
|
||||
//! To make mesh picking entirely opt-in, set [`MeshPickingSettings::require_markers`]
|
||||
//! to `true` and add a [`RayCastPickable`] component to the desired camera and target entities.
|
||||
@ -72,7 +72,7 @@ pub fn update_hits(
|
||||
backend_settings: Res<MeshPickingSettings>,
|
||||
ray_map: Res<RayMap>,
|
||||
picking_cameras: Query<(&Camera, Option<&RayCastPickable>, Option<&RenderLayers>)>,
|
||||
pickables: Query<&PickingBehavior>,
|
||||
pickables: Query<&Pickable>,
|
||||
marked_targets: Query<&RayCastPickable>,
|
||||
layers: Query<&RenderLayers>,
|
||||
mut ray_cast: MeshRayCast,
|
||||
|
@ -37,7 +37,7 @@ pub enum SpritePickingMode {
|
||||
#[reflect(Resource, Default)]
|
||||
pub struct SpritePickingSettings {
|
||||
/// When set to `true` sprite picking will only consider cameras marked with
|
||||
/// [`SpritePickingCamera`] and entities marked with [`PickingBehavior`]. `false` by default.
|
||||
/// [`SpritePickingCamera`] and entities marked with [`Pickable`]. `false` by default.
|
||||
///
|
||||
/// This setting is provided to give you fine-grained control over which cameras and entities
|
||||
/// should be used by the sprite picking backend at runtime.
|
||||
@ -89,17 +89,17 @@ fn sprite_picking(
|
||||
Entity,
|
||||
&Sprite,
|
||||
&GlobalTransform,
|
||||
Option<&PickingBehavior>,
|
||||
Option<&Pickable>,
|
||||
&ViewVisibility,
|
||||
)>,
|
||||
mut output: EventWriter<PointerHits>,
|
||||
) {
|
||||
let mut sorted_sprites: Vec<_> = sprite_query
|
||||
.iter()
|
||||
.filter_map(|(entity, sprite, transform, picking_behavior, vis)| {
|
||||
let marker_requirement = !settings.require_markers || picking_behavior.is_some();
|
||||
.filter_map(|(entity, sprite, transform, pickable, vis)| {
|
||||
let marker_requirement = !settings.require_markers || pickable.is_some();
|
||||
if !transform.affine().is_nan() && vis.get() && marker_requirement {
|
||||
Some((entity, sprite, transform, picking_behavior))
|
||||
Some((entity, sprite, transform, pickable))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -149,7 +149,7 @@ fn sprite_picking(
|
||||
let picks: Vec<(Entity, HitData)> = sorted_sprites
|
||||
.iter()
|
||||
.copied()
|
||||
.filter_map(|(entity, sprite, sprite_transform, picking_behavior)| {
|
||||
.filter_map(|(entity, sprite, sprite_transform, pickable)| {
|
||||
if blocked {
|
||||
return None;
|
||||
}
|
||||
@ -215,7 +215,7 @@ fn sprite_picking(
|
||||
};
|
||||
|
||||
blocked = cursor_in_valid_pixels_of_sprite
|
||||
&& picking_behavior.is_none_or(|p| p.should_block_lower);
|
||||
&& pickable.is_none_or(|p| p.should_block_lower);
|
||||
|
||||
cursor_in_valid_pixels_of_sprite.then(|| {
|
||||
let hit_pos_world =
|
||||
|
@ -8,8 +8,8 @@
|
||||
//! ## Important Note
|
||||
//!
|
||||
//! This backend completely ignores [`FocusPolicy`](crate::FocusPolicy). The design of `bevy_ui`'s
|
||||
//! focus systems and the picking plugin are not compatible. Instead, use the optional [`PickingBehavior`] component
|
||||
//! to override how an entity responds to picking focus. Nodes without the [`PickingBehavior`] component
|
||||
//! focus systems and the picking plugin are not compatible. Instead, use the optional [`Pickable`] component
|
||||
//! to override how an entity responds to picking focus. Nodes without the [`Pickable`] component
|
||||
//! will still trigger events and block items below it from being hovered.
|
||||
//!
|
||||
//! ## Implementation Notes
|
||||
@ -48,7 +48,7 @@ pub struct NodeQuery {
|
||||
entity: Entity,
|
||||
node: &'static ComputedNode,
|
||||
global_transform: &'static GlobalTransform,
|
||||
picking_behavior: Option<&'static PickingBehavior>,
|
||||
pickable: Option<&'static Pickable>,
|
||||
calculated_clip: Option<&'static CalculatedClip>,
|
||||
view_visibility: Option<&'static ViewVisibility>,
|
||||
target_camera: Option<&'static TargetCamera>,
|
||||
@ -196,13 +196,13 @@ pub fn ui_picking(
|
||||
|
||||
picks.push((node.entity, HitData::new(camera_entity, depth, None, None)));
|
||||
|
||||
if let Some(picking_behavior) = node.picking_behavior {
|
||||
// If an entity has a `PickingBehavior` component, we will use that as the source of truth.
|
||||
if picking_behavior.should_block_lower {
|
||||
if let Some(pickable) = node.pickable {
|
||||
// If an entity has a `Pickable` component, we will use that as the source of truth.
|
||||
if pickable.should_block_lower {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// If the PickingBehavior component doesn't exist, default behavior is to block.
|
||||
// If the `Pickable` component doesn't exist, default behavior is to block.
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -319,11 +319,11 @@ const fn uv_rect_opengl(gl_min: Vec2, size: Vec2) -> Rect {
|
||||
/// hit on the sphere itself.
|
||||
fn make_sphere_nonpickable(
|
||||
mut commands: Commands,
|
||||
mut query: Query<(Entity, &Name), (With<Mesh3d>, Without<PickingBehavior>)>,
|
||||
mut query: Query<(Entity, &Name), (With<Mesh3d>, Without<Pickable>)>,
|
||||
) {
|
||||
for (sphere, name) in &mut query {
|
||||
if &**name == "Sphere" {
|
||||
commands.entity(sphere).insert(PickingBehavior::IGNORE);
|
||||
commands.entity(sphere).insert(Pickable::IGNORE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ fn setup_scene(
|
||||
commands.spawn((
|
||||
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0).subdivisions(10))),
|
||||
MeshMaterial3d(ground_matl.clone()),
|
||||
PickingBehavior::IGNORE, // Disable picking for the ground plane.
|
||||
Pickable::IGNORE, // Disable picking for the ground plane.
|
||||
));
|
||||
|
||||
// Light
|
||||
|
@ -36,7 +36,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
justify_content: JustifyContent::SpaceBetween,
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.with_children(|parent| {
|
||||
// left vertical fill (border)
|
||||
parent
|
||||
@ -174,7 +174,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
Label,
|
||||
AccessibilityNode(Accessible::new(Role::ListItem)),
|
||||
))
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
});
|
||||
@ -236,7 +236,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
justify_content: JustifyContent::Center,
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn((
|
||||
@ -352,7 +352,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
padding: UiRect::all(Val::Px(10.)),
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.with_children(|parent| {
|
||||
for (flip_x, flip_y) in
|
||||
[(false, false), (false, true), (true, true), (true, false)]
|
||||
|
@ -35,7 +35,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
flex_direction: FlexDirection::Column,
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.with_children(|parent| {
|
||||
// horizontal scroll example
|
||||
parent
|
||||
@ -84,7 +84,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
align_content: AlignContent::Center,
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
})
|
||||
@ -151,7 +151,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
max_height: Val::Px(LINE_HEIGHT),
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
})
|
||||
@ -169,7 +169,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
Role::ListItem,
|
||||
)),
|
||||
))
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
});
|
||||
@ -218,7 +218,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
flex_direction: FlexDirection::Row,
|
||||
..default()
|
||||
})
|
||||
.insert(PickingBehavior::IGNORE)
|
||||
.insert(Pickable::IGNORE)
|
||||
.with_children(|parent| {
|
||||
// Elements in each row
|
||||
for i in 0..25 {
|
||||
@ -236,7 +236,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
Role::ListItem,
|
||||
)),
|
||||
))
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
});
|
||||
@ -292,7 +292,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
},
|
||||
BackgroundColor(Color::srgb(0.05, 0.05, 0.05)),
|
||||
))
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
})
|
||||
@ -312,7 +312,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
Role::ListItem,
|
||||
)),
|
||||
))
|
||||
.insert(PickingBehavior {
|
||||
.insert(Pickable {
|
||||
should_block_lower: false,
|
||||
..default()
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user