Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
5335b24
Squashed commit of the following:
micttyoid Mar 13, 2026
e7bab9f
Apply migration guide to examples
micttyoid Mar 13, 2026
6c8b886
Include `InputDispatchPlugin` in `DefaultPlugins`
micttyoid Mar 14, 2026
714bd13
Move popover and scrollbar to bevy_ui
micttyoid Mar 15, 2026
d310bdf
Ambiguate the execution orders of systems in `InputDispatchPlugin`
micttyoid Mar 15, 2026
79940d7
Wrap the execution orders in system sets
micttyoid Mar 16, 2026
8ec74b4
Wrap the execution orders in system sets
micttyoid Mar 16, 2026
fb25d06
Stub in migration guide
micttyoid Mar 16, 2026
f7fad09
Regress update_scrollbar_thumb and position_popover to private
micttyoid Mar 16, 2026
12bb5f7
Update the migration guide
micttyoid Mar 16, 2026
36ddbad
Resolve MD031/blanks-around-fences
micttyoid Mar 16, 2026
9c21ed7
Update the migration guide
micttyoid Mar 16, 2026
e2d6051
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 17, 2026
d36148e
Update release-content/migration-guides/ui_widgets_plugins_and_input_…
micttyoid Mar 17, 2026
aee5607
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 17, 2026
56937a6
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 20, 2026
e2ff949
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 23, 2026
3e1f711
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 27, 2026
39cc0e3
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 28, 2026
69fa98e
Add `UiSystems::ComputeRelative`
micttyoid Mar 28, 2026
25880c6
Remove unused import
micttyoid Mar 29, 2026
8e6a735
Remove dead code
micttyoid Mar 29, 2026
edf8a06
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 29, 2026
62ca63a
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 31, 2026
5d315cb
Fix TODO in migration guide
alice-i-cecile Mar 31, 2026
ab08ea2
Yeet unneeded migration guides for subplugins
alice-i-cecile Mar 31, 2026
568e28d
Focus on PostLayout
micttyoid Mar 31, 2026
de19e2d
Remove unused import
micttyoid Mar 31, 2026
302e158
Reyeet migration guide
micttyoid Mar 31, 2026
4cfc631
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Mar 31, 2026
28989e7
Remove redundant ordering
micttyoid Mar 31, 2026
c623595
Removed `Node` from scrollbar thumb nodes, instead `CoreScrollbarThum…
ickshonpe Mar 31, 2026
a6ad25a
Migrate example multiple_text_inputs
micttyoid Mar 31, 2026
f05c5d3
Remove empty add_plugins
micttyoid Mar 31, 2026
dc46d3e
Remove unused import
micttyoid Mar 31, 2026
7f31047
Move scrollbar to UiSystems::PostLayout
micttyoid Mar 31, 2026
02858f3
fixed doc link
ickshonpe Mar 31, 2026
8ad3da4
Correctly order UiSystems::Stack
alice-i-cecile Mar 31, 2026
c6c3ae3
Remove unused before(UiSystems::Prepare)
micttyoid Mar 31, 2026
61b0ae6
Merge remote-tracking branch 'ickshonpe/thumb' into ui-widgets-to-def…
micttyoid Mar 31, 2026
1beedf8
Merge remote-tracking branch 'alice/order-ui-systems-better' into ui-…
micttyoid Mar 31, 2026
26bde1f
Show some direction
micttyoid Mar 31, 2026
f6c60a3
Revert "Show some direction"
micttyoid Apr 1, 2026
a5e13f8
Revert "Merge remote-tracking branch 'alice/order-ui-systems-better' …
micttyoid Apr 1, 2026
536aea6
Go edgy on PostLayout
micttyoid Apr 1, 2026
04826fb
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Apr 1, 2026
0c60af7
Chain instead of ambiguity
micttyoid Apr 1, 2026
37be382
Re-revert merged bevy_error.rs and handler.rs from "Merge remote-trac…
micttyoid Apr 1, 2026
1d76860
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Apr 1, 2026
b1c9d20
Merge branch 'main' into ui-widgets-to-default-2
micttyoid Apr 1, 2026
9ef4f8e
Apply system ordering fixes from ickshonpe
alice-i-cecile Apr 2, 2026
a05747c
Add clipping ordering fix
alice-i-cecile Apr 2, 2026
217a2ef
Clean up unused variable
alice-i-cecile Apr 2, 2026
aa7774e
All input dispatching should run after InputSystems
alice-i-cecile Apr 2, 2026
a1b1480
Fix cycle of position_popover
alice-i-cecile Apr 2, 2026
0596318
Merge branch 'main' into ui-widgets-to-default-2
alice-i-cecile Apr 2, 2026
4d63f82
Remove unused import
alice-i-cecile Apr 2, 2026
74c3b89
Fix spurious merge conflict change for ScrollbarPlugin order
alice-i-cecile Apr 2, 2026
de3cf6d
Remove old comments
alice-i-cecile Apr 2, 2026
d9fad7b
Fix timing of position_popover
alice-i-cecile Apr 2, 2026
3920238
Fix missing imports
alice-i-cecile Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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();
}
```
5 changes: 1 addition & 4 deletions crates/bevy_feathers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -100,8 +99,6 @@ pub struct FeathersPlugins;
impl PluginGroup for FeathersPlugins {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
.add_group(UiWidgetsPlugins)
.add(InputDispatchPlugin)
.add(TabNavigationPlugin)
.add(FeathersPlugin)
}
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_input_focus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -219,6 +220,7 @@ impl Traversal<AcquireFocus> for WindowTraversal {
///
/// To add bubbling to your own input events, add the [`dispatch_focused_input::<MyEvent>`](dispatch_focused_input) system to your app,
/// as described in the docs for [`FocusedInput`].
#[derive(Default)]
pub struct InputDispatchPlugin;

impl Plugin for InputDispatchPlugin {
Expand All @@ -238,7 +240,9 @@ impl Plugin for InputDispatchPlugin {
#[cfg(feature = "mouse")]
dispatch_focused_input::<MouseWheel>,
)
.in_set(InputFocusSystems::Dispatch),
.chain()
.in_set(InputFocusSystems::Dispatch)
.after(InputSystems),
);
}
}
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_internal/src/default_plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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)]
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_ui/src/accessibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down
16 changes: 8 additions & 8 deletions crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,28 +179,28 @@ 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);

app.add_systems(
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),
Comment thread
micttyoid marked this conversation as resolved.
update_clipping_system.in_set(UiSystems::PostLayout),
// Potential conflicts: `Assets<Image>`
// They run independently since `widget::image_node_system` will only ever observe
// its own ImageNode, and `widget::text_system` & `bevy_text::update_text2d_layout`
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ui_widgets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
16 changes: 12 additions & 4 deletions crates/bevy_ui_widgets/src/popover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -95,7 +97,7 @@ impl Clone for Popover {
}
}

fn position_popover(
pub(crate) fn position_popover(
mut q_popover: Query<(
Entity,
&mut Node,
Expand Down Expand Up @@ -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),
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ui_widgets/src/scrollbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<ScrollbarThumb>>,
q_scrollbar: Query<
(&Scrollbar, &ComputedNode, &UiGlobalTransform, &Children),
Expand Down
9 changes: 2 additions & 7 deletions examples/ui/navigation/directional_navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use bevy::{
camera::NormalizedRenderTarget,
input_focus::{
directional_navigation::{AutoNavigationConfig, DirectionalNavigationPlugin},
InputDispatchPlugin, InputFocus, InputFocusVisible,
InputFocus, InputFocusVisible,
},
math::{CompassOctant, Dir2, Rot2},
picking::{
Expand All @@ -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))
Expand Down
8 changes: 2 additions & 6 deletions examples/ui/navigation/directional_navigation_overrides.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use bevy::{
directional_navigation::{
AutoNavigationConfig, DirectionalNavigationMap, DirectionalNavigationPlugin,
},
InputDispatchPlugin, InputFocus, InputFocusVisible,
InputFocus, InputFocusVisible,
},
math::{CompassOctant, Dir2},
picking::{
Expand All @@ -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))
Expand Down
18 changes: 4 additions & 14 deletions examples/ui/scroll_and_overflow/scrollbars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 3 additions & 10 deletions examples/ui/text/multiple_text_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 3 additions & 8 deletions examples/ui/widgets/standard_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bevy::{
color::palettes::basic::*,
input_focus::{
tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin},
InputDispatchPlugin, InputFocus,
InputFocus,
},
picking::hover::Hovered,
prelude::*,
Expand All @@ -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,
Expand Down
Loading