Migrate UI bundles to required components (#15898)

# 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 <mcanders1@gmail.com>
This commit is contained in:
VitalyR 2024-10-18 05:11:02 +08:00 committed by GitHub
parent 683d6c90a9
commit eb19a9ea0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
69 changed files with 1577 additions and 1730 deletions

View file

@ -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,
};
@ -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| {

View file

@ -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);
@ -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));
});
@ -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();

View file

@ -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)]

View file

@ -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);
@ -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);
@ -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`
@ -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);
@ -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);
@ -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
})
@ -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);
@ -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,
@ -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),
))
@ -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),
@ -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();
@ -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);

View file

@ -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;
@ -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},

View file

@ -1,9 +1,10 @@
//! This module contains basic node bundles used to build UIs
#![expect(deprecated)]
use crate::{
widget::{Button, UiImageSize},
BackgroundColor, BorderColor, BorderRadius, ContentSize, FocusPolicy, Interaction, Node,
ScrollPosition, Style, UiImage, UiMaterial, UiMaterialHandle, ZIndex,
BackgroundColor, BorderColor, BorderRadius, ContentSize, FocusPolicy, Interaction,
MaterialNode, Node, ScrollPosition, Style, UiImage, UiMaterial, ZIndex,
};
use bevy_ecs::bundle::Bundle;
use bevy_render::view::{InheritedVisibility, ViewVisibility, Visibility};
@ -15,6 +16,10 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
///
/// See [`node_bundles`](crate::node_bundles) for more specialized bundles like [`ImageBundle`].
#[derive(Bundle, Clone, Debug, Default)]
#[deprecated(
since = "0.15.0",
note = "Use the `Node` component instead. Inserting `Node` will also insert the other components required automatically."
)]
pub struct NodeBundle {
/// Describes the logical size of the node
pub node: Node,
@ -59,6 +64,10 @@ pub struct NodeBundle {
/// - [`ImageScaleMode`](bevy_sprite::ImageScaleMode) to enable either slicing or tiling of the texture
/// - [`TextureAtlas`](bevy_sprite::TextureAtlas) to draw a specific section of the texture
#[derive(Bundle, Debug, Default)]
#[deprecated(
since = "0.15.0",
note = "Use the `UiImage` component instead. Inserting `UiImage` will also insert the other components required automatically."
)]
pub struct ImageBundle {
/// Describes the logical size of the node
pub node: Node,
@ -108,6 +117,10 @@ pub struct ImageBundle {
/// - [`ImageScaleMode`](bevy_sprite::ImageScaleMode) to enable either slicing or tiling of the texture
/// - [`TextureAtlas`](bevy_sprite::TextureAtlas) to draw a specific section of the texture
#[derive(Bundle, Clone, Debug)]
#[deprecated(
since = "0.15.0",
note = "Use the `Button` component instead. Inserting `Button` will also insert the other components required automatically."
)]
pub struct ButtonBundle {
/// Describes the logical size of the node
pub node: Node,
@ -174,6 +187,10 @@ impl Default for ButtonBundle {
/// Adding a `BackgroundColor` component to an entity with this bundle will ignore the custom
/// material and use the background color instead.
#[derive(Bundle, Clone, Debug)]
#[deprecated(
since = "0.15.0",
note = "Use the `MaterialNode` component instead. Inserting `MaterialNode` will also insert the other components required automatically."
)]
pub struct MaterialNodeBundle<M: UiMaterial> {
/// Describes the logical size of the node
pub node: Node,
@ -181,7 +198,7 @@ pub struct MaterialNodeBundle<M: UiMaterial> {
/// In some cases these styles also affect how the node drawn/painted.
pub style: Style,
/// The [`UiMaterial`] used to render the node.
pub material: UiMaterialHandle<M>,
pub material: MaterialNode<M>,
/// Whether this node should block interaction with lower nodes
pub focus_policy: FocusPolicy,
/// The transform of the node

View file

@ -65,6 +65,25 @@ pub mod graph {
}
}
/// Z offsets of "extracted nodes" for a given entity. These exist to allow rendering multiple "extracted nodes"
/// for a given source entity (ex: render both a background color _and_ a custom material for a given node).
///
/// When possible these offsets should be defined in _this_ module to ensure z-index coordination across contexts.
/// When this is _not_ possible, pick a suitably unique index unlikely to clash with other things (ex: `0.1826823` not `0.1`).
///
/// Offsets should be unique for a given node entity to avoid z fighting.
/// These should pretty much _always_ be larger than -1.0 and smaller than 1.0 to avoid clipping into nodes
/// above / below the current node in the stack.
///
/// A z-index of 0.0 is the baseline, which is used as the primary "background color" of the node.
///
/// Note that nodes "stack" on each other, so a negative offset on the node above could clip _into_
/// a positive offset on a node below.
pub mod stack_z_offsets {
pub const BACKGROUND_COLOR: f32 = 0.0;
pub const MATERIAL: f32 = 0.18267;
}
pub const UI_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(13012847047162779583);
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
@ -823,7 +842,7 @@ pub fn queue_uinodes(
pipeline,
entity: (*entity, extracted_uinode.main_entity),
sort_key: (
FloatOrd(extracted_uinode.stack_index as f32),
FloatOrd(extracted_uinode.stack_index as f32 + stack_z_offsets::BACKGROUND_COLOR),
entity.index(),
),
// batch_range will be calculated in prepare_uinodes

View file

@ -60,9 +60,9 @@ where
Shader::from_wgsl
);
app.init_asset::<M>()
.register_type::<UiMaterialHandle<M>>()
.register_type::<MaterialNode<M>>()
.add_plugins((
ExtractComponentPlugin::<UiMaterialHandle<M>>::extract_visible(),
ExtractComponentPlugin::<MaterialNode<M>>::extract_visible(),
RenderAssetPlugin::<PreparedUiMaterial<M>>::default(),
));
@ -363,18 +363,15 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
materials: Extract<Res<Assets<M>>>,
default_ui_camera: Extract<DefaultUiCamera>,
uinode_query: Extract<
Query<
(
Entity,
&Node,
&GlobalTransform,
&UiMaterialHandle<M>,
&ViewVisibility,
Option<&CalculatedClip>,
Option<&TargetCamera>,
),
Without<BackgroundColor>,
>,
Query<(
Entity,
&Node,
&GlobalTransform,
&MaterialNode<M>,
&ViewVisibility,
Option<&CalculatedClip>,
Option<&TargetCamera>,
)>,
>,
render_entity_lookup: Extract<Query<RenderEntity>>,
) {
@ -652,7 +649,7 @@ pub fn queue_ui_material_nodes<M: UiMaterial>(
pipeline,
entity: (*entity, extracted_uinode.main_entity),
sort_key: (
FloatOrd(extracted_uinode.stack_index as f32),
FloatOrd(extracted_uinode.stack_index as f32 + stack_z_offsets::MATERIAL),
entity.index(),
),
batch_range: 0..0,

View file

@ -1,5 +1,6 @@
use core::hash::Hash;
use crate::Node;
use bevy_asset::{Asset, AssetId, Handle};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{component::Component, reflect::ReflectComponent};
@ -10,7 +11,7 @@ use bevy_render::{
};
use derive_more::derive::From;
/// Materials are used alongside [`UiMaterialPlugin`](crate::UiMaterialPlugin) and [`MaterialNodeBundle`](crate::prelude::MaterialNodeBundle)
/// Materials are used alongside [`UiMaterialPlugin`](crate::UiMaterialPlugin) and [`MaterialNode`]
/// to spawn entities that are rendered with a specific [`UiMaterial`] type. They serve as an easy to use high level
/// way to render `Node` entities with custom shader logic.
///
@ -58,17 +59,16 @@ use derive_more::derive::From;
///
/// // Spawn an entity using `CustomMaterial`.
/// fn setup(mut commands: Commands, mut materials: ResMut<Assets<CustomMaterial>>, asset_server: Res<AssetServer>) {
/// commands.spawn(MaterialNodeBundle {
/// style: Style {
/// width: Val::Percent(100.0),
/// ..Default::default()
/// },
/// material: UiMaterialHandle(materials.add(CustomMaterial {
/// commands.spawn((
/// MaterialNode(materials.add(CustomMaterial {
/// color: LinearRgba::RED,
/// color_texture: asset_server.load("some_image.png"),
/// })),
/// ..Default::default()
/// });
/// Style {
/// width: Val::Percent(100.0),
/// ..Default::default()
/// },
/// ));
/// }
/// ```
/// In WGSL shaders, the material's binding would look like this:
@ -157,22 +157,23 @@ where
Component, Clone, Debug, Deref, DerefMut, Reflect, PartialEq, Eq, ExtractComponent, From,
)]
#[reflect(Component, Default)]
pub struct UiMaterialHandle<M: UiMaterial>(pub Handle<M>);
#[require(Node)]
pub struct MaterialNode<M: UiMaterial>(pub Handle<M>);
impl<M: UiMaterial> Default for UiMaterialHandle<M> {
impl<M: UiMaterial> Default for MaterialNode<M> {
fn default() -> Self {
Self(Handle::default())
}
}
impl<M: UiMaterial> From<UiMaterialHandle<M>> for AssetId<M> {
fn from(material: UiMaterialHandle<M>) -> Self {
impl<M: UiMaterial> From<MaterialNode<M>> for AssetId<M> {
fn from(material: MaterialNode<M>) -> Self {
material.id()
}
}
impl<M: UiMaterial> From<&UiMaterialHandle<M>> for AssetId<M> {
fn from(material: &UiMaterialHandle<M>) -> Self {
impl<M: UiMaterial> From<&MaterialNode<M>> for AssetId<M> {
fn from(material: &MaterialNode<M>) -> Self {
material.id()
}
}

View file

@ -1,4 +1,4 @@
use crate::{UiRect, Val};
use crate::{widget::UiImageSize, ContentSize, FocusPolicy, UiRect, Val};
use bevy_asset::Handle;
use bevy_color::Color;
use bevy_ecs::{prelude::*, system::SystemParam};
@ -7,8 +7,10 @@ use bevy_reflect::prelude::*;
use bevy_render::{
camera::{Camera, RenderTarget},
texture::{Image, TRANSPARENT_IMAGE_HANDLE},
view::Visibility,
};
use bevy_sprite::BorderRect;
use bevy_transform::components::Transform;
use bevy_utils::warn_once;
use bevy_window::{PrimaryWindow, WindowRef};
use core::num::NonZero;
@ -25,6 +27,18 @@ use smallvec::SmallVec;
/// - [`Interaction`](crate::Interaction) to obtain the interaction state of this node
#[derive(Component, Debug, Copy, Clone, PartialEq, Reflect)]
#[reflect(Component, Default, Debug)]
#[require(
Style,
BackgroundColor,
BorderColor,
BorderRadius,
ContentSize,
FocusPolicy,
ScrollPosition,
Transform,
Visibility,
ZIndex
)]
pub struct Node {
/// The order of the node in the UI layout.
/// Nodes with a higher stack index are drawn on top of and receive interactions before nodes with lower stack indices.
@ -883,7 +897,7 @@ pub enum Display {
/// Use no layout, don't render this node and its children.
///
/// If you want to hide a node and its children,
/// but keep its layout in place, set its [`Visibility`](bevy_render::view::Visibility) component instead.
/// but keep its layout in place, set its [`Visibility`] component instead.
None,
}
@ -1955,22 +1969,20 @@ impl Default for BorderColor {
/// The [`Outline`] component adds an outline outside the edge of a UI node.
/// Outlines do not take up space in the layout.
///
/// To add an [`Outline`] to a ui node you can spawn a `(NodeBundle, Outline)` tuple bundle:
/// To add an [`Outline`] to a ui node you can spawn a `(Node, Outline)` tuple bundle:
/// ```
/// # use bevy_ecs::prelude::*;
/// # use bevy_ui::prelude::*;
/// # use bevy_color::palettes::basic::{RED, BLUE};
/// fn setup_ui(mut commands: Commands) {
/// commands.spawn((
/// NodeBundle {
/// style: Style {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// ..Default::default()
/// },
/// background_color: BLUE.into(),
/// Node::default(),
/// Style {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// ..Default::default()
/// },
/// BackgroundColor(BLUE.into()),
/// Outline::new(Val::Px(10.), Val::ZERO, RED.into())
/// ));
/// }
@ -2032,6 +2044,7 @@ impl Outline {
/// The 2D texture displayed for this UI node
#[derive(Component, Clone, Debug, Reflect)]
#[reflect(Component, Default, Debug)]
#[require(Node, UiImageSize)]
pub struct UiImage {
/// The tint color used to draw the image.
///
@ -2173,32 +2186,30 @@ pub struct GlobalZIndex(pub i32);
/// dimension, either width or height.
///
/// # Example
/// ```
/// ```rust
/// # use bevy_ecs::prelude::*;
/// # use bevy_ui::prelude::*;
/// # use bevy_color::palettes::basic::{BLUE};
/// fn setup_ui(mut commands: Commands) {
/// commands.spawn((
/// NodeBundle {
/// style: Style {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// border: UiRect::all(Val::Px(2.)),
/// ..Default::default()
/// },
/// background_color: BLUE.into(),
/// border_radius: BorderRadius::new(
/// // top left
/// Val::Px(10.),
/// // top right
/// Val::Px(20.),
/// // bottom right
/// Val::Px(30.),
/// // bottom left
/// Val::Px(40.),
/// ),
/// Node::default(),
/// Style {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// border: UiRect::all(Val::Px(2.)),
/// ..Default::default()
/// },
/// BackgroundColor(BLUE.into()),
/// BorderRadius::new(
/// // top left
/// Val::Px(10.),
/// // top right
/// Val::Px(20.),
/// // bottom right
/// Val::Px(30.),
/// // bottom left
/// Val::Px(40.),
/// ),
/// ));
/// }
/// ```

View file

@ -1,7 +1,9 @@
use crate::{FocusPolicy, Interaction, Node};
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
/// Marker struct for buttons
#[derive(Component, Debug, Default, Clone, Copy, PartialEq, Eq, Reflect)]
#[reflect(Component, Default, Debug, PartialEq)]
#[require(Node, FocusPolicy(|| FocusPolicy::Block), Interaction)]
pub struct Button;

View file

@ -1,6 +1,6 @@
use crate::{
ContentSize, DefaultUiCamera, FixedMeasure, FocusPolicy, Measure, MeasureArgs, Node,
NodeMeasure, Style, TargetCamera, UiScale, ZIndex,
ContentSize, DefaultUiCamera, FixedMeasure, Measure, MeasureArgs, Node, NodeMeasure,
TargetCamera, UiScale,
};
use bevy_asset::Assets;
use bevy_color::Color;
@ -16,14 +16,13 @@ use bevy_ecs::{
};
use bevy_math::Vec2;
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{camera::Camera, texture::Image, view::Visibility};
use bevy_render::{camera::Camera, texture::Image};
use bevy_sprite::TextureAtlasLayout;
use bevy_text::{
scale_value, ComputedTextBlock, CosmicFontSystem, Font, FontAtlasSets, LineBreak, SwashCache,
TextBounds, TextColor, TextError, TextFont, TextLayout, TextLayoutInfo, TextMeasureInfo,
TextPipeline, TextReader, TextRoot, TextSpanAccess, TextWriter, YAxisOrientation,
};
use bevy_transform::components::Transform;
use bevy_utils::{tracing::error, Entry};
use taffy::style::AvailableSpace;
@ -67,7 +66,7 @@ pub struct TextBundle {}
/// The string in this component is the first 'text span' in a hierarchy of text spans that are collected into
/// a [`ComputedTextBlock`]. See [`TextSpan`](bevy_text::TextSpan) for the component used by children of entities with [`Text`].
///
/// Note that [`Transform`] on this entity is managed automatically by the UI layout system.
/// Note that [`Transform`](bevy_transform::components::Transform) on this entity is managed automatically by the UI layout system.
///
///
/// ```
@ -103,19 +102,7 @@ pub struct TextBundle {}
/// ```
#[derive(Component, Debug, Default, Clone, Deref, DerefMut, Reflect)]
#[reflect(Component, Default, Debug)]
#[require(
TextLayout,
TextFont,
TextColor,
TextNodeFlags,
Node,
Style, // TODO: Remove when Node uses required components.
ContentSize, // TODO: Remove when Node uses required components.
FocusPolicy, // TODO: Remove when Node uses required components.
ZIndex, // TODO: Remove when Node uses required components.
Visibility, // TODO: Remove when Node uses required components.
Transform // TODO: Remove when Node uses required components.
)]
#[require(TextLayout, TextFont, TextColor, TextNodeFlags, Node)]
pub struct Text(pub String);
impl Text {

View file

@ -114,18 +114,17 @@ fn setup(
Transform::from_xyz(0.0, 0.0, 0.0),
));
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()
});
));
let text_style = TextFont::default();

View file

@ -192,11 +192,9 @@ fn setup(
let mut label = |entity: Entity, label: &str| {
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
..default()
},
Node::default(),
Style {
position_type: PositionType::Absolute,
..default()
},
ExampleLabel { entity },

View file

@ -138,8 +138,9 @@ fn setup(
fn add_buttons(commands: &mut Commands, font: &Handle<Font>, color_grading: &ColorGrading) {
// Spawn the parent node that contains all the buttons.
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
@ -147,8 +148,7 @@ fn add_buttons(commands: &mut Commands, font: &Handle<Font>, color_grading: &Col
bottom: Val::Px(12.0),
..default()
},
..default()
})
))
.with_children(|parent| {
// Create the first row, which contains the global controls.
add_buttons_for_global_controls(parent, color_grading, font);
@ -172,36 +172,31 @@ fn add_buttons_for_global_controls(
font: &Handle<Font>,
) {
// Add the parent node for the row.
parent
.spawn(NodeBundle {
style: Style::default(),
..default()
})
.with_children(|parent| {
// Add some placeholder text to fill this column.
parent.spawn(NodeBundle {
style: Style {
width: Val::Px(125.0),
..default()
},
parent.spawn(Node::default()).with_children(|parent| {
// Add some placeholder text to fill this column.
parent.spawn((
Node::default(),
Style {
width: Val::Px(125.0),
..default()
});
},
));
// Add each global color grading option button.
for option in [
SelectedGlobalColorGradingOption::Exposure,
SelectedGlobalColorGradingOption::Temperature,
SelectedGlobalColorGradingOption::Tint,
SelectedGlobalColorGradingOption::Hue,
] {
add_button_for_value(
parent,
SelectedColorGradingOption::Global(option),
color_grading,
font,
);
}
});
// Add each global color grading option button.
for option in [
SelectedGlobalColorGradingOption::Exposure,
SelectedGlobalColorGradingOption::Temperature,
SelectedGlobalColorGradingOption::Tint,
SelectedGlobalColorGradingOption::Hue,
] {
add_button_for_value(
parent,
SelectedColorGradingOption::Global(option),
color_grading,
font,
);
}
});
}
/// Adds the buttons that control color grading for individual sections
@ -214,13 +209,13 @@ fn add_buttons_for_section(
) {
// Spawn the row container.
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
// Spawn the label ("Highlights", etc.)
add_text(parent, &section.to_string(), font, Color::WHITE).insert(Style {
@ -255,8 +250,9 @@ fn add_button_for_value(
) {
// Add the button node.
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
border: UiRect::all(Val::Px(1.0)),
width: Val::Px(200.0),
justify_content: JustifyContent::Center,
@ -265,11 +261,10 @@ fn add_button_for_value(
margin: UiRect::right(Val::Px(12.0)),
..default()
},
border_color: BorderColor(Color::WHITE),
border_radius: BorderRadius::MAX,
background_color: Color::BLACK.into(),
..default()
})
BorderColor(Color::WHITE),
BorderRadius::MAX,
BackgroundColor(Color::BLACK),
))
.insert(ColorGradingOptionWidget {
widget_type: ColorGradingOptionWidgetType::Button,
option,
@ -286,13 +281,13 @@ fn add_button_for_value(
});
// Add a spacer.
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
flex_grow: 1.0,
..default()
},
..default()
});
));
// Add the value text.
add_text(

View file

@ -209,10 +209,7 @@ fn spawn_gltf_scene(commands: &mut Commands, asset_server: &AssetServer) {
/// Spawns all the buttons at the bottom of the screen.
fn spawn_buttons(commands: &mut Commands) {
commands
.spawn(NodeBundle {
style: widgets::main_ui_style(),
..default()
})
.spawn((Node::default(), widgets::main_ui_style()))
.with_children(|parent| {
widgets::spawn_option_buttons(
parent,

View file

@ -98,15 +98,13 @@ fn setup(
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::BLACK.with_alpha(0.75).into(),
Node::default(),
Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
BackgroundColor(Color::BLACK.with_alpha(0.75)),
GlobalZIndex(i32::MAX),
))
.with_children(|p| {

View file

@ -85,12 +85,10 @@ fn setup(
commands
.spawn((
TargetCamera(camera),
NodeBundle {
style: Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
))
@ -110,8 +108,9 @@ fn setup(
fn buttons_panel(parent: &mut ChildBuilder) {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -122,8 +121,7 @@ fn setup(
padding: UiRect::all(Val::Px(20.)),
..default()
},
..default()
})
))
.with_children(|parent| {
rotate_button(parent, "<", Direction::Left);
rotate_button(parent, ">", Direction::Right);
@ -134,19 +132,17 @@ fn setup(
parent
.spawn((
RotateCamera(direction),
ButtonBundle {
style: Style {
width: Val::Px(40.),
height: Val::Px(40.),
border: UiRect::all(Val::Px(2.)),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
border_color: Color::WHITE.into(),
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
Button,
Style {
width: Val::Px(40.),
height: Val::Px(40.),
border: UiRect::all(Val::Px(2.)),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BorderColor(Color::WHITE),
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|parent| {
parent.spawn(Text::new(caption));

View file

@ -150,9 +150,10 @@ fn setup(
// contains the `AnimationPlayer`, as well as a child node that contains the
// text to be animated.
commands
.spawn(NodeBundle {
.spawn((
Node::default(),
// Cover the whole screen, and center contents.
style: Style {
Style {
position_type: PositionType::Absolute,
top: Val::Px(0.0),
left: Val::Px(0.0),
@ -162,8 +163,7 @@ fn setup(
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.insert(animation_player)
.insert(AnimationGraphHandle(animation_graph))
.with_children(|builder| {

View file

@ -283,22 +283,20 @@ fn setup_node_rects(commands: &mut Commands) {
let container = {
let mut container = commands.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
bottom: Val::Px(node_rect.bottom),
left: Val::Px(node_rect.left),
height: Val::Px(node_rect.height),
width: Val::Px(node_rect.width),
align_items: AlignItems::Center,
justify_items: JustifyItems::Center,
align_content: AlignContent::Center,
justify_content: JustifyContent::Center,
..default()
},
border_color: WHITE.into(),
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(node_rect.bottom),
left: Val::Px(node_rect.left),
height: Val::Px(node_rect.height),
width: Val::Px(node_rect.width),
align_items: AlignItems::Center,
justify_items: JustifyItems::Center,
align_content: AlignContent::Center,
justify_content: JustifyContent::Center,
..default()
},
BorderColor(WHITE.into()),
Outline::new(Val::Px(1.), Val::ZERO, Color::WHITE),
));
@ -316,8 +314,9 @@ fn setup_node_rects(commands: &mut Commands) {
// Create the background color.
if let NodeType::Clip(_) = node_type {
let background = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
top: Val::Px(0.),
left: Val::Px(0.),
@ -325,9 +324,8 @@ fn setup_node_rects(commands: &mut Commands) {
width: Val::Px(node_rect.width),
..default()
},
background_color: DARK_GREEN.into(),
..default()
})
BackgroundColor(DARK_GREEN.into()),
))
.id();
commands.entity(container).add_child(background);
@ -343,8 +341,9 @@ fn setup_node_rects(commands: &mut Commands) {
/// vertical and horizontal lines, respectively.
fn setup_node_lines(commands: &mut Commands) {
for line in &HORIZONTAL_LINES {
commands.spawn(NodeBundle {
style: Style {
commands.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(line.bottom),
left: Val::Px(line.left),
@ -353,14 +352,14 @@ fn setup_node_lines(commands: &mut Commands) {
border: UiRect::bottom(Val::Px(1.0)),
..default()
},
border_color: WHITE.into(),
..default()
});
BorderColor(WHITE.into()),
));
}
for line in &VERTICAL_LINES {
commands.spawn(NodeBundle {
style: Style {
commands.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(line.bottom),
left: Val::Px(line.left),
@ -369,9 +368,8 @@ fn setup_node_lines(commands: &mut Commands) {
border: UiRect::left(Val::Px(1.0)),
..default()
},
border_color: WHITE.into(),
..default()
});
BorderColor(WHITE.into()),
));
}
}

View file

@ -168,8 +168,9 @@ fn setup_ui(mut commands: Commands) {
// Add the buttons that allow the user to toggle mask groups on and off.
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
@ -177,8 +178,7 @@ fn setup_ui(mut commands: Commands) {
bottom: Val::Px(12.0),
..default()
},
..default()
})
))
.with_children(|parent| {
let row_style = Style {
flex_direction: FlexDirection::Row,
@ -189,10 +189,7 @@ fn setup_ui(mut commands: Commands) {
add_mask_group_control(parent, "Head", Val::Auto, MASK_GROUP_HEAD);
parent
.spawn(NodeBundle {
style: row_style.clone(),
..default()
})
.spawn((Node::default(), row_style.clone()))
.with_children(|parent| {
add_mask_group_control(
parent,
@ -209,10 +206,7 @@ fn setup_ui(mut commands: Commands) {
});
parent
.spawn(NodeBundle {
style: row_style,
..default()
})
.spawn((Node::default(), row_style))
.with_children(|parent| {
add_mask_group_control(
parent,
@ -251,8 +245,9 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
);
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
border: UiRect::all(Val::Px(1.0)),
width,
flex_direction: FlexDirection::Column,
@ -262,15 +257,15 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
margin: UiRect::ZERO,
..default()
},
border_color: BorderColor(Color::WHITE),
border_radius: BorderRadius::all(Val::Px(3.0)),
background_color: Color::BLACK.into(),
..default()
})
BorderColor(Color::WHITE),
BorderRadius::all(Val::Px(3.0)),
BackgroundColor(Color::BLACK),
))
.with_children(|builder| {
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
border: UiRect::ZERO,
width: Val::Percent(100.0),
justify_content: JustifyContent::Center,
@ -279,9 +274,8 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
margin: UiRect::ZERO,
..default()
},
background_color: Color::BLACK.into(),
..default()
})
BackgroundColor(Color::BLACK),
))
.with_child((
Text::new(label),
label_text_style.clone(),
@ -292,8 +286,9 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
));
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::Center,
@ -301,9 +296,8 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
border: UiRect::top(Val::Px(1.0)),
..default()
},
border_color: BorderColor(Color::WHITE),
..default()
})
BorderColor(Color::WHITE),
))
.with_children(|builder| {
for (index, label) in [
AnimationLabel::Run,
@ -315,13 +309,14 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
.enumerate()
{
builder
.spawn(ButtonBundle {
background_color: if index > 0 {
Color::BLACK.into()
.spawn((
Button,
BackgroundColor(if index > 0 {
Color::BLACK
} else {
Color::WHITE.into()
},
style: Style {
Color::WHITE
}),
Style {
flex_grow: 1.0,
border: if index > 0 {
UiRect::left(Val::Px(1.0))
@ -330,9 +325,8 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
},
..default()
},
border_color: BorderColor(Color::WHITE),
..default()
})
BorderColor(Color::WHITE),
))
.with_child((
Text(format!("{:?}", label)),
if index > 0 {

View file

@ -126,14 +126,12 @@ fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
NodeBundle {
style: Style {
width: Val::Vw(100.0),
height: Val::Vh(100.0),
flex_direction: FlexDirection::Column,
padding: UiRect::all(Val::Px(12.)),
..default()
},
Node::default(),
Style {
width: Val::Vw(100.0),
height: Val::Vh(100.0),
flex_direction: FlexDirection::Column,
padding: UiRect::all(Val::Px(12.)),
..default()
},
LogViewerRoot,

View file

@ -192,15 +192,15 @@ fn spawn_lights(mut commands: Commands) {
fn spawn_text(mut commands: Commands) {
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
..default()
})
))
.with_child(Text::new(concat!(
"Move the camera with your mouse.\n",
"Press arrow up to decrease the FOV of the world model.\n",

View file

@ -393,15 +393,15 @@ fn gameover_keyboard(
// display the number of cake eaten before losing
fn display_score(mut commands: Commands, game: Res<Game>) {
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_child((
Text::new(format!("Cake eaten: {}", game.cake_eaten)),
TextFont {

View file

@ -75,28 +75,25 @@ mod splash {
// Display the logo
commands
.spawn((
NodeBundle {
style: Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
Node::default(),
Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
OnSplashScreen,
))
.with_children(|parent| {
parent.spawn(ImageBundle {
style: Style {
parent.spawn((
UiImage::new(icon),
Style {
// This will set the logo to be 200px wide, and auto adjust its height
width: Val::Px(200.0),
..default()
},
image: UiImage::new(icon),
..default()
});
));
});
// Insert the timer as a resource
commands.insert_resource(SplashTimer(Timer::from_seconds(1.0, TimerMode::Once)));
@ -144,24 +141,23 @@ mod game {
) {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
// center children
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
// center children
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
OnGameScreen,
))
.with_children(|parent| {
// First create a `NodeBundle` for centering what we want to display
// First create a `Node` and `Style` for centering what we want to display
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// This will display its children in a column, from top to bottom
flex_direction: FlexDirection::Column,
// `align_items` will align children on the cross axis. Here the main axis is
@ -170,9 +166,8 @@ mod game {
align_items: AlignItems::Center,
..default()
},
background_color: Color::BLACK.into(),
..default()
})
BackgroundColor(Color::BLACK),
))
.with_children(|p| {
p.spawn((
Text::new("Will be back to the menu shortly..."),
@ -405,29 +400,27 @@ mod menu {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
OnMainMenuScreen,
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
// Display the game name
parent.spawn((
@ -449,20 +442,14 @@ mod menu {
// - quit
parent
.spawn((
ButtonBundle {
style: button_style.clone(),
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style.clone(),
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Play,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/right.png");
parent.spawn(ImageBundle {
style: button_icon_style.clone(),
image: UiImage::new(icon),
..default()
});
parent.spawn((UiImage::new(icon), button_icon_style.clone()));
parent.spawn((
Text::new("New Game"),
button_text_font.clone(),
@ -471,20 +458,14 @@ mod menu {
});
parent
.spawn((
ButtonBundle {
style: button_style.clone(),
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style.clone(),
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Settings,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/wrench.png");
parent.spawn(ImageBundle {
style: button_icon_style.clone(),
image: UiImage::new(icon),
..default()
});
parent.spawn((UiImage::new(icon), button_icon_style.clone()));
parent.spawn((
Text::new("Settings"),
button_text_font.clone(),
@ -493,20 +474,14 @@ mod menu {
});
parent
.spawn((
ButtonBundle {
style: button_style,
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Quit,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/exitRight.png");
parent.spawn(ImageBundle {
style: button_icon_style,
image: UiImage::new(icon),
..default()
});
parent.spawn((UiImage::new(icon), button_icon_style));
parent.spawn((
Text::new("Quit"),
button_text_font,
@ -537,29 +512,27 @@ mod menu {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
OnSettingsMenuScreen,
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
for (action, text) in [
(MenuButtonAction::SettingsDisplay, "Display"),
@ -568,11 +541,9 @@ mod menu {
] {
parent
.spawn((
ButtonBundle {
style: button_style.clone(),
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style.clone(),
BackgroundColor(NORMAL_BUTTON),
action,
))
.with_children(|parent| {
@ -602,41 +573,39 @@ mod menu {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
OnDisplaySettingsMenuScreen,
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
// Create a new `NodeBundle`, this time not setting its `flex_direction`. It will
// Create a new `Node` and `Style` , this time not setting its `flex_direction`. It will
// use the default value, `FlexDirection::Row`, from left to right.
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
// Display a label for the current setting
parent.spawn((
@ -650,15 +619,13 @@ mod menu {
DisplayQuality::High,
] {
let mut entity = parent.spawn((
ButtonBundle {
style: Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
..button_style.clone()
},
background_color: NORMAL_BUTTON.into(),
..default()
Button,
Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
..button_style.clone()
},
BackgroundColor(NORMAL_BUTTON),
quality_setting,
));
entity.with_children(|parent| {
@ -675,11 +642,9 @@ mod menu {
// Display the back button to return to the settings screen
parent
.spawn((
ButtonBundle {
style: button_style,
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::BackToSettings,
))
.with_children(|parent| {
@ -708,52 +673,48 @@ mod menu {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
OnSoundSettingsMenuScreen,
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
background_color: CRIMSON.into(),
..default()
})
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
parent.spawn((Text::new("Volume"), button_text_style.clone()));
for volume_setting in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] {
let mut entity = parent.spawn((
ButtonBundle {
style: Style {
width: Val::Px(30.0),
height: Val::Px(65.0),
..button_style.clone()
},
background_color: NORMAL_BUTTON.into(),
..default()
Button,
Style {
width: Val::Px(30.0),
height: Val::Px(65.0),
..button_style.clone()
},
BackgroundColor(NORMAL_BUTTON),
Volume(volume_setting),
));
if *volume == Volume(volume_setting) {
@ -763,11 +724,9 @@ mod menu {
});
parent
.spawn((
ButtonBundle {
style: button_style,
background_color: NORMAL_BUTTON.into(),
..default()
},
Button,
button_style,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::BackToSettings,
))
.with_child((Text::new("Back"), button_text_style));

View file

@ -82,15 +82,15 @@ fn setup(mut commands: Commands) {
..default()
};
commands
.spawn(NodeBundle {
background_color: BackgroundColor(Color::NONE),
style: Style {
.spawn((
Node::default(),
BackgroundColor(Color::NONE),
Style {
justify_self: JustifySelf::Center,
align_self: AlignSelf::FlexEnd,
..default()
},
..default()
})
))
.with_child((Text::new("Press 1 or 2 to load a new scene."), text_style));
}
@ -257,15 +257,13 @@ fn load_loading_screen(mut commands: Commands) {
// Spawn the UI that will make up the loading screen.
commands
.spawn((
NodeBundle {
background_color: BackgroundColor(Color::BLACK),
style: Style {
height: Val::Percent(100.0),
width: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
Node::default(),
BackgroundColor(Color::BLACK),
Style {
height: Val::Percent(100.0),
width: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
LoadingScreen,

View file

@ -58,8 +58,9 @@ pub fn spawn_option_button<T>(
// Add the button node.
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
border: UiRect::all(Val::Px(1.0)).with_left(if is_first {
Val::Px(1.0)
} else {
@ -70,13 +71,12 @@ pub fn spawn_option_button<T>(
padding: UiRect::axes(Val::Px(12.0), Val::Px(6.0)),
..default()
},
border_color: BorderColor(Color::WHITE),
border_radius: BorderRadius::ZERO
BorderColor(Color::WHITE),
BorderRadius::ZERO
.with_left(if is_first { Val::Px(6.0) } else { Val::Px(0.0) })
.with_right(if is_last { Val::Px(6.0) } else { Val::Px(0.0) }),
background_color: BackgroundColor(bg_color),
..default()
})
BackgroundColor(bg_color),
))
.insert(RadioButton)
.insert(WidgetClickSender(option_value.clone()))
.with_children(|parent| {
@ -97,13 +97,13 @@ where
{
// Add the parent node for the row.
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
spawn_ui_text(parent, title, Color::BLACK).insert(Style {
width: Val::Px(125.0),

View file

@ -78,8 +78,9 @@ fn setup(mut commands: Commands) {
let style = TextFont::default();
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -87,8 +88,7 @@ fn setup(mut commands: Commands) {
row_gap: Val::Px(20.0),
..default()
},
..default()
})
))
.with_children(|parent| {
parent.spawn((Text::new(instructions_text), style.clone()));
parent.spawn((SplineModeText, Text(spline_mode_text), style.clone()));

View file

@ -370,12 +370,10 @@ fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
commands
.spawn((
HeaderNode,
NodeBundle {
style: Style {
justify_self: JustifySelf::Center,
top: Val::Px(5.0),
..Default::default()
},
Node::default(),
Style {
justify_self: JustifySelf::Center,
top: Val::Px(5.0),
..Default::default()
},
TargetCamera(active_camera),

View file

@ -114,8 +114,9 @@ fn setup_scene(
// Test ui
commands
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
position_type: PositionType::Absolute,
@ -124,8 +125,7 @@ fn setup_scene(
bottom: Val::Px(50.0),
..default()
},
..default()
})
))
.with_child((
Text::new("Test Button"),
TextFont {

View file

@ -145,15 +145,15 @@ fn spawn_player(mut commands: Commands, asset_server: Res<AssetServer>) {
/// Spawn a bit of UI text to explain how to move the player.
fn spawn_text(mut commands: Commands) {
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
..default()
})
))
.with_child((
Text::new("Move the player with WASD"),
TextFont {

View file

@ -336,8 +336,9 @@ mod ui {
pub fn setup_menu(mut commands: Commands, tutorial_state: Res<State<TutorialState>>) {
let button_entity = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -347,24 +348,21 @@ mod ui {
row_gap: Val::Px(10.),
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn((
ButtonBundle {
style: Style {
width: Val::Px(200.),
height: Val::Px(65.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
Button,
Style {
width: Val::Px(200.),
height: Val::Px(65.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
BackgroundColor(NORMAL_BUTTON),
MenuButton::Play,
))
.with_children(|parent| {
@ -380,23 +378,20 @@ mod ui {
parent
.spawn((
ButtonBundle {
style: Style {
width: Val::Px(200.),
height: Val::Px(65.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
background_color: match tutorial_state.get() {
TutorialState::Active => ACTIVE_BUTTON,
TutorialState::Inactive => NORMAL_BUTTON,
}
.into(),
Button,
Style {
width: Val::Px(200.),
height: Val::Px(65.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
BackgroundColor(match tutorial_state.get() {
TutorialState::Active => ACTIVE_BUTTON,
TutorialState::Inactive => NORMAL_BUTTON,
}),
MenuButton::Tutorial,
))
.with_children(|parent| {
@ -464,37 +459,33 @@ mod ui {
commands
.spawn((
StateScoped(IsPaused::Paused),
NodeBundle {
style: Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
))
.with_children(|parent| {
parent
.spawn((
NodeBundle {
style: Style {
width: Val::Px(400.),
height: Val::Px(400.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
Node::default(),
Style {
width: Val::Px(400.),
height: Val::Px(400.),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
BackgroundColor(NORMAL_BUTTON),
MenuButton::Play,
))
.with_children(|parent| {
@ -514,18 +505,16 @@ mod ui {
commands
.spawn((
StateScoped(TurboMode),
NodeBundle {
style: Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Start,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Start,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
))
@ -556,18 +545,16 @@ mod ui {
commands
.spawn((
StateScoped(Tutorial::MovementInstructions),
NodeBundle {
style: Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::End,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::End,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
))
@ -613,18 +600,16 @@ mod ui {
commands
.spawn((
StateScoped(Tutorial::PauseInstructions),
NodeBundle {
style: Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::End,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::End,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
position_type: PositionType::Absolute,
..default()
},
))

View file

@ -243,8 +243,9 @@ const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
fn setup_menu(mut commands: Commands) {
let button_entity = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -252,12 +253,12 @@ fn setup_menu(mut commands: Commands) {
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.),
height: Val::Px(65.),
// horizontally center child text
@ -266,9 +267,8 @@ fn setup_menu(mut commands: Commands) {
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
..default()
})
BackgroundColor(NORMAL_BUTTON),
))
.with_children(|parent| {
parent.spawn((
Text::new("Play"),

View file

@ -51,8 +51,9 @@ fn setup(mut commands: Commands) {
fn setup_menu(mut commands: Commands) {
let button_entity = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -60,12 +61,12 @@ fn setup_menu(mut commands: Commands) {
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.),
height: Val::Px(65.),
// horizontally center child text
@ -74,9 +75,8 @@ fn setup_menu(mut commands: Commands) {
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
..default()
})
BackgroundColor(NORMAL_BUTTON),
))
.with_children(|parent| {
parent.spawn((
Text::new("Play"),

View file

@ -156,8 +156,9 @@ mod ui {
pub fn setup_menu(mut commands: Commands) {
let button_entity = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -165,12 +166,12 @@ mod ui {
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.),
height: Val::Px(65.),
// horizontally center child text
@ -179,9 +180,8 @@ mod ui {
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
..default()
})
BackgroundColor(NORMAL_BUTTON),
))
.with_children(|parent| {
parent.spawn((
Text::new("Play"),
@ -205,24 +205,23 @@ mod ui {
commands
.spawn((
StateScoped(IsPaused::Paused),
NodeBundle {
style: Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
..default()
},
Node::default(),
Style {
// center button
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
row_gap: Val::Px(10.),
..default()
},
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(400.),
height: Val::Px(400.),
// horizontally center child text
@ -231,9 +230,8 @@ mod ui {
align_items: AlignItems::Center,
..default()
},
background_color: NORMAL_BUTTON.into(),
..default()
})
BackgroundColor(NORMAL_BUTTON),
))
.with_children(|parent| {
parent.spawn((
Text::new("Paused"),

View file

@ -261,15 +261,13 @@ fn setup(
commands.spawn(Camera2d);
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::BLACK.with_alpha(0.75).into(),
Node::default(),
Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
BackgroundColor(Color::BLACK.with_alpha(0.75)),
GlobalZIndex(i32::MAX),
))
.with_children(|p| {

View file

@ -138,8 +138,9 @@ fn setup_flex(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<
let as_rainbow = |i: usize| Color::hsl((i as f32 / buttons_f) * 360.0, 0.9, 0.8);
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
@ -147,32 +148,29 @@ fn setup_flex(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<
height: Val::Percent(100.),
..default()
},
..default()
})
))
.with_children(|commands| {
for column in 0..args.buttons {
commands
.spawn(NodeBundle::default())
.with_children(|commands| {
for row in 0..args.buttons {
let color = as_rainbow(row % column.max(1));
let border_color = Color::WHITE.with_alpha(0.5).into();
spawn_button(
commands,
color,
buttons_f,
column,
row,
!args.no_text,
border,
border_color,
image
.as_ref()
.filter(|_| (column + row) % args.image_freq == 0)
.cloned(),
);
}
});
commands.spawn(Node::default()).with_children(|commands| {
for row in 0..args.buttons {
let color = as_rainbow(row % column.max(1));
let border_color = Color::WHITE.with_alpha(0.5).into();
spawn_button(
commands,
color,
buttons_f,
column,
row,
!args.no_text,
border,
border_color,
image
.as_ref()
.filter(|_| (column + row) % args.image_freq == 0)
.cloned(),
);
}
});
}
});
}
@ -195,8 +193,9 @@ fn setup_grid(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<
let as_rainbow = |i: usize| Color::hsl((i as f32 / buttons_f) * 360.0, 0.9, 0.8);
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
width: Val::Percent(100.),
height: Val::Percent(100.0),
@ -204,8 +203,7 @@ fn setup_grid(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<
grid_template_rows: RepeatedGridTrack::flex(args.buttons as u16, 1.0),
..default()
},
..default()
})
))
.with_children(|commands| {
for column in 0..args.buttons {
for row in 0..args.buttons {
@ -246,20 +244,18 @@ fn spawn_button(
let height = Val::Vh(90.0 / buttons);
let margin = UiRect::axes(width * 0.05, height * 0.05);
let mut builder = commands.spawn((
ButtonBundle {
style: Style {
width,
height,
margin,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
border,
..default()
},
background_color: background_color.into(),
border_color,
Button,
Style {
width,
height,
margin,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
border,
..default()
},
BackgroundColor(background_color),
border_color,
IdleColor(background_color),
));

View file

@ -56,24 +56,24 @@ fn setup(mut commands: Commands) {
};
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|commands| {
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(1000.),
..Default::default()
},
..Default::default()
})
))
.with_child((Text(text_string.clone()), text_font.clone(), text_block));
});

View file

@ -77,8 +77,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
let font_size = 33.;
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Flex,
justify_content: JustifyContent::SpaceBetween,
width: Val::Percent(100.),
@ -87,8 +88,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
padding: UiRect::all(Val::Px(20.0)),
..default()
},
..default()
})
))
.with_children(|builder| {
// real time info
builder.spawn((

View file

@ -12,8 +12,9 @@ fn main() {
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
let root = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect::all(Val::Px(25.0)),
align_self: AlignSelf::Stretch,
justify_self: JustifySelf::Stretch,
@ -21,16 +22,16 @@ fn setup(mut commands: Commands) {
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
align_content: AlignContent::FlexStart,
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.id();
let root_rounded = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect::all(Val::Px(25.0)),
align_self: AlignSelf::Stretch,
justify_self: JustifySelf::Stretch,
@ -38,11 +39,10 @@ fn setup(mut commands: Commands) {
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
align_content: AlignContent::FlexStart,
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.id();
// labels for the different border edges
@ -124,32 +124,30 @@ fn setup(mut commands: Commands) {
for (label, border) in border_labels.into_iter().zip(borders) {
let inner_spot = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(10.),
height: Val::Px(10.),
..Default::default()
..default()
},
background_color: YELLOW.into(),
..Default::default()
})
BackgroundColor(YELLOW.into()),
))
.id();
let border_node = commands
.spawn((
NodeBundle {
style: Style {
width: Val::Px(50.),
height: Val::Px(50.),
border,
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
},
background_color: MAROON.into(),
border_color: RED.into(),
..Default::default()
Node::default(),
Style {
width: Val::Px(50.),
height: Val::Px(50.),
border,
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
BackgroundColor(MAROON.into()),
BorderColor(RED.into()),
Outline {
width: Val::Px(6.),
offset: Val::Px(6.),
@ -168,14 +166,14 @@ fn setup(mut commands: Commands) {
))
.id();
let container = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..Default::default()
..default()
},
..Default::default()
})
))
.add_children(&[border_node, label_node])
.id();
commands.entity(root).add_child(container);
@ -183,16 +181,16 @@ fn setup(mut commands: Commands) {
for (label, border) in border_labels.into_iter().zip(borders) {
let inner_spot = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(10.),
height: Val::Px(10.),
..Default::default()
..default()
},
border_radius: BorderRadius::MAX,
background_color: YELLOW.into(),
..Default::default()
})
BorderRadius::MAX,
BackgroundColor(YELLOW.into()),
))
.id();
let non_zero = |x, y| x != Val::Px(0.) && y != Val::Px(0.);
let border_size = |x, y| if non_zero(x, y) { f32::MAX } else { 0. };
@ -204,21 +202,19 @@ fn setup(mut commands: Commands) {
);
let border_node = commands
.spawn((
NodeBundle {
style: Style {
width: Val::Px(50.),
height: Val::Px(50.),
border,
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
},
background_color: MAROON.into(),
border_color: RED.into(),
border_radius,
..Default::default()
Node::default(),
Style {
width: Val::Px(50.),
height: Val::Px(50.),
border,
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
BackgroundColor(MAROON.into()),
BorderColor(RED.into()),
border_radius,
Outline {
width: Val::Px(6.),
offset: Val::Px(6.),
@ -237,33 +233,33 @@ fn setup(mut commands: Commands) {
))
.id();
let container = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..Default::default()
..default()
},
..Default::default()
})
))
.add_children(&[border_node, label_node])
.id();
commands.entity(root_rounded).add_child(container);
}
let border_label = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect {
left: Val::Px(25.0),
right: Val::Px(25.0),
top: Val::Px(25.0),
bottom: Val::Px(0.0),
},
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|builder| {
builder.spawn((
Text::new("Borders"),
@ -276,19 +272,19 @@ fn setup(mut commands: Commands) {
.id();
let border_rounded_label = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect {
left: Val::Px(25.0),
right: Val::Px(25.0),
top: Val::Px(25.0),
bottom: Val::Px(0.0),
},
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|builder| {
builder.spawn((
Text::new("Borders Rounded"),
@ -301,8 +297,9 @@ fn setup(mut commands: Commands) {
.id();
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect::all(Val::Px(25.0)),
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
@ -311,11 +308,10 @@ fn setup(mut commands: Commands) {
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
align_content: AlignContent::FlexStart,
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.add_child(border_label)
.add_child(root)
.add_child(border_rounded_label)

View file

@ -34,8 +34,9 @@ fn setup(mut commands: Commands) {
commands.spawn((Camera2d, UiBoxShadowSamples(args.samples)));
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
padding: UiRect::all(Val::Px(30.)),
@ -43,9 +44,8 @@ fn setup(mut commands: Commands) {
flex_wrap: FlexWrap::Wrap,
..default()
},
background_color: BackgroundColor(DEEP_SKY_BLUE.into()),
..Default::default()
})
BackgroundColor(DEEP_SKY_BLUE.into()),
))
.with_children(|commands| {
let example_nodes = [
(
@ -201,18 +201,16 @@ fn box_shadow_node_bundle(
border_radius: BorderRadius,
) -> impl Bundle {
(
NodeBundle {
style: Style {
width: Val::Px(size.x),
height: Val::Px(size.y),
border: UiRect::all(Val::Px(4.)),
..default()
},
border_color: BorderColor(LIGHT_SKY_BLUE.into()),
border_radius,
background_color: BackgroundColor(DEEP_SKY_BLUE.into()),
..Default::default()
Node::default(),
Style {
width: Val::Px(size.x),
height: Val::Px(size.y),
border: UiRect::all(Val::Px(4.)),
..default()
},
BorderColor(LIGHT_SKY_BLUE.into()),
border_radius,
BackgroundColor(DEEP_SKY_BLUE.into()),
BoxShadow {
color: Color::BLACK.with_alpha(0.8),
x_offset: Val::Percent(offset.x),

View file

@ -55,20 +55,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// ui camera
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
border: UiRect::all(Val::Px(5.0)),
@ -78,11 +79,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
align_items: AlignItems::Center,
..default()
},
border_color: BorderColor(Color::BLACK),
border_radius: BorderRadius::MAX,
background_color: NORMAL_BUTTON.into(),
..default()
})
BorderColor(Color::BLACK),
BorderRadius::MAX,
BackgroundColor(NORMAL_BUTTON),
))
.with_child((
Text::new("Button"),
TextFont {

View file

@ -82,8 +82,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
};
commands.spawn(Camera2d);
commands.spawn(NodeBundle {
style: Style {
commands.spawn((Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
@ -91,9 +91,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
justify_content: JustifyContent::SpaceEvenly,
..Default::default()
},
background_color: BackgroundColor(Color::BLACK),
..Default::default()
}).with_children(|parent| {
BackgroundColor(Color::BLACK),
)).with_children(|parent| {
parent.spawn((Text::new("Use the panel on the right to change the Display and Visibility properties for the respective nodes of the panel on the left"),
text_font.clone(),
TextLayout::new_with_justify(JustifyText::Center),
@ -104,48 +103,49 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|parent| {
let mut target_ids = vec![];
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Percent(50.),
height: Val::Px(520.),
justify_content: JustifyContent::Center,
..Default::default()
..default()
},
..Default::default()
}).with_children(|parent| {
)).with_children(|parent| {
target_ids = spawn_left_panel(parent, &palette);
});
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Percent(50.),
justify_content: JustifyContent::Center,
..Default::default()
..default()
},
..Default::default()
}).with_children(|parent| {
)).with_children(|parent| {
spawn_right_panel(parent, text_font, &palette, target_ids);
});
});
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
align_items: AlignItems::Start,
justify_content: JustifyContent::Start,
column_gap: Val::Px(10.),
..Default::default()
..default()
},
..default() })
))
.with_children(|builder| {
let text_font = TextFont {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
@ -172,93 +172,90 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
fn spawn_left_panel(builder: &mut ChildBuilder, palette: &[Color; 4]) -> Vec<Entity> {
let mut target_ids = vec![];
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
padding: UiRect::all(Val::Px(10.)),
..Default::default()
..default()
},
background_color: BackgroundColor(Color::WHITE),
..Default::default()
})
BackgroundColor(Color::WHITE),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
background_color: BackgroundColor(Color::BLACK),
..Default::default()
})
.spawn((Node::default(), BackgroundColor(Color::BLACK)))
.with_children(|parent| {
let id = parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::FlexEnd,
justify_content: JustifyContent::FlexEnd,
..Default::default()
..default()
},
background_color: BackgroundColor(palette[0]),
..Default::default()
})
BackgroundColor(palette[0]),
))
.with_children(|parent| {
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Px(100.),
height: Val::Px(500.),
..Default::default()
..default()
},
..Default::default()
});
));
let id = parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
height: Val::Px(400.),
align_items: AlignItems::FlexEnd,
justify_content: JustifyContent::FlexEnd,
..Default::default()
..default()
},
background_color: BackgroundColor(palette[1]),
..Default::default()
})
BackgroundColor(palette[1]),
))
.with_children(|parent| {
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Px(100.),
height: Val::Px(400.),
..Default::default()
..default()
},
..Default::default()
});
));
let id = parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
height: Val::Px(300.),
align_items: AlignItems::FlexEnd,
justify_content: JustifyContent::FlexEnd,
..Default::default()
..default()
},
background_color: BackgroundColor(palette[2]),
..Default::default()
})
BackgroundColor(palette[2]),
))
.with_children(|parent| {
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Px(100.),
height: Val::Px(300.),
..Default::default()
..default()
},
..Default::default()
});
));
let id = parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(200.),
height: Val::Px(200.),
..Default::default()
..default()
},
background_color: BackgroundColor(palette[3]),
..Default::default()
})
BackgroundColor(palette[3]),
))
.id();
target_ids.push(id);
})
@ -286,18 +283,19 @@ fn spawn_right_panel(
spawn_button::<Visibility>(parent, text_font.clone(), target_id);
};
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
padding: UiRect::all(Val::Px(10.)),
..Default::default()
..default()
},
background_color: BackgroundColor(Color::WHITE),
..Default::default()
})
BackgroundColor(Color::WHITE),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(500.),
height: Val::Px(500.),
flex_direction: FlexDirection::Column,
@ -306,19 +304,19 @@ fn spawn_right_panel(
padding: UiRect {
left: Val::Px(5.),
top: Val::Px(5.),
..Default::default()
..default()
},
..Default::default()
..default()
},
background_color: BackgroundColor(palette[0]),
..Default::default()
})
BackgroundColor(palette[0]),
))
.with_children(|parent| {
spawn_buttons(parent, target_ids.pop().unwrap());
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(400.),
height: Val::Px(400.),
flex_direction: FlexDirection::Column,
@ -327,19 +325,19 @@ fn spawn_right_panel(
padding: UiRect {
left: Val::Px(5.),
top: Val::Px(5.),
..Default::default()
..default()
},
..Default::default()
..default()
},
background_color: BackgroundColor(palette[1]),
..Default::default()
})
BackgroundColor(palette[1]),
))
.with_children(|parent| {
spawn_buttons(parent, target_ids.pop().unwrap());
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(300.),
height: Val::Px(300.),
flex_direction: FlexDirection::Column,
@ -348,19 +346,19 @@ fn spawn_right_panel(
padding: UiRect {
left: Val::Px(5.),
top: Val::Px(5.),
..Default::default()
..default()
},
..Default::default()
..default()
},
background_color: BackgroundColor(palette[2]),
..Default::default()
})
BackgroundColor(palette[2]),
))
.with_children(|parent| {
spawn_buttons(parent, target_ids.pop().unwrap());
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(200.),
height: Val::Px(200.),
align_items: AlignItems::FlexStart,
@ -369,24 +367,23 @@ fn spawn_right_panel(
padding: UiRect {
left: Val::Px(5.),
top: Val::Px(5.),
..Default::default()
..default()
},
..Default::default()
..default()
},
background_color: BackgroundColor(palette[3]),
..Default::default()
})
BackgroundColor(palette[3]),
))
.with_children(|parent| {
spawn_buttons(parent, target_ids.pop().unwrap());
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Px(100.),
height: Val::Px(100.),
..Default::default()
..default()
},
..Default::default()
});
));
});
});
});
@ -401,15 +398,13 @@ where
{
parent
.spawn((
ButtonBundle {
style: Style {
align_self: AlignSelf::FlexStart,
padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
..Default::default()
},
background_color: Color::BLACK.with_alpha(0.5).into(),
..Default::default()
Button,
Style {
align_self: AlignSelf::FlexStart,
padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
..default()
},
BackgroundColor(Color::BLACK.with_alpha(0.5)),
Target::<T>::new(target),
))
.with_children(|builder| {

View file

@ -22,8 +22,9 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// fill the entire window
width: Val::Percent(100.),
height: Val::Percent(100.),
@ -33,19 +34,18 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
row_gap: MARGIN,
..Default::default()
},
background_color: BackgroundColor(Color::BLACK),
..Default::default()
})
BackgroundColor(Color::BLACK),
))
.with_children(|builder| {
// spawn the key
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|builder| {
spawn_nested_text_bundle(
builder,
@ -64,16 +64,16 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
});
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
row_gap: MARGIN,
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|builder| {
// spawn one child node for each combination of `AlignItems` and `JustifyContent`
let justifications = [
@ -93,16 +93,16 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
];
for align_items in alignments {
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Row,
column_gap: MARGIN,
..Default::default()
},
..Default::default()
})
))
.with_children(|builder| {
for justify_content in justifications {
spawn_child_node(
@ -125,18 +125,18 @@ fn spawn_child_node(
justify_content: JustifyContent,
) {
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items,
justify_content,
width: Val::Percent(100.),
height: Val::Percent(100.),
..Default::default()
..default()
},
background_color: BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|builder| {
let labels = [
(format!("{align_items:?}"), ALIGN_ITEMS_COLOR, 0.),
@ -163,15 +163,15 @@ fn spawn_nested_text_bundle(
text: &str,
) {
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin,
padding: UiRect::axes(Val::Px(5.), Val::Px(1.)),
..Default::default()
..default()
},
background_color: BackgroundColor(background_color),
..Default::default()
})
BackgroundColor(background_color),
))
.with_children(|builder| {
builder.spawn((
Text::new(text),

View file

@ -48,16 +48,15 @@ fn atlas_render_system(
}
let font_atlas = &font_atlas[state.atlas_count as usize];
state.atlas_count += 1;
commands.spawn(ImageBundle {
image: font_atlas.texture.clone().into(),
style: Style {
commands.spawn((
UiImage::new(font_atlas.texture.clone()),
Style {
position_type: PositionType::Absolute,
top: Val::ZERO,
left: Val::Px(512.0 * x_offset),
..default()
},
..default()
});
));
}
}
}
@ -86,15 +85,15 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut state: ResM
state.handle = font_handle.clone();
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
background_color: Color::NONE.into(),
style: Style {
.spawn((
Node::default(),
BackgroundColor(Color::NONE),
Style {
position_type: PositionType::Absolute,
bottom: Val::ZERO,
..default()
},
..default()
})
))
.with_children(|parent| {
parent.spawn((
Text::new("a"),

View file

@ -33,29 +33,27 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn(GhostNode::new())
.with_children(|ghost_root| {
ghost_root
.spawn(NodeBundle::default())
.with_child(create_label(
"This text node is rendered under a ghost root",
font_handle.clone(),
));
ghost_root.spawn(Node::default()).with_child(create_label(
"This text node is rendered under a ghost root",
font_handle.clone(),
));
});
// Normal UI root
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn((NodeBundle::default(), Counter(0)))
.spawn((Node::default(), Counter(0)))
.with_children(|layout_parent| {
layout_parent
.spawn((GhostNode::new(), Counter(0)))
@ -78,9 +76,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
}
fn create_button() -> ButtonBundle {
ButtonBundle {
style: Style {
fn create_button() -> impl Bundle {
(
Button,
Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
border: UiRect::all(Val::Px(5.0)),
@ -90,11 +89,10 @@ fn create_button() -> ButtonBundle {
align_items: AlignItems::Center,
..default()
},
border_color: BorderColor(Color::BLACK),
border_radius: BorderRadius::MAX,
background_color: Color::srgb(0.15, 0.15, 0.15).into(),
..default()
}
BorderColor(Color::BLACK),
BorderRadius::MAX,
BackgroundColor(Color::srgb(0.15, 0.15, 0.15)),
)
}
fn create_label(text: &str, font: Handle<Font>) -> (Text, TextFont, TextColor) {

View file

@ -21,8 +21,9 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
// Top-level grid (app frame)
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// Use the CSS Grid algorithm for laying out this node
display: Display::Grid,
// Make node fill the entirety of its parent (in this case the window)
@ -43,30 +44,30 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
],
..default()
},
background_color: BackgroundColor(Color::WHITE),
..default()
})
BackgroundColor(Color::WHITE),
))
.with_children(|builder| {
// Header
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
// Make this node span two grid columns so that it takes up the entire top tow
grid_column: GridPlacement::span(2),
padding: UiRect::all(Val::Px(6.0)),
..default()
},
..default()
})
))
.with_children(|builder| {
spawn_nested_text_bundle(builder, font.clone(), "Bevy CSS Grid Layout Example");
});
// Main content grid (auto placed in row 2, column 1)
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
// Make the height of the node fill its parent
height: Val::Percent(100.0),
// Make the grid have a 1:1 aspect ratio meaning it will scale as an exact square
@ -87,9 +88,8 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
column_gap: Val::Px(12.0),
..default()
},
background_color: BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
..default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|builder| {
// Note there is no need to specify the position for each grid item. Grid items that are
// not given an explicit position will be automatically positioned into the next available
@ -116,8 +116,9 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
// Right side bar (auto placed in row 2, column 2)
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
// Align content towards the start (top) in the vertical axis
align_items: AlignItems::Start,
@ -132,9 +133,8 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
row_gap: Val::Px(10.),
..default()
},
background_color: BackgroundColor(BLACK.into()),
..default()
})
BackgroundColor(BLACK.into()),
))
.with_children(|builder| {
builder.spawn((Text::new("Sidebar"),
TextFont {
@ -149,24 +149,25 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
..default()
},
));
builder.spawn(NodeBundle::default());
builder.spawn(Node::default());
});
// Footer / status bar
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
// Make this node span two grid column so that it takes up the entire bottom row
grid_column: GridPlacement::span(2),
..default()
},
background_color: BackgroundColor(WHITE.into()),
..default()
});
BackgroundColor(WHITE.into()),
));
// Modal (absolutely positioned on top of content - currently hidden: to view it, change its visibility)
builder.spawn(NodeBundle {
visibility: Visibility::Hidden,
style: Style {
builder.spawn((
Node::default(),
Visibility::Hidden,
Style {
position_type: PositionType::Absolute,
margin: UiRect {
top: Val::Px(100.),
@ -179,9 +180,8 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
max_width: Val::Px(600.),
..default()
},
background_color: BackgroundColor(Color::WHITE.with_alpha(0.8)),
..default()
});
BackgroundColor(Color::WHITE.with_alpha(0.8)),
));
});
}
@ -190,20 +190,17 @@ fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
/// which will allow it to take its size from the size of the grid area it occupies.
fn item_rect(builder: &mut ChildBuilder, color: Srgba) {
builder
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
padding: UiRect::all(Val::Px(3.0)),
..default()
},
background_color: BackgroundColor(BLACK.into()),
..default()
})
BackgroundColor(BLACK.into()),
))
.with_children(|builder| {
builder.spawn(NodeBundle {
background_color: BackgroundColor(color.into()),
..default()
});
builder.spawn((Node::default(), BackgroundColor(color.into())));
});
}

View file

@ -20,17 +20,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let image = asset_server.load("branding/icon.png");
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
},
background_color: ANTIQUE_WHITE.into(),
..Default::default()
})
BackgroundColor(ANTIQUE_WHITE.into()),
))
.with_children(|parent| {
for overflow in [
Overflow::visible(),
@ -39,33 +39,34 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
Overflow::clip(),
] {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
margin: UiRect::horizontal(Val::Px(25.)),
..Default::default()
},
..Default::default()
})
))
.with_children(|parent| {
let label = format!("{overflow:#?}");
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
padding: UiRect::all(Val::Px(10.)),
margin: UiRect::bottom(Val::Px(25.)),
..Default::default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_children(|parent| {
parent.spawn((Text::new(label), text_style.clone()));
});
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(100.),
height: Val::Px(100.),
padding: UiRect {
@ -75,22 +76,18 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
},
border: UiRect::all(Val::Px(5.)),
overflow,
..Default::default()
..default()
},
border_color: Color::BLACK.into(),
background_color: GRAY.into(),
..Default::default()
})
BorderColor(Color::BLACK),
BackgroundColor(GRAY.into()),
))
.with_children(|parent| {
parent.spawn((
ImageBundle {
image: UiImage::new(image.clone()),
style: Style {
min_width: Val::Px(100.),
min_height: Val::Px(100.),
..Default::default()
},
..Default::default()
UiImage::new(image.clone()),
Style {
min_width: Val::Px(100.),
min_height: Val::Px(100.),
..default()
},
Interaction::default(),
Outline {

View file

@ -17,19 +17,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let image = asset_server.load("branding/icon.png");
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
row_gap: Val::Px(40.),
flex_direction: FlexDirection::Column,
..Default::default()
..default()
},
background_color: ANTIQUE_WHITE.into(),
..Default::default()
})
BackgroundColor(ANTIQUE_WHITE.into()),
))
.with_children(|parent| {
for overflow_clip_margin in [
OverflowClipMargin::border_box().with_margin(25.),
@ -38,30 +38,31 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
OverflowClipMargin::content_box(),
] {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
column_gap: Val::Px(20.),
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
padding: UiRect::all(Val::Px(10.)),
margin: UiRect::bottom(Val::Px(25.)),
..Default::default()
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
))
.with_child(Text(format!("{overflow_clip_margin:#?}")));
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
margin: UiRect::top(Val::Px(10.)),
width: Val::Px(100.),
height: Val::Px(100.),
@ -69,32 +70,30 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
border: UiRect::all(Val::Px(5.)),
overflow: Overflow::clip(),
overflow_clip_margin,
..Default::default()
..default()
},
border_color: Color::BLACK.into(),
background_color: GRAY.into(),
..Default::default()
})
BackgroundColor(GRAY.into()),
BorderColor(Color::BLACK),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
min_width: Val::Px(50.),
min_height: Val::Px(50.),
..Default::default()
..default()
},
background_color: LIGHT_CYAN.into(),
..Default::default()
})
.with_child(ImageBundle {
image: UiImage::new(image.clone()),
style: Style {
BackgroundColor(LIGHT_CYAN.into()),
))
.with_child((
UiImage::new(image.clone()),
Style {
min_width: Val::Px(100.),
min_height: Val::Px(100.),
..Default::default()
..default()
},
..Default::default()
});
));
});
});
}

View file

@ -105,20 +105,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Overflow Debug
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
display: Display::Grid,
grid_template_columns: RepeatedGridTrack::px(3, CONTAINER_SIZE),
grid_template_rows: RepeatedGridTrack::px(2, CONTAINER_SIZE),
@ -126,8 +127,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
column_gap: Val::Px(80.),
..default()
},
..default()
})
))
.with_children(|parent| {
spawn_image(parent, &asset_server, Move);
spawn_image(parent, &asset_server, Scale);
@ -146,17 +146,16 @@ fn spawn_image(
update_transform: impl UpdateTransform + Component,
) {
spawn_container(parent, update_transform, |parent| {
parent.spawn(ImageBundle {
image: UiImage::new(asset_server.load("branding/bevy_logo_dark_big.png")),
style: Style {
parent.spawn((
UiImage::new(asset_server.load("branding/bevy_logo_dark_big.png")),
Style {
height: Val::Px(100.),
position_type: PositionType::Absolute,
top: Val::Px(-50.),
left: Val::Px(-200.),
..default()
},
..default()
});
));
});
}
@ -188,34 +187,30 @@ fn spawn_container(
parent
.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
overflow: Overflow::clip(),
..default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
overflow: Overflow::clip(),
..default()
},
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
Container(0),
))
.with_children(|parent| {
parent
.spawn((
NodeBundle {
style: Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
top: Val::Px(transform.translation.x),
left: Val::Px(transform.translation.y),
..default()
},
transform,
Node::default(),
Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
top: Val::Px(transform.translation.x),
left: Val::Px(transform.translation.y),
..default()
},
transform,
update_transform,
))
.with_children(spawn_children);

View file

@ -29,8 +29,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
@ -38,20 +39,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
flex_direction: FlexDirection::Column,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(250.),
height: Val::Px(250.),
margin: UiRect::bottom(Val::Px(15.)),
..default()
},
background_color: Color::srgb(235., 35., 12.).into(),
..default()
})
BackgroundColor(Color::srgb(235., 35., 12.)),
))
.insert(RelativeCursorPosition::default());
parent.spawn((

View file

@ -65,19 +65,17 @@ fn setup(
commands
.spawn((
NodeBundle {
style: Style {
// Cover the whole image
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
background_color: GOLD.into(),
Node::default(),
Style {
// Cover the whole image
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(GOLD.into()),
TargetCamera(texture_camera),
))
.with_children(|parent| {

View file

@ -30,28 +30,28 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// root node
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::SpaceBetween,
flex_direction: FlexDirection::Column,
..default()
},
..default()
})
))
.insert(PickingBehavior::IGNORE)
.with_children(|parent| {
// horizontal scroll example
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
flex_direction: FlexDirection::Column,
..default()
},
..default()
})
))
.with_children(|parent| {
// header
parent.spawn((
@ -66,17 +66,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// horizontal scroll container
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(80.),
margin: UiRect::all(Val::Px(10.)),
flex_direction: FlexDirection::Row,
overflow: Overflow::scroll_x(), // n.b.
..default()
},
background_color: Color::srgb(0.10, 0.10, 0.10).into(),
..default()
})
BackgroundColor(Color::srgb(0.10, 0.10, 0.10)),
))
.with_children(|parent| {
for i in 0..100 {
parent.spawn((Text(format!("Item {i}")),
@ -111,29 +111,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// container for all other examples
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceBetween,
..default()
},
..default()
})
))
.with_children(|parent| {
// vertical scroll example
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
width: Val::Px(200.),
..default()
},
..default()
})
))
.with_children(|parent| {
// Title
parent.spawn((
@ -147,29 +147,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
// Scrolling list
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
height: Val::Percent(50.),
overflow: Overflow::scroll_y(), // n.b.
..default()
},
background_color: Color::srgb(0.10, 0.10, 0.10).into(),
..default()
})
BackgroundColor(Color::srgb(0.10, 0.10, 0.10)),
))
.with_children(|parent| {
// List items
for i in 0..25 {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
min_height: Val::Px(LINE_HEIGHT),
max_height: Val::Px(LINE_HEIGHT),
..default()
},
..default()
})
))
.insert(PickingBehavior {
should_block_lower: false,
..default()
@ -199,16 +199,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Bidirectional scroll example
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
width: Val::Px(200.),
..default()
},
..default()
})
))
.with_children(|parent| {
// Title
parent.spawn((
@ -222,28 +222,28 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
// Scrolling list
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
height: Val::Percent(50.),
overflow: Overflow::scroll(), // n.b.
..default()
},
background_color: Color::srgb(0.10, 0.10, 0.10).into(),
..default()
})
BackgroundColor(Color::srgb(0.10, 0.10, 0.10)),
))
.with_children(|parent| {
// Rows in each column
for oi in 0..10 {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
..default()
},
..default()
})
))
.insert(PickingBehavior::IGNORE)
.with_children(|parent| {
// Elements in each row
@ -274,16 +274,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Nested scrolls example
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
width: Val::Px(200.),
..default()
},
..default()
})
))
.with_children(|parent| {
// Title
parent.spawn((
@ -297,8 +297,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
// Outer, horizontal scrolling container
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
column_gap: Val::Px(20.),
flex_direction: FlexDirection::Row,
align_self: AlignSelf::Stretch,
@ -306,24 +307,22 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
overflow: Overflow::scroll_x(), // n.b.
..default()
},
background_color: Color::srgb(0.10, 0.10, 0.10).into(),
..default()
})
BackgroundColor(Color::srgb(0.10, 0.10, 0.10)),
))
.with_children(|parent| {
// Inner, scrolling columns
for oi in 0..30 {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
overflow: Overflow::scroll_y(),
..default()
},
background_color: Color::srgb(0.05, 0.05, 0.05)
.into(),
..default()
})
BackgroundColor(Color::srgb(0.05, 0.05, 0.05)),
))
.insert(PickingBehavior {
should_block_lower: false,
..default()

View file

@ -52,28 +52,28 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..Default::default()
..default()
},
background_color: Color::BLACK.into(),
..Default::default()
})
BackgroundColor(Color::BLACK),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|parent| {
parent.spawn((
Text::new("Size Constraints Example"),
@ -87,17 +87,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
spawn_bar(parent);
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Stretch,
padding: UiRect::all(Val::Px(10.)),
margin: UiRect::top(Val::Px(50.)),
..Default::default()
..default()
},
background_color: YELLOW.into(),
..Default::default()
})
BackgroundColor(YELLOW.into()),
))
.with_children(|parent| {
for constraint in [
Constraint::MinWidth,
@ -114,40 +114,31 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
fn spawn_bar(parent: &mut ChildBuilder) {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_basis: Val::Percent(100.0),
align_self: AlignSelf::Stretch,
padding: UiRect::all(Val::Px(10.)),
..Default::default()
..default()
},
background_color: YELLOW.into(),
..Default::default()
})
BackgroundColor(YELLOW.into()),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
align_items: AlignItems::Stretch,
width: Val::Percent(100.),
height: Val::Px(100.),
padding: UiRect::all(Val::Px(4.)),
..Default::default()
..default()
},
background_color: Color::BLACK.into(),
..Default::default()
})
BackgroundColor(Color::BLACK),
))
.with_children(|parent| {
parent.spawn((
NodeBundle {
style: Style {
..Default::default()
},
background_color: Color::WHITE.into(),
..Default::default()
},
Bar,
));
parent.spawn((Node::default(), BackgroundColor(Color::WHITE), Bar));
});
});
}
@ -165,67 +156,63 @@ fn spawn_button_row(
};
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
padding: UiRect::all(Val::Px(2.)),
align_items: AlignItems::Stretch,
..Default::default()
..default()
},
background_color: Color::BLACK.into(),
..Default::default()
})
BackgroundColor(Color::BLACK),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::End,
padding: UiRect::all(Val::Px(2.)),
..Default::default()
..default()
},
..Default::default()
})
))
.with_children(|parent| {
// spawn row label
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
min_width: Val::Px(200.),
max_width: Val::Px(200.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..Default::default()
..default()
},
..Default::default()
})
))
.with_child((Text::new(label), text_style.clone()));
// spawn row buttons
parent
.spawn(NodeBundle {
..Default::default()
})
.with_children(|parent| {
parent.spawn(Node::default()).with_children(|parent| {
spawn_button(
parent,
constraint,
ButtonValue(Val::Auto),
"Auto".to_string(),
text_style.clone(),
true,
);
for percent in [0., 25., 50., 75., 100., 125.] {
spawn_button(
parent,
constraint,
ButtonValue(Val::Auto),
"Auto".to_string(),
ButtonValue(Val::Percent(percent)),
format!("{percent}%"),
text_style.clone(),
true,
false,
);
for percent in [0., 25., 50., 75., 100., 125.] {
spawn_button(
parent,
constraint,
ButtonValue(Val::Percent(percent)),
format!("{percent}%"),
text_style.clone(),
false,
);
}
});
}
});
});
});
}
@ -240,41 +227,37 @@ fn spawn_button(
) {
parent
.spawn((
ButtonBundle {
style: Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
border: UiRect::all(Val::Px(2.)),
margin: UiRect::horizontal(Val::Px(2.)),
..Default::default()
},
border_color: if active {
ACTIVE_BORDER_COLOR
} else {
INACTIVE_BORDER_COLOR
}
.into(),
Button,
Style {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
border: UiRect::all(Val::Px(2.)),
margin: UiRect::horizontal(Val::Px(2.)),
..Default::default()
},
BorderColor(if active {
ACTIVE_BORDER_COLOR
} else {
INACTIVE_BORDER_COLOR
}),
constraint,
action,
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(100.),
justify_content: JustifyContent::Center,
..Default::default()
..default()
},
background_color: if active {
BackgroundColor(if active {
ACTIVE_INNER_COLOR
} else {
INACTIVE_INNER_COLOR
}
.into(),
..Default::default()
})
}),
))
.with_child((
Text::new(label),
text_style.0,

View file

@ -36,19 +36,21 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
let root_uinode = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::SpaceBetween,
..default()
},
..default()
})
))
.id();
let left_column = commands.spawn(NodeBundle {
style: Style {
let left_column = commands
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Start,
@ -56,8 +58,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
margin: UiRect::axes(Val::Px(15.), Val::Px(5.)),
..default()
},
..default()
}).with_children(|builder| {
)).with_children(|builder| {
builder.spawn((
Text::new("This is\ntext with\nline breaks\nin the top left."),
TextFont {
@ -101,17 +102,17 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
);
}).id();
let right_column = commands.spawn(NodeBundle {
style: Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::End,
flex_grow: 1.,
margin: UiRect::axes(Val::Px(15.), Val::Px(5.)),
..default()
},
..default()
}).with_children(|builder| {
let right_column = commands.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::End,
flex_grow: 1.,
margin: UiRect::axes(Val::Px(15.), Val::Px(5.)),
..default()
},
)).with_children(|builder| {
builder.spawn((Text::new(
"This text is very long, has a limited width, is center-justified, is positioned in the top right and is also colored pink."),

View file

@ -52,16 +52,16 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
};
let root = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
..Default::default()
..default()
},
background_color: Color::BLACK.into(),
..Default::default()
})
BackgroundColor(Color::BLACK),
))
.id();
for linebreak in [
@ -71,17 +71,17 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
LineBreak::NoWrap,
] {
let row_id = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceAround,
align_items: AlignItems::Center,
width: Val::Percent(100.),
height: Val::Percent(50.),
..Default::default()
..default()
},
..Default::default()
})
))
.id();
let justifications = vec![
@ -96,18 +96,18 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
for (i, justification) in justifications.into_iter().enumerate() {
let c = 0.3 + i as f32 * 0.1;
let column_id = commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
justify_content: justification,
flex_direction: FlexDirection::Column,
width: Val::Percent(16.),
height: Val::Percent(95.),
overflow: Overflow::clip_x(),
..Default::default()
..default()
},
background_color: Color::srgb(0.5, c, 1.0 - c).into(),
..Default::default()
})
BackgroundColor(Color::srgb(0.5, c, 1.0 - c)),
))
.id();
let messages = [

View file

@ -17,29 +17,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let font_handle = asset_server.load("fonts/FiraSans-Bold.ttf");
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::SpaceAround,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
background_color: Color::srgb(0.1, 0.5, 0.1).into(),
..default()
})
BackgroundColor(Color::srgb(0.1, 0.5, 0.1)),
))
.with_children(|parent| {
parent.spawn((
Text::new("Button 1"),
@ -56,17 +56,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Button with a different color,
// to demonstrate the text looks different due to its transparency.
parent
.spawn(ButtonBundle {
style: Style {
.spawn((
Button,
Style {
width: Val::Px(150.0),
height: Val::Px(65.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
background_color: Color::srgb(0.5, 0.1, 0.5).into(),
..default()
})
BackgroundColor(Color::srgb(0.5, 0.1, 0.5)),
))
.with_children(|parent| {
parent.spawn((
Text::new("Button 2"),

View file

@ -35,42 +35,42 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// root node
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::SpaceBetween,
..default()
},
..default()
})
))
.insert(PickingBehavior::IGNORE)
.with_children(|parent| {
// left vertical fill (border)
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(200.),
border: UiRect::all(Val::Px(2.)),
..default()
},
background_color: Color::srgb(0.65, 0.65, 0.65).into(),
..default()
})
BackgroundColor(Color::srgb(0.65, 0.65, 0.65)),
))
.with_children(|parent| {
// left vertical fill (content)
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
flex_direction: FlexDirection::Column,
padding: UiRect::all(Val::Px(5.)),
row_gap: Val::Px(5.),
..default()
},
background_color: Color::srgb(0.15, 0.15, 0.15).into(),
..default()
})
BackgroundColor(Color::srgb(0.15, 0.15, 0.15)),
))
.with_children(|parent| {
// text
parent.spawn((
@ -110,16 +110,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
// right vertical fill
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
width: Val::Px(200.),
..default()
},
..default()
})
))
.with_children(|parent| {
// Title
parent.spawn((
@ -133,17 +133,17 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
));
// Scrolling list
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
height: Val::Percent(50.),
overflow: Overflow::scroll_y(),
..default()
},
background_color: Color::srgb(0.10, 0.10, 0.10).into(),
..default()
})
BackgroundColor(Color::srgb(0.10, 0.10, 0.10)),
))
.with_children(|parent| {
// List items
for i in 0..25 {
@ -166,8 +166,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(200.0),
height: Val::Px(200.0),
position_type: PositionType::Absolute,
@ -176,20 +177,19 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
border: UiRect::all(Val::Px(20.)),
..default()
},
border_color: LIME.into(),
background_color: Color::srgb(0.4, 0.4, 1.).into(),
..default()
})
BorderColor(LIME.into()),
BackgroundColor(Color::srgb(0.4, 0.4, 1.)),
))
.with_children(|parent| {
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
background_color: Color::srgb(0.8, 0.8, 1.).into(),
..default()
});
BackgroundColor(Color::srgb(0.8, 0.8, 1.)),
));
});
let shadow = BoxShadow {
@ -202,8 +202,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// render order test: reddest in the back, whitest in the front (flex center)
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
@ -211,84 +212,73 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.insert(PickingBehavior::IGNORE)
.with_children(|parent| {
parent
.spawn((
NodeBundle {
style: Style {
width: Val::Px(100.0),
height: Val::Px(100.0),
..default()
},
background_color: Color::srgb(1.0, 0.0, 0.).into(),
Node::default(),
Style {
width: Val::Px(100.0),
height: Val::Px(100.0),
..default()
},
BackgroundColor(Color::srgb(1.0, 0.0, 0.)),
shadow,
))
.with_children(|parent| {
parent.spawn((
NodeBundle {
style: Style {
// Take the size of the parent node.
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(20.),
bottom: Val::Px(20.),
..default()
},
background_color: Color::srgb(1.0, 0.3, 0.3).into(),
Node::default(),
Style {
// Take the size of the parent node.
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(20.),
bottom: Val::Px(20.),
..default()
},
BackgroundColor(Color::srgb(1.0, 0.3, 0.3)),
shadow,
));
parent.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(40.),
bottom: Val::Px(40.),
..default()
},
background_color: Color::srgb(1.0, 0.5, 0.5).into(),
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(40.),
bottom: Val::Px(40.),
..default()
},
BackgroundColor(Color::srgb(1.0, 0.5, 0.5)),
shadow,
));
parent.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(60.),
bottom: Val::Px(60.),
..default()
},
background_color: Color::srgb(0.0, 0.7, 0.7).into(),
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(60.),
bottom: Val::Px(60.),
..default()
},
BackgroundColor(Color::srgb(0.0, 0.7, 0.7)),
shadow,
));
// alpha test
parent.spawn((
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(80.),
bottom: Val::Px(80.),
..default()
},
background_color: Color::srgba(1.0, 0.9, 0.9, 0.4).into(),
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
position_type: PositionType::Absolute,
left: Val::Px(80.),
bottom: Val::Px(80.),
..default()
},
BackgroundColor(Color::srgba(1.0, 0.9, 0.9, 0.4)),
BoxShadow {
color: Color::BLACK.with_alpha(0.3),
..shadow
@ -298,44 +288,37 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
});
// bevy logo (flex center)
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
position_type: PositionType::Absolute,
justify_content: JustifyContent::Center,
align_items: AlignItems::FlexStart,
..default()
},
..default()
})
))
.with_children(|parent| {
// bevy logo (image)
// A `NodeBundle` is used to display the logo the image as an `ImageBundle` can't automatically
// size itself with a child node present.
parent
.spawn((
NodeBundle {
style: Style {
width: Val::Px(500.0),
height: Val::Px(125.0),
margin: UiRect::top(Val::VMin(5.)),
..default()
},
UiImage::new(asset_server.load("branding/bevy_logo_dark_big.png")),
Style {
width: Val::Px(500.0),
height: Val::Px(125.0),
margin: UiRect::top(Val::VMin(5.)),
..default()
},
UiImage::new(asset_server.load("branding/bevy_logo_dark_big.png")),
))
.with_children(|parent| {
// alt text
// This UI node takes up no space in the layout and the `Text` component is used by the accessibility module
// and is not rendered.
parent.spawn((
NodeBundle {
style: Style {
display: Display::None,
..Default::default()
},
..Default::default()
Node::default(),
Style {
display: Display::None,
..default()
},
Text::new("Bevy logo"),
));

View file

@ -1,6 +1,6 @@
//! Demonstrates the use of [`UiMaterials`](UiMaterial) and how to change material values
use bevy::{prelude::*, reflect::TypePath, render::render_resource::*};
use bevy::{color::palettes::css::RED, prelude::*, reflect::TypePath, render::render_resource::*};
/// This example uses a shader source file from the assets subdirectory
const SHADER_ASSET_PATH: &str = "shaders/custom_ui_material.wgsl";
@ -23,34 +23,34 @@ fn setup(
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
let banner_scale_factor = 0.5;
parent.spawn(MaterialNodeBundle {
style: Style {
parent.spawn((
MaterialNode(ui_materials.add(CustomUiMaterial {
color: LinearRgba::WHITE.to_f32_array().into(),
slider: 0.5,
color_texture: asset_server.load("branding/banner.png"),
border_color: LinearRgba::WHITE.to_f32_array().into(),
})),
Style {
position_type: PositionType::Absolute,
width: Val::Px(905.0 * banner_scale_factor),
height: Val::Px(363.0 * banner_scale_factor),
border: UiRect::all(Val::Px(10.)),
..default()
},
material: UiMaterialHandle(ui_materials.add(CustomUiMaterial {
color: LinearRgba::WHITE.to_f32_array().into(),
slider: 0.5,
color_texture: asset_server.load("branding/banner.png"),
border_color: LinearRgba::WHITE.to_f32_array().into(),
})),
..default()
});
BackgroundColor(RED.into()),
));
});
}
@ -82,7 +82,7 @@ impl UiMaterial for CustomUiMaterial {
// Also updates the color of the image to a rainbow color
fn animate(
mut materials: ResMut<Assets<CustomUiMaterial>>,
q: Query<&UiMaterialHandle<CustomUiMaterial>>,
q: Query<&MaterialNode<CustomUiMaterial>>,
time: Res<Time>,
) {
let duration = 2.0;

View file

@ -29,8 +29,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
};
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(50.0),
height: Val::Percent(50.0),
position_type: PositionType::Absolute,
@ -40,41 +41,39 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
align_items: AlignItems::Center,
..default()
},
background_color: ANTIQUE_WHITE.into(),
..default()
})
BackgroundColor(ANTIQUE_WHITE.into()),
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(40.0),
height: Val::Px(40.0),
..default()
},
background_color: RED.into(),
..default()
})
BackgroundColor(RED.into()),
))
.with_children(|parent| {
parent.spawn((Text::new("Size!"), text_font, TextColor::BLACK));
});
parent.spawn(NodeBundle {
style: Style {
parent.spawn((
Node::default(),
Style {
width: Val::Percent(15.0),
height: Val::Percent(15.0),
..default()
},
background_color: BLUE.into(),
..default()
});
parent.spawn(ImageBundle {
style: Style {
BackgroundColor(BLUE.into()),
));
parent.spawn((
UiImage::new(asset_server.load("branding/icon.png")),
Style {
width: Val::Px(30.0),
height: Val::Px(30.0),
..default()
},
image: asset_server.load("branding/icon.png").into(),
..default()
});
));
});
}

View file

@ -33,8 +33,9 @@ fn setup(
// root node
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
flex_direction: FlexDirection::Column,
@ -43,20 +44,16 @@ fn setup(
row_gap: Val::Px(text_font.font_size * 2.),
..default()
},
..default()
})
))
.with_children(|parent| {
parent.spawn((
ImageBundle {
style: Style {
width: Val::Px(256.),
height: Val::Px(256.),
..default()
},
image: UiImage::new(texture_handle),
background_color: BackgroundColor(ANTIQUE_WHITE.into()),
UiImage::new(texture_handle),
Style {
width: Val::Px(256.),
height: Val::Px(256.),
..default()
},
BackgroundColor(ANTIQUE_WHITE.into()),
TextureAtlas::from(texture_atlas_handle),
Outline::new(Val::Px(8.0), Val::ZERO, CRIMSON.into()),
));

View file

@ -63,16 +63,16 @@ fn setup(
// ui camera
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
for (idx, [w, h]) in [
(0, [150.0, 150.0]),
@ -81,18 +81,16 @@ fn setup(
] {
parent
.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: texture_handle.clone().into(),
Button,
UiImage::new(texture_handle.clone()),
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()
},
ImageScaleMode::Sliced(slicer.clone()),

View file

@ -55,34 +55,32 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// ui camera
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
for [w, h] in [[150.0, 150.0], [300.0, 150.0], [150.0, 300.0]] {
parent
.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::new(image.clone()),
ImageScaleMode::Sliced(slicer.clone()),
))
.with_children(|parent| {

View file

@ -39,8 +39,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
justify_content: JustifyContent::Center,
@ -50,8 +51,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
row_gap: Val::Px(10.),
..default()
},
..default()
})
))
.with_children(|parent| {
for ([width, height], flip_x, flip_y) in [
([160., 160.], false, false),
@ -60,19 +60,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
([160., 160.], true, true),
] {
parent.spawn((
NodeBundle {
style: Style {
width: Val::Px(width),
height: Val::Px(height),
..default()
},
..Default::default()
},
UiImage {
texture: image.clone(),
flip_x,
flip_y,
..Default::default()
..default()
},
Style {
width: Val::Px(width),
height: Val::Px(height),
..default()
},
ImageScaleMode::Sliced(slicer.clone()),
));

View file

@ -68,173 +68,169 @@ fn setup(mut commands: Commands) {
fn spawn_with_viewport_coords(commands: &mut Commands) {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Vw(100.),
height: Val::Vh(100.),
border: UiRect::axes(Val::Vw(5.), Val::Vh(5.)),
flex_wrap: FlexWrap::Wrap,
..default()
},
border_color: PALETTE[0].into(),
Node::default(),
Style {
width: Val::Vw(100.),
height: Val::Vh(100.),
border: UiRect::axes(Val::Vw(5.), Val::Vh(5.)),
flex_wrap: FlexWrap::Wrap,
..default()
},
BorderColor(PALETTE[0].into()),
Coords::Viewport,
))
.with_children(|builder| {
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(30.),
height: Val::Vh(30.),
border: UiRect::all(Val::VMin(5.)),
..default()
},
background_color: PALETTE[2].into(),
border_color: PALETTE[9].into(),
..default()
});
BackgroundColor(PALETTE[2].into()),
BorderColor(PALETTE[9].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(60.),
height: Val::Vh(30.),
..default()
},
background_color: PALETTE[3].into(),
..default()
});
BackgroundColor(PALETTE[3].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(45.),
height: Val::Vh(30.),
border: UiRect::left(Val::VMax(45. / 2.)),
..default()
},
background_color: PALETTE[4].into(),
border_color: PALETTE[8].into(),
..default()
});
BackgroundColor(PALETTE[4].into()),
BorderColor(PALETTE[8].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(45.),
height: Val::Vh(30.),
border: UiRect::right(Val::VMax(45. / 2.)),
..default()
},
background_color: PALETTE[5].into(),
border_color: PALETTE[8].into(),
..default()
});
BackgroundColor(PALETTE[5].into()),
BorderColor(PALETTE[8].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(60.),
height: Val::Vh(30.),
..default()
},
background_color: PALETTE[6].into(),
..default()
});
BackgroundColor(PALETTE[6].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Vw(30.),
height: Val::Vh(30.),
border: UiRect::all(Val::VMin(5.)),
..default()
},
background_color: PALETTE[7].into(),
border_color: PALETTE[9].into(),
..default()
});
BackgroundColor(PALETTE[7].into()),
BorderColor(PALETTE[9].into()),
));
});
}
fn spawn_with_pixel_coords(commands: &mut Commands) {
commands
.spawn((
NodeBundle {
style: Style {
width: Val::Px(640.),
height: Val::Px(360.),
border: UiRect::axes(Val::Px(32.), Val::Px(18.)),
flex_wrap: FlexWrap::Wrap,
..default()
},
border_color: PALETTE[1].into(),
Node::default(),
Style {
width: Val::Px(640.),
height: Val::Px(360.),
border: UiRect::axes(Val::Px(32.), Val::Px(18.)),
flex_wrap: FlexWrap::Wrap,
..default()
},
BorderColor(PALETTE[1].into()),
Coords::Pixel,
))
.with_children(|builder| {
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(192.),
height: Val::Px(108.),
border: UiRect::axes(Val::Px(18.), Val::Px(18.)),
..default()
},
background_color: PALETTE[2].into(),
border_color: PALETTE[9].into(),
..default()
});
BackgroundColor(PALETTE[2].into()),
BorderColor(PALETTE[9].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(384.),
height: Val::Px(108.),
..default()
},
background_color: PALETTE[3].into(),
..default()
});
BackgroundColor(PALETTE[3].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(288.),
height: Val::Px(108.),
border: UiRect::left(Val::Px(144.)),
..default()
},
background_color: PALETTE[4].into(),
border_color: PALETTE[8].into(),
..default()
});
BackgroundColor(PALETTE[4].into()),
BorderColor(PALETTE[8].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(288.),
height: Val::Px(108.),
border: UiRect::right(Val::Px(144.)),
..default()
},
background_color: PALETTE[5].into(),
border_color: PALETTE[8].into(),
..default()
});
BackgroundColor(PALETTE[5].into()),
BorderColor(PALETTE[8].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(384.),
height: Val::Px(108.),
..default()
},
background_color: PALETTE[6].into(),
..default()
});
BackgroundColor(PALETTE[6].into()),
));
builder.spawn(NodeBundle {
style: Style {
builder.spawn((
Node::default(),
Style {
width: Val::Px(192.),
height: Val::Px(108.),
border: UiRect::axes(Val::Px(18.), Val::Px(18.)),
..default()
},
background_color: PALETTE[7].into(),
border_color: PALETTE[9].into(),
..default()
});
BackgroundColor(PALETTE[7].into()),
BorderColor(PALETTE[9].into()),
));
});
}

View file

@ -23,32 +23,32 @@ fn setup(mut commands: Commands) {
// the default z-index value is `ZIndex::Local(0)`.
// because this is a root UI node, using local or global values will do the same thing.
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
})
))
.with_children(|parent| {
parent
.spawn(NodeBundle {
background_color: GRAY.into(),
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(180.0),
height: Val::Px(100.0),
..default()
},
..default()
})
BackgroundColor(GRAY.into()),
))
.with_children(|parent| {
// spawn a node with default z-index.
parent.spawn(NodeBundle {
background_color: RED.into(),
style: Style {
parent.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
left: Val::Px(10.0),
bottom: Val::Px(40.0),
@ -56,15 +56,14 @@ fn setup(mut commands: Commands) {
height: Val::Px(50.0),
..default()
},
..default()
});
BackgroundColor(RED.into()),
));
// spawn a node with a positive local z-index of 2.
// it will show above other nodes in the gray container.
parent.spawn(NodeBundle {
z_index: ZIndex(2),
background_color: BLUE.into(),
style: Style {
parent.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
left: Val::Px(45.0),
bottom: Val::Px(30.0),
@ -72,15 +71,15 @@ fn setup(mut commands: Commands) {
height: Val::Px(50.),
..default()
},
..default()
});
ZIndex(2),
BackgroundColor(BLUE.into()),
));
// spawn a node with a negative local z-index.
// it will show under other nodes in the gray container.
parent.spawn(NodeBundle {
z_index: ZIndex(-1),
background_color: LIME.into(),
style: Style {
parent.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
left: Val::Px(70.0),
bottom: Val::Px(20.0),
@ -88,25 +87,24 @@ fn setup(mut commands: Commands) {
height: Val::Px(75.),
..default()
},
..default()
});
ZIndex(-1),
BackgroundColor(LIME.into()),
));
// spawn a node with a positive global z-index of 1.
// it will show above all other nodes, because it's the highest global z-index in this example.
// by default, boxes all share the global z-index of 0 that the gray container is added to.
parent.spawn((
NodeBundle {
background_color: PURPLE.into(),
style: Style {
position_type: PositionType::Absolute,
left: Val::Px(15.0),
bottom: Val::Px(10.0),
width: Val::Px(100.),
height: Val::Px(60.),
..default()
},
..Default::default()
Node::default(),
Style {
position_type: PositionType::Absolute,
left: Val::Px(15.0),
bottom: Val::Px(10.0),
width: Val::Px(100.),
height: Val::Px(60.),
..default()
},
BackgroundColor(PURPLE.into()),
GlobalZIndex(1),
));
@ -114,18 +112,16 @@ fn setup(mut commands: Commands) {
// this will show under all other nodes including its parent, because it's the lowest global z-index
// in this example.
parent.spawn((
NodeBundle {
background_color: YELLOW.into(),
style: Style {
position_type: PositionType::Absolute,
left: Val::Px(-15.0),
bottom: Val::Px(-15.0),
width: Val::Px(100.),
height: Val::Px(125.),
..default()
},
..Default::default()
Node::default(),
Style {
position_type: PositionType::Absolute,
left: Val::Px(-15.0),
bottom: Val::Px(-15.0),
width: Val::Px(100.),
height: Val::Px(125.),
..default()
},
BackgroundColor(YELLOW.into()),
GlobalZIndex(-1),
));
});

View file

@ -28,28 +28,28 @@ fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
// root node
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::SpaceBetween,
..default()
},
..default()
})
))
.with_children(|parent| {
// left vertical fill (border)
parent
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Px(300.0),
height: Val::Percent(100.0),
border: UiRect::all(Val::Px(2.0)),
..default()
},
background_color: Color::srgb(0.65, 0.65, 0.65).into(),
..default()
})
BackgroundColor(Color::srgb(0.65, 0.65, 0.65)),
))
.with_child((
CustomText,
Text::new("Example text"),

View file

@ -62,15 +62,13 @@ fn setup(mut commands: Commands) {
// UI
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::BLACK.with_alpha(0.75).into(),
Node::default(),
Style {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
BackgroundColor(Color::BLACK.with_alpha(0.75)),
GlobalZIndex(i32::MAX),
))
.with_children(|p| {

View file

@ -35,13 +35,13 @@ fn setup_camera(mut commands: Commands) {
fn setup_ui(mut commands: Commands) {
// Node that fills entire background
commands
.spawn(NodeBundle {
style: Style {
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
..default()
},
..default()
})
))
// Text where we display current resolution
.with_child((
Text::new("Resolution"),