From 5335b245f454b0f1b6565c93fb1f4e581cc2655c Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Thu, 12 Mar 2026 21:40:59 -0700 Subject: [PATCH 01/16] Squashed commit of the following: commit cf4a2dbdc9c27820317da2908a55942b21ed7f9d Merge: 41c5874f4 3fea954ea Author: Luke Yoo Date: Thu Mar 12 21:40:00 2026 -0700 Merge branch 'main' into ui-widgets-to-default commit 41c5874f4c9d082cf95aae6469bbb30cf42c6c1d Author: Luke Yoo Date: Thu Mar 12 21:35:43 2026 -0700 Remove unused imports commit 24987e82b1c70933c1517e3b9526f6eb778abd9c Author: Luke Yoo Date: Thu Mar 12 21:10:19 2026 -0700 Add InputDispatchPlugin at UIWidgetPlugins commit 8bd32958572b154a36dd7237ec4f03bb3a9f8aca Author: Luke Yoo Date: Thu Mar 12 16:02:59 2026 -0700 Add `UiWidgetsPlugins` to the plugin group for `DefaultPlugins` --- crates/bevy_feathers/src/lib.rs | 5 +---- crates/bevy_internal/src/default_plugins.rs | 3 +++ crates/bevy_ui_widgets/src/lib.rs | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/bevy_feathers/src/lib.rs b/crates/bevy_feathers/src/lib.rs index ed6517d84d8d6..3dce1fffae53d 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}, @@ -101,8 +100,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_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 0f75594b7bf91..d35d79c98a063 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -88,6 +88,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_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 8f30e2842701a..1b7a55d225d2f 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -37,11 +37,13 @@ pub use slider::*; use bevy_app::{PluginGroup, PluginGroupBuilder}; use bevy_ecs::{entity::Entity, event::EntityEvent}; +use bevy_input_focus::InputDispatchPlugin; 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 { @@ -54,6 +56,7 @@ impl PluginGroup for UiWidgetsPlugins { .add(RadioGroupPlugin) .add(ScrollbarPlugin) .add(SliderPlugin) + .add(InputDispatchPlugin) } } From e7bab9fb8322e63fbbd0cc92f6441e5b9194b08b Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Thu, 12 Mar 2026 23:11:13 -0700 Subject: [PATCH 02/16] Apply migration guide to examples --- examples/ui/widgets/standard_widgets.rs | 6 ++---- examples/ui/widgets/standard_widgets_observers.rs | 9 ++------- examples/ui/widgets/vertical_slider.rs | 9 ++------- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/examples/ui/widgets/standard_widgets.rs b/examples/ui/widgets/standard_widgets.rs index 0f281a9dd607f..5d58fd384e0f4 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,7 +20,7 @@ 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, }, }; @@ -28,8 +28,6 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, TabNavigationPlugin, )) .insert_resource(DemoWidgetStates { diff --git a/examples/ui/widgets/standard_widgets_observers.rs b/examples/ui/widgets/standard_widgets_observers.rs index c5a24f1833f71..585c9f11778a4 100644 --- a/examples/ui/widgets/standard_widgets_observers.rs +++ b/examples/ui/widgets/standard_widgets_observers.rs @@ -6,17 +6,14 @@ 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, }, }; @@ -24,8 +21,6 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, TabNavigationPlugin, )) .insert_resource(DemoWidgetStates { slider_value: 50.0 }) diff --git a/examples/ui/widgets/vertical_slider.rs b/examples/ui/widgets/vertical_slider.rs index e210e48155c62..b580c4083496e 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, }, }; @@ -20,8 +17,6 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - UiWidgetsPlugins, - InputDispatchPlugin, TabNavigationPlugin, )) .add_systems(Startup, setup) From 6c8b886be2149e6bdb3136314deed69a76093189 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sat, 14 Mar 2026 15:33:55 -0700 Subject: [PATCH 03/16] Include `InputDispatchPlugin` in `DefaultPlugins` --- crates/bevy_input_focus/src/lib.rs | 1 + crates/bevy_internal/src/default_plugins.rs | 2 ++ crates/bevy_ui_widgets/src/lib.rs | 2 -- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 47efd05797875..a82a0bc475203 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -219,6 +219,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 { diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index d35d79c98a063..71fa409c7cff6 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")] diff --git a/crates/bevy_ui_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 1b7a55d225d2f..6ff9c69db9ee4 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -37,7 +37,6 @@ pub use slider::*; use bevy_app::{PluginGroup, PluginGroupBuilder}; use bevy_ecs::{entity::Entity, event::EntityEvent}; -use bevy_input_focus::InputDispatchPlugin; use crate::popover::PopoverPlugin; @@ -56,7 +55,6 @@ impl PluginGroup for UiWidgetsPlugins { .add(RadioGroupPlugin) .add(ScrollbarPlugin) .add(SliderPlugin) - .add(InputDispatchPlugin) } } From 714bd13e28b4c447434c2d45b30a20fe1a88ac5e Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sun, 15 Mar 2026 13:06:16 -0700 Subject: [PATCH 04/16] Move popover and scrollbar to bevy_ui --- crates/bevy_ui/src/lib.rs | 2 ++ crates/bevy_ui/src/widget/mod.rs | 4 ++++ .../src => bevy_ui/src/widget}/popover.rs | 17 ++++++++++++----- .../src => bevy_ui/src/widget}/scrollbar.rs | 18 ++++++++++++++---- crates/bevy_ui_widgets/src/lib.rs | 7 ------- .../ui/navigation/directional_navigation.rs | 8 ++------ .../directional_navigation_overrides.rs | 8 ++------ examples/ui/scroll_and_overflow/scrollbars.rs | 16 ++++------------ examples/ui/widgets/standard_widgets.rs | 5 +---- .../ui/widgets/standard_widgets_observers.rs | 5 +---- examples/ui/widgets/tab_navigation.rs | 4 ++-- examples/ui/widgets/vertical_slider.rs | 5 +---- 12 files changed, 45 insertions(+), 54 deletions(-) rename crates/{bevy_ui_widgets/src => bevy_ui/src/widget}/popover.rs (96%) rename crates/{bevy_ui_widgets/src => bevy_ui/src/widget}/scrollbar.rs (96%) diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index d2e1e46589baf..79363ee4d7e14 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -216,6 +216,8 @@ impl Plugin for UiPlugin { ), ); + app.add_plugins((widget::PopoverPlugin, widget::ScrollbarPlugin)); + build_text_interop(app); } } diff --git a/crates/bevy_ui/src/widget/mod.rs b/crates/bevy_ui/src/widget/mod.rs index bbd319e986f09..b239a74789c72 100644 --- a/crates/bevy_ui/src/widget/mod.rs +++ b/crates/bevy_ui/src/widget/mod.rs @@ -3,11 +3,15 @@ mod button; mod image; mod label; +pub mod popover; +pub mod scrollbar; mod text; mod viewport; pub use button::*; pub use image::*; pub use label::*; +pub use popover::*; +pub use scrollbar::*; pub use text::*; pub use viewport::*; diff --git a/crates/bevy_ui_widgets/src/popover.rs b/crates/bevy_ui/src/widget/popover.rs similarity index 96% rename from crates/bevy_ui_widgets/src/popover.rs rename to crates/bevy_ui/src/widget/popover.rs index eb32d2d61f5ea..ee5391a5c8bd8 100644 --- a/crates/bevy_ui_widgets/src/popover.rs +++ b/crates/bevy_ui/src/widget/popover.rs @@ -1,5 +1,9 @@ //! Framework for positioning of popups, tooltips, and other popover UI elements. +use crate::{ + ui_stack_system, ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, + UiGlobalTransform, UiSystems, Val, +}; use bevy_app::{App, Plugin, PostUpdate}; use bevy_camera::visibility::Visibility; use bevy_ecs::{ @@ -7,9 +11,6 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::Query, }; use bevy_math::{Rect, Vec2}; -use bevy_ui::{ - ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, UiGlobalTransform, UiSystems, Val, -}; /// Which side of the parent element the popover element should be placed. #[derive(Debug, Default, Clone, Copy, PartialEq)] @@ -91,7 +92,8 @@ impl Clone for Popover { } } -fn position_popover( +/// Clips or positions popovers +pub fn position_popover( mut q_popover: Query<( &mut Node, &mut Visibility, @@ -242,7 +244,12 @@ pub struct PopoverPlugin; impl Plugin for PopoverPlugin { fn build(&self, app: &mut App) { - app.add_systems(PostUpdate, position_popover.in_set(UiSystems::Prepare)); + app.add_systems( + PostUpdate, + position_popover + .ambiguous_with(ui_stack_system) + .in_set(UiSystems::Prepare), + ); } } diff --git a/crates/bevy_ui_widgets/src/scrollbar.rs b/crates/bevy_ui/src/widget/scrollbar.rs similarity index 96% rename from crates/bevy_ui_widgets/src/scrollbar.rs rename to crates/bevy_ui/src/widget/scrollbar.rs index 6c3087d7576b5..4a9708d2aab7f 100644 --- a/crates/bevy_ui_widgets/src/scrollbar.rs +++ b/crates/bevy_ui/src/widget/scrollbar.rs @@ -6,13 +6,16 @@ use bevy_ecs::{ observer::On, query::{With, Without}, reflect::ReflectComponent, + schedule::IntoScheduleConfigs, system::{Query, Res}, }; use bevy_math::Vec2; use bevy_picking::events::{Cancel, Drag, DragEnd, DragStart, Pointer, Press}; use bevy_reflect::{prelude::ReflectDefault, Reflect}; -use bevy_ui::{ - ComputedNode, ComputedUiRenderTargetInfo, Node, ScrollPosition, UiGlobalTransform, UiScale, Val, + +use crate::{ + ui_layout_system, ui_stack_system, widget::popover, ComputedNode, ComputedUiRenderTargetInfo, + Node, ScrollPosition, UiGlobalTransform, UiScale, UiSystems, Val, }; /// Used to select the orientation of a scrollbar, slider, or other oriented control. @@ -243,7 +246,7 @@ fn scrollbar_on_drag_cancel( } } -fn update_scrollbar_thumb( +pub fn update_scrollbar_thumb( q_scroll_area: Query<(&ScrollPosition, &ComputedNode)>, q_scrollbar: Query<(&Scrollbar, &ComputedNode, &Children)>, mut q_thumb: Query<&mut Node, With>, @@ -363,6 +366,13 @@ impl Plugin for ScrollbarPlugin { .add_observer(scrollbar_on_drag_end) .add_observer(scrollbar_on_drag_cancel) .add_observer(scrollbar_on_drag) - .add_systems(PostUpdate, update_scrollbar_thumb); + .add_systems( + PostUpdate, + update_scrollbar_thumb + .ambiguous_with(popover::position_popover) + .ambiguous_with(ui_stack_system) + .ambiguous_with(ui_layout_system) + .in_set(UiSystems::Prepare), + ); } } diff --git a/crates/bevy_ui_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 6ff9c69db9ee4..9b497c55591f2 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -22,9 +22,7 @@ mod button; mod checkbox; mod menu; mod observe; -pub mod popover; mod radio; -mod scrollbar; mod slider; pub use button::*; @@ -32,14 +30,11 @@ pub use checkbox::*; pub use menu::*; pub use observe::*; pub use radio::*; -pub use scrollbar::*; pub use slider::*; use bevy_app::{PluginGroup, PluginGroupBuilder}; use bevy_ecs::{entity::Entity, event::EntityEvent}; -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)] @@ -48,12 +43,10 @@ pub struct UiWidgetsPlugins; impl PluginGroup for UiWidgetsPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() - .add(PopoverPlugin) .add(ButtonPlugin) .add(CheckboxPlugin) .add(MenuPlugin) .add(RadioGroupPlugin) - .add(ScrollbarPlugin) .add(SliderPlugin) } } diff --git a/examples/ui/navigation/directional_navigation.rs b/examples/ui/navigation/directional_navigation.rs index 5b6a96fd7b528..1433829745643 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::{ @@ -35,11 +35,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 a3b1a754c32a3..bea0d28599785 100644 --- a/examples/ui/scroll_and_overflow/scrollbars.rs +++ b/examples/ui/scroll_and_overflow/scrollbars.rs @@ -2,25 +2,17 @@ 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, CoreScrollbarThumb, Scrollbar, ScrollbarPlugin, + ui::widget::scrollbar::{ + ControlOrientation, CoreScrollbarDragState, CoreScrollbarThumb, Scrollbar, }, }; fn main() { App::new() - .add_plugins(( - DefaultPlugins, - ScrollbarPlugin, - InputDispatchPlugin, - TabNavigationPlugin, - )) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .insert_resource(UiScale(1.25)) .add_systems(Startup, setup_view_root) .add_systems(Update, update_scrollbar_thumb) diff --git a/examples/ui/widgets/standard_widgets.rs b/examples/ui/widgets/standard_widgets.rs index 5d58fd384e0f4..c9c297812faf6 100644 --- a/examples/ui/widgets/standard_widgets.rs +++ b/examples/ui/widgets/standard_widgets.rs @@ -26,10 +26,7 @@ use bevy::{ fn main() { App::new() - .add_plugins(( - DefaultPlugins, - 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 585c9f11778a4..56eb42b9336a4 100644 --- a/examples/ui/widgets/standard_widgets_observers.rs +++ b/examples/ui/widgets/standard_widgets_observers.rs @@ -19,10 +19,7 @@ use bevy::{ fn main() { App::new() - .add_plugins(( - DefaultPlugins, - 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 b580c4083496e..1d1dfab354e2b 100644 --- a/examples/ui/widgets/vertical_slider.rs +++ b/examples/ui/widgets/vertical_slider.rs @@ -15,10 +15,7 @@ const SLIDER_THUMB: Color = Color::srgb(0.35, 0.75, 0.35); fn main() { App::new() - .add_plugins(( - DefaultPlugins, - TabNavigationPlugin, - )) + .add_plugins((DefaultPlugins, TabNavigationPlugin)) .add_systems(Startup, setup) .add_systems(Update, (update_slider_visuals, update_value_labels)) .run(); From d310bdff700e15c1f8ceefc529dedb270d53e3bc Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sun, 15 Mar 2026 15:51:23 -0700 Subject: [PATCH 05/16] Ambiguate the execution orders of systems in `InputDispatchPlugin` --- crates/bevy_input_focus/src/lib.rs | 38 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index a82a0bc475203..5c93d2cb852a8 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -233,11 +233,43 @@ impl Plugin for InputDispatchPlugin { PreUpdate, ( #[cfg(feature = "keyboard")] - dispatch_focused_input::, + { + let s = dispatch_focused_input::; + + #[cfg(feature = "gamepad")] + let s = s + .ambiguous_with(dispatch_focused_input::) + .after(bevy_input::gamepad::gamepad_event_processing_system); + + #[cfg(feature = "mouse")] + let s = s.ambiguous_with(dispatch_focused_input::); + s + }, #[cfg(feature = "gamepad")] - dispatch_focused_input::, + { + let s = dispatch_focused_input:: + .after(bevy_input::gamepad::gamepad_event_processing_system); + + #[cfg(feature = "keyboard")] + let s = s.ambiguous_with(dispatch_focused_input::); + + #[cfg(feature = "mouse")] + let s = s.ambiguous_with(dispatch_focused_input::); + s + }, #[cfg(feature = "mouse")] - dispatch_focused_input::, + { + let s = dispatch_focused_input::; + + #[cfg(feature = "keyboard")] + let s = s.ambiguous_with(dispatch_focused_input::); + + #[cfg(feature = "gamepad")] + let s = s + .ambiguous_with(dispatch_focused_input::) + .after(bevy_input::gamepad::gamepad_event_processing_system); + s + }, ) .in_set(InputFocusSystems::Dispatch), ); From 79940d74af54be7c8c70f40b79a462c5601030d3 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 14:11:08 -0700 Subject: [PATCH 06/16] Wrap the execution orders in system sets --- crates/bevy_ui/src/lib.rs | 2 -- crates/bevy_ui/src/widget/mod.rs | 4 ---- crates/bevy_ui_widgets/Cargo.toml | 1 + crates/bevy_ui_widgets/src/lib.rs | 7 +++++++ .../widget => bevy_ui_widgets/src}/popover.rs | 15 +++++++++------ .../widget => bevy_ui_widgets/src}/scrollbar.rs | 17 +++++++++-------- examples/ui/scroll_and_overflow/scrollbars.rs | 4 +--- 7 files changed, 27 insertions(+), 23 deletions(-) rename crates/{bevy_ui/src/widget => bevy_ui_widgets/src}/popover.rs (96%) rename crates/{bevy_ui/src/widget => bevy_ui_widgets/src}/scrollbar.rs (97%) diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 79363ee4d7e14..d2e1e46589baf 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -216,8 +216,6 @@ impl Plugin for UiPlugin { ), ); - app.add_plugins((widget::PopoverPlugin, widget::ScrollbarPlugin)); - build_text_interop(app); } } diff --git a/crates/bevy_ui/src/widget/mod.rs b/crates/bevy_ui/src/widget/mod.rs index b239a74789c72..bbd319e986f09 100644 --- a/crates/bevy_ui/src/widget/mod.rs +++ b/crates/bevy_ui/src/widget/mod.rs @@ -3,15 +3,11 @@ mod button; mod image; mod label; -pub mod popover; -pub mod scrollbar; mod text; mod viewport; pub use button::*; pub use image::*; pub use label::*; -pub use popover::*; -pub use scrollbar::*; pub use text::*; pub use viewport::*; diff --git a/crates/bevy_ui_widgets/Cargo.toml b/crates/bevy_ui_widgets/Cargo.toml index 136019c6693cf..d369b6351232c 100644 --- a/crates/bevy_ui_widgets/Cargo.toml +++ b/crates/bevy_ui_widgets/Cargo.toml @@ -21,6 +21,7 @@ bevy_math = { path = "../bevy_math", version = "0.19.0-dev" } bevy_picking = { path = "../bevy_picking", version = "0.19.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.19.0-dev" } bevy_ui = { path = "../bevy_ui", version = "0.19.0-dev" } +bevy_render = { path = "../bevy_render", version = "0.19.0-dev" } # other accesskit = "0.24" diff --git a/crates/bevy_ui_widgets/src/lib.rs b/crates/bevy_ui_widgets/src/lib.rs index 9b497c55591f2..42a359f2fdbd0 100644 --- a/crates/bevy_ui_widgets/src/lib.rs +++ b/crates/bevy_ui_widgets/src/lib.rs @@ -22,7 +22,9 @@ mod button; mod checkbox; mod menu; mod observe; +pub mod popover; mod radio; +mod scrollbar; mod slider; pub use button::*; @@ -30,11 +32,14 @@ pub use checkbox::*; pub use menu::*; pub use observe::*; pub use radio::*; +pub use scrollbar::*; pub use slider::*; use bevy_app::{PluginGroup, PluginGroupBuilder}; use bevy_ecs::{entity::Entity, event::EntityEvent}; +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)] @@ -43,11 +48,13 @@ pub struct UiWidgetsPlugins; impl PluginGroup for UiWidgetsPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() + .add(PopoverPlugin) .add(ButtonPlugin) .add(CheckboxPlugin) .add(MenuPlugin) .add(RadioGroupPlugin) .add(SliderPlugin) + .add(ScrollbarPlugin) } } diff --git a/crates/bevy_ui/src/widget/popover.rs b/crates/bevy_ui_widgets/src/popover.rs similarity index 96% rename from crates/bevy_ui/src/widget/popover.rs rename to crates/bevy_ui_widgets/src/popover.rs index ee5391a5c8bd8..a7c84c8fe773e 100644 --- a/crates/bevy_ui/src/widget/popover.rs +++ b/crates/bevy_ui_widgets/src/popover.rs @@ -1,9 +1,5 @@ //! Framework for positioning of popups, tooltips, and other popover UI elements. -use crate::{ - ui_stack_system, ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, - UiGlobalTransform, UiSystems, Val, -}; use bevy_app::{App, Plugin, PostUpdate}; use bevy_camera::visibility::Visibility; use bevy_ecs::{ @@ -11,6 +7,10 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::Query, }; use bevy_math::{Rect, Vec2}; +use bevy_render::RenderSystems; +use bevy_ui::{ + ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, UiGlobalTransform, UiSystems, Val, +}; /// Which side of the parent element the popover element should be placed. #[derive(Debug, Default, Clone, Copy, PartialEq)] @@ -247,8 +247,11 @@ impl Plugin for PopoverPlugin { app.add_systems( PostUpdate, position_popover - .ambiguous_with(ui_stack_system) - .in_set(UiSystems::Prepare), + .in_set(UiSystems::Prepare) + .ambiguous_with(UiSystems::Prepare) + .ambiguous_with(UiSystems::Stack) + .before(RenderSystems::Render) + .before(UiSystems::Layout), ); } } diff --git a/crates/bevy_ui/src/widget/scrollbar.rs b/crates/bevy_ui_widgets/src/scrollbar.rs similarity index 97% rename from crates/bevy_ui/src/widget/scrollbar.rs rename to crates/bevy_ui_widgets/src/scrollbar.rs index 4a9708d2aab7f..b3c6bd1fd96c7 100644 --- a/crates/bevy_ui/src/widget/scrollbar.rs +++ b/crates/bevy_ui_widgets/src/scrollbar.rs @@ -12,10 +12,10 @@ use bevy_ecs::{ use bevy_math::Vec2; use bevy_picking::events::{Cancel, Drag, DragEnd, DragStart, Pointer, Press}; use bevy_reflect::{prelude::ReflectDefault, Reflect}; - -use crate::{ - ui_layout_system, ui_stack_system, widget::popover, ComputedNode, ComputedUiRenderTargetInfo, - Node, ScrollPosition, UiGlobalTransform, UiScale, UiSystems, Val, +use bevy_render::RenderSystems; +use bevy_ui::{ + ComputedNode, ComputedUiRenderTargetInfo, Node, ScrollPosition, UiGlobalTransform, UiScale, + UiSystems, Val, }; /// Used to select the orientation of a scrollbar, slider, or other oriented control. @@ -369,10 +369,11 @@ impl Plugin for ScrollbarPlugin { .add_systems( PostUpdate, update_scrollbar_thumb - .ambiguous_with(popover::position_popover) - .ambiguous_with(ui_stack_system) - .ambiguous_with(ui_layout_system) - .in_set(UiSystems::Prepare), + .in_set(UiSystems::Prepare) + .ambiguous_with(UiSystems::Prepare) + .ambiguous_with(UiSystems::Stack) + .before(RenderSystems::Render) + .before(UiSystems::Layout), ); } } diff --git a/examples/ui/scroll_and_overflow/scrollbars.rs b/examples/ui/scroll_and_overflow/scrollbars.rs index bea0d28599785..b25ed998508d2 100644 --- a/examples/ui/scroll_and_overflow/scrollbars.rs +++ b/examples/ui/scroll_and_overflow/scrollbars.rs @@ -5,9 +5,7 @@ use bevy::{ input_focus::tab_navigation::{TabGroup, TabNavigationPlugin}, picking::hover::Hovered, prelude::*, - ui::widget::scrollbar::{ - ControlOrientation, CoreScrollbarDragState, CoreScrollbarThumb, Scrollbar, - }, + ui_widgets::{ControlOrientation, CoreScrollbarDragState, CoreScrollbarThumb, Scrollbar}, }; fn main() { From 8ec74b4c388f7bd9ac150e6478a11e271ef5f389 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 14:22:21 -0700 Subject: [PATCH 07/16] Wrap the execution orders in system sets --- crates/bevy_input_focus/src/lib.rs | 43 +++++------------------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 5c93d2cb852a8..b5cfdf35389e0 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; @@ -233,45 +234,15 @@ impl Plugin for InputDispatchPlugin { PreUpdate, ( #[cfg(feature = "keyboard")] - { - let s = dispatch_focused_input::; - - #[cfg(feature = "gamepad")] - let s = s - .ambiguous_with(dispatch_focused_input::) - .after(bevy_input::gamepad::gamepad_event_processing_system); - - #[cfg(feature = "mouse")] - let s = s.ambiguous_with(dispatch_focused_input::); - s - }, + dispatch_focused_input::, #[cfg(feature = "gamepad")] - { - let s = dispatch_focused_input:: - .after(bevy_input::gamepad::gamepad_event_processing_system); - - #[cfg(feature = "keyboard")] - let s = s.ambiguous_with(dispatch_focused_input::); - - #[cfg(feature = "mouse")] - let s = s.ambiguous_with(dispatch_focused_input::); - s - }, + dispatch_focused_input::, #[cfg(feature = "mouse")] - { - let s = dispatch_focused_input::; - - #[cfg(feature = "keyboard")] - let s = s.ambiguous_with(dispatch_focused_input::); - - #[cfg(feature = "gamepad")] - let s = s - .ambiguous_with(dispatch_focused_input::) - .after(bevy_input::gamepad::gamepad_event_processing_system); - s - }, + dispatch_focused_input::, ) - .in_set(InputFocusSystems::Dispatch), + .in_set(InputFocusSystems::Dispatch) + .ambiguous_with(InputFocusSystems::Dispatch) + .after(InputSystems), ); } } From fb25d065617d8c29b04807bf78f25ef254583333 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 14:35:49 -0700 Subject: [PATCH 08/16] Stub in migration guide --- ...ns_and_input_dispatch_plugin_are_now_default.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md 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..c15a30710e1f7 --- /dev/null +++ b/release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md @@ -0,0 +1,14 @@ +--- +title: Feature that broke +pull_requests: [14791, 15458, 15269] +--- + +Copy the contents of this file into a new file in `./migration-guides`, update the metadata, and add migration guide content here. + +Remember, your aim is to communicate: + +- What has changed since the last release? +- Why did we make this breaking change? +- How can users migrate their existing code? + +For more specifics about style and content, see the [instructions](./migration_guides.md). From f7fad09ed1126d34c8c284bce85c99821fed1d51 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 14:38:30 -0700 Subject: [PATCH 09/16] Regress update_scrollbar_thumb and position_popover to private --- crates/bevy_ui_widgets/src/popover.rs | 3 +-- crates/bevy_ui_widgets/src/scrollbar.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ui_widgets/src/popover.rs b/crates/bevy_ui_widgets/src/popover.rs index a7c84c8fe773e..aedff98a46c73 100644 --- a/crates/bevy_ui_widgets/src/popover.rs +++ b/crates/bevy_ui_widgets/src/popover.rs @@ -92,8 +92,7 @@ impl Clone for Popover { } } -/// Clips or positions popovers -pub fn position_popover( +fn position_popover( mut q_popover: Query<( &mut Node, &mut Visibility, diff --git a/crates/bevy_ui_widgets/src/scrollbar.rs b/crates/bevy_ui_widgets/src/scrollbar.rs index b3c6bd1fd96c7..069d9f41402fd 100644 --- a/crates/bevy_ui_widgets/src/scrollbar.rs +++ b/crates/bevy_ui_widgets/src/scrollbar.rs @@ -246,7 +246,7 @@ fn scrollbar_on_drag_cancel( } } -pub fn update_scrollbar_thumb( +fn update_scrollbar_thumb( q_scroll_area: Query<(&ScrollPosition, &ComputedNode)>, q_scrollbar: Query<(&Scrollbar, &ComputedNode, &Children)>, mut q_thumb: Query<&mut Node, With>, From 12bb5f75c3bac2c0c0e28110d2fa87d0c3b6b11f Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 16:21:24 -0700 Subject: [PATCH 10/16] Update the migration guide --- ...d_input_dispatch_plugin_are_now_default.md | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) 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 index c15a30710e1f7..e746ea8286793 100644 --- 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 @@ -1,14 +1,47 @@ --- -title: Feature that broke -pull_requests: [14791, 15458, 15269] +title: "Include `UiWidgetsPlugins` in `DefaultPlugins`" +pull_requests: [23346] --- -Copy the contents of this file into a new file in `./migration-guides`, update the metadata, and add migration guide content here. +TODO: What has changed since the last release? -Remember, your aim is to communicate: +TODO: Why did we make this breaking change? -- What has changed since the last release? -- Why did we make this breaking change? -- How can users migrate their existing code? +Remove `UiWidgetsPlugins` if you have `DefaultPlugins` -For more specifics about style and content, see the [instructions](./migration_guides.md). +```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(); +} +``` \ No newline at end of file From 36ddbad30399b2784296e7f69c12b94f41190afc Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 16:41:23 -0700 Subject: [PATCH 11/16] Resolve MD031/blanks-around-fences --- ..._widgets_plugins_and_input_dispatch_plugin_are_now_default.md | 1 + 1 file changed, 1 insertion(+) 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 index e746ea8286793..07dde369b184b 100644 --- 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 @@ -28,6 +28,7 @@ fn main() { ``` Remove `InputDispatchPlugin` if you have `DefaultPlugins` + ```rs // 0.18 fn main() { From 9c21ed74394705cf79fe639870c0e1bba825c0e1 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Mon, 16 Mar 2026 16:51:31 -0700 Subject: [PATCH 12/16] Update the migration guide --- ...d_input_dispatch_plugin_are_now_default.md | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) 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 index 07dde369b184b..8e5f3e83d1507 100644 --- 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 @@ -3,7 +3,7 @@ title: "Include `UiWidgetsPlugins` in `DefaultPlugins`" pull_requests: [23346] --- -TODO: What has changed since the last release? +`UiWidgetsPlugins` and `InputDispatchPlugin` are now part of `DefaultPlugins`. TODO: Why did we make this breaking change? @@ -45,4 +45,44 @@ fn main() { .add_plugins((my_sequel_game::game_plugin)) .run(); } -``` \ No newline at end of file +``` + +Remove `PopoverPlugin` if you have `DefaultPlugins` + +```rs +// 0.18 +fn main() { + App::new() + .add_plugins(DefaultPlugins, PopoverPlugin) + .add_plugins((my_threequel_game::game_plugin)) + .run(); +} + +// 0.19 +fn main() { + App::new() + .add_plugins(DefaultPlugins) // Puff! + .add_plugins((my_threequel_game::game_plugin)) + .run(); +} +``` + +Remove `ScrollbarPlugin` if you have `DefaultPlugins` + +```rs +// 0.18 +fn main() { + App::new() + .add_plugins(DefaultPlugins, ScrollbarPlugin) + .add_plugins((my_fourquel_game::game_plugin)) + .run(); +} + +// 0.19 +fn main() { + App::new() + .add_plugins(DefaultPlugins) // Puff! + .add_plugins((my_fourquel_game::game_plugin)) + .run(); +} +``` From d36148ea083fe9e3888c0f422219cf417720c016 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Tue, 17 Mar 2026 20:16:07 +0000 Subject: [PATCH 13/16] Update release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md Co-authored-by: Kevin Chen --- ...widgets_plugins_and_input_dispatch_plugin_are_now_default.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 8e5f3e83d1507..c7daafdf202c6 100644 --- 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 @@ -1,5 +1,5 @@ --- -title: "Include `UiWidgetsPlugins` in `DefaultPlugins`" +title: "`UiWidgetsPlugins` and `InputDispatchPlugin` are now in `DefaultPlugins`" pull_requests: [23346] --- From 69fa98e9200fd9e68ff5f6261251bcc4ccbb7f07 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sat, 28 Mar 2026 16:23:01 -0700 Subject: [PATCH 14/16] Add `UiSystems::ComputeRelative` --- crates/bevy_gizmos_render/Cargo.toml | 1 + .../src/transform_gizmo_render.rs | 5 ++++- crates/bevy_ui/src/lib.rs | 8 ++++++-- crates/bevy_ui_widgets/Cargo.toml | 1 - crates/bevy_ui_widgets/src/popover.rs | 18 ++++++++++-------- crates/bevy_ui_widgets/src/scrollbar.rs | 14 +++++++------- 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/bevy_gizmos_render/Cargo.toml b/crates/bevy_gizmos_render/Cargo.toml index 41d9197e1880d..ba62810a3798c 100644 --- a/crates/bevy_gizmos_render/Cargo.toml +++ b/crates/bevy_gizmos_render/Cargo.toml @@ -33,6 +33,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.19.0-dev" } bevy_color = { path = "../bevy_color", version = "0.19.0-dev" } bevy_material = { path = "../bevy_material", version = "0.19.0-dev" } bevy_log = { path = "../bevy_log", version = "0.19.0-dev" } +bevy_ui = { path = "../bevy_ui", version = "0.19.0-dev" } # other bytemuck = "1.0" diff --git a/crates/bevy_gizmos_render/src/transform_gizmo_render.rs b/crates/bevy_gizmos_render/src/transform_gizmo_render.rs index ed4dca2610684..6fb5ece849494 100644 --- a/crates/bevy_gizmos_render/src/transform_gizmo_render.rs +++ b/crates/bevy_gizmos_render/src/transform_gizmo_render.rs @@ -34,6 +34,8 @@ use bevy_gizmos::transform_gizmo::{ VIEW_CIRCLE_MAJOR, VIEW_CIRCLE_MINOR, VIEW_RING_MAJOR, VIEW_RING_MINOR, }; +use bevy_ui::UiSystems; + /// The render layer used exclusively for gizmo meshes. const GIZMO_RENDER_LAYER: usize = 15; @@ -88,7 +90,8 @@ impl Plugin for TransformGizmoRenderPlugin { PostUpdate, update_gizmo_meshes .after(bevy_transform::TransformSystems::Propagate) - .after(bevy_camera::visibility::VisibilitySystems::VisibilityPropagate), + .after(bevy_camera::visibility::VisibilitySystems::VisibilityPropagate) + .ambiguous_with(bevy_ui::UiSystems::ComputeRelative), ); } } diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index d5c6f2c710c19..17342ea7b2578 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -74,7 +74,7 @@ pub mod prelude { } use bevy_app::{prelude::*, AnimationSystems, HierarchyPropagatePlugin, PropagateSet}; -use bevy_camera::CameraUpdateSystems; +use bevy_camera::{visibility::VisibilitySystems, CameraUpdateSystems}; use bevy_ecs::prelude::*; use bevy_input::InputSystems; use bevy_transform::TransformSystems; @@ -112,6 +112,8 @@ pub enum UiSystems { /// /// Runs in [`PostUpdate`]. Stack, + /// After this label, TODO + ComputeRelative, } /// The current scale of the UI. @@ -150,6 +152,7 @@ impl Plugin for UiPlugin { UiSystems::Content, UiSystems::Layout, UiSystems::PostLayout, + UiSystems::ComputeRelative.after(VisibilitySystems::VisibilityPropagate), ) .chain(), ) @@ -216,7 +219,8 @@ impl Plugin for UiPlugin { .in_set(UiSystems::PostLayout) .in_set(AmbiguousWithText) .in_set(AmbiguousWithUpdateText2dLayout), - ), + ) + .before(UiSystems::ComputeRelative), ); build_text_interop(app); diff --git a/crates/bevy_ui_widgets/Cargo.toml b/crates/bevy_ui_widgets/Cargo.toml index c194d1d090727..0566386299841 100644 --- a/crates/bevy_ui_widgets/Cargo.toml +++ b/crates/bevy_ui_widgets/Cargo.toml @@ -21,7 +21,6 @@ bevy_math = { path = "../bevy_math", version = "0.19.0-dev" } bevy_picking = { path = "../bevy_picking", version = "0.19.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.19.0-dev" } bevy_ui = { path = "../bevy_ui", version = "0.19.0-dev" } -bevy_render = { path = "../bevy_render", version = "0.19.0-dev" } bevy_text = { path = "../bevy_text", version = "0.19.0-dev" } # other diff --git a/crates/bevy_ui_widgets/src/popover.rs b/crates/bevy_ui_widgets/src/popover.rs index aedff98a46c73..ee9e7d3c52603 100644 --- a/crates/bevy_ui_widgets/src/popover.rs +++ b/crates/bevy_ui_widgets/src/popover.rs @@ -7,7 +7,6 @@ use bevy_ecs::{ schedule::IntoScheduleConfigs, system::Query, }; use bevy_math::{Rect, Vec2}; -use bevy_render::RenderSystems; use bevy_ui::{ ComputedNode, ComputedUiRenderTargetInfo, Node, PositionType, UiGlobalTransform, UiSystems, Val, }; @@ -243,14 +242,17 @@ pub struct PopoverPlugin; impl Plugin for PopoverPlugin { fn build(&self, app: &mut App) { - app.add_systems( + app.configure_sets( PostUpdate, - position_popover - .in_set(UiSystems::Prepare) - .ambiguous_with(UiSystems::Prepare) - .ambiguous_with(UiSystems::Stack) - .before(RenderSystems::Render) - .before(UiSystems::Layout), + ( + bevy_app::PropagateSet::::default(), + bevy_app::PropagateSet::::default(), + ) + .in_set(UiSystems::ComputeRelative), + ) + .add_systems( + PostUpdate, + position_popover.in_set(UiSystems::ComputeRelative), ); } } diff --git a/crates/bevy_ui_widgets/src/scrollbar.rs b/crates/bevy_ui_widgets/src/scrollbar.rs index 069d9f41402fd..8e3e70c2d57b5 100644 --- a/crates/bevy_ui_widgets/src/scrollbar.rs +++ b/crates/bevy_ui_widgets/src/scrollbar.rs @@ -12,7 +12,6 @@ use bevy_ecs::{ use bevy_math::Vec2; use bevy_picking::events::{Cancel, Drag, DragEnd, DragStart, Pointer, Press}; use bevy_reflect::{prelude::ReflectDefault, Reflect}; -use bevy_render::RenderSystems; use bevy_ui::{ ComputedNode, ComputedUiRenderTargetInfo, Node, ScrollPosition, UiGlobalTransform, UiScale, UiSystems, Val, @@ -51,7 +50,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. @@ -366,14 +365,15 @@ impl Plugin for ScrollbarPlugin { .add_observer(scrollbar_on_drag_end) .add_observer(scrollbar_on_drag_cancel) .add_observer(scrollbar_on_drag) + .configure_sets( + PostUpdate, + bevy_app::PropagateSet::::default().in_set(UiSystems::ComputeRelative), + ) .add_systems( PostUpdate, update_scrollbar_thumb - .in_set(UiSystems::Prepare) - .ambiguous_with(UiSystems::Prepare) - .ambiguous_with(UiSystems::Stack) - .before(RenderSystems::Render) - .before(UiSystems::Layout), + .in_set(UiSystems::ComputeRelative) + .ambiguous_with(UiSystems::ComputeRelative), ); } } From 25880c6867fd87be19459b77862a29100a7dae8d Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sun, 29 Mar 2026 12:02:45 -0700 Subject: [PATCH 15/16] Remove unused import --- crates/bevy_gizmos_render/src/transform_gizmo_render.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/bevy_gizmos_render/src/transform_gizmo_render.rs b/crates/bevy_gizmos_render/src/transform_gizmo_render.rs index 6fb5ece849494..35fbdef636db2 100644 --- a/crates/bevy_gizmos_render/src/transform_gizmo_render.rs +++ b/crates/bevy_gizmos_render/src/transform_gizmo_render.rs @@ -34,8 +34,6 @@ use bevy_gizmos::transform_gizmo::{ VIEW_CIRCLE_MAJOR, VIEW_CIRCLE_MINOR, VIEW_RING_MAJOR, VIEW_RING_MINOR, }; -use bevy_ui::UiSystems; - /// The render layer used exclusively for gizmo meshes. const GIZMO_RENDER_LAYER: usize = 15; From 8e6a735d865e7616971a9838a83687b15051f512 Mon Sep 17 00:00:00 2001 From: Luke Yoo Date: Sun, 29 Mar 2026 12:36:37 -0700 Subject: [PATCH 16/16] Remove dead code --- crates/bevy_ui_widgets/src/popover.rs | 10 +--------- crates/bevy_ui_widgets/src/scrollbar.rs | 4 ---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/crates/bevy_ui_widgets/src/popover.rs b/crates/bevy_ui_widgets/src/popover.rs index ee9e7d3c52603..42ff24b139ee0 100644 --- a/crates/bevy_ui_widgets/src/popover.rs +++ b/crates/bevy_ui_widgets/src/popover.rs @@ -242,15 +242,7 @@ pub struct PopoverPlugin; impl Plugin for PopoverPlugin { fn build(&self, app: &mut App) { - app.configure_sets( - PostUpdate, - ( - bevy_app::PropagateSet::::default(), - bevy_app::PropagateSet::::default(), - ) - .in_set(UiSystems::ComputeRelative), - ) - .add_systems( + app.add_systems( PostUpdate, position_popover.in_set(UiSystems::ComputeRelative), ); diff --git a/crates/bevy_ui_widgets/src/scrollbar.rs b/crates/bevy_ui_widgets/src/scrollbar.rs index 8e3e70c2d57b5..ff0c7d55c2b7c 100644 --- a/crates/bevy_ui_widgets/src/scrollbar.rs +++ b/crates/bevy_ui_widgets/src/scrollbar.rs @@ -365,10 +365,6 @@ impl Plugin for ScrollbarPlugin { .add_observer(scrollbar_on_drag_end) .add_observer(scrollbar_on_drag_cancel) .add_observer(scrollbar_on_drag) - .configure_sets( - PostUpdate, - bevy_app::PropagateSet::::default().in_set(UiSystems::ComputeRelative), - ) .add_systems( PostUpdate, update_scrollbar_thumb