mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 12:13:25 +00:00
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:
parent
624f573443
commit
015f2c69ca
149 changed files with 1258 additions and 1616 deletions
|
@ -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()
|
||||
|
|
|
@ -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>,
|
||||
),
|
||||
|
|
|
@ -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);
|
||||
/// }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -365,7 +365,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
|
|||
uinode_query: Extract<
|
||||
Query<(
|
||||
Entity,
|
||||
&Node,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&MaterialNode<M>,
|
||||
&ViewVisibility,
|
||||
|
|
|
@ -251,7 +251,7 @@ pub fn extract_ui_texture_slices(
|
|||
slicers_query: Extract<
|
||||
Query<(
|
||||
Entity,
|
||||
&Node,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
/// },
|
||||
|
|
|
@ -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.)),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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, §ion.to_string(), font, Color::WHITE).insert(Style {
|
||||
add_text(parent, §ion.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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -98,8 +98,7 @@ fn setup(
|
|||
|
||||
commands
|
||||
.spawn((
|
||||
Node::default(),
|
||||
Style {
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
..default()
|
||||
|
|
|
@ -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.)),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -225,7 +225,7 @@ fn setup(
|
|||
},
|
||||
TextColor(TEXT_COLOR),
|
||||
ScoreboardUi,
|
||||
Style {
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
top: SCOREBOARD_TEXT_PADDING,
|
||||
left: SCOREBOARD_TEXT_PADDING,
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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,
|
||||
))
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
});
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -116,7 +116,7 @@ fn setup_scene(
|
|||
commands
|
||||
.spawn((
|
||||
Button,
|
||||
Style {
|
||||
Node {
|
||||
justify_content: JustifyContent::Center,
|
||||
align_items: AlignItems::Center,
|
||||
position_type: PositionType::Absolute,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue