Skip to content

Commit 489c1e1

Browse files
ickshonpealice-i-cecile
authored andcommitted
Resolve UI outlines using the correct target's viewport size (#14947)
`resolve_outlines_system` wasn't updated when multi-window support was added and it always uses the size of the primary window when resolving viewport coords, regardless of the layout's camera target. Fixes #14945 It's awkward to get the viewport size of the target for an individual node without walking the tree or adding extra fields to `Node`, so I removed `resolve_outlines_system` and instead the outline values are updated in `ui_layout_system`. --------- Co-authored-by: Alice Cecile <[email protected]>
1 parent a4ea708 commit 489c1e1

File tree

4 files changed

+32
-49
lines changed

4 files changed

+32
-49
lines changed

crates/bevy_ui/src/accessibility.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ impl Plugin for AccessibilityPlugin {
154154
.after(bevy_transform::TransformSystem::TransformPropagate)
155155
.after(CameraUpdateSystem)
156156
// the listed systems do not affect calculated size
157-
.ambiguous_with(crate::resolve_outlines_system)
158157
.ambiguous_with(crate::ui_stack_system),
159158
button_changed,
160159
image_changed,

crates/bevy_ui/src/layout/mod.rs

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub fn ui_layout_system(
9393
children_query: Query<(Entity, Ref<Children>), With<Node>>,
9494
just_children_query: Query<&Children>,
9595
mut removed_components: UiLayoutSystemRemovedComponentParam,
96-
mut node_transform_query: Query<(&mut Node, &mut Transform)>,
96+
mut node_transform_query: Query<(&mut Node, &mut Transform, Option<&Outline>)>,
9797
) {
9898
struct CameraLayoutInfo {
9999
size: UVec2,
@@ -232,6 +232,7 @@ pub fn ui_layout_system(
232232
update_uinode_geometry_recursive(
233233
*root,
234234
&ui_surface,
235+
None,
235236
&mut node_transform_query,
236237
&just_children_query,
237238
inverse_target_scale_factor,
@@ -244,13 +245,14 @@ pub fn ui_layout_system(
244245
fn update_uinode_geometry_recursive(
245246
entity: Entity,
246247
ui_surface: &UiSurface,
247-
node_transform_query: &mut Query<(&mut Node, &mut Transform)>,
248+
root_size: Option<Vec2>,
249+
node_transform_query: &mut Query<(&mut Node, &mut Transform, Option<&Outline>)>,
248250
children_query: &Query<&Children>,
249251
inverse_target_scale_factor: f32,
250252
parent_size: Vec2,
251253
mut absolute_location: Vec2,
252254
) {
253-
if let Ok((mut node, mut transform)) = node_transform_query.get_mut(entity) {
255+
if let Ok((mut node, mut transform, outline)) = node_transform_query.get_mut(entity) {
254256
let Ok(layout) = ui_surface.get_layout(entity) else {
255257
return;
256258
};
@@ -272,14 +274,35 @@ pub fn ui_layout_system(
272274
node.calculated_size = rounded_size;
273275
node.unrounded_size = layout_size;
274276
}
277+
278+
let viewport_size = root_size.unwrap_or(node.calculated_size);
279+
280+
if let Some(outline) = outline {
281+
// don't trigger change detection when only outlines are changed
282+
let node = node.bypass_change_detection();
283+
node.outline_width = outline
284+
.width
285+
.resolve(node.size().x, viewport_size)
286+
.unwrap_or(0.)
287+
.max(0.);
288+
289+
node.outline_offset = outline
290+
.offset
291+
.resolve(node.size().x, viewport_size)
292+
.unwrap_or(0.)
293+
.max(0.);
294+
}
295+
275296
if transform.translation.truncate() != rounded_location {
276297
transform.translation = rounded_location.extend(0.);
277298
}
299+
278300
if let Ok(children) = children_query.get(entity) {
279301
for &child_uinode in children {
280302
update_uinode_geometry_recursive(
281303
child_uinode,
282304
ui_surface,
305+
Some(viewport_size),
283306
node_transform_query,
284307
children_query,
285308
inverse_target_scale_factor,
@@ -292,34 +315,6 @@ pub fn ui_layout_system(
292315
}
293316
}
294317

295-
/// Resolve and update the widths of Node outlines
296-
pub fn resolve_outlines_system(
297-
primary_window: Query<&Window, With<PrimaryWindow>>,
298-
ui_scale: Res<UiScale>,
299-
mut outlines_query: Query<(&Outline, &mut Node)>,
300-
) {
301-
let viewport_size = primary_window
302-
.get_single()
303-
.map(|window| window.size())
304-
.unwrap_or(Vec2::ZERO)
305-
/ ui_scale.0;
306-
307-
for (outline, mut node) in outlines_query.iter_mut() {
308-
let node = node.bypass_change_detection();
309-
node.outline_width = outline
310-
.width
311-
.resolve(node.size().x, viewport_size)
312-
.unwrap_or(0.)
313-
.max(0.);
314-
315-
node.outline_offset = outline
316-
.offset
317-
.resolve(node.size().x, viewport_size)
318-
.unwrap_or(0.)
319-
.max(0.);
320-
}
321-
}
322-
323318
#[inline]
324319
/// Round `value` to the nearest whole integer, with ties (values with a fractional part equal to 0.5) rounded towards positive infinity.
325320
fn round_ties_up(value: f32) -> f32 {

crates/bevy_ui/src/lib.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ pub enum UiSystem {
7777
Focus,
7878
/// After this label, the [`UiStack`] resource has been updated
7979
Stack,
80-
/// After this label, node outline widths have been updated
81-
Outlines,
8280
}
8381

8482
/// The current scale of the UI.
@@ -132,13 +130,7 @@ impl Plugin for UiPlugin {
132130
.register_type::<Outline>()
133131
.configure_sets(
134132
PostUpdate,
135-
(
136-
CameraUpdateSystem,
137-
UiSystem::Stack,
138-
UiSystem::Layout,
139-
UiSystem::Outlines,
140-
)
141-
.chain(),
133+
(CameraUpdateSystem, UiSystem::Stack, UiSystem::Layout).chain(),
142134
)
143135
.add_systems(
144136
PreUpdate,
@@ -156,17 +148,10 @@ impl Plugin for UiPlugin {
156148
ui_layout_system
157149
.in_set(UiSystem::Layout)
158150
.before(TransformSystem::TransformPropagate),
159-
resolve_outlines_system
160-
.in_set(UiSystem::Outlines)
161-
.after(UiSystem::Layout)
162-
// clipping doesn't care about outlines
163-
.ambiguous_with(update_clipping_system)
164-
.in_set(AmbiguousWithTextSystem),
165151
ui_stack_system
166152
.in_set(UiSystem::Stack)
167153
// the systems don't care about stack index
168154
.ambiguous_with(update_clipping_system)
169-
.ambiguous_with(resolve_outlines_system)
170155
.ambiguous_with(ui_layout_system)
171156
.in_set(AmbiguousWithTextSystem),
172157
update_clipping_system.after(TransformSystem::TransformPropagate),

crates/bevy_ui/src/ui_node.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ pub struct Node {
3535
pub(crate) calculated_size: Vec2,
3636
/// The width of this node's outline.
3737
/// If this value is `Auto`, negative or `0.` then no outline will be rendered.
38+
/// Outline updates bypass change detection.
3839
///
39-
/// Automatically calculated by [`super::layout::resolve_outlines_system`].
40+
/// Automatically calculated by [`super::layout::ui_layout_system`].
4041
pub(crate) outline_width: f32,
4142
/// The amount of space between the outline and the edge of the node.
43+
/// Outline updates bypass change detection.
44+
///
45+
/// Automatically calculated by [`super::layout::ui_layout_system`].
4246
pub(crate) outline_offset: f32,
4347
/// The unrounded size of the node as width and height in logical pixels.
4448
///

0 commit comments

Comments
 (0)