Unify picking backends (#17348)
# Objective Currently, our picking backends are inconsistent: - Mesh picking and sprite picking both have configurable opt in/out behavior. UI picking does not. - Sprite picking uses `SpritePickingCamera` and `Pickable` for control, but mesh picking uses `RayCastPickable`. - `MeshPickingPlugin` is not a part of `DefaultPlugins`. `SpritePickingPlugin` and `UiPickingPlugin` are. ## Solution - Add configurable opt in/out behavior to UI picking (defaults to opt out). - Replace `RayCastPickable` with `MeshPickingCamera` and `Pickable`. - Remove `SpritePickingPlugin` and `UiPickingPlugin` from `DefaultPlugins`. ## Testing Ran some examples. ## Migration Guide `UiPickingPlugin` and `SpritePickingPlugin` are no longer included in `DefaultPlugins`. They must be explicitly added. `RayCastPickable` has been replaced in favor of the `MeshPickingCamera` and `Pickable` components. You should add them to cameras and entities, respectively, if you have `MeshPickingSettings::require_markers` set to `true`. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
c9f37efeb7
commit
f04406ccce
@ -179,7 +179,7 @@ pub mod prelude {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::mesh_picking::{
|
pub use crate::mesh_picking::{
|
||||||
ray_cast::{MeshRayCast, MeshRayCastSettings, RayCastBackfaces, RayCastVisibility},
|
ray_cast::{MeshRayCast, MeshRayCastSettings, RayCastBackfaces, RayCastVisibility},
|
||||||
MeshPickingPlugin, MeshPickingSettings, RayCastPickable,
|
MeshPickingCamera, MeshPickingPlugin, MeshPickingSettings,
|
||||||
};
|
};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
//! by adding [`Pickable::IGNORE`].
|
//! by adding [`Pickable::IGNORE`].
|
||||||
//!
|
//!
|
||||||
//! To make mesh picking entirely opt-in, set [`MeshPickingSettings::require_markers`]
|
//! 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.
|
//! to `true` and add [`MeshPickingCamera`] and [`Pickable`] components to the desired camera and
|
||||||
|
//! target entities.
|
||||||
//!
|
//!
|
||||||
//! To manually perform mesh ray casts independent of picking, use the [`MeshRayCast`] system parameter.
|
//! To manually perform mesh ray casts independent of picking, use the [`MeshRayCast`] system parameter.
|
||||||
//!
|
//!
|
||||||
@ -26,12 +27,19 @@ use bevy_reflect::prelude::*;
|
|||||||
use bevy_render::{prelude::*, view::RenderLayers};
|
use bevy_render::{prelude::*, view::RenderLayers};
|
||||||
use ray_cast::{MeshRayCast, MeshRayCastSettings, RayCastVisibility, SimplifiedMesh};
|
use ray_cast::{MeshRayCast, MeshRayCastSettings, RayCastVisibility, SimplifiedMesh};
|
||||||
|
|
||||||
|
/// An optional component that marks cameras that should be used in the [`MeshPickingPlugin`].
|
||||||
|
///
|
||||||
|
/// Only needed if [`MeshPickingSettings::require_markers`] is set to `true`, and ignored otherwise.
|
||||||
|
#[derive(Debug, Clone, Default, Component, Reflect)]
|
||||||
|
#[reflect(Debug, Default, Component)]
|
||||||
|
pub struct MeshPickingCamera;
|
||||||
|
|
||||||
/// Runtime settings for the [`MeshPickingPlugin`].
|
/// Runtime settings for the [`MeshPickingPlugin`].
|
||||||
#[derive(Resource, Reflect)]
|
#[derive(Resource, Reflect)]
|
||||||
#[reflect(Resource, Default)]
|
#[reflect(Resource, Default)]
|
||||||
pub struct MeshPickingSettings {
|
pub struct MeshPickingSettings {
|
||||||
/// When set to `true` ray casting will only happen between cameras and entities marked with
|
/// When set to `true` ray casting will only consider cameras marked with
|
||||||
/// [`RayCastPickable`]. `false` by default.
|
/// [`MeshPickingCamera`] and entities marked with [`Pickable`]. `false` by default.
|
||||||
///
|
///
|
||||||
/// This setting is provided to give you fine-grained control over which cameras and entities
|
/// This setting is provided to give you fine-grained control over which cameras and entities
|
||||||
/// should be used by the mesh picking backend at runtime.
|
/// should be used by the mesh picking backend at runtime.
|
||||||
@ -54,12 +62,6 @@ impl Default for MeshPickingSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An optional component that marks cameras and target entities that should be used in the [`MeshPickingPlugin`].
|
|
||||||
/// Only needed if [`MeshPickingSettings::require_markers`] is set to `true`, and ignored otherwise.
|
|
||||||
#[derive(Debug, Clone, Default, Component, Reflect)]
|
|
||||||
#[reflect(Component, Default, Clone)]
|
|
||||||
pub struct RayCastPickable;
|
|
||||||
|
|
||||||
/// Adds the mesh picking backend to your app.
|
/// Adds the mesh picking backend to your app.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct MeshPickingPlugin;
|
pub struct MeshPickingPlugin;
|
||||||
@ -67,7 +69,6 @@ pub struct MeshPickingPlugin;
|
|||||||
impl Plugin for MeshPickingPlugin {
|
impl Plugin for MeshPickingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<MeshPickingSettings>()
|
app.init_resource::<MeshPickingSettings>()
|
||||||
.register_type::<RayCastPickable>()
|
|
||||||
.register_type::<MeshPickingSettings>()
|
.register_type::<MeshPickingSettings>()
|
||||||
.register_type::<SimplifiedMesh>()
|
.register_type::<SimplifiedMesh>()
|
||||||
.add_systems(PreUpdate, update_hits.in_set(PickSet::Backend));
|
.add_systems(PreUpdate, update_hits.in_set(PickSet::Backend));
|
||||||
@ -78,18 +79,18 @@ impl Plugin for MeshPickingPlugin {
|
|||||||
pub fn update_hits(
|
pub fn update_hits(
|
||||||
backend_settings: Res<MeshPickingSettings>,
|
backend_settings: Res<MeshPickingSettings>,
|
||||||
ray_map: Res<RayMap>,
|
ray_map: Res<RayMap>,
|
||||||
picking_cameras: Query<(&Camera, Option<&RayCastPickable>, Option<&RenderLayers>)>,
|
picking_cameras: Query<(&Camera, Has<MeshPickingCamera>, Option<&RenderLayers>)>,
|
||||||
pickables: Query<&Pickable>,
|
pickables: Query<&Pickable>,
|
||||||
marked_targets: Query<&RayCastPickable>,
|
marked_targets: Query<&Pickable>,
|
||||||
layers: Query<&RenderLayers>,
|
layers: Query<&RenderLayers>,
|
||||||
mut ray_cast: MeshRayCast,
|
mut ray_cast: MeshRayCast,
|
||||||
mut output: EventWriter<PointerHits>,
|
mut output: EventWriter<PointerHits>,
|
||||||
) {
|
) {
|
||||||
for (&ray_id, &ray) in ray_map.map().iter() {
|
for (&ray_id, &ray) in ray_map.map().iter() {
|
||||||
let Ok((camera, cam_pickable, cam_layers)) = picking_cameras.get(ray_id.camera) else {
|
let Ok((camera, cam_can_pick, cam_layers)) = picking_cameras.get(ray_id.camera) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if backend_settings.require_markers && cam_pickable.is_none() {
|
if backend_settings.require_markers && !cam_can_pick {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@ mod texture_slice;
|
|||||||
///
|
///
|
||||||
/// This includes the most common types in this crate, re-exported for your convenience.
|
/// This includes the most common types in this crate, re-exported for your convenience.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
#[cfg(feature = "bevy_sprite_picking_backend")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::picking_backend::{
|
||||||
|
SpritePickingCamera, SpritePickingMode, SpritePickingPlugin, SpritePickingSettings,
|
||||||
|
};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
sprite::{Sprite, SpriteImageMode},
|
sprite::{Sprite, SpriteImageMode},
|
||||||
@ -52,28 +57,8 @@ use bevy_render::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Adds support for 2D sprite rendering.
|
/// Adds support for 2D sprite rendering.
|
||||||
pub struct SpritePlugin {
|
#[derive(Default)]
|
||||||
/// Whether to add the sprite picking backend to the app.
|
pub struct SpritePlugin;
|
||||||
#[cfg(feature = "bevy_sprite_picking_backend")]
|
|
||||||
pub add_picking: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[expect(
|
|
||||||
clippy::allow_attributes,
|
|
||||||
reason = "clippy::derivable_impls is not always linted"
|
|
||||||
)]
|
|
||||||
#[allow(
|
|
||||||
clippy::derivable_impls,
|
|
||||||
reason = "Known false positive with clippy: <https://github.com/rust-lang/rust-clippy/issues/13160>"
|
|
||||||
)]
|
|
||||||
impl Default for SpritePlugin {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
#[cfg(feature = "bevy_sprite_picking_backend")]
|
|
||||||
add_picking: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const SPRITE_SHADER_HANDLE: Handle<Shader> =
|
pub const SPRITE_SHADER_HANDLE: Handle<Shader> =
|
||||||
weak_handle!("ed996613-54c0-49bd-81be-1c2d1a0d03c2");
|
weak_handle!("ed996613-54c0-49bd-81be-1c2d1a0d03c2");
|
||||||
@ -125,9 +110,7 @@ impl Plugin for SpritePlugin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "bevy_sprite_picking_backend")]
|
#[cfg(feature = "bevy_sprite_picking_backend")]
|
||||||
if self.add_picking {
|
app.add_plugins(SpritePickingPlugin);
|
||||||
app.add_plugins(SpritePickingPlugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||||
render_app
|
render_app
|
||||||
|
@ -20,7 +20,10 @@ use bevy_render::prelude::*;
|
|||||||
use bevy_transform::prelude::*;
|
use bevy_transform::prelude::*;
|
||||||
use bevy_window::PrimaryWindow;
|
use bevy_window::PrimaryWindow;
|
||||||
|
|
||||||
/// A component that marks cameras that should be used in the [`SpritePickingPlugin`].
|
/// An optional component that marks cameras that should be used in the [`SpritePickingPlugin`].
|
||||||
|
///
|
||||||
|
/// Only needed if [`SpritePickingSettings::require_markers`] is set to `true`, and ignored
|
||||||
|
/// otherwise.
|
||||||
#[derive(Debug, Clone, Default, Component, Reflect)]
|
#[derive(Debug, Clone, Default, Component, Reflect)]
|
||||||
#[reflect(Debug, Default, Component, Clone)]
|
#[reflect(Debug, Default, Component, Clone)]
|
||||||
pub struct SpritePickingCamera;
|
pub struct SpritePickingCamera;
|
||||||
@ -62,6 +65,7 @@ impl Default for SpritePickingSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enables the sprite picking backend, allowing you to click on, hover over and drag sprites.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SpritePickingPlugin;
|
pub struct SpritePickingPlugin;
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ pub use focus::*;
|
|||||||
pub use geometry::*;
|
pub use geometry::*;
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
pub use measurement::*;
|
pub use measurement::*;
|
||||||
|
use prelude::UiPickingPlugin;
|
||||||
pub use render::*;
|
pub use render::*;
|
||||||
pub use ui_material::*;
|
pub use ui_material::*;
|
||||||
pub use ui_node::*;
|
pub use ui_node::*;
|
||||||
@ -45,6 +46,9 @@ use widget::{ImageNode, ImageNodeSize};
|
|||||||
///
|
///
|
||||||
/// This includes the most common types in this crate, re-exported for your convenience.
|
/// This includes the most common types in this crate, re-exported for your convenience.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
#[cfg(feature = "bevy_ui_picking_backend")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::picking_backend::{UiPickingCamera, UiPickingPlugin, UiPickingSettings};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "bevy_ui_debug")]
|
#[cfg(feature = "bevy_ui_debug")]
|
||||||
pub use crate::render::UiDebugOptions;
|
pub use crate::render::UiDebugOptions;
|
||||||
@ -79,17 +83,12 @@ pub struct UiPlugin {
|
|||||||
/// If set to false, the UI's rendering systems won't be added to the `RenderApp` and no UI elements will be drawn.
|
/// If set to false, the UI's rendering systems won't be added to the `RenderApp` and no UI elements will be drawn.
|
||||||
/// The layout and interaction components will still be updated as normal.
|
/// The layout and interaction components will still be updated as normal.
|
||||||
pub enable_rendering: bool,
|
pub enable_rendering: bool,
|
||||||
/// Whether to add the UI picking backend to the app.
|
|
||||||
#[cfg(feature = "bevy_ui_picking_backend")]
|
|
||||||
pub add_picking: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UiPlugin {
|
impl Default for UiPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enable_rendering: true,
|
enable_rendering: true,
|
||||||
#[cfg(feature = "bevy_ui_picking_backend")]
|
|
||||||
add_picking: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,6 +180,7 @@ impl Plugin for UiPlugin {
|
|||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
)
|
)
|
||||||
|
.add_plugins(UiPickingPlugin)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
ui_focus_system.in_set(UiSystem::Focus).after(InputSystem),
|
ui_focus_system.in_set(UiSystem::Focus).after(InputSystem),
|
||||||
@ -219,11 +219,6 @@ impl Plugin for UiPlugin {
|
|||||||
);
|
);
|
||||||
build_text_interop(app);
|
build_text_interop(app);
|
||||||
|
|
||||||
#[cfg(feature = "bevy_ui_picking_backend")]
|
|
||||||
if self.add_picking {
|
|
||||||
app.add_plugins(picking_backend::UiPickingPlugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.enable_rendering {
|
if !self.enable_rendering {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -29,18 +29,59 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_ecs::{prelude::*, query::QueryData};
|
use bevy_ecs::{prelude::*, query::QueryData};
|
||||||
use bevy_math::{Rect, Vec2};
|
use bevy_math::{Rect, Vec2};
|
||||||
use bevy_platform_support::collections::HashMap;
|
use bevy_platform_support::collections::HashMap;
|
||||||
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
use bevy_render::prelude::*;
|
use bevy_render::prelude::*;
|
||||||
use bevy_transform::prelude::*;
|
use bevy_transform::prelude::*;
|
||||||
use bevy_window::PrimaryWindow;
|
use bevy_window::PrimaryWindow;
|
||||||
|
|
||||||
use bevy_picking::backend::prelude::*;
|
use bevy_picking::backend::prelude::*;
|
||||||
|
|
||||||
|
/// An optional component that marks cameras that should be used in the [`UiPickingPlugin`].
|
||||||
|
///
|
||||||
|
/// Only needed if [`UiPickingSettings::require_markers`] is set to `true`, and ignored
|
||||||
|
/// otherwise.
|
||||||
|
#[derive(Debug, Clone, Default, Component, Reflect)]
|
||||||
|
#[reflect(Debug, Default, Component)]
|
||||||
|
pub struct UiPickingCamera;
|
||||||
|
|
||||||
|
/// Runtime settings for the [`UiPickingPlugin`].
|
||||||
|
#[derive(Resource, Reflect)]
|
||||||
|
#[reflect(Resource, Default)]
|
||||||
|
pub struct UiPickingSettings {
|
||||||
|
/// When set to `true` UI picking will only consider cameras marked with
|
||||||
|
/// [`UiPickingCamera`] 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 UI picking backend at runtime.
|
||||||
|
pub require_markers: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(
|
||||||
|
clippy::allow_attributes,
|
||||||
|
reason = "clippy::derivable_impls is not always linted"
|
||||||
|
)]
|
||||||
|
#[allow(
|
||||||
|
clippy::derivable_impls,
|
||||||
|
reason = "Known false positive with clippy: <https://github.com/rust-lang/rust-clippy/issues/13160>"
|
||||||
|
)]
|
||||||
|
impl Default for UiPickingSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
require_markers: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A plugin that adds picking support for UI nodes.
|
/// A plugin that adds picking support for UI nodes.
|
||||||
|
///
|
||||||
|
/// This is included by default in [`UiPlugin`](crate::UiPlugin).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UiPickingPlugin;
|
pub struct UiPickingPlugin;
|
||||||
impl Plugin for UiPickingPlugin {
|
impl Plugin for UiPickingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(PreUpdate, ui_picking.in_set(PickSet::Backend));
|
app.init_resource::<UiPickingSettings>()
|
||||||
|
.register_type::<(UiPickingCamera, UiPickingSettings)>()
|
||||||
|
.add_systems(PreUpdate, ui_picking.in_set(PickSet::Backend));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +104,14 @@ pub struct NodeQuery {
|
|||||||
/// we need for determining picking.
|
/// we need for determining picking.
|
||||||
pub fn ui_picking(
|
pub fn ui_picking(
|
||||||
pointers: Query<(&PointerId, &PointerLocation)>,
|
pointers: Query<(&PointerId, &PointerLocation)>,
|
||||||
camera_query: Query<(Entity, &Camera, Has<IsDefaultUiCamera>)>,
|
camera_query: Query<(
|
||||||
|
Entity,
|
||||||
|
&Camera,
|
||||||
|
Has<IsDefaultUiCamera>,
|
||||||
|
Has<UiPickingCamera>,
|
||||||
|
)>,
|
||||||
primary_window: Query<Entity, With<PrimaryWindow>>,
|
primary_window: Query<Entity, With<PrimaryWindow>>,
|
||||||
|
settings: Res<UiPickingSettings>,
|
||||||
ui_stack: Res<UiStack>,
|
ui_stack: Res<UiStack>,
|
||||||
node_query: Query<NodeQuery>,
|
node_query: Query<NodeQuery>,
|
||||||
mut output: EventWriter<PointerHits>,
|
mut output: EventWriter<PointerHits>,
|
||||||
@ -81,7 +128,8 @@ pub fn ui_picking(
|
|||||||
// cameras. We want to ensure we return all cameras with a matching target.
|
// cameras. We want to ensure we return all cameras with a matching target.
|
||||||
for camera in camera_query
|
for camera in camera_query
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(entity, camera, _)| {
|
.filter(|(_, _, _, cam_can_pick)| !settings.require_markers || *cam_can_pick)
|
||||||
|
.map(|(entity, camera, _, _)| {
|
||||||
(
|
(
|
||||||
entity,
|
entity,
|
||||||
camera.target.normalize(primary_window.single().ok()),
|
camera.target.normalize(primary_window.single().ok()),
|
||||||
@ -91,7 +139,7 @@ pub fn ui_picking(
|
|||||||
.filter(|(_entity, target)| target == &pointer_location.target)
|
.filter(|(_entity, target)| target == &pointer_location.target)
|
||||||
.map(|(cam_entity, _target)| cam_entity)
|
.map(|(cam_entity, _target)| cam_entity)
|
||||||
{
|
{
|
||||||
let Ok((_, camera_data, _)) = camera_query.get(camera) else {
|
let Ok((_, camera_data, _, _)) = camera_query.get(camera) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let mut pointer_pos =
|
let mut pointer_pos =
|
||||||
@ -122,6 +170,10 @@ pub fn ui_picking(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if settings.require_markers && node.pickable.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Nodes that are not rendered should not be interactable
|
// Nodes that are not rendered should not be interactable
|
||||||
if node
|
if node
|
||||||
.inherited_visibility
|
.inherited_visibility
|
||||||
@ -208,7 +260,7 @@ pub fn ui_picking(
|
|||||||
|
|
||||||
let order = camera_query
|
let order = camera_query
|
||||||
.get(*camera)
|
.get(*camera)
|
||||||
.map(|(_, cam, _)| cam.order)
|
.map(|(_, cam, _, _)| cam.order)
|
||||||
.unwrap_or_default() as f32
|
.unwrap_or_default() as f32
|
||||||
+ 0.5; // bevy ui can run on any camera, it's a special case
|
+ 0.5; // bevy ui can run on any camera, it's a special case
|
||||||
|
|
||||||
|
@ -10,8 +10,7 @@ fn main() {
|
|||||||
filter: "bevy_dev_tools=trace".into(), // Show picking logs trace level and up
|
filter: "bevy_dev_tools=trace".into(), // Show picking logs trace level and up
|
||||||
..default()
|
..default()
|
||||||
}))
|
}))
|
||||||
// Unlike UiPickingPlugin, MeshPickingPlugin is not a default plugin
|
.add_plugins((MeshPickingPlugin, DebugPickingPlugin, UiPickingPlugin))
|
||||||
.add_plugins((MeshPickingPlugin, DebugPickingPlugin))
|
|
||||||
.add_systems(Startup, setup_scene)
|
.add_systems(Startup, setup_scene)
|
||||||
.insert_resource(DebugPickingMode::Normal)
|
.insert_resource(DebugPickingMode::Normal)
|
||||||
// A system that cycles the debugging state when you press F3:
|
// A system that cycles the debugging state when you press F3:
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
//!
|
//!
|
||||||
//! By default, the mesh picking plugin will raycast against all entities, which is especially
|
//! By default, the mesh picking plugin will raycast against all entities, which is especially
|
||||||
//! useful for debugging. If you want mesh picking to be opt-in, you can set
|
//! useful for debugging. If you want mesh picking to be opt-in, you can set
|
||||||
//! [`MeshPickingSettings::require_markers`] to `true` and add a [`RayCastPickable`] component to
|
//! [`MeshPickingSettings::require_markers`] to `true` and add a [`Pickable`] component to the
|
||||||
//! the desired camera and target entities.
|
//! desired camera and target entities.
|
||||||
|
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
// Unlike UiPickingPlugin, MeshPickingPlugin is not a default plugin
|
.add_plugins((DefaultPlugins, MeshPickingPlugin, UiPickingPlugin))
|
||||||
.add_plugins((DefaultPlugins, MeshPickingPlugin))
|
|
||||||
.add_systems(Startup, setup_scene)
|
.add_systems(Startup, setup_scene)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,10 @@ use std::fmt::Debug;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
|
.add_plugins((
|
||||||
|
DefaultPlugins.set(ImagePlugin::default_nearest()),
|
||||||
|
SpritePickingPlugin,
|
||||||
|
))
|
||||||
.add_systems(Startup, (setup, setup_atlas))
|
.add_systems(Startup, (setup, setup_atlas))
|
||||||
.add_systems(Update, (move_sprite, animate_sprite))
|
.add_systems(Update, (move_sprite, animate_sprite))
|
||||||
.run();
|
.run();
|
||||||
|
@ -31,6 +31,7 @@ fn main() {
|
|||||||
DefaultPlugins,
|
DefaultPlugins,
|
||||||
InputDispatchPlugin,
|
InputDispatchPlugin,
|
||||||
DirectionalNavigationPlugin,
|
DirectionalNavigationPlugin,
|
||||||
|
UiPickingPlugin,
|
||||||
))
|
))
|
||||||
// This resource is canonically used to track whether or not to render a focus indicator
|
// This resource is canonically used to track whether or not to render a focus indicator
|
||||||
// It starts as false, but we set it to true here as we would like to see the focus indicator
|
// It starts as false, but we set it to true here as we would like to see the focus indicator
|
||||||
|
@ -11,7 +11,7 @@ use bevy::{
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
app.add_plugins(DefaultPlugins)
|
app.add_plugins((DefaultPlugins, UiPickingPlugin))
|
||||||
.insert_resource(WinitSettings::desktop_app())
|
.insert_resource(WinitSettings::desktop_app())
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, update_scroll_position);
|
.add_systems(Update, update_scroll_position);
|
||||||
|
@ -12,7 +12,12 @@ use bevy::{
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, InputDispatchPlugin, TabNavigationPlugin))
|
.add_plugins((
|
||||||
|
DefaultPlugins,
|
||||||
|
InputDispatchPlugin,
|
||||||
|
TabNavigationPlugin,
|
||||||
|
UiPickingPlugin,
|
||||||
|
))
|
||||||
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
|
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
|
||||||
.insert_resource(WinitSettings::desktop_app())
|
.insert_resource(WinitSettings::desktop_app())
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
|
Loading…
Reference in New Issue
Block a user