diff --git a/_release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md b/_release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md new file mode 100644 index 0000000000000..729e3b9febb0f --- /dev/null +++ b/_release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md @@ -0,0 +1,48 @@ +--- +title: "`UiWidgetsPlugins` and `InputDispatchPlugin` are now in `DefaultPlugins`" +pull_requests: [23346] +--- + +`UiWidgetsPlugins` and `InputDispatchPlugin` are now part of `DefaultPlugins`. + +These plugins are now mature enough to be included as part of the default Bevy experience. + +Remove `UiWidgetsPlugins` if you have `DefaultPlugins` + +```rs +// 0.18 +fn main() { + App::new() + .add_plugins(DefaultPlugins, UiWidgetsPlugins) + .add_plugins((my_ambitious_game::game_plugin)) + .run(); +} + +// 0.19 +fn main() { + App::new() + .add_plugins(DefaultPlugins) // Puff! + .add_plugins((my_ambitious_game::game_plugin)) + .run(); +} +``` + +Remove `InputDispatchPlugin` if you have `DefaultPlugins` + +```rs +// 0.18 +fn main() { + App::new() + .add_plugins(DefaultPlugins, UiWidgetsPlugins, InputDispatchPlugin) + .add_plugins((my_sequel_game::game_plugin)) + .run(); +} + +// 0.19 +fn main() { + App::new() + .add_plugins(DefaultPlugins) // Puff! + .add_plugins((my_sequel_game::game_plugin)) + .run(); +} +``` diff --git a/crates/bevy_feathers/src/lib.rs b/crates/bevy_feathers/src/lib.rs index fab9dadde4e74..a1da134a8e82f 100644 --- a/crates/bevy_feathers/src/lib.rs +++ b/crates/bevy_feathers/src/lib.rs @@ -23,11 +23,10 @@ use bevy_app::{ }; use bevy_asset::embedded_asset; use bevy_ecs::{query::With, schedule::IntoScheduleConfigs}; -use bevy_input_focus::{tab_navigation::TabNavigationPlugin, InputDispatchPlugin}; +use bevy_input_focus::tab_navigation::TabNavigationPlugin; use bevy_text::{TextColor, TextFont}; use bevy_ui::UiSystems; use bevy_ui_render::UiMaterialPlugin; -use bevy_ui_widgets::UiWidgetsPlugins; use crate::{ alpha_pattern::{AlphaPatternMaterial, AlphaPatternResource}, @@ -100,8 +99,6 @@ pub struct FeathersPlugins; impl PluginGroup for FeathersPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() - .add_group(UiWidgetsPlugins) - .add(InputDispatchPlugin) .add(TabNavigationPlugin) .add(FeathersPlugin) } diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 47efd05797875..772d36eda4e5c 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -43,6 +43,7 @@ use bevy_input::gamepad::GamepadButtonChangedEvent; use bevy_input::keyboard::KeyboardInput; #[cfg(feature = "mouse")] use bevy_input::mouse::MouseWheel; +use bevy_input::InputSystems; use bevy_window::{PrimaryWindow, Window}; use core::fmt::Debug; @@ -219,6 +220,7 @@ impl Traversal for WindowTraversal { /// /// To add bubbling to your own input events, add the [`dispatch_focused_input::`](dispatch_focused_input) system to your app, /// as described in the docs for [`FocusedInput`]. +#[derive(Default)] pub struct InputDispatchPlugin; impl Plugin for InputDispatchPlugin { @@ -238,7 +240,9 @@ impl Plugin for InputDispatchPlugin { #[cfg(feature = "mouse")] dispatch_focused_input::, ) - .in_set(InputFocusSystems::Dispatch), + .chain() + .in_set(InputFocusSystems::Dispatch) + .after(InputSystems), ); } } diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 34ad5f98382e9..c6d5dc40a55e8 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -12,6 +12,8 @@ plugin_group! { bevy_transform:::TransformPlugin, bevy_diagnostic:::DiagnosticsPlugin, bevy_input:::InputPlugin, + #[cfg(feature = "bevy_input_focus")] + bevy_input_focus:::InputDispatchPlugin, #[custom(cfg(not(feature = "bevy_window")))] bevy_app:::ScheduleRunnerPlugin, #[cfg(feature = "bevy_window")] @@ -90,6 +92,9 @@ plugin_group! { #[cfg(feature = "hotpatching")] bevy_app::hotpatch:::HotPatchPlugin, #[plugin_group] + #[cfg(feature = "bevy_ui_widgets")] + bevy_ui_widgets:::UiWidgetsPlugins, + #[plugin_group] #[cfg(feature = "bevy_picking")] bevy_picking:::DefaultPickingPlugins, #[doc(hidden)] diff --git a/crates/bevy_ui/src/accessibility.rs b/crates/bevy_ui/src/accessibility.rs index 8ec9ae02b8ee3..5f24d3069f322 100644 --- a/crates/bevy_ui/src/accessibility.rs +++ b/crates/bevy_ui/src/accessibility.rs @@ -3,7 +3,7 @@ use crate::{ prelude::{Button, Label}, ui_transform::UiGlobalTransform, widget::{ImageNode, TextUiReader}, - ComputedNode, + ComputedNode, UiSystems, }; use bevy_a11y::AccessibilityNode; use bevy_app::{App, Plugin, PostUpdate}; @@ -153,7 +153,8 @@ impl Plugin for AccessibilityPlugin { .after(bevy_transform::TransformSystems::Propagate) .after(CameraUpdateSystems) // the listed systems do not affect calculated size - .ambiguous_with(crate::ui_stack_system), + .ambiguous_with(crate::ui_stack_system) + .before(UiSystems::PostLayout), button_changed, image_changed, label_changed, diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index d5c6f2c710c19..f22d248c7d3a4 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -179,11 +179,9 @@ impl Plugin for UiPlugin { widget::viewport_picking.in_set(PickingSystems::PostInput), ); - let ui_layout_system_config = ui_layout_system + ui_layout_system .in_set(UiSystems::Layout) - .before(TransformSystems::Propagate); - - let ui_layout_system_config = ui_layout_system_config + .before(TransformSystems::Propagate) // Text and Text2D operate on disjoint sets of entities .ambiguous_with(bevy_sprite::update_text2d_layout); @@ -191,16 +189,18 @@ impl Plugin for UiPlugin { PostUpdate, ( propagate_ui_target_cameras.in_set(UiSystems::Prepare), - ui_layout_system_config, + ui_layout_system + .in_set(UiSystems::Layout) + .ambiguous_with(bevy_sprite::update_text2d_layout), ui_stack_system .in_set(UiSystems::Stack) // These systems don't care about stack index .ambiguous_with(widget::measure_text_system) - .ambiguous_with(update_clipping_system) .ambiguous_with(ui_layout_system) .ambiguous_with(widget::update_viewport_render_target_size) - .in_set(AmbiguousWithText), - update_clipping_system.after(TransformSystems::Propagate), + .in_set(AmbiguousWithText) + .before(UiSystems::PostLayout), + update_clipping_system.in_set(UiSystems::PostLayout), // Potential conflicts: `Assets` // They run independently since `widget::image_node_system` will only ever observe // its own ImageNode, and `widget::text_system` & `bevy_text::update_text2d_layout` diff --git a/crates/bevy_ui_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 52d3d665f31ff..027ebbf85951c 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -44,6 +44,7 @@ use crate::popover::PopoverPlugin; /// A plugin group that registers the observers for all of the widgets in this crate. If you don't want to /// use all of the widgets, you can import the individual widget plugins instead. +#[derive(Default)] pub struct UiWidgetsPlugins; impl PluginGroup for UiWidgetsPlugins { diff --git a/crates/bevy_ui_widgets/src/popover.rs b/crates/bevy_ui_widgets/src/popover.rs index 337d4f0fc88a3..88acd2e28eb31 100644 --- a/crates/bevy_ui_widgets/src/popover.rs +++ b/crates/bevy_ui_widgets/src/popover.rs @@ -11,10 +11,12 @@ use bevy_ecs::{ }; use bevy_math::{Affine2, Rect, Vec2}; use bevy_ui::{ - ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, UiGlobalTransform, UiSystems, - UiTransform, Val2, + ui_layout_system, ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, + UiGlobalTransform, UiSystems, UiTransform, Val2, }; +use crate::update_scrollbar_thumb; + /// Which side of the parent element the popover element should be placed. #[derive(Debug, Default, Clone, Copy, PartialEq)] pub enum PopoverSide { @@ -95,7 +97,7 @@ impl Clone for Popover { } } -fn position_popover( +pub(crate) fn position_popover( mut q_popover: Query<( Entity, &mut Node, @@ -305,7 +307,13 @@ pub struct PopoverPlugin; impl Plugin for PopoverPlugin { fn build(&self, app: &mut App) { - app.add_systems(PostUpdate, position_popover.in_set(UiSystems::PostLayout)); + app.add_systems( + PostUpdate, + position_popover + .in_set(UiSystems::Layout) + .after(ui_layout_system) + .before(update_scrollbar_thumb), + ); } } diff --git a/crates/bevy_ui_widgets/src/scrollbar.rs b/crates/bevy_ui_widgets/src/scrollbar.rs index 688d09c047393..d73296212f8e4 100644 --- a/crates/bevy_ui_widgets/src/scrollbar.rs +++ b/crates/bevy_ui_widgets/src/scrollbar.rs @@ -53,7 +53,7 @@ pub enum ControlOrientation { /// The application is free to position the scrollbars relative to the scrolling container however /// it wants: it can overlay them on top of the scrolling content, or use a grid layout to displace /// the content to make room for the scrollbars. -#[derive(Component, Debug, Reflect)] +#[derive(Component, Debug, Reflect, Clone, PartialEq)] #[reflect(Component)] pub struct Scrollbar { /// Entity being scrolled. @@ -270,7 +270,7 @@ fn scrollbar_on_drag_cancel( } } -fn update_scrollbar_thumb( +pub(crate) fn update_scrollbar_thumb( q_scroll_area: Query<(&ScrollPosition, &ComputedNode), Without>, q_scrollbar: Query< (&Scrollbar, &ComputedNode, &UiGlobalTransform, &Children), diff --git a/examples/ui/navigation/directional_navigation.rs b/examples/ui/navigation/directional_navigation.rs index 5b6a96fd7b528..1412e6e160737 100644 --- a/examples/ui/navigation/directional_navigation.rs +++ b/examples/ui/navigation/directional_navigation.rs @@ -20,7 +20,7 @@ use bevy::{ camera::NormalizedRenderTarget, input_focus::{ directional_navigation::{AutoNavigationConfig, DirectionalNavigationPlugin}, - InputDispatchPlugin, InputFocus, InputFocusVisible, + InputFocus, InputFocusVisible, }, math::{CompassOctant, Dir2, Rot2}, picking::{ @@ -34,12 +34,7 @@ use bevy::{ fn main() { App::new() - // Input focus is not enabled by default, so we need to add the corresponding plugins - .add_plugins(( - DefaultPlugins, - InputDispatchPlugin, - DirectionalNavigationPlugin, - )) + .add_plugins((DefaultPlugins, DirectionalNavigationPlugin)) // 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 .insert_resource(InputFocusVisible(true)) diff --git a/examples/ui/navigation/directional_navigation_overrides.rs b/examples/ui/navigation/directional_navigation_overrides.rs index 75a7f601ec4ca..ed5ac605dbc57 100644 --- a/examples/ui/navigation/directional_navigation_overrides.rs +++ b/examples/ui/navigation/directional_navigation_overrides.rs @@ -25,7 +25,7 @@ use bevy::{ directional_navigation::{ AutoNavigationConfig, DirectionalNavigationMap, DirectionalNavigationPlugin, }, - InputDispatchPlugin, InputFocus, InputFocusVisible, + InputFocus, InputFocusVisible, }, math::{CompassOctant, Dir2}, picking::{ @@ -41,11 +41,7 @@ fn main() { App::new() // Input focus is not enabled by default, so we need to add the corresponding plugins // The navigation system's resources are initialized by the DirectionalNavigationPlugin. - .add_plugins(( - DefaultPlugins, - InputDispatchPlugin, - DirectionalNavigationPlugin, - )) + .add_plugins((DefaultPlugins, DirectionalNavigationPlugin)) // 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 .insert_resource(InputFocusVisible(true)) diff --git a/examples/ui/scroll_and_overflow/scrollbars.rs b/examples/ui/scroll_and_overflow/scrollbars.rs index b1e68569357dd..82c1ea9899f5c 100644 --- a/examples/ui/scroll_and_overflow/scrollbars.rs +++ b/examples/ui/scroll_and_overflow/scrollbars.rs @@ -2,26 +2,16 @@ use bevy::{ ecs::{relationship::RelatedSpawner, spawn::SpawnWith}, - input_focus::{ - tab_navigation::{TabGroup, TabNavigationPlugin}, - InputDispatchPlugin, - }, + input_focus::tab_navigation::{TabGroup, TabNavigationPlugin}, picking::hover::Hovered, prelude::*, - ui_widgets::{ - ControlOrientation, CoreScrollbarDragState, Scrollbar, ScrollbarPlugin, ScrollbarThumb, - }, + ui_widgets::{ControlOrientation, CoreScrollbarDragState, Scrollbar, ScrollbarThumb}, }; fn main() { App::new() - .add_plugins(( - DefaultPlugins, - ScrollbarPlugin, - InputDispatchPlugin, - TabNavigationPlugin, - )) - .insert_resource(UiScale(2.)) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) + .insert_resource(UiScale(1.25)) .add_systems(Startup, setup_view_root) .add_systems(Update, update_scrollbar_thumb) .run(); diff --git a/examples/ui/text/multiple_text_inputs.rs b/examples/ui/text/multiple_text_inputs.rs index 5372ff67feec3..80a0e39101e89 100644 --- a/examples/ui/text/multiple_text_inputs.rs +++ b/examples/ui/text/multiple_text_inputs.rs @@ -9,22 +9,15 @@ use bevy::input::keyboard::Key; use bevy::input_focus::AutoFocus; use bevy::input_focus::{ tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, - InputDispatchPlugin, InputFocus, + InputFocus, }; use bevy::prelude::*; use bevy::text::{EditableText, FontCx, LayoutCx, TextCursorStyle}; -use bevy::ui_widgets::EditableTextInputPlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugins(( - // `EditableTextInputPlugin` is also part of `UiWidgetsPlugins`, but we only need `EditableText` for this example - EditableTextInputPlugin, - // Input focus is required to direct keyboard input to the correct `EditableText` - InputDispatchPlugin, - TabNavigationPlugin, - )) + // `EditableTextInputPlugin` is part of `DefaultPlugins` + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .add_systems(Startup, setup) .add_systems( Update, diff --git a/examples/ui/widgets/standard_widgets.rs b/examples/ui/widgets/standard_widgets.rs index 2ab9d1bbab296..1696b23f224e8 100644 --- a/examples/ui/widgets/standard_widgets.rs +++ b/examples/ui/widgets/standard_widgets.rs @@ -10,7 +10,7 @@ use bevy::{ color::palettes::basic::*, input_focus::{ tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, - InputDispatchPlugin, InputFocus, + InputFocus, }, picking::hover::Hovered, prelude::*, @@ -20,18 +20,13 @@ use bevy::{ popover::{Popover, PopoverAlign, PopoverPlacement, PopoverSide}, Activate, Button, Checkbox, CoreSliderDragState, MenuAction, MenuButton, MenuEvent, MenuItem, MenuPopup, RadioButton, RadioGroup, Slider, SliderRange, SliderThumb, - SliderValue, TrackClick, UiWidgetsPlugins, ValueChange, + SliderValue, TrackClick, ValueChange, }, }; fn main() { App::new() - .add_plugins(( - DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, - TabNavigationPlugin, - )) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .insert_resource(DemoWidgetStates { slider_value: 50.0, slider_click: TrackClick::Snap, diff --git a/examples/ui/widgets/standard_widgets_observers.rs b/examples/ui/widgets/standard_widgets_observers.rs index c5a24f1833f71..56eb42b9336a4 100644 --- a/examples/ui/widgets/standard_widgets_observers.rs +++ b/examples/ui/widgets/standard_widgets_observers.rs @@ -6,28 +6,20 @@ use bevy::{ color::palettes::basic::*, - input_focus::{ - tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, - InputDispatchPlugin, - }, + input_focus::tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, picking::hover::Hovered, prelude::*, reflect::Is, ui::{Checked, InteractionDisabled, Pressed}, ui_widgets::{ checkbox_self_update, observe, Activate, Button, Checkbox, Slider, SliderRange, - SliderThumb, SliderValue, UiWidgetsPlugins, ValueChange, + SliderThumb, SliderValue, ValueChange, }, }; fn main() { App::new() - .add_plugins(( - DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, - TabNavigationPlugin, - )) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .insert_resource(DemoWidgetStates { slider_value: 50.0 }) .add_systems(Startup, setup) .add_observer(button_on_interaction::) diff --git a/examples/ui/widgets/tab_navigation.rs b/examples/ui/widgets/tab_navigation.rs index 2755d0fdf1a0b..29897630ac6fb 100644 --- a/examples/ui/widgets/tab_navigation.rs +++ b/examples/ui/widgets/tab_navigation.rs @@ -4,14 +4,14 @@ use bevy::{ color::palettes::basic::*, input_focus::{ tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, - InputDispatchPlugin, InputFocus, + InputFocus, }, prelude::*, }; fn main() { App::new() - .add_plugins((DefaultPlugins, InputDispatchPlugin, TabNavigationPlugin)) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .add_systems(Startup, setup) .add_systems(Update, (button_system, focus_system)) .run(); diff --git a/examples/ui/widgets/vertical_slider.rs b/examples/ui/widgets/vertical_slider.rs index e210e48155c62..1d1dfab354e2b 100644 --- a/examples/ui/widgets/vertical_slider.rs +++ b/examples/ui/widgets/vertical_slider.rs @@ -1,15 +1,12 @@ //! Simple example showing vertical and horizontal slider widgets with snap behavior and value labels use bevy::{ - input_focus::{ - tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, - InputDispatchPlugin, - }, + input_focus::tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin}, picking::hover::Hovered, prelude::*, ui_widgets::{ observe, slider_self_update, CoreSliderDragState, Slider, SliderRange, SliderThumb, - SliderValue, TrackClick, UiWidgetsPlugins, + SliderValue, TrackClick, }, }; @@ -18,12 +15,7 @@ const SLIDER_THUMB: Color = Color::srgb(0.35, 0.75, 0.35); fn main() { App::new() - .add_plugins(( - DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, - TabNavigationPlugin, - )) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .add_systems(Startup, setup) .add_systems(Update, (update_slider_visuals, update_value_labels)) .run();