Fix bevy_picking plugin suffixes (#16082)

# Objective

- `MeshPickingBackend` and `SpritePickingBackend` do not have the
`Plugin` suffix
- `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality
it should be a `PluginGroup`
- Fixes #16081.

## Solution

- Rename some structures:

|Original Name|New Name|
|-|-|
|`MeshPickingBackend`|`MeshPickingPlugin`|
|`MeshPickingBackendSettings`|`MeshPickingSettings`|
|`SpritePickingBackend`|`SpritePickingPlugin`|
|`UiPickingBackendPlugin`|`UiPickingPlugin`|

- Make `DefaultPickingPlugins` a `PluginGroup`.
- Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin
group, I also added support for nested plugin groups to the
`plugin_group!` macro.

## Testing

- I used ripgrep to ensure all references were properly renamed.
- For the `plugin_group!` macro, I used `cargo expand` to manually
inspect the expansion of `DefaultPlugins`.

---

## Migration Guide

> [!NOTE]
>
> All 3 of the changed structures were added after 0.14, so this does
not need to be included in the 0.14 to 0.15 migration guide.

- `MeshPickingBackend` is now named `MeshPickingPlugin`.
- `MeshPickingBackendSettings` is now named `MeshPickingSettings`.
- `SpritePickingBackend` is now named `SpritePickingPlugin`.
- `UiPickingBackendPlugin` is now named `UiPickingPlugin`.
- `DefaultPickingPlugins` is now a a `PluginGroup` instead of a
`Plugin`.
This commit is contained in:
BD103 2024-10-25 16:11:51 -04:00 committed by GitHub
parent 611ba8b98e
commit 7c593179e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 82 additions and 31 deletions

View file

@ -48,6 +48,17 @@ use core::any::TypeId;
/// # impl Plugin for WebCompatibilityPlugin { fn build(&self, _: &mut App) {} } /// # impl Plugin for WebCompatibilityPlugin { fn build(&self, _: &mut App) {} }
/// # } /// # }
/// # /// #
/// # mod audio {
/// # use bevy_app::*;
/// # #[derive(Default)]
/// # pub struct AudioPlugins;
/// # impl PluginGroup for AudioPlugins {
/// # fn build(self) -> PluginGroupBuilder {
/// # PluginGroupBuilder::start::<Self>()
/// # }
/// # }
/// # }
/// #
/// # mod internal { /// # mod internal {
/// # use bevy_app::*; /// # use bevy_app::*;
/// # #[derive(Default)] /// # #[derive(Default)]
@ -75,6 +86,10 @@ use core::any::TypeId;
/// // generation, in which case you must wrap it in `#[custom()]`. /// // generation, in which case you must wrap it in `#[custom()]`.
/// #[custom(cfg(target_arch = "wasm32"))] /// #[custom(cfg(target_arch = "wasm32"))]
/// web:::WebCompatibilityPlugin, /// web:::WebCompatibilityPlugin,
/// // You can nest `PluginGroup`s within other `PluginGroup`s, you just need the
/// // `#[plugin_group]` attribute.
/// #[plugin_group]
/// audio:::AudioPlugins,
/// // You can hide plugins from documentation. Due to macro limitations, hidden plugins /// // You can hide plugins from documentation. Due to macro limitations, hidden plugins
/// // must be last. /// // must be last.
/// #[doc(hidden)] /// #[doc(hidden)]
@ -94,6 +109,14 @@ macro_rules! plugin_group {
$(#[custom($plugin_meta:meta)])* $(#[custom($plugin_meta:meta)])*
$($plugin_path:ident::)* : $plugin_name:ident $($plugin_path:ident::)* : $plugin_name:ident
),* ),*
$(
$(,)?$(
#[plugin_group]
$(#[cfg(feature = $plugin_group_feature:literal)])?
$(#[custom($plugin_group_meta:meta)])*
$($plugin_group_path:ident::)* : $plugin_group_name:ident
),+
)?
$( $(
$(,)?$( $(,)?$(
#[doc(hidden)] #[doc(hidden)]
@ -113,6 +136,10 @@ macro_rules! plugin_group {
" - [`", stringify!($plugin_name), "`](" $(, stringify!($plugin_path), "::")*, stringify!($plugin_name), ")" " - [`", stringify!($plugin_name), "`](" $(, stringify!($plugin_path), "::")*, stringify!($plugin_name), ")"
$(, " - with feature `", $plugin_feature, "`")? $(, " - with feature `", $plugin_feature, "`")?
)])* )])*
$($(#[doc = concat!(
" - [`", stringify!($plugin_group_name), "`](" $(, stringify!($plugin_group_path), "::")*, stringify!($plugin_group_name), ")"
$(, " - with feature `", $plugin_group_feature, "`")?
)]),+)?
$( $(
/// ///
$(#[doc = $post_doc])+ $(#[doc = $post_doc])+
@ -135,6 +162,18 @@ macro_rules! plugin_group {
group = group.add(<$($plugin_path::)*$plugin_name>::default()); group = group.add(<$($plugin_path::)*$plugin_name>::default());
} }
)* )*
$($(
$(#[cfg(feature = $plugin_group_feature)])?
$(#[$plugin_group_meta])*
{
const _: () = {
const fn check_default<T: Default>() {}
check_default::<$($plugin_group_path::)*$plugin_group_name>();
};
group = group.add_group(<$($plugin_group_path::)*$plugin_group_name>::default());
}
)+)?
$($( $($(
$(#[cfg(feature = $hidden_plugin_feature)])? $(#[cfg(feature = $hidden_plugin_feature)])?
$(#[$hidden_plugin_meta])* $(#[$hidden_plugin_meta])*

View file

@ -56,12 +56,13 @@ plugin_group! {
bevy_gizmos:::GizmoPlugin, bevy_gizmos:::GizmoPlugin,
#[cfg(feature = "bevy_state")] #[cfg(feature = "bevy_state")]
bevy_state::app:::StatesPlugin, bevy_state::app:::StatesPlugin,
#[cfg(feature = "bevy_picking")]
bevy_picking:::DefaultPickingPlugins,
#[cfg(feature = "bevy_dev_tools")] #[cfg(feature = "bevy_dev_tools")]
bevy_dev_tools:::DevToolsPlugin, bevy_dev_tools:::DevToolsPlugin,
#[cfg(feature = "bevy_ci_testing")] #[cfg(feature = "bevy_ci_testing")]
bevy_dev_tools::ci_testing:::CiTestingPlugin, bevy_dev_tools::ci_testing:::CiTestingPlugin,
#[plugin_group]
#[cfg(feature = "bevy_picking")]
bevy_picking:::DefaultPickingPlugins,
#[doc(hidden)] #[doc(hidden)]
:IgnoreAmbiguitiesPlugin, :IgnoreAmbiguitiesPlugin,
} }

View file

@ -160,7 +160,7 @@ pub mod input;
pub mod mesh_picking; pub mod mesh_picking;
pub mod pointer; pub mod pointer;
use bevy_app::prelude::*; use bevy_app::{prelude::*, PluginGroupBuilder};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_reflect::prelude::*; use bevy_reflect::prelude::*;
@ -172,7 +172,7 @@ pub mod prelude {
#[doc(hidden)] #[doc(hidden)]
pub use crate::mesh_picking::{ pub use crate::mesh_picking::{
ray_cast::{MeshRayCast, RayCastBackfaces, RayCastSettings, RayCastVisibility}, ray_cast::{MeshRayCast, RayCastBackfaces, RayCastSettings, RayCastVisibility},
MeshPickingBackend, MeshPickingBackendSettings, RayCastPickable, MeshPickingPlugin, MeshPickingSettings, RayCastPickable,
}; };
#[doc(hidden)] #[doc(hidden)]
pub use crate::{ pub use crate::{
@ -275,15 +275,26 @@ pub enum PickSet {
#[derive(Default)] #[derive(Default)]
pub struct DefaultPickingPlugins; pub struct DefaultPickingPlugins;
impl Plugin for DefaultPickingPlugins { impl PluginGroup for DefaultPickingPlugins {
fn build(&self, app: &mut App) { fn build(self) -> PluginGroupBuilder {
app.add_plugins(( #[cfg_attr(
input::PointerInputPlugin::default(), not(feature = "bevy_mesh"),
PickingPlugin::default(), expect(
InteractionPlugin, unused_mut,
)); reason = "Group is not mutated when `bevy_mesh` is not enabled."
)
)]
let mut group = PluginGroupBuilder::start::<Self>()
.add(input::PointerInputPlugin::default())
.add(PickingPlugin::default())
.add(InteractionPlugin);
#[cfg(feature = "bevy_mesh")] #[cfg(feature = "bevy_mesh")]
app.add_plugins(mesh_picking::MeshPickingBackend); {
group = group.add(mesh_picking::MeshPickingPlugin);
};
group
} }
} }

View file

@ -3,7 +3,7 @@
//! By default, all meshes are pickable. Picking can be disabled for individual entities //! By default, all meshes are pickable. Picking can be disabled for individual entities
//! by adding [`PickingBehavior::IGNORE`]. //! by adding [`PickingBehavior::IGNORE`].
//! //!
//! To make mesh picking entirely opt-in, set [`MeshPickingBackendSettings::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 a [`RayCastPickable`] component 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.
@ -21,10 +21,10 @@ use bevy_reflect::prelude::*;
use bevy_render::{prelude::*, view::RenderLayers}; use bevy_render::{prelude::*, view::RenderLayers};
use ray_cast::{MeshRayCast, RayCastSettings, RayCastVisibility, SimplifiedMesh}; use ray_cast::{MeshRayCast, RayCastSettings, RayCastVisibility, SimplifiedMesh};
/// Runtime settings for the [`MeshPickingBackend`]. /// Runtime settings for the [`MeshPickingPlugin`].
#[derive(Resource, Reflect)] #[derive(Resource, Reflect)]
#[reflect(Resource, Default)] #[reflect(Resource, Default)]
pub struct MeshPickingBackendSettings { 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 happen between cameras and entities marked with
/// [`RayCastPickable`]. `false` by default. /// [`RayCastPickable`]. `false` by default.
/// ///
@ -40,7 +40,7 @@ pub struct MeshPickingBackendSettings {
pub ray_cast_visibility: RayCastVisibility, pub ray_cast_visibility: RayCastVisibility,
} }
impl Default for MeshPickingBackendSettings { impl Default for MeshPickingSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
require_markers: false, require_markers: false,
@ -49,28 +49,28 @@ impl Default for MeshPickingBackendSettings {
} }
} }
/// An optional component that marks cameras and target entities that should be used in the [`MeshPickingBackend`]. /// An optional component that marks cameras and target entities that should be used in the [`MeshPickingPlugin`].
/// Only needed if [`MeshPickingBackendSettings::require_markers`] is set to `true`, and ignored otherwise. /// Only needed if [`MeshPickingSettings::require_markers`] is set to `true`, and ignored otherwise.
#[derive(Debug, Clone, Default, Component, Reflect)] #[derive(Debug, Clone, Default, Component, Reflect)]
#[reflect(Component, Default)] #[reflect(Component, Default)]
pub struct RayCastPickable; 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 MeshPickingBackend; pub struct MeshPickingPlugin;
impl Plugin for MeshPickingBackend { impl Plugin for MeshPickingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<MeshPickingBackendSettings>() app.init_resource::<MeshPickingSettings>()
.register_type::<(RayCastPickable, MeshPickingBackendSettings, SimplifiedMesh)>() .register_type::<(RayCastPickable, MeshPickingSettings, SimplifiedMesh)>()
.add_systems(PreUpdate, update_hits.in_set(PickSet::Backend)); .add_systems(PreUpdate, update_hits.in_set(PickSet::Backend));
} }
} }
/// Casts rays into the scene using [`MeshPickingBackendSettings`] and sends [`PointerHits`] events. /// Casts rays into the scene using [`MeshPickingSettings`] and sends [`PointerHits`] events.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn update_hits( pub fn update_hits(
backend_settings: Res<MeshPickingBackendSettings>, backend_settings: Res<MeshPickingSettings>,
ray_map: Res<RayMap>, ray_map: Res<RayMap>,
picking_cameras: Query<(&Camera, Option<&RayCastPickable>, Option<&RenderLayers>)>, picking_cameras: Query<(&Camera, Option<&RayCastPickable>, Option<&RenderLayers>)>,
pickables: Query<&PickingBehavior>, pickables: Query<&PickingBehavior>,

View file

@ -135,7 +135,7 @@ impl Plugin for SpritePlugin {
); );
#[cfg(feature = "bevy_sprite_picking_backend")] #[cfg(feature = "bevy_sprite_picking_backend")]
app.add_plugins(picking_backend::SpritePickingBackend); app.add_plugins(picking_backend::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

View file

@ -15,9 +15,9 @@ use bevy_transform::prelude::*;
use bevy_window::PrimaryWindow; use bevy_window::PrimaryWindow;
#[derive(Clone)] #[derive(Clone)]
pub struct SpritePickingBackend; pub struct SpritePickingPlugin;
impl Plugin for SpritePickingBackend { impl Plugin for SpritePickingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(PreUpdate, sprite_picking.in_set(PickSet::Backend)); app.add_systems(PreUpdate, sprite_picking.in_set(PickSet::Backend));
} }

View file

@ -219,7 +219,7 @@ impl Plugin for UiPlugin {
build_text_interop(app); build_text_interop(app);
#[cfg(feature = "bevy_ui_picking_backend")] #[cfg(feature = "bevy_ui_picking_backend")]
app.add_plugins(picking_backend::UiPickingBackendPlugin); app.add_plugins(picking_backend::UiPickingPlugin);
if !self.enable_rendering { if !self.enable_rendering {
return; return;

View file

@ -36,8 +36,8 @@ use bevy_picking::backend::prelude::*;
/// A plugin that adds picking support for UI nodes. /// A plugin that adds picking support for UI nodes.
#[derive(Clone)] #[derive(Clone)]
pub struct UiPickingBackendPlugin; pub struct UiPickingPlugin;
impl Plugin for UiPickingBackendPlugin { 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.add_systems(PreUpdate, ui_picking.in_set(PickSet::Backend));
} }

View file

@ -3,7 +3,7 @@
//! By default, all meshes are pickable. Picking can be disabled for individual entities //! By default, all meshes are pickable. Picking can be disabled for individual entities
//! by adding [`PickingBehavior::IGNORE`]. //! by adding [`PickingBehavior::IGNORE`].
//! //!
//! If you want mesh picking to be entirely opt-in, you can set [`MeshPickingBackendSettings::require_markers`] //! If you want mesh picking to be entirely opt-in, you can set [`MeshPickingSettings::require_markers`]
//! to `true` and add a [`RayCastPickable`] component to the desired camera and target entities. //! to `true` and add a [`RayCastPickable`] component to the desired camera and target entities.
use std::f32::consts::PI; use std::f32::consts::PI;