Skip to content

Commit

Permalink
Migrate UI bundles to required components (#15898)
Browse files Browse the repository at this point in the history
# Objective

- Migrate UI bundles to required components, fixes #15889

## Solution

- deprecate `NodeBundle` in favor of `Node`
- deprecate `ImageBundle` in favor of `UiImage`
- deprecate `ButtonBundle` in favor of `Button`

## Testing

CI.

## Migration Guide

- Replace all uses of `NodeBundle` with `Node`. e.g.
```diff
     commands
-        .spawn(NodeBundle {
-            style: Style {
+        .spawn((
+            Node::default(),
+            Style {
                 width: Val::Percent(100.),
                 align_items: AlignItems::Center,
                 justify_content: JustifyContent::Center,
                 ..default()
             },
-            ..default()
-        })
+        ))
``` 
- Replace all uses of `ButtonBundle` with `Button`. e.g.
```diff
                     .spawn((
-                        ButtonBundle {
-                            style: Style {
-                                width: Val::Px(w),
-                                height: Val::Px(h),
-                                // horizontally center child text
-                                justify_content: JustifyContent::Center,
-                                // vertically center child text
-                                align_items: AlignItems::Center,
-                                margin: UiRect::all(Val::Px(20.0)),
-                                ..default()
-                            },
-                            image: image.clone().into(),
+                        Button,
+                        Style {
+                            width: Val::Px(w),
+                            height: Val::Px(h),
+                            // horizontally center child text
+                            justify_content: JustifyContent::Center,
+                            // vertically center child text
+                            align_items: AlignItems::Center,
+                            margin: UiRect::all(Val::Px(20.0)),
                             ..default()
                         },
+                        UiImage::from(image.clone()),
                         ImageScaleMode::Sliced(slicer.clone()),
                     ))
```
- Replace all uses of `ImageBundle` with `UiImage`. e.g.
```diff
-    commands.spawn(ImageBundle {
-        image: UiImage {
+    commands.spawn((
+        UiImage {
             texture: metering_mask,
             ..default()
         },
-        style: Style {
+        Style {
             width: Val::Percent(100.0),
             height: Val::Percent(100.0),
             ..default()
         },
-        ..default()
-    });
+    ));
 ```

---------

Co-authored-by: Carter Anderson <[email protected]>
  • Loading branch information
VitalyAnkh and cart authored Oct 17, 2024
1 parent 683d6c9 commit eb19a9e
Show file tree
Hide file tree
Showing 69 changed files with 1,578 additions and 1,731 deletions.
14 changes: 6 additions & 8 deletions crates/bevy_dev_tools/src/fps_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use bevy_ecs::{
use bevy_hierarchy::{BuildChildren, ChildBuild};
use bevy_render::view::Visibility;
use bevy_text::{Font, TextColor, TextFont, TextSpan};
use bevy_ui::Node;
use bevy_ui::{
node_bundles::NodeBundle,
widget::{Text, TextUiWriter},
GlobalZIndex, PositionType, Style,
};
Expand Down Expand Up @@ -89,15 +89,13 @@ struct FpsText;
fn setup(mut commands: Commands, overlay_config: Res<FpsOverlayConfig>) {
commands
.spawn((
NodeBundle {
style: Style {
// We need to make sure the overlay doesn't affect the position of other UI nodes
position_type: PositionType::Absolute,
..default()
},
// Render overlay on top of everything
Node::default(),
Style {
// We need to make sure the overlay doesn't affect the position of other UI nodes
position_type: PositionType::Absolute,
..default()
},
// Render overlay on top of everything
GlobalZIndex(FPS_OVERLAY_ZINDEX),
))
.with_children(|p| {
Expand Down
23 changes: 11 additions & 12 deletions crates/bevy_ui/src/experimental/ghost_hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ mod tests {
};
use bevy_hierarchy::{BuildChildren, ChildBuild};

use super::{GhostNode, UiChildren, UiRootNodes};
use crate::prelude::NodeBundle;
use super::{GhostNode, Node, UiChildren, UiRootNodes};

#[derive(Component, PartialEq, Debug)]
struct A(usize);
Expand All @@ -182,22 +181,22 @@ mod tests {

// Normal root
world
.spawn((A(1), NodeBundle::default()))
.spawn((A(1), Node::default()))
.with_children(|parent| {
parent.spawn((A(2), NodeBundle::default()));
parent.spawn((A(2), Node::default()));
parent
.spawn((A(3), GhostNode::new()))
.with_child((A(4), NodeBundle::default()));
.with_child((A(4), Node::default()));
});

// Ghost root
world
.spawn((A(5), GhostNode::new()))
.with_children(|parent| {
parent.spawn((A(6), NodeBundle::default()));
parent.spawn((A(6), Node::default()));
parent
.spawn((A(7), GhostNode::new()))
.with_child((A(8), NodeBundle::default()))
.with_child((A(8), Node::default()))
.with_child(A(9));
});

Expand All @@ -213,17 +212,17 @@ mod tests {
fn iterate_ui_children() {
let world = &mut World::new();

let n1 = world.spawn((A(1), NodeBundle::default())).id();
let n1 = world.spawn((A(1), Node::default())).id();
let n2 = world.spawn((A(2), GhostNode::new())).id();
let n3 = world.spawn((A(3), GhostNode::new())).id();
let n4 = world.spawn((A(4), NodeBundle::default())).id();
let n5 = world.spawn((A(5), NodeBundle::default())).id();
let n4 = world.spawn((A(4), Node::default())).id();
let n5 = world.spawn((A(5), Node::default())).id();

let n6 = world.spawn((A(6), GhostNode::new())).id();
let n7 = world.spawn((A(7), GhostNode::new())).id();
let n8 = world.spawn((A(8), NodeBundle::default())).id();
let n8 = world.spawn((A(8), Node::default())).id();
let n9 = world.spawn((A(9), GhostNode::new())).id();
let n10 = world.spawn((A(10), NodeBundle::default())).id();
let n10 = world.spawn((A(10), Node::default())).id();

let no_ui = world.spawn_empty().id();

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ui/src/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
///
/// # See also
///
/// - [`ButtonBundle`](crate::node_bundles::ButtonBundle) which includes this component
/// - [`Button`](crate::widget::Button) which requires this component
/// - [`RelativeCursorPosition`] to obtain the position of the cursor relative to current node
#[derive(Component, Copy, Clone, Eq, PartialEq, Debug, Reflect)]
#[reflect(Component, Default, PartialEq, Debug)]
Expand Down
116 changes: 55 additions & 61 deletions crates/bevy_ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,25 +581,25 @@ mod tests {

// spawn a root entity with width and height set to fill 100% of its parent
let ui_root = world
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
..default()
})
))
.id();

let ui_child = world
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
..default()
})
))
.id();

world.entity_mut(ui_root).add_child(ui_child);
Expand All @@ -624,7 +624,7 @@ mod tests {
let ui_surface = world.resource::<UiSurface>();
assert!(ui_surface.entity_to_taffy.is_empty());

let ui_entity = world.spawn(NodeBundle::default()).id();
let ui_entity = world.spawn(Node::default()).id();

// `ui_layout_system` should map `ui_entity` to a ui node in `UiSurface::entity_to_taffy`
ui_schedule.run(&mut world);
Expand Down Expand Up @@ -666,7 +666,7 @@ mod tests {
let camera_entity = world.spawn(Camera2d).id();

let ui_entity = world
.spawn((NodeBundle::default(), TargetCamera(camera_entity)))
.spawn((Node::default(), TargetCamera(camera_entity)))
.id();

// `ui_layout_system` should map `camera_entity` to a ui node in `UiSurface::camera_entity_to_taffy`
Expand Down Expand Up @@ -696,7 +696,7 @@ mod tests {
fn despawning_a_ui_entity_should_remove_its_corresponding_ui_node() {
let (mut world, mut ui_schedule) = setup_ui_test_world();

let ui_entity = world.spawn(NodeBundle::default()).id();
let ui_entity = world.spawn(Node::default()).id();

// `ui_layout_system` will insert a ui node into the internal layout tree corresponding to `ui_entity`
ui_schedule.run(&mut world);
Expand All @@ -721,7 +721,7 @@ mod tests {
fn changes_to_children_of_a_ui_entity_change_its_corresponding_ui_nodes_children() {
let (mut world, mut ui_schedule) = setup_ui_test_world();

let ui_parent_entity = world.spawn(NodeBundle::default()).id();
let ui_parent_entity = world.spawn(Node::default()).id();

// `ui_layout_system` will insert a ui node into the internal layout tree corresponding to `ui_entity`
ui_schedule.run(&mut world);
Expand All @@ -734,7 +734,7 @@ mod tests {

let mut ui_child_entities = (0..10)
.map(|_| {
let child = world.spawn(NodeBundle::default()).id();
let child = world.spawn(Node::default()).id();
world.entity_mut(ui_parent_entity).add_child(child);
child
})
Expand Down Expand Up @@ -828,40 +828,40 @@ mod tests {

let mut size = 150.;

world.spawn(NodeBundle {
style: Style {
world.spawn((
Node::default(),
Style {
// test should pass without explicitly requiring position_type to be set to Absolute
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
},
..default()
});
));

size -= 50.;

world.spawn(NodeBundle {
style: Style {
world.spawn((
Node::default(),
Style {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
},
..default()
});
));

size -= 50.;

world.spawn(NodeBundle {
style: Style {
world.spawn((
Node::default(),
Style {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
},
..default()
});
));

ui_schedule.run(&mut world);

Expand Down Expand Up @@ -996,13 +996,11 @@ mod tests {
));

world.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
top: Val::Px(0.),
left: Val::Px(0.),
..default()
},
Node::default(),
Style {
position_type: PositionType::Absolute,
top: Val::Px(0.),
left: Val::Px(0.),
..default()
},
MovingUiNode,
Expand Down Expand Up @@ -1052,12 +1050,10 @@ mod tests {

let ui_entity = world
.spawn((
NodeBundle {
style: Style {
align_self: AlignSelf::Start,
..Default::default()
},
..Default::default()
Node::default(),
Style {
align_self: AlignSelf::Start,
..default()
},
ContentSize::fixed_size(content_size),
))
Expand All @@ -1080,11 +1076,9 @@ mod tests {
let content_size = Vec2::new(50., 25.);
let ui_entity = world
.spawn((
NodeBundle {
style: Style {
align_self: AlignSelf::Start,
..Default::default()
},
Node::default(),
Style {
align_self: AlignSelf::Start,
..Default::default()
},
ContentSize::fixed_size(content_size),
Expand Down Expand Up @@ -1121,26 +1115,26 @@ mod tests {
let (mut world, mut ui_schedule) = setup_ui_test_world();

let parent = world
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
grid_template_columns: RepeatedGridTrack::min_content(2),
margin: UiRect::all(Val::Px(4.0)),
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|commands| {
for _ in 0..2 {
commands.spawn(NodeBundle {
style: Style {
commands.spawn((
Node::default(),
Style {
display: Display::Grid,
width: Val::Px(160.),
height: Val::Px(160.),
..Default::default()
..default()
},
..Default::default()
});
));
}
})
.id();
Expand Down Expand Up @@ -1211,25 +1205,25 @@ mod tests {
);

let ui_root = world
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
..default()
})
))
.id();

let ui_child = world
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
..default()
})
))
.id();

world.entity_mut(ui_root).add_child(ui_child);
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

//! This crate contains Bevy's UI system, which can be used to create UI for both 2D and 3D games
//! # Basic usage
//! Spawn UI elements with [`node_bundles::ButtonBundle`], [`node_bundles::ImageBundle`], [`Text`](prelude::Text) and [`node_bundles::NodeBundle`]
//! Spawn UI elements with [`widget::Button`], [`UiImage`], [`Text`](prelude::Text) and [`Node`]
//! This UI is laid out with the Flexbox and CSS Grid layout models (see <https://cssreference.io/flexbox/>)
pub mod measurement;
Expand Down Expand Up @@ -59,7 +59,7 @@ pub mod prelude {
ui_material::*,
ui_node::*,
widget::{Button, Label},
Interaction, UiMaterialHandle, UiMaterialPlugin, UiScale,
Interaction, MaterialNode, UiMaterialPlugin, UiScale,
},
// `bevy_sprite` re-exports for texture slicing
bevy_sprite::{BorderRect, ImageScaleMode, SliceScaleMode, TextureSlicer},
Expand Down
Loading

0 comments on commit eb19a9e

Please sign in to comment.