Merge Style properties into Node. Use ComputedNode for computed properties. (#15975)

# Objective

Continue improving the user experience of our UI Node API in the
direction specified by [Bevy's Next Generation Scene / UI
System](https://github.com/bevyengine/bevy/discussions/14437)

## Solution

As specified in the document above, merge `Style` fields into `Node`,
and move "computed Node fields" into `ComputedNode` (I chose this name
over something like `ComputedNodeLayout` because it currently contains
more than just layout info. If we want to break this up / rename these
concepts, lets do that in a separate PR). `Style` has been removed.

This accomplishes a number of goals:

## Ergonomics wins

Specifying both `Node` and `Style` is now no longer required for
non-default styles

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

## Conceptual clarity

`Style` was never a comprehensive "style sheet". It only defined "core"
style properties that all `Nodes` shared. Any "styled property" that
couldn't fit that mold had to be in a separate component. A "real" style
system would style properties _across_ components (`Node`, `Button`,
etc). We have plans to build a true style system (see the doc linked
above).

By moving the `Style` fields to `Node`, we fully embrace `Node` as the
driving concept and remove the "style system" confusion.

## Next Steps

* Consider identifying and splitting out "style properties that aren't
core to Node". This should not happen for Bevy 0.15.

---

## Migration Guide

Move any fields set on `Style` into `Node` and replace all `Style`
component usage with `Node`.

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

For any usage of the "computed node properties" that used to live on
`Node`, use `ComputedNode` instead:

Before:
```rust
fn system(nodes: Query<&Node>) {
    for node in &nodes {
        let computed_size = node.size();
    }
}
```

After:
```rust
fn system(computed_nodes: Query<&ComputedNode>) {
    for computed_node in &computed_nodes {
        let computed_size = computed_node.size();
    }
}
```
This commit is contained in:
Carter Anderson 2024-10-18 17:25:33 -05:00 committed by GitHub
parent 624f573443
commit 015f2c69ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
149 changed files with 1258 additions and 1616 deletions

View file

@ -15,10 +15,9 @@ 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::{
widget::{Text, TextUiWriter},
GlobalZIndex, PositionType, Style,
GlobalZIndex, Node, PositionType,
};
use bevy_utils::default;
@ -89,8 +88,7 @@ struct FpsText;
fn setup(mut commands: Commands, overlay_config: Res<FpsOverlayConfig>) {
commands
.spawn((
Node::default(),
Style {
Node {
// We need to make sure the overlay doesn't affect the position of other UI nodes
position_type: PositionType::Absolute,
..default()

View file

@ -15,7 +15,7 @@ use bevy_render::{
view::{RenderLayers, VisibilitySystems},
};
use bevy_transform::{prelude::GlobalTransform, TransformSystem};
use bevy_ui::{DefaultUiCamera, Display, Node, Style, TargetCamera, UiScale};
use bevy_ui::{ComputedNode, DefaultUiCamera, Display, Node, TargetCamera, UiScale};
use bevy_utils::{default, warn_once};
use bevy_window::{PrimaryWindow, Window, WindowRef};
@ -37,7 +37,7 @@ struct LayoutRect {
}
impl LayoutRect {
fn new(trans: &GlobalTransform, node: &Node, scale: f32) -> Self {
fn new(trans: &GlobalTransform, node: &ComputedNode, scale: f32) -> Self {
let mut this = Self {
pos: trans.translation().xy() * scale,
size: node.size() * scale,
@ -123,8 +123,8 @@ fn outline_nodes(outline: &OutlineParam, draw: &mut InsetGizmo, this_entity: Ent
return;
};
for (entity, trans, node, style, children) in outline.nodes.iter_many(to_iter) {
if style.is_none() || style.is_some_and(|s| matches!(s.display, Display::None)) {
for (entity, trans, node, computed_node, children) in outline.nodes.iter_many(to_iter) {
if matches!(node.display, Display::None) {
continue;
}
@ -133,7 +133,7 @@ fn outline_nodes(outline: &OutlineParam, draw: &mut InsetGizmo, this_entity: Ent
continue;
}
}
let rect = LayoutRect::new(trans, node, scale);
let rect = LayoutRect::new(trans, computed_node, scale);
outline_node(entity, rect, draw);
if children.is_some() {
outline_nodes(outline, draw, entity, scale);
@ -146,7 +146,7 @@ type NodesQuery = (
Entity,
&'static GlobalTransform,
&'static Node,
Option<&'static Style>,
&'static ComputedNode,
Option<&'static Children>,
);
@ -178,7 +178,7 @@ fn outline_roots(
(
Entity,
&GlobalTransform,
&Node,
&ComputedNode,
Option<&ViewVisibility>,
Option<&TargetCamera>,
),

View file

@ -352,9 +352,9 @@ unsafe impl<T: Component> QueryFilter for Without<T> {
/// # #[derive(Component, Debug)]
/// # struct Color {};
/// # #[derive(Component)]
/// # struct Style {};
/// # struct Node {};
/// #
/// fn print_cool_entity_system(query: Query<Entity, Or<(Changed<Color>, Changed<Style>)>>) {
/// fn print_cool_entity_system(query: Query<Entity, Or<(Changed<Color>, Changed<Node>)>>) {
/// for entity in &query {
/// println!("Entity {:?} got a new style or color", entity);
/// }

View file

@ -171,11 +171,11 @@ impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
fn next(&mut self) -> Option<Self::Item> {
// Root
if let Some(root_entity) = self.root_entity.take() {
if let Ok((text, style, color, maybe_children)) = self.roots.get(root_entity) {
if let Ok((text, text_font, color, maybe_children)) = self.roots.get(root_entity) {
if let Some(children) = maybe_children {
self.stack.push((children, 0));
}
return Some((root_entity, 0, text.read_span(), style, color.0));
return Some((root_entity, 0, text.read_span(), text_font, color.0));
}
return None;
}
@ -193,7 +193,7 @@ impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
*idx += 1;
let entity = *child;
let Ok((span, style, color, maybe_children)) = self.spans.get(entity) else {
let Ok((span, text_font, color, maybe_children)) = self.spans.get(entity) else {
continue;
};
@ -201,7 +201,7 @@ impl<'a, R: TextRoot> Iterator for TextSpanIter<'a, R> {
if let Some(children) = maybe_children {
self.stack.push((children, 0));
}
return Some((entity, depth, span.read_span(), style, color.0));
return Some((entity, depth, span.read_span(), text_font, color.0));
}
// All children at this stack entry have been iterated.

View file

@ -2,7 +2,7 @@ use crate::{
experimental::UiChildren,
prelude::{Button, Label},
widget::TextUiReader,
Node, UiImage,
ComputedNode, UiImage,
};
use bevy_a11y::{
accesskit::{NodeBuilder, Rect, Role},
@ -38,7 +38,11 @@ fn calc_name(
fn calc_bounds(
camera: Query<(&Camera, &GlobalTransform)>,
mut nodes: Query<(&mut AccessibilityNode, Ref<Node>, Ref<GlobalTransform>)>,
mut nodes: Query<(
&mut AccessibilityNode,
Ref<ComputedNode>,
Ref<GlobalTransform>,
)>,
) {
if let Ok((camera, camera_transform)) = camera.get_single() {
for (mut accessible, node, transform) in &mut nodes {

View file

@ -1,5 +1,6 @@
use crate::{
CalculatedClip, DefaultUiCamera, Node, ResolvedBorderRadius, TargetCamera, UiScale, UiStack,
CalculatedClip, ComputedNode, DefaultUiCamera, ResolvedBorderRadius, TargetCamera, UiScale,
UiStack,
};
use bevy_ecs::{
change_detection::DetectChangesMut,
@ -74,7 +75,7 @@ impl Default for Interaction {
///
/// It can be used alongside [`Interaction`] to get the position of the press.
///
/// The component is updated when it is in the same entity with [`Node`].
/// The component is updated when it is in the same entity with [`Node`](crate::Node).
#[derive(Component, Copy, Clone, Default, PartialEq, Debug, Reflect)]
#[reflect(Component, Default, PartialEq, Debug)]
#[cfg_attr(
@ -135,7 +136,7 @@ pub struct State {
#[query_data(mutable)]
pub struct NodeQuery {
entity: Entity,
node: &'static Node,
node: &'static ComputedNode,
global_transform: &'static GlobalTransform,
interaction: Option<&'static mut Interaction>,
relative_cursor_position: Option<&'static mut RelativeCursorPosition>,

View file

@ -8,7 +8,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
/// Represents the possible value types for layout properties.
///
/// This enum allows specifying values for various [`Style`](crate::Style) properties in different units,
/// This enum allows specifying values for various [`Node`](crate::Node) properties in different units,
/// such as logical pixels, percentages, or automatically determined values.
#[derive(Copy, Clone, Debug, Reflect)]
#[reflect(Default, PartialEq, Debug)]
@ -18,7 +18,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
reflect(Serialize, Deserialize)
)]
pub enum Val {
/// Automatically determine the value based on the context and other [`Style`](crate::Style) properties.
/// Automatically determine the value based on the context and other [`Node`](crate::Node) properties.
Auto,
/// Set this value in logical pixels.
Px(f32),
@ -27,7 +27,7 @@ pub enum Val {
/// If the UI node has no parent, the percentage is calculated based on the window's length
/// along the corresponding axis.
///
/// The chosen axis depends on the [`Style`](crate::Style) field set:
/// The chosen axis depends on the [`Node`](crate::Node) field set:
/// * For `flex_basis`, the percentage is relative to the main-axis length determined by the `flex_direction`.
/// * For `gap`, `min_size`, `size`, and `max_size`:
/// - `width` is relative to the parent's width.

View file

@ -3,8 +3,8 @@ use taffy::style_helpers;
use crate::{
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, GridAutoFlow,
GridPlacement, GridTrack, GridTrackRepetition, JustifyContent, JustifyItems, JustifySelf,
MaxTrackSizingFunction, MinTrackSizingFunction, OverflowAxis, PositionType, RepeatedGridTrack,
Style, UiRect, Val,
MaxTrackSizingFunction, MinTrackSizingFunction, Node, OverflowAxis, PositionType,
RepeatedGridTrack, UiRect, Val,
};
use super::LayoutContext;
@ -63,37 +63,33 @@ impl UiRect {
}
}
pub fn from_style(
context: &LayoutContext,
style: &Style,
ignore_border: bool,
) -> taffy::style::Style {
pub fn from_node(node: &Node, context: &LayoutContext, ignore_border: bool) -> taffy::style::Style {
taffy::style::Style {
display: style.display.into(),
display: node.display.into(),
overflow: taffy::Point {
x: style.overflow.x.into(),
y: style.overflow.y.into(),
x: node.overflow.x.into(),
y: node.overflow.y.into(),
},
scrollbar_width: 0.0,
position: style.position_type.into(),
flex_direction: style.flex_direction.into(),
flex_wrap: style.flex_wrap.into(),
align_items: style.align_items.into(),
justify_items: style.justify_items.into(),
align_self: style.align_self.into(),
justify_self: style.justify_self.into(),
align_content: style.align_content.into(),
justify_content: style.justify_content.into(),
position: node.position_type.into(),
flex_direction: node.flex_direction.into(),
flex_wrap: node.flex_wrap.into(),
align_items: node.align_items.into(),
justify_items: node.justify_items.into(),
align_self: node.align_self.into(),
justify_self: node.justify_self.into(),
align_content: node.align_content.into(),
justify_content: node.justify_content.into(),
inset: taffy::Rect {
left: style.left.into_length_percentage_auto(context),
right: style.right.into_length_percentage_auto(context),
top: style.top.into_length_percentage_auto(context),
bottom: style.bottom.into_length_percentage_auto(context),
left: node.left.into_length_percentage_auto(context),
right: node.right.into_length_percentage_auto(context),
top: node.top.into_length_percentage_auto(context),
bottom: node.bottom.into_length_percentage_auto(context),
},
margin: style
margin: node
.margin
.map_to_taffy_rect(|m| m.into_length_percentage_auto(context)),
padding: style
padding: node
.padding
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
// Ignore border for leaf nodes as it isn't implemented in the rendering engine.
@ -101,53 +97,52 @@ pub fn from_style(
border: if ignore_border {
taffy::Rect::zero()
} else {
style
.border
node.border
.map_to_taffy_rect(|m| m.into_length_percentage(context))
},
flex_grow: style.flex_grow,
flex_shrink: style.flex_shrink,
flex_basis: style.flex_basis.into_dimension(context),
flex_grow: node.flex_grow,
flex_shrink: node.flex_shrink,
flex_basis: node.flex_basis.into_dimension(context),
size: taffy::Size {
width: style.width.into_dimension(context),
height: style.height.into_dimension(context),
width: node.width.into_dimension(context),
height: node.height.into_dimension(context),
},
min_size: taffy::Size {
width: style.min_width.into_dimension(context),
height: style.min_height.into_dimension(context),
width: node.min_width.into_dimension(context),
height: node.min_height.into_dimension(context),
},
max_size: taffy::Size {
width: style.max_width.into_dimension(context),
height: style.max_height.into_dimension(context),
width: node.max_width.into_dimension(context),
height: node.max_height.into_dimension(context),
},
aspect_ratio: style.aspect_ratio,
aspect_ratio: node.aspect_ratio,
gap: taffy::Size {
width: style.column_gap.into_length_percentage(context),
height: style.row_gap.into_length_percentage(context),
width: node.column_gap.into_length_percentage(context),
height: node.row_gap.into_length_percentage(context),
},
grid_auto_flow: style.grid_auto_flow.into(),
grid_template_rows: style
grid_auto_flow: node.grid_auto_flow.into(),
grid_template_rows: node
.grid_template_rows
.iter()
.map(|track| track.clone_into_repeated_taffy_track(context))
.collect::<Vec<_>>(),
grid_template_columns: style
grid_template_columns: node
.grid_template_columns
.iter()
.map(|track| track.clone_into_repeated_taffy_track(context))
.collect::<Vec<_>>(),
grid_auto_rows: style
grid_auto_rows: node
.grid_auto_rows
.iter()
.map(|track| track.into_taffy_track(context))
.collect::<Vec<_>>(),
grid_auto_columns: style
grid_auto_columns: node
.grid_auto_columns
.iter()
.map(|track| track.into_taffy_track(context))
.collect::<Vec<_>>(),
grid_row: style.grid_row.into(),
grid_column: style.grid_column.into(),
grid_row: node.grid_row.into(),
grid_column: node.grid_column.into(),
}
}
@ -448,7 +443,7 @@ mod tests {
use sh::TaffyZero;
use taffy::style_helpers as sh;
let bevy_style = Style {
let node = Node {
display: Display::Flex,
position_type: PositionType::Absolute,
left: Val::ZERO,
@ -516,7 +511,7 @@ mod tests {
grid_row: GridPlacement::span(3),
};
let viewport_values = LayoutContext::new(1.0, bevy_math::Vec2::new(800., 600.));
let taffy_style = from_style(&viewport_values, &bevy_style, false);
let taffy_style = from_node(&node, &viewport_values, false);
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
assert_eq!(

View file

@ -1,7 +1,7 @@
use crate::{
experimental::{UiChildren, UiRootNodes},
BorderRadius, ContentSize, DefaultUiCamera, Display, Node, Outline, OverflowAxis,
ScrollPosition, Style, TargetCamera, UiScale,
BorderRadius, ComputedNode, ContentSize, DefaultUiCamera, Display, Node, Outline, OverflowAxis,
ScrollPosition, TargetCamera, UiScale,
};
use bevy_ecs::{
change_detection::{DetectChanges, DetectChangesMut},
@ -115,22 +115,19 @@ pub fn ui_layout_system(
mut resize_events: EventReader<bevy_window::WindowResized>,
mut ui_surface: ResMut<UiSurface>,
root_nodes: UiRootNodes,
mut style_query: Query<
(
Entity,
Ref<Style>,
Option<&mut ContentSize>,
Option<&TargetCamera>,
),
With<Node>,
>,
node_query: Query<(Entity, Option<Ref<Parent>>), With<Node>>,
mut node_query: Query<(
Entity,
Ref<Node>,
Option<&mut ContentSize>,
Option<&TargetCamera>,
)>,
computed_node_query: Query<(Entity, Option<Ref<Parent>>), With<ComputedNode>>,
ui_children: UiChildren,
mut removed_components: UiLayoutSystemRemovedComponentParam,
mut node_transform_query: Query<(
&mut Node,
&mut ComputedNode,
&mut Transform,
&Style,
&Node,
Option<&BorderRadius>,
Option<&Outline>,
Option<&ScrollPosition>,
@ -173,7 +170,7 @@ pub fn ui_layout_system(
// Precalculate the layout info for each camera, so we have fast access to it for each node
camera_layout_info.clear();
style_query
node_query
.iter_many(root_nodes.iter())
.for_each(|(entity, _, _, target_camera)| {
match camera_with_default(target_camera) {
@ -211,17 +208,17 @@ pub fn ui_layout_system(
ui_surface.try_remove_node_context(entity);
}
// Sync Style and ContentSize to Taffy for all nodes
style_query
// Sync Node and ContentSize to Taffy for all nodes
node_query
.iter_mut()
.for_each(|(entity, style, content_size, target_camera)| {
.for_each(|(entity, node, content_size, target_camera)| {
if let Some(camera) =
camera_with_default(target_camera).and_then(|c| camera_layout_info.get(&c))
{
if camera.resized
|| !scale_factor_events.is_empty()
|| ui_scale.is_changed()
|| style.is_changed()
|| node.is_changed()
|| content_size
.as_ref()
.map(|c| c.measure.is_some())
@ -232,10 +229,10 @@ pub fn ui_layout_system(
[camera.size.x as f32, camera.size.y as f32].into(),
);
let measure = content_size.and_then(|mut c| c.measure.take());
ui_surface.upsert_node(&layout_context, entity, &style, measure);
ui_surface.upsert_node(&layout_context, entity, &node, measure);
}
} else {
ui_surface.upsert_node(&LayoutContext::DEFAULT, entity, &Style::default(), None);
ui_surface.upsert_node(&LayoutContext::DEFAULT, entity, &Node::default(), None);
}
});
scale_factor_events.clear();
@ -259,30 +256,32 @@ pub fn ui_layout_system(
ui_surface.try_remove_children(entity);
}
node_query.iter().for_each(|(entity, maybe_parent)| {
if let Some(parent) = maybe_parent {
// Note: This does not cover the case where a parent's Node component was removed.
// Users are responsible for fixing hierarchies if they do that (it is not recommended).
// Detecting it here would be a permanent perf burden on the hot path.
if parent.is_changed() && !ui_children.is_ui_node(parent.get()) {
warn!(
"Styled child ({entity}) in a non-UI entity hierarchy. You are using an entity \
computed_node_query
.iter()
.for_each(|(entity, maybe_parent)| {
if let Some(parent) = maybe_parent {
// Note: This does not cover the case where a parent's Node component was removed.
// Users are responsible for fixing hierarchies if they do that (it is not recommended).
// Detecting it here would be a permanent perf burden on the hot path.
if parent.is_changed() && !ui_children.is_ui_node(parent.get()) {
warn!(
"Node ({entity}) is in a non-UI entity hierarchy. You are using an entity \
with UI components as a child of an entity without UI components, your UI layout may be broken."
);
);
}
}
}
if ui_children.is_changed(entity) {
ui_surface.update_children(entity, ui_children.iter_ui_children(entity));
}
});
if ui_children.is_changed(entity) {
ui_surface.update_children(entity, ui_children.iter_ui_children(entity));
}
});
let text_buffers = &mut buffer_query;
// clean up removed nodes after syncing children to avoid potential panic (invalid SlotMap key used)
ui_surface.remove_entities(removed_components.removed_nodes.read());
// Re-sync changed children: avoid layout glitches caused by removed nodes that are still set as a child of another node
node_query.iter().for_each(|(entity, _)| {
computed_node_query.iter().for_each(|(entity, _)| {
if ui_children.is_changed(entity) {
ui_surface.update_children(entity, ui_children.iter_ui_children(entity));
}
@ -319,9 +318,9 @@ with UI components as a child of an entity without UI components, your UI layout
ui_surface: &UiSurface,
root_size: Option<Vec2>,
node_transform_query: &mut Query<(
&mut Node,
&mut ComputedNode,
&mut Transform,
&Style,
&Node,
Option<&BorderRadius>,
Option<&Outline>,
Option<&ScrollPosition>,
@ -581,25 +580,19 @@ mod tests {
// spawn a root entity with width and height set to fill 100% of its parent
let ui_root = world
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
))
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
})
.id();
let ui_child = world
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
))
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
})
.id();
world.entity_mut(ui_root).add_child(ui_child);
@ -828,45 +821,36 @@ mod tests {
let mut size = 150.;
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()
},
));
world.spawn(Node {
// 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()
});
size -= 50.;
world.spawn((
Node::default(),
Style {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
},
));
world.spawn(Node {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
});
size -= 50.;
world.spawn((
Node::default(),
Style {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
},
));
world.spawn(Node {
// position_type: PositionType::Absolute,
width: Val::Px(size),
height: Val::Px(size),
..default()
});
ui_schedule.run(&mut world);
let overlap_check = world
.query_filtered::<(Entity, &Node, &GlobalTransform), Without<Parent>>()
.query_filtered::<(Entity, &ComputedNode, &GlobalTransform), Without<Parent>>()
.iter(&world)
.fold(
Option::<(Rect, bool)>::None,
@ -949,7 +933,7 @@ mod tests {
commands
.entity(moving_ui_entity)
.insert(TargetCamera(target_camera_entity))
.insert(Style {
.insert(Node {
position_type: PositionType::Absolute,
top: Val::Px(pos.y),
left: Val::Px(pos.x),
@ -996,8 +980,7 @@ mod tests {
));
world.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(0.),
left: Val::Px(0.),
@ -1050,8 +1033,7 @@ mod tests {
let ui_entity = world
.spawn((
Node::default(),
Style {
Node {
align_self: AlignSelf::Start,
..default()
},
@ -1076,8 +1058,7 @@ mod tests {
let content_size = Vec2::new(50., 25.);
let ui_entity = world
.spawn((
Node::default(),
Style {
Node {
align_self: AlignSelf::Start,
..Default::default()
},
@ -1115,26 +1096,20 @@ mod tests {
let (mut world, mut ui_schedule) = setup_ui_test_world();
let parent = world
.spawn((
Node::default(),
Style {
display: Display::Grid,
grid_template_columns: RepeatedGridTrack::min_content(2),
margin: UiRect::all(Val::Px(4.0)),
..default()
},
))
.spawn(Node {
display: Display::Grid,
grid_template_columns: RepeatedGridTrack::min_content(2),
margin: UiRect::all(Val::Px(4.0)),
..default()
})
.with_children(|commands| {
for _ in 0..2 {
commands.spawn((
Node::default(),
Style {
display: Display::Grid,
width: Val::Px(160.),
height: Val::Px(160.),
..default()
},
));
commands.spawn(Node {
display: Display::Grid,
width: Val::Px(160.),
height: Val::Px(160.),
..default()
});
}
})
.id();
@ -1154,9 +1129,9 @@ mod tests {
ui_schedule.run(&mut world);
let width_sum: f32 = children
.iter()
.map(|child| world.get::<Node>(*child).unwrap().calculated_size.x)
.map(|child| world.get::<ComputedNode>(*child).unwrap().calculated_size.x)
.sum();
let parent_width = world.get::<Node>(parent).unwrap().calculated_size.x;
let parent_width = world.get::<ComputedNode>(parent).unwrap().calculated_size.x;
assert!((width_sum - parent_width).abs() < 0.001);
assert!((width_sum - 320.).abs() <= 1.);
s += r;
@ -1205,25 +1180,19 @@ mod tests {
);
let ui_root = world
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
))
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
})
.id();
let ui_child = world
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
},
))
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
})
.id();
world.entity_mut(ui_root).add_child(ui_child);
@ -1254,7 +1223,7 @@ mod tests {
ui_surface.upsert_node(
&LayoutContext::TEST_CONTEXT,
params.root_node_entity,
&Style::default(),
&Node::default(),
None,
);

View file

@ -9,9 +9,7 @@ use bevy_ecs::{
use bevy_math::UVec2;
use bevy_utils::default;
use crate::{
layout::convert, LayoutContext, LayoutError, Measure, MeasureArgs, NodeMeasure, Style,
};
use crate::{layout::convert, LayoutContext, LayoutError, Measure, MeasureArgs, Node, NodeMeasure};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RootNodePair {
@ -71,7 +69,7 @@ impl UiSurface {
&mut self,
layout_context: &LayoutContext,
entity: Entity,
style: &Style,
node: &Node,
mut new_node_context: Option<NodeMeasure>,
) {
let taffy = &mut self.taffy;
@ -81,14 +79,11 @@ impl UiSurface {
added = true;
if let Some(measure) = new_node_context.take() {
taffy
.new_leaf_with_context(
convert::from_style(layout_context, style, true),
measure,
)
.new_leaf_with_context(convert::from_node(node, layout_context, true), measure)
.unwrap()
} else {
taffy
.new_leaf(convert::from_style(layout_context, style, false))
.new_leaf(convert::from_node(node, layout_context, false))
.unwrap()
}
});
@ -106,7 +101,7 @@ impl UiSurface {
taffy
.set_style(
taffy_node_id,
convert::from_style(layout_context, style, has_measure),
convert::from_node(node, layout_context, has_measure),
)
.unwrap();
}
@ -353,17 +348,17 @@ mod tests {
let mut ui_surface = UiSurface::default();
let camera_entity = Entity::from_raw(0);
let root_node_entity = Entity::from_raw(1);
let style = Style::default();
let node = Node::default();
// standard upsert
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
// should be inserted into taffy
assert_eq!(ui_surface.taffy.total_node_count(), 1);
assert!(ui_surface.entity_to_taffy.contains_key(&root_node_entity));
// test duplicate insert 1
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
// node count should not have increased
assert_eq!(ui_surface.taffy.total_node_count(), 1);
@ -380,7 +375,7 @@ mod tests {
assert!(is_root_node_pair_valid(&ui_surface.taffy, root_node_pair));
// test duplicate insert 2
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
// node count should not have increased
assert_eq!(ui_surface.taffy.total_node_count(), 2);
@ -418,9 +413,9 @@ mod tests {
let mut ui_surface = UiSurface::default();
let camera_entity = Entity::from_raw(0);
let root_node_entity = Entity::from_raw(1);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
// assign root node to camera
ui_surface.set_camera_children(camera_entity, [root_node_entity].into_iter());
@ -453,9 +448,9 @@ mod tests {
let mut ui_surface = UiSurface::default();
let camera_entity = Entity::from_raw(0);
let root_node_entity = Entity::from_raw(1);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
// assign root node to camera
ui_surface.set_camera_children(camera_entity, [root_node_entity].into_iter());
@ -502,9 +497,9 @@ mod tests {
let mut ui_surface = UiSurface::default();
let camera_entity = Entity::from_raw(0);
let root_node_entity = Entity::from_raw(1);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
ui_surface.set_camera_children(camera_entity, [root_node_entity].into_iter());
@ -548,9 +543,9 @@ mod tests {
fn test_try_update_measure() {
let mut ui_surface = UiSurface::default();
let root_node_entity = Entity::from_raw(1);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
let mut content_size = ContentSize::default();
content_size.set(NodeMeasure::Fixed(FixedMeasure { size: Vec2::ONE }));
let measure_func = content_size.measure.take().unwrap();
@ -564,10 +559,10 @@ mod tests {
let mut ui_surface = UiSurface::default();
let root_node_entity = Entity::from_raw(1);
let child_entity = Entity::from_raw(2);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &node, None);
ui_surface.update_children(root_node_entity, vec![child_entity].into_iter());
@ -583,10 +578,10 @@ mod tests {
let camera_entity = Entity::from_raw(0);
let root_node_entity = Entity::from_raw(1);
let child_entity = Entity::from_raw(2);
let style = Style::default();
let node = Node::default();
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &style, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &node, None);
let root_taffy_node = *ui_surface.entity_to_taffy.get(&root_node_entity).unwrap();
let child_taffy = *ui_surface.entity_to_taffy.get(&child_entity).unwrap();

View file

@ -129,10 +129,6 @@ struct AmbiguousWithTextSystem;
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
struct AmbiguousWithUpdateText2DLayout;
/// A convenient alias for `With<Node>`, for use with
/// [`bevy_render::view::VisibleEntities`].
pub type WithNode = With<Node>;
impl Plugin for UiPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<UiSurface>()
@ -140,13 +136,13 @@ impl Plugin for UiPlugin {
.init_resource::<UiStack>()
.register_type::<BackgroundColor>()
.register_type::<CalculatedClip>()
.register_type::<ComputedNode>()
.register_type::<ContentSize>()
.register_type::<FocusPolicy>()
.register_type::<Interaction>()
.register_type::<Node>()
.register_type::<RelativeCursorPosition>()
.register_type::<ScrollPosition>()
.register_type::<Style>()
.register_type::<TargetCamera>()
.register_type::<UiImage>()
.register_type::<UiImageSize>()
@ -189,7 +185,7 @@ impl Plugin for UiPlugin {
app.add_systems(
PostUpdate,
(
check_visibility::<WithNode>.in_set(VisibilitySystems::CheckVisibility),
check_visibility::<With<Node>>.in_set(VisibilitySystems::CheckVisibility),
update_target_camera_system.in_set(UiSystem::Prepare),
ui_layout_system_config,
ui_stack_system

View file

@ -3,8 +3,8 @@
use crate::{
widget::{Button, UiImageSize},
BackgroundColor, BorderColor, BorderRadius, ContentSize, FocusPolicy, Interaction,
MaterialNode, Node, ScrollPosition, Style, UiImage, UiMaterial, ZIndex,
BackgroundColor, BorderColor, BorderRadius, ComputedNode, ContentSize, FocusPolicy,
Interaction, MaterialNode, Node, ScrollPosition, UiImage, UiMaterial, ZIndex,
};
use bevy_ecs::bundle::Bundle;
use bevy_render::view::{InheritedVisibility, ViewVisibility, Visibility};
@ -21,11 +21,11 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
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
/// Controls the layout (size and position) of the node and its children
/// This also affect how the node is drawn/painted.
pub node: Node,
/// Styles which control the layout (size and position) of the node and its children
/// In some cases these styles also affect how the node drawn/painted.
pub style: Style,
/// Describes the logical size of the node
pub computed_node: ComputedNode,
/// The background color, which serves as a "fill" for this node
pub background_color: BackgroundColor,
/// The color of the Node's border
@ -39,12 +39,12 @@ pub struct NodeBundle {
/// The transform of the node
///
/// This component is automatically managed by the UI layout system.
/// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `NodeBundle`, use the properties of the [`Node`] component.
pub transform: Transform,
/// The global transform of the node
///
/// This component is automatically updated by the [`TransformPropagate`](`bevy_transform::TransformSystem::TransformPropagate`) systems.
/// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `NodeBundle`, use the properties of the [`Node`] component.
pub global_transform: GlobalTransform,
/// Describes the visibility properties of the node
pub visibility: Visibility,
@ -70,10 +70,10 @@ pub struct NodeBundle {
)]
pub struct ImageBundle {
/// Describes the logical size of the node
pub computed_node: ComputedNode,
/// Controls the layout (size and position) of the node and its children
/// This also affects how the node is drawn/painted.
pub node: Node,
/// Styles which control the layout (size and position) of the node and its children
/// In some cases these styles also affect how the node drawn/painted.
pub style: Style,
/// The calculated size based on the given image
pub calculated_size: ContentSize,
/// The image of the node.
@ -93,7 +93,7 @@ pub struct ImageBundle {
/// The transform of the node
///
/// This component is automatically managed by the UI layout system.
/// To alter the position of the `ImageBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `ImageBundle`, use the properties of the [`Node`] component.
pub transform: Transform,
/// The global transform of the node
///
@ -123,12 +123,12 @@ pub struct ImageBundle {
)]
pub struct ButtonBundle {
/// Describes the logical size of the node
pub node: Node,
pub computed_node: ComputedNode,
/// Marker component that signals this node is a button
pub button: Button,
/// Styles which control the layout (size and position) of the node and its children
/// In some cases these styles also affect how the node drawn/painted.
pub style: Style,
/// Controls the layout (size and position) of the node and its children
/// Also affect how the node is drawn/painted.
pub node: Node,
/// Describes whether and how the button has been interacted with by the input
pub interaction: Interaction,
/// Whether this node should block interaction with lower nodes
@ -144,7 +144,7 @@ pub struct ButtonBundle {
/// The transform of the node
///
/// This component is automatically managed by the UI layout system.
/// To alter the position of the `ButtonBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `ButtonBundle`, use the properties of the [`Node`] component.
pub transform: Transform,
/// The global transform of the node
///
@ -164,8 +164,8 @@ impl Default for ButtonBundle {
fn default() -> Self {
Self {
node: Default::default(),
computed_node: Default::default(),
button: Default::default(),
style: Default::default(),
interaction: Default::default(),
focus_policy: FocusPolicy::Block,
border_color: Default::default(),
@ -193,10 +193,10 @@ impl Default for ButtonBundle {
)]
pub struct MaterialNodeBundle<M: UiMaterial> {
/// Describes the logical size of the node
pub computed_node: ComputedNode,
/// Controls the layout (size and position) of the node and its children
/// Also affects how the node is drawn/painted.
pub node: Node,
/// Styles which control the layout (size and position) of the node and its children
/// In some cases these styles also affect how the node drawn/painted.
pub style: Style,
/// The [`UiMaterial`] used to render the node.
pub material: MaterialNode<M>,
/// Whether this node should block interaction with lower nodes
@ -204,12 +204,12 @@ pub struct MaterialNodeBundle<M: UiMaterial> {
/// The transform of the node
///
/// This field is automatically managed by the UI layout system.
/// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `NodeBundle`, use the properties of the [`Node`] component.
pub transform: Transform,
/// The global transform of the node
///
/// This field is automatically managed by the UI layout system.
/// To alter the position of the `NodeBundle`, use the properties of the [`Style`] component.
/// To alter the position of the `NodeBundle`, use the properties of the [`Node`] component.
pub global_transform: GlobalTransform,
/// Describes the visibility properties of the node
pub visibility: Visibility,
@ -225,7 +225,7 @@ impl<M: UiMaterial> Default for MaterialNodeBundle<M> {
fn default() -> Self {
Self {
node: Default::default(),
style: Default::default(),
computed_node: Default::default(),
material: Default::default(),
focus_policy: Default::default(),
transform: Default::default(),

View file

@ -48,7 +48,7 @@ impl Plugin for UiPickingBackendPlugin {
#[query_data(mutable)]
pub struct NodeQuery {
entity: Entity,
node: &'static Node,
node: &'static ComputedNode,
global_transform: &'static GlobalTransform,
picking_behavior: Option<&'static PickingBehavior>,
calculated_clip: Option<&'static CalculatedClip>,

View file

@ -1,7 +1,7 @@
use core::{hash::Hash, ops::Range};
use crate::{
BoxShadow, CalculatedClip, DefaultUiCamera, Node, RenderUiSystem, ResolvedBorderRadius,
BoxShadow, CalculatedClip, ComputedNode, DefaultUiCamera, RenderUiSystem, ResolvedBorderRadius,
TargetCamera, TransparentUi, UiBoxShadowSamples, UiScale, Val,
};
use bevy_app::prelude::*;
@ -239,7 +239,7 @@ pub fn extract_shadows(
box_shadow_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
&BoxShadow,

View file

@ -5,7 +5,7 @@ mod ui_material_pipeline;
pub mod ui_texture_slice_pipeline;
use crate::{
BackgroundColor, BorderColor, CalculatedClip, DefaultUiCamera, Node, Outline,
BackgroundColor, BorderColor, CalculatedClip, ComputedNode, DefaultUiCamera, Outline,
ResolvedBorderRadius, TargetCamera, UiAntiAlias, UiBoxShadowSamples, UiImage, UiScale,
};
use bevy_app::prelude::*;
@ -245,7 +245,7 @@ pub fn extract_uinode_background_colors(
uinode_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
Option<&CalculatedClip>,
@ -309,7 +309,7 @@ pub fn extract_uinode_images(
Query<
(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
Option<&CalculatedClip>,
@ -398,7 +398,7 @@ pub fn extract_uinode_borders(
uinode_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
Option<&CalculatedClip>,
@ -613,7 +613,7 @@ pub fn extract_text_sections(
uinode_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
Option<&CalculatedClip>,

View file

@ -365,7 +365,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
uinode_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&MaterialNode<M>,
&ViewVisibility,

View file

@ -251,7 +251,7 @@ pub fn extract_ui_texture_slices(
slicers_query: Extract<
Query<(
Entity,
&Node,
&ComputedNode,
&GlobalTransform,
&ViewVisibility,
Option<&CalculatedClip>,

View file

@ -5,7 +5,7 @@ use bevy_utils::HashSet;
use crate::{
experimental::{UiChildren, UiRootNodes},
GlobalZIndex, Node, ZIndex,
ComputedNode, GlobalZIndex, ZIndex,
};
/// The current UI stack, which contains all UI nodes ordered by their depth (back-to-front).
@ -46,10 +46,10 @@ pub fn ui_stack_system(
mut ui_stack: ResMut<UiStack>,
ui_root_nodes: UiRootNodes,
root_node_query: Query<(Entity, Option<&GlobalZIndex>, Option<&ZIndex>)>,
zindex_global_node_query: Query<(Entity, &GlobalZIndex, Option<&ZIndex>), With<Node>>,
zindex_global_node_query: Query<(Entity, &GlobalZIndex, Option<&ZIndex>), With<ComputedNode>>,
ui_children: UiChildren,
zindex_query: Query<Option<&ZIndex>, (With<Node>, Without<GlobalZIndex>)>,
mut update_query: Query<&mut Node>,
zindex_query: Query<Option<&ZIndex>, (With<ComputedNode>, Without<GlobalZIndex>)>,
mut update_query: Query<&mut ComputedNode>,
) {
ui_stack.uinodes.clear();
visited_root_nodes.clear();
@ -102,7 +102,7 @@ fn update_uistack_recursive(
cache: &mut ChildBufferCache,
node_entity: Entity,
ui_children: &UiChildren,
zindex_query: &Query<Option<&ZIndex>, (With<Node>, Without<GlobalZIndex>)>,
zindex_query: &Query<Option<&ZIndex>, (With<ComputedNode>, Without<GlobalZIndex>)>,
ui_stack: &mut Vec<Entity>,
) {
ui_stack.push(node_entity);

View file

@ -1,5 +1,3 @@
use core::hash::Hash;
use crate::Node;
use bevy_asset::{Asset, AssetId, Handle};
use bevy_derive::{Deref, DerefMut};
@ -9,6 +7,7 @@ use bevy_render::{
extract_component::ExtractComponent,
render_resource::{AsBindGroup, RenderPipelineDescriptor, ShaderRef},
};
use core::hash::Hash;
use derive_more::derive::From;
/// Materials are used alongside [`UiMaterialPlugin`](crate::UiMaterialPlugin) and [`MaterialNode`]
@ -64,7 +63,7 @@ use derive_more::derive::From;
/// color: LinearRgba::RED,
/// color_texture: asset_server.load("some_image.png"),
/// })),
/// Style {
/// Node {
/// width: Val::Percent(100.0),
/// ..Default::default()
/// },

View file

@ -17,29 +17,10 @@ use core::num::NonZero;
use derive_more::derive::{Display, Error, From};
use smallvec::SmallVec;
/// Base component for a UI node, which also provides the computed size of the node.
///
/// # See also
///
/// - [`node_bundles`](crate::node_bundles) for the list of built-in bundles that set up UI node
/// - [`RelativeCursorPosition`](crate::RelativeCursorPosition)
/// to obtain the cursor position relative to this node
/// - [`Interaction`](crate::Interaction) to obtain the interaction state of this node
/// Provides the computed size and layout properties of the 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 {
pub struct ComputedNode {
/// 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.
pub(crate) stack_index: u32,
@ -79,7 +60,7 @@ pub struct Node {
pub(crate) padding: BorderRect,
}
impl Node {
impl ComputedNode {
/// The calculated node size as width and height in logical pixels.
///
/// Automatically calculated by [`super::layout::ui_layout_system`].
@ -215,7 +196,7 @@ impl Node {
}
}
impl Node {
impl ComputedNode {
pub const DEFAULT: Self = Self {
stack_index: 0,
calculated_size: Vec2::ZERO,
@ -228,7 +209,7 @@ impl Node {
};
}
impl Default for Node {
impl Default for ComputedNode {
fn default() -> Self {
Self::DEFAULT
}
@ -238,7 +219,7 @@ impl Default for Node {
///
/// Updating the values of `ScrollPosition` will reposition the children of the node by the offset amount.
/// `ScrollPosition` may be updated by the layout system when a layout change makes a previously valid `ScrollPosition` invalid.
/// Changing this does nothing on a `Node` without a `Style` setting at least one `OverflowAxis` to `OverflowAxis::Scroll`.
/// Changing this does nothing on a `Node` without setting at least one `OverflowAxis` to `OverflowAxis::Scroll`.
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component, Default)]
pub struct ScrollPosition {
@ -276,7 +257,9 @@ impl From<&Vec2> for ScrollPosition {
}
}
/// Describes the style of a UI container node
/// The base component for UI entities. It describes UI layout and style properties.
///
/// When defining new types of UI entities, require [`Node`] to make them behave like UI nodes.
///
/// Nodes can be laid out using either Flexbox or CSS Grid Layout.
///
@ -293,15 +276,32 @@ impl From<&Vec2> for ScrollPosition {
/// - [MDN: Basic Concepts of Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout)
/// - [A Complete Guide To CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) by CSS Tricks. This is detailed guide with illustrations and comprehensive written explanation of the different CSS Grid properties and how they work.
/// - [CSS Grid Garden](https://cssgridgarden.com/). An interactive tutorial/game that teaches the essential parts of CSS Grid in a fun engaging way.
///
/// # See also
///
/// - [`RelativeCursorPosition`](crate::RelativeCursorPosition) to obtain the cursor position relative to this node
/// - [`Interaction`](crate::Interaction) to obtain the interaction state of this node
#[derive(Component, Clone, PartialEq, Debug, Reflect)]
#[require(
ComputedNode,
BackgroundColor,
BorderColor,
BorderRadius,
ContentSize,
FocusPolicy,
ScrollPosition,
Transform,
Visibility,
ZIndex
)]
#[reflect(Component, Default, PartialEq, Debug)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct Style {
pub struct Node {
/// Which layout algorithm to use when laying out this node's contents:
/// - [`Display::Flex`]: Use the Flexbox layout algorithm
/// - [`Display::Grid`]: Use the CSS Grid layout algorithm
@ -446,8 +446,8 @@ pub struct Style {
///
/// # Example
/// ```
/// # use bevy_ui::{Style, UiRect, Val};
/// let style = Style {
/// # use bevy_ui::{Node, UiRect, Val};
/// let node = Node {
/// margin: UiRect {
/// left: Val::Percent(10.),
/// right: Val::Percent(10.),
@ -468,8 +468,8 @@ pub struct Style {
///
/// # Example
/// ```
/// # use bevy_ui::{Style, UiRect, Val};
/// let style = Style {
/// # use bevy_ui::{Node, UiRect, Val};
/// let node = Node {
/// padding: UiRect {
/// left: Val::Percent(1.),
/// right: Val::Percent(2.),
@ -574,7 +574,7 @@ pub struct Style {
pub grid_column: GridPlacement,
}
impl Style {
impl Node {
pub const DEFAULT: Self = Self {
display: Display::DEFAULT,
position_type: PositionType::DEFAULT,
@ -617,7 +617,7 @@ impl Style {
};
}
impl Default for Style {
impl Default for Node {
fn default() -> Self {
Self::DEFAULT
}
@ -879,7 +879,7 @@ impl Default for JustifyContent {
/// Defines the layout model used by this node.
///
/// Part of the [`Style`] component.
/// Part of the [`Node`] component.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)]
#[reflect(Default, PartialEq)]
#[cfg_attr(
@ -1976,8 +1976,7 @@ impl Default for BorderColor {
/// # use bevy_color::palettes::basic::{RED, BLUE};
/// fn setup_ui(mut commands: Commands) {
/// commands.spawn((
/// Node::default(),
/// Style {
/// Node {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// ..Default::default()
@ -2192,8 +2191,7 @@ pub struct GlobalZIndex(pub i32);
/// # use bevy_color::palettes::basic::{BLUE};
/// fn setup_ui(mut commands: Commands) {
/// commands.spawn((
/// Node::default(),
/// Style {
/// Node {
/// width: Val::Px(100.),
/// height: Val::Px(100.),
/// border: UiRect::all(Val::Px(2.)),

View file

@ -2,10 +2,10 @@
use crate::{
experimental::{UiChildren, UiRootNodes},
CalculatedClip, Display, OverflowAxis, Style, TargetCamera,
CalculatedClip, Display, Node, OverflowAxis, TargetCamera,
};
use super::Node;
use super::ComputedNode;
use bevy_ecs::{
entity::Entity,
query::{Changed, With},
@ -20,7 +20,12 @@ use bevy_utils::HashSet;
pub fn update_clipping_system(
mut commands: Commands,
root_nodes: UiRootNodes,
mut node_query: Query<(&Node, &GlobalTransform, &Style, Option<&mut CalculatedClip>)>,
mut node_query: Query<(
&Node,
&ComputedNode,
&GlobalTransform,
Option<&mut CalculatedClip>,
)>,
ui_children: UiChildren,
) {
for root_node in root_nodes.iter() {
@ -37,17 +42,23 @@ pub fn update_clipping_system(
fn update_clipping(
commands: &mut Commands,
ui_children: &UiChildren,
node_query: &mut Query<(&Node, &GlobalTransform, &Style, Option<&mut CalculatedClip>)>,
node_query: &mut Query<(
&Node,
&ComputedNode,
&GlobalTransform,
Option<&mut CalculatedClip>,
)>,
entity: Entity,
mut maybe_inherited_clip: Option<Rect>,
) {
let Ok((node, global_transform, style, maybe_calculated_clip)) = node_query.get_mut(entity)
let Ok((node, computed_node, global_transform, maybe_calculated_clip)) =
node_query.get_mut(entity)
else {
return;
};
// If `display` is None, clip the entire node and all its descendants by replacing the inherited clip with a default rect (which is empty)
if style.display == Display::None {
if node.display == Display::None {
maybe_inherited_clip = Some(Rect::default());
}
@ -72,7 +83,7 @@ fn update_clipping(
}
// Calculate new clip rectangle for children nodes
let children_clip = if style.overflow.is_visible() {
let children_clip = if node.overflow.is_visible() {
// When `Visible`, children might be visible even when they are outside
// the current node's boundaries. In this case they inherit the current
// node's parent clip. If an ancestor is set as `Hidden`, that clip will
@ -84,17 +95,19 @@ fn update_clipping(
// of nested `Overflow::Hidden` nodes. If parent `clip` is not
// defined, use the current node's clip.
let mut clip_rect =
Rect::from_center_size(global_transform.translation().truncate(), node.size());
let mut clip_rect = Rect::from_center_size(
global_transform.translation().truncate(),
computed_node.size(),
);
// Content isn't clipped at the edges of the node but at the edges of the region specified by [`Style::overflow_clip_margin`].
// Content isn't clipped at the edges of the node but at the edges of the region specified by [`Node::overflow_clip_margin`].
//
// `clip_inset` should always fit inside `node_rect`.
// Even if `clip_inset` were to overflow, we won't return a degenerate result as `Rect::intersect` will clamp the intersection, leaving it empty.
let clip_inset = match style.overflow_clip_margin.visual_box {
let clip_inset = match node.overflow_clip_margin.visual_box {
crate::OverflowClipBox::BorderBox => BorderRect::ZERO,
crate::OverflowClipBox::ContentBox => node.content_inset(),
crate::OverflowClipBox::PaddingBox => node.border(),
crate::OverflowClipBox::ContentBox => computed_node.content_inset(),
crate::OverflowClipBox::PaddingBox => computed_node.border(),
};
clip_rect.min.x += clip_inset.left;
@ -102,13 +115,13 @@ fn update_clipping(
clip_rect.max.x -= clip_inset.right;
clip_rect.max.y -= clip_inset.bottom;
clip_rect = clip_rect.inflate(style.overflow_clip_margin.margin.max(0.));
clip_rect = clip_rect.inflate(node.overflow_clip_margin.margin.max(0.));
if style.overflow.x == OverflowAxis::Visible {
if node.overflow.x == OverflowAxis::Visible {
clip_rect.min.x = -f32::INFINITY;
clip_rect.max.x = f32::INFINITY;
}
if style.overflow.y == OverflowAxis::Visible {
if node.overflow.y == OverflowAxis::Visible {
clip_rect.min.y = -f32::INFINITY;
clip_rect.max.y = f32::INFINITY;
}

View file

@ -1,6 +1,6 @@
use crate::{
ContentSize, DefaultUiCamera, FixedMeasure, Measure, MeasureArgs, Node, NodeMeasure,
TargetCamera, UiScale,
ComputedNode, ContentSize, DefaultUiCamera, FixedMeasure, Measure, MeasureArgs, Node,
NodeMeasure, TargetCamera, UiScale,
};
use bevy_asset::Assets;
use bevy_color::Color;
@ -102,7 +102,7 @@ pub struct TextBundle {}
/// ```
#[derive(Component, Debug, Default, Clone, Deref, DerefMut, Reflect)]
#[reflect(Component, Default, Debug)]
#[require(TextLayout, TextFont, TextColor, TextNodeFlags, Node)]
#[require(Node, TextLayout, TextFont, TextColor, TextNodeFlags)]
pub struct Text(pub String);
impl Text {
@ -331,7 +331,7 @@ fn queue_text(
scale_factor: f32,
inverse_scale_factor: f32,
block: &TextLayout,
node: Ref<Node>,
node: Ref<ComputedNode>,
mut text_flags: Mut<TextNodeFlags>,
text_layout_info: Mut<TextLayoutInfo>,
computed: &mut ComputedTextBlock,
@ -408,7 +408,7 @@ pub fn text_system(
mut text_pipeline: ResMut<TextPipeline>,
mut text_query: Query<(
Entity,
Ref<Node>,
Ref<ComputedNode>,
&TextLayout,
&mut TextLayoutInfo,
&mut TextNodeFlags,

View file

@ -66,7 +66,7 @@ fn setup(
#[cfg(not(target_arch = "wasm32"))]
commands.spawn((
Text::new("Press space to toggle wireframes"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -59,7 +59,7 @@ fn setup(
// UI
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -254,7 +254,7 @@ fn setup(mut commands: Commands) {
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -135,7 +135,7 @@ fn setup(
// create a minimal UI explaining how to interact with the example
commands.spawn((
Text::new("Left Arrow Key: Animate Left Sprite\nRight Arrow Key: Animate Right Sprite"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -90,7 +90,7 @@ fn setup(
// Text used to show controls
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -135,7 +135,7 @@ fn setup(
#[cfg(not(target_arch = "wasm32"))]
commands.spawn((
Text::new("Press space to toggle wireframes"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -83,7 +83,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_status: Res
fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
commands.spawn((
app_status.create_help_text(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -328,7 +328,7 @@ fn setup(
// example instructions
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -86,7 +86,7 @@ fn setup_terrain_scene(
fn setup_instructions(mut commands: Commands) {
commands.spawn((Text::new("Press Spacebar to Toggle Atmospheric Fog.\nPress S to Toggle Directional Light Fog Influence."),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -119,17 +119,17 @@ fn setup(
texture: metering_mask,
..default()
},
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
));
let text_style = TextFont::default();
let text_font = TextFont::default();
commands.spawn((Text::new("Left / Right - Rotate Camera\nC - Toggle Compensation Curve\nM - Toggle Metering Mask\nV - Visualize Metering Mask"),
text_style.clone(), Style {
text_font.clone(), Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -139,8 +139,8 @@ fn setup(
commands.spawn((
Text::default(),
text_style,
Style {
text_font,
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
right: Val::Px(12.0),
@ -162,7 +162,7 @@ struct ExampleResources {
fn example_control_system(
camera: Single<(&mut Transform, &mut AutoExposure), With<Camera3d>>,
mut display: Single<&mut Text, With<ExampleDisplay>>,
mut mask_image: Single<&mut Style, With<UiImage>>,
mut mask_image: Single<&mut Node, With<UiImage>>,
time: Res<Time>,
input: Res<ButtonInput<KeyCode>>,
resources: Res<ExampleResources>,

View file

@ -169,7 +169,7 @@ fn setup(
commands.spawn((Text::new("Up / Down — Increase / Decrease Alpha\nLeft / Right — Rotate Camera\nH - Toggle HDR\nSpacebar — Toggle Unlit\nC — Randomize Colors"),
text_style.clone(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -180,7 +180,7 @@ fn setup(
commands.spawn((
Text::default(),
text_style,
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
right: Val::Px(12.0),
@ -192,8 +192,7 @@ fn setup(
let mut label = |entity: Entity, label: &str| {
commands
.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
..default()
},
@ -203,7 +202,7 @@ fn setup(
parent.spawn((
Text::new(label),
label_text_style.clone(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::ZERO,
..default()
@ -253,7 +252,7 @@ fn example_control_system(
mut materials: ResMut<Assets<StandardMaterial>>,
controllable: Query<(&MeshMaterial3d<StandardMaterial>, &ExampleControls)>,
camera: Single<(&mut Camera, &mut Transform, &GlobalTransform), With<Camera3d>>,
mut labels: Query<(&mut Style, &ExampleLabel)>,
mut labels: Query<(&mut Node, &ExampleLabel)>,
mut display: Single<&mut Text, With<ExampleDisplay>>,
labelled: Query<&GlobalTransform>,
mut state: Local<ExampleState>,
@ -308,15 +307,15 @@ fn example_control_system(
camera_transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(rotation));
for (mut style, label) in &mut labels {
for (mut node, label) in &mut labels {
let world_position = labelled.get(label.entity).unwrap().translation() + Vec3::Y;
let viewport_position = camera
.world_to_viewport(camera_global_transform, world_position)
.unwrap();
style.top = Val::Px(viewport_position.y);
style.left = Val::Px(viewport_position.x);
node.top = Val::Px(viewport_position.y);
node.left = Val::Px(viewport_position.x);
}
display.0 = format!(

View file

@ -86,7 +86,7 @@ fn setup_scene(
// example instructions
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -219,7 +219,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
fn spawn_text(commands: &mut Commands, light_mode: &LightMode) {
commands.spawn((
light_mode.create_help_text(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -138,17 +138,14 @@ 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((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
left: Val::Px(12.0),
bottom: Val::Px(12.0),
..default()
},
))
.spawn(Node {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
left: Val::Px(12.0),
bottom: Val::Px(12.0),
..default()
})
.with_children(|parent| {
// Create the first row, which contains the global controls.
add_buttons_for_global_controls(parent, color_grading, font);
@ -174,13 +171,10 @@ fn add_buttons_for_global_controls(
// Add the parent node for the row.
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()
},
));
parent.spawn(Node {
width: Val::Px(125.0),
..default()
});
// Add each global color grading option button.
for option in [
@ -209,16 +203,13 @@ fn add_buttons_for_section(
) {
// Spawn the row container.
parent
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
))
.spawn(Node {
align_items: AlignItems::Center,
..default()
})
.with_children(|parent| {
// Spawn the label ("Highlights", etc.)
add_text(parent, &section.to_string(), font, Color::WHITE).insert(Style {
add_text(parent, &section.to_string(), font, Color::WHITE).insert(Node {
width: Val::Px(125.0),
..default()
});
@ -252,7 +243,7 @@ fn add_button_for_value(
parent
.spawn((
Button,
Style {
Node {
border: UiRect::all(Val::Px(1.0)),
width: Val::Px(200.0),
justify_content: JustifyContent::Center,
@ -281,13 +272,10 @@ fn add_button_for_value(
});
// Add a spacer.
parent.spawn((
Node::default(),
Style {
flex_grow: 1.0,
..default()
},
));
parent.spawn(Node {
flex_grow: 1.0,
..default()
});
// Add the value text.
add_text(
@ -315,7 +303,7 @@ fn add_help_text(
font: font.clone(),
..default()
},
Style {
Node {
position_type: PositionType::Absolute,
left: Val::Px(12.0),
top: Val::Px(12.0),

View file

@ -190,7 +190,7 @@ fn setup(
// Example instructions
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -94,7 +94,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_settings: R
// Spawn the help text.
commands.spawn((
create_text(&app_settings),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -118,7 +118,7 @@ fn setup_pyramid_scene(
fn setup_instructions(mut commands: Commands) {
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -59,7 +59,7 @@ fn setup(
// Text to describe the controls.
commands.spawn((
Text::new("Controls:\nSpace: Change UVs\nX/Y/Z: Rotate\nR: Reset orientation"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -290,7 +290,7 @@ fn spawn_fox(commands: &mut Commands, assets: &ExampleAssets) {
fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
commands.spawn((
app_status.create_text(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -211,7 +211,7 @@ fn setup(
commands
.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -39,7 +39,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
font_size: 15.,
..default()
},
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -234,7 +234,7 @@ fn setup_ui(mut commands: Commands) {
commands
.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -53,7 +53,7 @@ fn setup(
commands
.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -298,7 +298,7 @@ fn setup(
commands
.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -65,7 +65,7 @@ fn setup(
font_size: 30.0,
..default()
},
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(20.0),
left: Val::Px(100.0),
@ -79,7 +79,7 @@ fn setup(
font_size: 30.0,
..default()
},
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(130.0),
right: Val::ZERO,
@ -97,7 +97,7 @@ fn setup(
font_size: 30.0,
..default()
},
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(20.0),
right: Val::Px(20.0),

View file

@ -209,7 +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((Node::default(), widgets::main_ui_style()))
.spawn(widgets::main_ui_node())
.with_children(|parent| {
widgets::spawn_option_buttons(
parent,

View file

@ -124,7 +124,7 @@ fn spawn_scene(commands: &mut Commands, asset_server: &AssetServer) {
fn spawn_text(commands: &mut Commands, app_settings: &AppSettings) {
commands.spawn((
create_help_text(app_settings),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -154,7 +154,7 @@ fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
// Create the text.
commands.spawn((
app_status.create_text(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -98,8 +98,7 @@ fn setup(
commands
.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()

View file

@ -85,8 +85,7 @@ fn setup(
commands
.spawn((
TargetCamera(camera),
Node::default(),
Style {
Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
..default()
@ -95,7 +94,7 @@ fn setup(
.with_children(|parent| {
parent.spawn((
Text::new(*camera_name),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),
@ -108,20 +107,17 @@ fn setup(
fn buttons_panel(parent: &mut ChildBuilder) {
parent
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
width: Val::Percent(100.),
height: Val::Percent(100.),
display: Display::Flex,
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Center,
padding: UiRect::all(Val::Px(20.)),
..default()
},
))
.spawn(Node {
position_type: PositionType::Absolute,
width: Val::Percent(100.),
height: Val::Percent(100.),
display: Display::Flex,
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Center,
padding: UiRect::all(Val::Px(20.)),
..default()
})
.with_children(|parent| {
rotate_button(parent, "<", Direction::Left);
rotate_button(parent, ">", Direction::Right);
@ -133,7 +129,7 @@ fn setup(
.spawn((
RotateCamera(direction),
Button,
Style {
Node {
width: Val::Px(40.),
height: Val::Px(40.),
border: UiRect::all(Val::Px(2.)),

View file

@ -128,7 +128,7 @@ fn setup(
commands.spawn((
Text::new(INSTRUCTIONS),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -80,7 +80,7 @@ fn setup(
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -253,7 +253,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
fn spawn_text(commands: &mut Commands, app_settings: &AppSettings) {
commands.spawn((
create_text(app_settings),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -83,7 +83,7 @@ fn setup(
// ui
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -178,7 +178,7 @@ fn setup_image_viewer_scene(
},
TextColor(Color::BLACK),
TextLayout::new_with_justify(JustifyText::Center),
Style {
Node {
align_self: AlignSelf::Center,
margin: UiRect::all(Val::Auto),
..default()

View file

@ -333,7 +333,7 @@ fn setup(
// Controls Text
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -151,7 +151,7 @@ fn setup(
// Create the text.
commands.spawn((
app_status.create_text(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -125,7 +125,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_settings: R
// Add the help text.
commands.spawn((
create_text(&app_settings),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -101,7 +101,7 @@ fn setup(
// Text used to show controls
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -151,9 +151,8 @@ fn setup(
// text to be animated.
commands
.spawn((
Node::default(),
// Cover the whole screen, and center contents.
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(0.0),
left: Val::Px(0.0),
@ -163,9 +162,9 @@ fn setup(
align_items: AlignItems::Center,
..default()
},
animation_player,
AnimationGraphHandle(animation_graph),
))
.insert(animation_player)
.insert(AnimationGraphHandle(animation_graph))
.with_children(|builder| {
// Build the text node.
let player = builder.parent_entity();

View file

@ -252,7 +252,7 @@ fn setup_scene(
fn setup_help_text(commands: &mut Commands) {
commands.spawn((
Text::new(HELP_TEXT),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -283,8 +283,7 @@ fn setup_node_rects(commands: &mut Commands) {
let container = {
let mut container = commands.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(node_rect.bottom),
left: Val::Px(node_rect.left),
@ -315,8 +314,7 @@ fn setup_node_rects(commands: &mut Commands) {
if let NodeType::Clip(_) = node_type {
let background = commands
.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(0.),
left: Val::Px(0.),
@ -342,8 +340,7 @@ fn setup_node_rects(commands: &mut Commands) {
fn setup_node_lines(commands: &mut Commands) {
for line in &HORIZONTAL_LINES {
commands.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(line.bottom),
left: Val::Px(line.left),
@ -358,8 +355,7 @@ fn setup_node_lines(commands: &mut Commands) {
for line in &VERTICAL_LINES {
commands.spawn((
Node::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(line.bottom),
left: Val::Px(line.left),
@ -421,7 +417,7 @@ fn handle_weight_drag(
// Updates the UI based on the weights that the user has chosen.
fn update_ui(
mut text_query: Query<&mut Text>,
mut background_query: Query<&mut Style, Without<Text>>,
mut background_query: Query<&mut Node, Without<Text>>,
container_query: Query<(&Children, &ClipNode)>,
animation_weights_query: Query<&ExampleAnimationWeights, Changed<ExampleAnimationWeights>>,
) {
@ -429,9 +425,9 @@ fn update_ui(
for (children, clip_node) in &container_query {
// Draw the green background color to visually indicate the weight.
let mut bg_iter = background_query.iter_many_mut(children);
if let Some(mut style) = bg_iter.fetch_next() {
if let Some(mut node) = bg_iter.fetch_next() {
// All nodes are the same width, so `NODE_RECTS[0]` is as good as any other.
style.width =
node.width =
Val::Px(NODE_RECTS[0].width * animation_weights.weights[clip_node.index]);
}

View file

@ -158,7 +158,7 @@ fn setup_ui(mut commands: Commands) {
// Add help text.
commands.spawn((
Text::new("Click on a button to toggle animations for its associated bones"),
Style {
Node {
position_type: PositionType::Absolute,
left: Val::Px(12.0),
top: Val::Px(12.0),
@ -168,19 +168,16 @@ fn setup_ui(mut commands: Commands) {
// Add the buttons that allow the user to toggle mask groups on and off.
commands
.spawn((
Node::default(),
Style {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
left: Val::Px(12.0),
bottom: Val::Px(12.0),
..default()
},
))
.spawn(Node {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
left: Val::Px(12.0),
bottom: Val::Px(12.0),
..default()
})
.with_children(|parent| {
let row_style = Style {
let row_node = Node {
flex_direction: FlexDirection::Row,
column_gap: Val::Px(6.0),
..default()
@ -188,39 +185,35 @@ fn setup_ui(mut commands: Commands) {
add_mask_group_control(parent, "Head", Val::Auto, MASK_GROUP_HEAD);
parent
.spawn((Node::default(), row_style.clone()))
.with_children(|parent| {
add_mask_group_control(
parent,
"Left Front Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_LEFT_FRONT_LEG,
);
add_mask_group_control(
parent,
"Right Front Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_RIGHT_FRONT_LEG,
);
});
parent.spawn(row_node.clone()).with_children(|parent| {
add_mask_group_control(
parent,
"Left Front Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_LEFT_FRONT_LEG,
);
add_mask_group_control(
parent,
"Right Front Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_RIGHT_FRONT_LEG,
);
});
parent
.spawn((Node::default(), row_style))
.with_children(|parent| {
add_mask_group_control(
parent,
"Left Hind Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_LEFT_HIND_LEG,
);
add_mask_group_control(
parent,
"Right Hind Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_RIGHT_HIND_LEG,
);
});
parent.spawn(row_node).with_children(|parent| {
add_mask_group_control(
parent,
"Left Hind Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_LEFT_HIND_LEG,
);
add_mask_group_control(
parent,
"Right Hind Leg",
Val::Px(MASK_GROUP_BUTTON_WIDTH),
MASK_GROUP_RIGHT_HIND_LEG,
);
});
add_mask_group_control(parent, "Tail", Val::Auto, MASK_GROUP_TAIL);
});
@ -246,8 +239,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
parent
.spawn((
Node::default(),
Style {
Node {
border: UiRect::all(Val::Px(1.0)),
width,
flex_direction: FlexDirection::Column,
@ -264,8 +256,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
.with_children(|builder| {
builder
.spawn((
Node::default(),
Style {
Node {
border: UiRect::ZERO,
width: Val::Percent(100.0),
justify_content: JustifyContent::Center,
@ -279,7 +270,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
.with_child((
Text::new(label),
label_text_style.clone(),
Style {
Node {
margin: UiRect::vertical(Val::Px(3.0)),
..default()
},
@ -287,8 +278,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
builder
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::Center,
@ -316,7 +306,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
} else {
Color::WHITE
}),
Style {
Node {
flex_grow: 1.0,
border: if index > 0 {
UiRect::left(Val::Px(1.0))
@ -335,7 +325,7 @@ fn add_mask_group_control(parent: &mut ChildBuilder, label: &str, width: Val, ma
selected_button_text_style.clone()
},
TextLayout::new_with_justify(JustifyText::Center),
Style {
Node {
flex_grow: 1.0,
margin: UiRect::vertical(Val::Px(3.0)),
..default()

View file

@ -88,7 +88,7 @@ fn setup(mut commands: Commands) {
}
commands.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -126,8 +126,7 @@ fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Node::default(),
Style {
Node {
width: Val::Vw(100.0),
height: Val::Vh(100.0),
flex_direction: FlexDirection::Column,

View file

@ -21,7 +21,7 @@ fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn((
Text::new("Press P to panic"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -138,7 +138,7 @@ fn spawn_text(mut commands: Commands) {
"Space: swap meshes by mutating a Handle<Mesh>\n\
Return: mutate the mesh itself, changing all copies of it",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -96,7 +96,7 @@ fn spawn_text(mut commands: Commands) {
"Space: swap the right sprite's image handle\n\
Return: modify the image Asset of the left sprite, affecting all uses of it",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -172,7 +172,7 @@ fn setup_ui(mut commands: Commands) {
commands.spawn((
LoadingText,
Text::new("Loading...".to_owned()),
Style {
Node {
position_type: PositionType::Absolute,
left: Val::Px(12.0),
top: Val::Px(12.0),

View file

@ -66,7 +66,7 @@ fn setup(
// example instructions
commands.spawn((
Text::new("Up/Down/Left/Right: Move Listener\nSpace: Toggle Emitter Movement"),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -65,7 +65,7 @@ fn setup(
// example instructions
commands.spawn((
Text::new("Up/Down/Left/Right: Move Listener\nSpace: Toggle Emitter Movement"),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -65,7 +65,7 @@ fn setup_scene(
fn setup_instructions(mut commands: Commands) {
commands.spawn((
Text::new("Hold space to trigger a screen shake"),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -51,7 +51,7 @@ fn setup_scene(
fn setup_instructions(mut commands: Commands) {
commands.spawn((
Text::new("Move the light with WASD.\nThe camera will smoothly track the light."),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -87,7 +87,7 @@ fn instructions(mut commands: Commands) {
Mouse left or right: yaw\n\
Mouse buttons: roll",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -192,15 +192,12 @@ fn spawn_lights(mut commands: Commands) {
fn spawn_text(mut commands: Commands) {
commands
.spawn((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
))
.spawn(Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..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

@ -99,7 +99,7 @@ fn instructions(mut commands: Commands) {
"Scroll mouse wheel to zoom in/out\n\
Space: switch between orthographic and perspective projections",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -51,7 +51,7 @@ fn setup(mut commands: Commands) {
"Press 3 to increase the overlay size.\n",
"Press 4 to toggle the overlay visibility."
)),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.),
left: Val::Px(12.),

View file

@ -76,7 +76,7 @@ fn setup(mut commands: Commands) {
"Click on a \"Mine\" to trigger it.\n\
When it explodes it will trigger all overlapping mines.",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -95,7 +95,7 @@ fn setup_ui(mut commands: Commands) {
.spawn((
Text::default(),
TextLayout::new_with_justify(JustifyText::Center),
Style {
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()

View file

@ -182,7 +182,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
..default()
},
TextColor(Color::srgb(0.5, 0.5, 1.0)),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
left: Val::Px(5.0),
@ -393,15 +393,12 @@ fn gameover_keyboard(
// display the number of cake eaten before losing
fn display_score(mut commands: Commands, game: Res<Game>) {
commands
.spawn((
Node::default(),
Style {
width: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
))
.spawn(Node {
width: Val::Percent(100.),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
})
.with_child((
Text::new(format!("Cake eaten: {}", game.cake_eaten)),
TextFont {

View file

@ -225,7 +225,7 @@ fn setup(
},
TextColor(TEXT_COLOR),
ScoreboardUi,
Style {
Node {
position_type: PositionType::Absolute,
top: SCOREBOARD_TEXT_PADDING,
left: SCOREBOARD_TEXT_PADDING,

View file

@ -148,7 +148,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
Text::new("Contributor showcase"),
text_style.clone(),
ContributorDisplay,
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -75,8 +75,7 @@ mod splash {
// Display the logo
commands
.spawn((
Node::default(),
Style {
Node {
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
width: Val::Percent(100.0),
@ -88,7 +87,7 @@ mod splash {
.with_children(|parent| {
parent.spawn((
UiImage::new(icon),
Style {
Node {
// This will set the logo to be 200px wide, and auto adjust its height
width: Val::Px(200.0),
..default()
@ -141,8 +140,7 @@ mod game {
) {
commands
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
// center children
@ -153,11 +151,10 @@ mod game {
OnGameScreen,
))
.with_children(|parent| {
// First create a `Node` and `Style` for centering what we want to display
// First create a `Node` for centering what we want to display
parent
.spawn((
Node::default(),
Style {
Node {
// 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
@ -176,14 +173,14 @@ mod game {
..default()
},
TextColor(TEXT_COLOR),
Style {
Node {
margin: UiRect::all(Val::Px(50.0)),
..default()
},
));
p.spawn((
Text::default(),
Style {
Node {
margin: UiRect::all(Val::Px(50.0)),
..default()
},
@ -377,7 +374,7 @@ mod menu {
fn main_menu_setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Common style for all buttons on the screen
let button_style = Style {
let button_node = Node {
width: Val::Px(300.0),
height: Val::Px(65.0),
margin: UiRect::all(Val::Px(20.0)),
@ -385,7 +382,7 @@ mod menu {
align_items: AlignItems::Center,
..default()
};
let button_icon_style = Style {
let button_icon_node = Node {
width: Val::Px(30.0),
// This takes the icons out of the flexbox flow, to be positioned exactly
position_type: PositionType::Absolute,
@ -400,8 +397,7 @@ mod menu {
commands
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
@ -413,8 +409,7 @@ mod menu {
.with_children(|parent| {
parent
.spawn((
Node::default(),
Style {
Node {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
@ -430,7 +425,7 @@ mod menu {
..default()
},
TextColor(TEXT_COLOR),
Style {
Node {
margin: UiRect::all(Val::Px(50.0)),
..default()
},
@ -443,13 +438,13 @@ mod menu {
parent
.spawn((
Button,
button_style.clone(),
button_node.clone(),
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Play,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/right.png");
parent.spawn((UiImage::new(icon), button_icon_style.clone()));
parent.spawn((UiImage::new(icon), button_icon_node.clone()));
parent.spawn((
Text::new("New Game"),
button_text_font.clone(),
@ -459,13 +454,13 @@ mod menu {
parent
.spawn((
Button,
button_style.clone(),
button_node.clone(),
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Settings,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/wrench.png");
parent.spawn((UiImage::new(icon), button_icon_style.clone()));
parent.spawn((UiImage::new(icon), button_icon_node.clone()));
parent.spawn((
Text::new("Settings"),
button_text_font.clone(),
@ -475,13 +470,13 @@ mod menu {
parent
.spawn((
Button,
button_style,
button_node,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::Quit,
))
.with_children(|parent| {
let icon = asset_server.load("textures/Game Icons/exitRight.png");
parent.spawn((UiImage::new(icon), button_icon_style));
parent.spawn((UiImage::new(icon), button_icon_node));
parent.spawn((
Text::new("Quit"),
button_text_font,
@ -493,7 +488,7 @@ mod menu {
}
fn settings_menu_setup(mut commands: Commands) {
let button_style = Style {
let button_node = Node {
width: Val::Px(200.0),
height: Val::Px(65.0),
margin: UiRect::all(Val::Px(20.0)),
@ -512,8 +507,7 @@ mod menu {
commands
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
@ -525,8 +519,7 @@ mod menu {
.with_children(|parent| {
parent
.spawn((
Node::default(),
Style {
Node {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
@ -542,7 +535,7 @@ mod menu {
parent
.spawn((
Button,
button_style.clone(),
button_node.clone(),
BackgroundColor(NORMAL_BUTTON),
action,
))
@ -555,7 +548,7 @@ mod menu {
}
fn display_settings_menu_setup(mut commands: Commands, display_quality: Res<DisplayQuality>) {
let button_style = Style {
let button_node = Node {
width: Val::Px(200.0),
height: Val::Px(65.0),
margin: UiRect::all(Val::Px(20.0)),
@ -573,8 +566,7 @@ mod menu {
commands
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
@ -586,8 +578,7 @@ mod menu {
.with_children(|parent| {
parent
.spawn((
Node::default(),
Style {
Node {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
@ -595,12 +586,11 @@ mod menu {
BackgroundColor(CRIMSON.into()),
))
.with_children(|parent| {
// Create a new `Node` and `Style` , this time not setting its `flex_direction`. It will
// Create a new `Node`, this time not setting its `flex_direction`. It will
// use the default value, `FlexDirection::Row`, from left to right.
parent
.spawn((
Node::default(),
Style {
Node {
align_items: AlignItems::Center,
..default()
},
@ -620,10 +610,10 @@ mod menu {
] {
let mut entity = parent.spawn((
Button,
Style {
Node {
width: Val::Px(150.0),
height: Val::Px(65.0),
..button_style.clone()
..button_node.clone()
},
BackgroundColor(NORMAL_BUTTON),
quality_setting,
@ -643,7 +633,7 @@ mod menu {
parent
.spawn((
Button,
button_style,
button_node,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::BackToSettings,
))
@ -655,7 +645,7 @@ mod menu {
}
fn sound_settings_menu_setup(mut commands: Commands, volume: Res<Volume>) {
let button_style = Style {
let button_node = Node {
width: Val::Px(200.0),
height: Val::Px(65.0),
margin: UiRect::all(Val::Px(20.0)),
@ -673,8 +663,7 @@ mod menu {
commands
.spawn((
Node::default(),
Style {
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
@ -686,8 +675,7 @@ mod menu {
.with_children(|parent| {
parent
.spawn((
Node::default(),
Style {
Node {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..default()
@ -697,8 +685,7 @@ mod menu {
.with_children(|parent| {
parent
.spawn((
Node::default(),
Style {
Node {
align_items: AlignItems::Center,
..default()
},
@ -709,10 +696,10 @@ mod menu {
for volume_setting in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] {
let mut entity = parent.spawn((
Button,
Style {
Node {
width: Val::Px(30.0),
height: Val::Px(65.0),
..button_style.clone()
..button_node.clone()
},
BackgroundColor(NORMAL_BUTTON),
Volume(volume_setting),
@ -725,7 +712,7 @@ mod menu {
parent
.spawn((
Button,
button_style,
button_node,
BackgroundColor(NORMAL_BUTTON),
MenuButtonAction::BackToSettings,
))

View file

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

View file

@ -165,7 +165,7 @@ fn build_ui(
.spawn((
Text::default(),
SteppingUi,
Style {
Node {
position_type: PositionType::Absolute,
top: state.ui_top,
left: state.ui_left,
@ -197,7 +197,7 @@ fn build_stepping_hint(mut commands: Commands) {
..default()
},
TextColor(FONT_COLOR),
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(5.0),
left: Val::Px(5.0),

View file

@ -28,7 +28,7 @@ fn setup(mut commands: Commands) {
Press 'U' / 'I' to cycle through line styles\n\
Press 'J' / 'K' to cycle through line joins",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),

View file

@ -62,7 +62,7 @@ fn setup(
Press 'U' or 'I' to cycle through line styles for straight or round gizmos\n\
Press 'J' or 'K' to cycle through line joins for straight or round gizmos",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -109,7 +109,7 @@ fn setup(
Press 'A' to toggle drawing of the light gizmos\n\
Press 'C' to cycle between the light gizmos coloring modes",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
@ -125,7 +125,7 @@ fn setup(
.spawn((
Text::new("Gizmo color mode: "),
GizmoColorText,
Style {
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -22,11 +22,11 @@ pub struct RadioButton;
#[derive(Clone, Copy, Component)]
pub struct RadioButtonText;
/// Returns a [`Style`] appropriate for the outer main UI node.
/// Returns a [`Node`] appropriate for the outer main UI node.
///
/// This UI is in the bottom left corner and has flex column support
pub fn main_ui_style() -> Style {
Style {
pub fn main_ui_node() -> Node {
Node {
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
row_gap: Val::Px(6.0),
@ -60,7 +60,7 @@ pub fn spawn_option_button<T>(
parent
.spawn((
Button,
Style {
Node {
border: UiRect::all(Val::Px(1.0)).with_left(if is_first {
Val::Px(1.0)
} else {
@ -97,15 +97,12 @@ where
{
// Add the parent node for the row.
parent
.spawn((
Node::default(),
Style {
align_items: AlignItems::Center,
..default()
},
))
.spawn(Node {
align_items: AlignItems::Center,
..default()
})
.with_children(|parent| {
spawn_ui_text(parent, title, Color::BLACK).insert(Style {
spawn_ui_text(parent, title, Color::BLACK).insert(Node {
width: Val::Px(125.0),
..default()
});

View file

@ -37,7 +37,7 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn((
Text::default(),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

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

View file

@ -157,14 +157,16 @@ fn setup(
));
// Example instructions
commands.spawn((Text::new("Press 'B' to toggle between no bounding shapes, bounding boxes (AABBs) and bounding spheres / circles\n\
commands.spawn((
Text::new("Press 'B' to toggle between no bounding shapes, bounding boxes (AABBs) and bounding spheres / circles\n\
Press 'Space' to switch between 3D and 2D"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
}));
},
));
}
// Rotate the 2D shapes.

View file

@ -118,7 +118,7 @@ fn setup(
D: Add 100 random samples.\n\
Rotate camera by holding left mouse and panning left/right.",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -370,8 +370,7 @@ fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
commands
.spawn((
HeaderNode,
Node::default(),
Style {
Node {
justify_self: JustifySelf::Center,
top: Val::Px(5.0),
..Default::default()

View file

@ -388,7 +388,7 @@ fn setup(
Move camera by L/R arrow keys.\n\
Tab: Toggle this text",
),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -116,7 +116,7 @@ fn setup_scene(
commands
.spawn((
Button,
Style {
Node {
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
position_type: PositionType::Absolute,

View file

@ -145,15 +145,12 @@ 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((
Node::default(),
Style {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
))
.spawn(Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
})
.with_child((
Text::new("Move the player with WASD"),
TextFont {

View file

@ -149,7 +149,7 @@ fn setup(
// Instructions
commands.spawn((
Text::new("Hover over the shapes to pick them"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),

View file

@ -20,7 +20,7 @@ fn setup(
commands
.spawn((
Text::new("Click Me to get a box"),
Style {
Node {
position_type: PositionType::Absolute,
top: Val::Percent(12.0),
left: Val::Percent(12.0),

View file

@ -152,7 +152,7 @@ fn infotext_system(mut commands: Commands) {
font_size: 42.0,
..default()
},
Style {
Node {
align_self: AlignSelf::FlexEnd,
..default()
},

Some files were not shown because too many files have changed in this diff Show more