From 7c593179e371c1b127d3be9f30fda9656ecc2bdf Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:11:51 -0400 Subject: [PATCH] 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`. --- crates/bevy_app/src/plugin_group.rs | 39 +++++++++++++++++++++ crates/bevy_internal/src/default_plugins.rs | 5 +-- crates/bevy_picking/src/lib.rs | 31 ++++++++++------ crates/bevy_picking/src/mesh_picking/mod.rs | 24 ++++++------- crates/bevy_sprite/src/lib.rs | 2 +- crates/bevy_sprite/src/picking_backend.rs | 4 +-- crates/bevy_ui/src/lib.rs | 2 +- crates/bevy_ui/src/picking_backend.rs | 4 +-- examples/picking/mesh_picking.rs | 2 +- 9 files changed, 82 insertions(+), 31 deletions(-) diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index 2fbff372f784f..e828a012d0400 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -48,6 +48,17 @@ use core::any::TypeId; /// # 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::() +/// # } +/// # } +/// # } +/// # /// # mod internal { /// # use bevy_app::*; /// # #[derive(Default)] @@ -75,6 +86,10 @@ use core::any::TypeId; /// // generation, in which case you must wrap it in `#[custom()]`. /// #[custom(cfg(target_arch = "wasm32"))] /// 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 /// // must be last. /// #[doc(hidden)] @@ -94,6 +109,14 @@ macro_rules! plugin_group { $(#[custom($plugin_meta:meta)])* $($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)] @@ -113,6 +136,10 @@ macro_rules! plugin_group { " - [`", stringify!($plugin_name), "`](" $(, stringify!($plugin_path), "::")*, stringify!($plugin_name), ")" $(, " - 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])+ @@ -135,6 +162,18 @@ macro_rules! plugin_group { group = group.add(<$($plugin_path::)*$plugin_name>::default()); } )* + $($( + $(#[cfg(feature = $plugin_group_feature)])? + $(#[$plugin_group_meta])* + { + const _: () = { + const fn check_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)])? $(#[$hidden_plugin_meta])* diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 74008dafafcc8..41754882c926a 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -56,12 +56,13 @@ plugin_group! { bevy_gizmos:::GizmoPlugin, #[cfg(feature = "bevy_state")] bevy_state::app:::StatesPlugin, - #[cfg(feature = "bevy_picking")] - bevy_picking:::DefaultPickingPlugins, #[cfg(feature = "bevy_dev_tools")] bevy_dev_tools:::DevToolsPlugin, #[cfg(feature = "bevy_ci_testing")] bevy_dev_tools::ci_testing:::CiTestingPlugin, + #[plugin_group] + #[cfg(feature = "bevy_picking")] + bevy_picking:::DefaultPickingPlugins, #[doc(hidden)] :IgnoreAmbiguitiesPlugin, } diff --git a/crates/bevy_picking/src/lib.rs b/crates/bevy_picking/src/lib.rs index 8ef2d36a12e48..6c62eb5b142be 100644 --- a/crates/bevy_picking/src/lib.rs +++ b/crates/bevy_picking/src/lib.rs @@ -160,7 +160,7 @@ pub mod input; pub mod mesh_picking; pub mod pointer; -use bevy_app::prelude::*; +use bevy_app::{prelude::*, PluginGroupBuilder}; use bevy_ecs::prelude::*; use bevy_reflect::prelude::*; @@ -172,7 +172,7 @@ pub mod prelude { #[doc(hidden)] pub use crate::mesh_picking::{ ray_cast::{MeshRayCast, RayCastBackfaces, RayCastSettings, RayCastVisibility}, - MeshPickingBackend, MeshPickingBackendSettings, RayCastPickable, + MeshPickingPlugin, MeshPickingSettings, RayCastPickable, }; #[doc(hidden)] pub use crate::{ @@ -275,15 +275,26 @@ pub enum PickSet { #[derive(Default)] pub struct DefaultPickingPlugins; -impl Plugin for DefaultPickingPlugins { - fn build(&self, app: &mut App) { - app.add_plugins(( - input::PointerInputPlugin::default(), - PickingPlugin::default(), - InteractionPlugin, - )); +impl PluginGroup for DefaultPickingPlugins { + fn build(self) -> PluginGroupBuilder { + #[cfg_attr( + not(feature = "bevy_mesh"), + expect( + unused_mut, + reason = "Group is not mutated when `bevy_mesh` is not enabled." + ) + )] + let mut group = PluginGroupBuilder::start::() + .add(input::PointerInputPlugin::default()) + .add(PickingPlugin::default()) + .add(InteractionPlugin); + #[cfg(feature = "bevy_mesh")] - app.add_plugins(mesh_picking::MeshPickingBackend); + { + group = group.add(mesh_picking::MeshPickingPlugin); + }; + + group } } diff --git a/crates/bevy_picking/src/mesh_picking/mod.rs b/crates/bevy_picking/src/mesh_picking/mod.rs index ce9129c54d536..62060540be692 100644 --- a/crates/bevy_picking/src/mesh_picking/mod.rs +++ b/crates/bevy_picking/src/mesh_picking/mod.rs @@ -3,7 +3,7 @@ //! By default, all meshes are pickable. Picking can be disabled for individual entities //! 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 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 ray_cast::{MeshRayCast, RayCastSettings, RayCastVisibility, SimplifiedMesh}; -/// Runtime settings for the [`MeshPickingBackend`]. +/// Runtime settings for the [`MeshPickingPlugin`]. #[derive(Resource, Reflect)] #[reflect(Resource, Default)] -pub struct MeshPickingBackendSettings { +pub struct MeshPickingSettings { /// When set to `true` ray casting will only happen between cameras and entities marked with /// [`RayCastPickable`]. `false` by default. /// @@ -40,7 +40,7 @@ pub struct MeshPickingBackendSettings { pub ray_cast_visibility: RayCastVisibility, } -impl Default for MeshPickingBackendSettings { +impl Default for MeshPickingSettings { fn default() -> Self { Self { 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`]. -/// Only needed if [`MeshPickingBackendSettings::require_markers`] is set to `true`, and ignored otherwise. +/// 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)] pub struct RayCastPickable; /// Adds the mesh picking backend to your app. #[derive(Clone, Default)] -pub struct MeshPickingBackend; +pub struct MeshPickingPlugin; -impl Plugin for MeshPickingBackend { +impl Plugin for MeshPickingPlugin { fn build(&self, app: &mut App) { - app.init_resource::() - .register_type::<(RayCastPickable, MeshPickingBackendSettings, SimplifiedMesh)>() + app.init_resource::() + .register_type::<(RayCastPickable, MeshPickingSettings, SimplifiedMesh)>() .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)] pub fn update_hits( - backend_settings: Res, + backend_settings: Res, ray_map: Res, picking_cameras: Query<(&Camera, Option<&RayCastPickable>, Option<&RenderLayers>)>, pickables: Query<&PickingBehavior>, diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index 659344ec9b8e1..ce62a1e975d4c 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -135,7 +135,7 @@ impl Plugin for SpritePlugin { ); #[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) { render_app diff --git a/crates/bevy_sprite/src/picking_backend.rs b/crates/bevy_sprite/src/picking_backend.rs index f62c3c4e045c5..55c06a8ec9ac3 100644 --- a/crates/bevy_sprite/src/picking_backend.rs +++ b/crates/bevy_sprite/src/picking_backend.rs @@ -15,9 +15,9 @@ use bevy_transform::prelude::*; use bevy_window::PrimaryWindow; #[derive(Clone)] -pub struct SpritePickingBackend; +pub struct SpritePickingPlugin; -impl Plugin for SpritePickingBackend { +impl Plugin for SpritePickingPlugin { fn build(&self, app: &mut App) { app.add_systems(PreUpdate, sprite_picking.in_set(PickSet::Backend)); } diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 658acc9b4814a..b0cdcddb839c0 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -219,7 +219,7 @@ impl Plugin for UiPlugin { build_text_interop(app); #[cfg(feature = "bevy_ui_picking_backend")] - app.add_plugins(picking_backend::UiPickingBackendPlugin); + app.add_plugins(picking_backend::UiPickingPlugin); if !self.enable_rendering { return; diff --git a/crates/bevy_ui/src/picking_backend.rs b/crates/bevy_ui/src/picking_backend.rs index cc41fb20b0148..93c14e35b4db0 100644 --- a/crates/bevy_ui/src/picking_backend.rs +++ b/crates/bevy_ui/src/picking_backend.rs @@ -36,8 +36,8 @@ use bevy_picking::backend::prelude::*; /// A plugin that adds picking support for UI nodes. #[derive(Clone)] -pub struct UiPickingBackendPlugin; -impl Plugin for UiPickingBackendPlugin { +pub struct UiPickingPlugin; +impl Plugin for UiPickingPlugin { fn build(&self, app: &mut App) { app.add_systems(PreUpdate, ui_picking.in_set(PickSet::Backend)); } diff --git a/examples/picking/mesh_picking.rs b/examples/picking/mesh_picking.rs index d4636fea4c5f7..9c0d813042e73 100644 --- a/examples/picking/mesh_picking.rs +++ b/examples/picking/mesh_picking.rs @@ -3,7 +3,7 @@ //! By default, all meshes are pickable. Picking can be disabled for individual entities //! 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. use std::f32::consts::PI;