Skip to content

Commit 547411d

Browse files
committed
starting to seperate out style elements from ui::Node
1 parent 3eb5cfc commit 547411d

File tree

7 files changed

+141
-38
lines changed

7 files changed

+141
-38
lines changed

crates/bevy_ui/src/layout/convert.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
AlignContent, AlignItems, AlignSelf, BoxSizing, Display, FlexDirection, FlexWrap, GridAutoFlow,
55
GridPlacement, GridTrack, GridTrackRepetition, JustifyContent, JustifyItems, JustifySelf,
66
MaxTrackSizingFunction, MinTrackSizingFunction, Node, OverflowAxis, PositionType,
7-
RepeatedGridTrack, UiRect, Val,
7+
RepeatedGridTrack, StyleQueryItem, UiRect, Val,
88
};
99

1010
use super::LayoutContext;
@@ -63,7 +63,12 @@ impl UiRect {
6363
}
6464
}
6565

66-
pub fn from_node(node: &Node, context: &LayoutContext, ignore_border: bool) -> taffy::style::Style {
66+
pub fn from_node(
67+
node: &Node,
68+
style: StyleQueryItem<'_, '_>,
69+
context: &LayoutContext,
70+
ignore_border: bool,
71+
) -> taffy::style::Style {
6772
taffy::style::Style {
6873
display: node.display.into(),
6974
box_sizing: node.box_sizing.into(),
@@ -118,7 +123,7 @@ pub fn from_node(node: &Node, context: &LayoutContext, ignore_border: bool) -> t
118123
width: node.max_width.into_dimension(context),
119124
height: node.max_height.into_dimension(context),
120125
},
121-
aspect_ratio: node.aspect_ratio,
126+
aspect_ratio: style.aspect_ratio.0,
122127
gap: taffy::Size {
123128
width: node.column_gap.into_length_percentage(context),
124129
height: node.row_gap.into_length_percentage(context),
@@ -500,7 +505,6 @@ mod tests {
500505
min_height: Val::ZERO,
501506
max_width: Val::Auto,
502507
max_height: Val::ZERO,
503-
aspect_ratio: None,
504508
overflow: crate::Overflow::clip(),
505509
overflow_clip_margin: crate::OverflowClipMargin::default(),
506510
scrollbar_width: 7.,
@@ -527,7 +531,8 @@ mod tests {
527531
grid_row: GridPlacement::span(3),
528532
};
529533
let viewport_values = LayoutContext::new(1.0, Vec2::new(800., 600.));
530-
let taffy_style = from_node(&node, &viewport_values, false);
534+
let style = StyleQueryItem::default();
535+
let taffy_style = from_node(&node, style, &viewport_values, false);
531536
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
532537
assert_eq!(taffy_style.box_sizing, taffy::style::BoxSizing::ContentBox);
533538
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);

crates/bevy_ui/src/layout/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
experimental::{UiChildren, UiRootNodes},
33
ui_transform::{UiGlobalTransform, UiTransform},
44
BorderRadius, ComputedNode, ComputedUiRenderTargetInfo, ContentSize, Display, LayoutConfig,
5-
Node, Outline, OverflowAxis, ScrollPosition,
5+
Node, Outline, OverflowAxis, ScrollPosition, StyleQuery,
66
};
77
use bevy_ecs::{
88
change_detection::{DetectChanges, DetectChangesMut},
@@ -77,6 +77,7 @@ pub fn ui_layout_system(
7777
mut node_query: Query<(
7878
Entity,
7979
Ref<Node>,
80+
StyleQuery,
8081
Option<&mut ContentSize>,
8182
Ref<ComputedUiRenderTargetInfo>,
8283
)>,
@@ -105,7 +106,7 @@ pub fn ui_layout_system(
105106
// Sync Node and ContentSize to Taffy for all nodes
106107
node_query
107108
.iter_mut()
108-
.for_each(|(entity, node, content_size, computed_target)| {
109+
.for_each(|(entity, node, style, content_size, computed_target)| {
109110
if computed_target.is_changed()
110111
|| node.is_changed()
111112
|| content_size
@@ -117,7 +118,7 @@ pub fn ui_layout_system(
117118
computed_target.physical_size.as_vec2(),
118119
);
119120
let measure = content_size.and_then(|mut c| c.measure.take());
120-
ui_surface.upsert_node(&layout_context, entity, &node, measure);
121+
ui_surface.upsert_node(&layout_context, entity, &node, style, measure);
121122
}
122123
});
123124

@@ -162,7 +163,7 @@ pub fn ui_layout_system(
162163
ui_root_entity,
163164
);
164165

165-
let (_, _, _, computed_target) = node_query.get(ui_root_entity).unwrap();
166+
let (_, _, _, _, computed_target) = node_query.get(ui_root_entity).unwrap();
166167

167168
ui_surface.compute_layout(
168169
ui_root_entity,
@@ -1130,6 +1131,7 @@ mod tests {
11301131
&LayoutContext::TEST_CONTEXT,
11311132
params.root_node_entity,
11321133
&Node::default(),
1134+
StyleQueryItem::default(),
11331135
None,
11341136
);
11351137

crates/bevy_ui/src/layout/ui_surface.rs

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use bevy_ecs::{
1010
use bevy_math::{UVec2, Vec2};
1111
use bevy_utils::default;
1212

13-
use crate::{layout::convert, LayoutContext, LayoutError, Measure, MeasureArgs, Node, NodeMeasure};
13+
use crate::{
14+
layout::convert, LayoutContext, LayoutError, Measure, MeasureArgs, Node, NodeMeasure,
15+
StyleQueryItem,
16+
};
1417
use bevy_text::CosmicFontSystem;
1518

1619
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -74,6 +77,7 @@ impl UiSurface {
7477
layout_context: &LayoutContext,
7578
entity: Entity,
7679
node: &Node,
80+
style: StyleQueryItem<'_, '_>,
7781
mut new_node_context: Option<NodeMeasure>,
7882
) {
7983
let taffy = &mut self.taffy;
@@ -93,18 +97,18 @@ impl UiSurface {
9397
taffy
9498
.set_style(
9599
taffy_node.id,
96-
convert::from_node(node, layout_context, has_measure),
100+
convert::from_node(node, style, layout_context, has_measure),
97101
)
98102
.unwrap();
99103
}
100104
Entry::Vacant(entry) => {
101105
let taffy_node = if let Some(measure) = new_node_context.take() {
102106
taffy.new_leaf_with_context(
103-
convert::from_node(node, layout_context, true),
107+
convert::from_node(node, style, layout_context, true),
104108
measure,
105109
)
106110
} else {
107-
taffy.new_leaf(convert::from_node(node, layout_context, false))
111+
taffy.new_leaf(convert::from_node(node, style, layout_context, false))
108112
};
109113
entry.insert(taffy_node.unwrap().into());
110114
}
@@ -320,16 +324,29 @@ mod tests {
320324
let mut ui_surface = UiSurface::default();
321325
let root_node_entity = Entity::from_raw_u32(1).unwrap();
322326
let node = Node::default();
327+
let style = StyleQueryItem::default();
323328

324329
// standard upsert
325-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
330+
ui_surface.upsert_node(
331+
&LayoutContext::TEST_CONTEXT,
332+
root_node_entity,
333+
&node,
334+
style,
335+
None,
336+
);
326337

327338
// should be inserted into taffy
328339
assert_eq!(ui_surface.taffy.total_node_count(), 1);
329340
assert!(ui_surface.entity_to_taffy.contains_key(&root_node_entity));
330341

331342
// test duplicate insert 1
332-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
343+
ui_surface.upsert_node(
344+
&LayoutContext::TEST_CONTEXT,
345+
root_node_entity,
346+
&node,
347+
style,
348+
None,
349+
);
333350

334351
// node count should not have increased
335352
assert_eq!(ui_surface.taffy.total_node_count(), 1);
@@ -341,7 +358,13 @@ mod tests {
341358
assert_eq!(ui_surface.taffy.total_node_count(), 2);
342359

343360
// test duplicate insert 2
344-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
361+
ui_surface.upsert_node(
362+
&LayoutContext::TEST_CONTEXT,
363+
root_node_entity,
364+
&node,
365+
style,
366+
None,
367+
);
345368

346369
// node count should not have increased
347370
assert_eq!(ui_surface.taffy.total_node_count(), 2);
@@ -352,8 +375,15 @@ mod tests {
352375
let mut ui_surface = UiSurface::default();
353376
let root_node_entity = Entity::from_raw_u32(1).unwrap();
354377
let node = Node::default();
355-
356-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
378+
let style = StyleQueryItem::default();
379+
380+
ui_surface.upsert_node(
381+
&LayoutContext::TEST_CONTEXT,
382+
root_node_entity,
383+
&node,
384+
style,
385+
None,
386+
);
357387

358388
ui_surface.get_or_insert_taffy_viewport_node(root_node_entity);
359389

@@ -368,8 +398,15 @@ mod tests {
368398
let mut ui_surface = UiSurface::default();
369399
let root_node_entity = Entity::from_raw_u32(1).unwrap();
370400
let node = Node::default();
371-
372-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
401+
let style = StyleQueryItem::default();
402+
403+
ui_surface.upsert_node(
404+
&LayoutContext::TEST_CONTEXT,
405+
root_node_entity,
406+
&node,
407+
style,
408+
None,
409+
);
373410
let mut content_size = ContentSize::default();
374411
content_size.set(NodeMeasure::Fixed(FixedMeasure { size: Vec2::ONE }));
375412
let measure_func = content_size.measure.take().unwrap();
@@ -384,9 +421,22 @@ mod tests {
384421
let root_node_entity = Entity::from_raw_u32(1).unwrap();
385422
let child_entity = Entity::from_raw_u32(2).unwrap();
386423
let node = Node::default();
387-
388-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
389-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &node, None);
424+
let style = StyleQueryItem::default();
425+
426+
ui_surface.upsert_node(
427+
&LayoutContext::TEST_CONTEXT,
428+
root_node_entity,
429+
&node,
430+
style,
431+
None,
432+
);
433+
ui_surface.upsert_node(
434+
&LayoutContext::TEST_CONTEXT,
435+
child_entity,
436+
&node,
437+
style,
438+
None,
439+
);
390440

391441
ui_surface.update_children(root_node_entity, vec![child_entity].into_iter());
392442

@@ -405,9 +455,22 @@ mod tests {
405455
let root_node_entity = Entity::from_raw_u32(1).unwrap();
406456
let child_entity = Entity::from_raw_u32(2).unwrap();
407457
let node = Node::default();
408-
409-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, root_node_entity, &node, None);
410-
ui_surface.upsert_node(&LayoutContext::TEST_CONTEXT, child_entity, &node, None);
458+
let style = StyleQueryItem::default();
459+
460+
ui_surface.upsert_node(
461+
&LayoutContext::TEST_CONTEXT,
462+
root_node_entity,
463+
&node,
464+
style,
465+
None,
466+
);
467+
ui_surface.upsert_node(
468+
&LayoutContext::TEST_CONTEXT,
469+
child_entity,
470+
&node,
471+
style,
472+
None,
473+
);
411474

412475
let root_taffy_node = *ui_surface.entity_to_taffy.get(&root_node_entity).unwrap();
413476
let child_taffy = *ui_surface.entity_to_taffy.get(&child_entity).unwrap();

crates/bevy_ui/src/ui_node.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
use bevy_camera::{visibility::Visibility, Camera, RenderTarget};
66
use bevy_color::{Alpha, Color};
77
use bevy_derive::{Deref, DerefMut};
8-
use bevy_ecs::{prelude::*, system::SystemParam};
8+
use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam};
99
use bevy_math::{vec4, Rect, UVec2, Vec2, Vec4Swizzles};
1010
use bevy_reflect::prelude::*;
1111
use bevy_sprite::BorderRect;
@@ -351,6 +351,44 @@ impl From<Vec2> for ScrollPosition {
351351
Self(value)
352352
}
353353
}
354+
/// The aspect ratio of the node (defined as `width / height`)
355+
///
356+
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio>
357+
#[derive(
358+
Component, Debug, Clone, Copy, Default, Deref, DerefMut, Reflect, PartialEq, PartialOrd,
359+
)]
360+
#[reflect(Component, Default, Clone)]
361+
pub struct AspectRatio(pub Option<f32>);
362+
363+
impl AspectRatio {
364+
pub const DEFAULT: Self = Self(None);
365+
}
366+
367+
impl From<Option<f32>> for AspectRatio {
368+
fn from(value: Option<f32>) -> Self {
369+
Self(value)
370+
}
371+
}
372+
373+
#[derive(QueryData, Clone, Copy)]
374+
#[query_data(derive(Clone, Copy))]
375+
pub struct StyleQuery {
376+
pub aspect_ratio: &'static AspectRatio,
377+
}
378+
impl Default for StyleQueryItem<'_, '_> {
379+
fn default() -> Self {
380+
Self {
381+
aspect_ratio: &AspectRatio::DEFAULT,
382+
}
383+
}
384+
}
385+
impl Default for StyleQuery {
386+
fn default() -> Self {
387+
Self {
388+
aspect_ratio: &AspectRatio::DEFAULT,
389+
}
390+
}
391+
}
354392

355393
/// The base component for UI entities. It describes UI layout and style properties.
356394
///
@@ -389,6 +427,7 @@ impl From<Vec2> for ScrollPosition {
389427
FocusPolicy,
390428
ScrollPosition,
391429
Visibility,
430+
AspectRatio,
392431
ZIndex
393432
)]
394433
#[reflect(Component, Default, PartialEq, Debug, Clone)]
@@ -493,11 +532,6 @@ pub struct Node {
493532
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/max-height>
494533
pub max_height: Val,
495534

496-
/// The aspect ratio of the node (defined as `width / height`)
497-
///
498-
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio>
499-
pub aspect_ratio: Option<f32>,
500-
501535
/// Used to control how each individual item is aligned by default within the space they're given.
502536
/// - For Flexbox containers, sets default cross axis alignment of the child items.
503537
/// - For CSS Grid containers, controls block (vertical) axis alignment of children of this grid container within their grid areas.
@@ -711,7 +745,6 @@ impl Node {
711745
min_height: Val::Auto,
712746
max_width: Val::Auto,
713747
max_height: Val::Auto,
714-
aspect_ratio: None,
715748
overflow: Overflow::DEFAULT,
716749
overflow_clip_margin: OverflowClipMargin::DEFAULT,
717750
scrollbar_width: 0.,

examples/testbed/ui.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,14 @@ mod grid {
248248
(
249249
Node {
250250
height: percent(100),
251-
aspect_ratio: Some(1.0),
252251
display: Display::Grid,
253252
grid_template_columns: RepeatedGridTrack::flex(3, 1.0),
254253
grid_template_rows: RepeatedGridTrack::flex(2, 1.0),
255254
row_gap: px(12),
256255
column_gap: px(12),
257256
..default()
258257
},
258+
AspectRatio(Some(1.0)),
259259
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
260260
children![
261261
(Node::default(), BackgroundColor(ORANGE.into())),

0 commit comments

Comments
 (0)