Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions _release-content/migration-guides/computed_stack_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: "`ComputedNode::stack_index` has been replaced by `ComputedStackIndex`"
pull_requests: [23878]
---

The `stack_index` field has been removed from `ComputedNode`. Instead the stack index for each UI node is stored on a specialized component `ComputedStackIndex`, which is required by `ComputedNode`.
4 changes: 1 addition & 3 deletions crates/bevy_ui/src/accessibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,7 @@ impl Plugin for AccessibilityPlugin {
sync_bounds_and_transforms
.after(button_changed)
.after(image_changed)
.after(label_changed)
// the listed systems do not affect calculated size
.ambiguous_with(crate::ui_stack_system),
.after(label_changed),
)
.in_set(UiSystems::PostLayout)
.before(AccessibilitySystems::Update),
Expand Down
12 changes: 2 additions & 10 deletions crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use bevy_input::InputSystems;
use bevy_transform::TransformSystems;
use layout::ui_surface::UiSurface;
use stack::ui_stack_system;
pub use stack::UiStack;
pub use stack::{ComputedStackIndex, UiStack};
use update::{propagate_ui_target_cameras, update_clipping_system};

/// The basic plugin for Bevy UI
Expand Down Expand Up @@ -192,14 +192,7 @@ impl Plugin for UiPlugin {
ui_layout_system
.in_set(UiSystems::Layout)
.ambiguous_with(bevy_sprite::update_text2d_layout),
ui_stack_system
.in_set(UiSystems::Stack)
// These systems don't care about stack index
.ambiguous_with(widget::measure_text_system)
.ambiguous_with(ui_layout_system)
.ambiguous_with(widget::update_viewport_render_target_size)
.in_set(AmbiguousWithText)
.before(UiSystems::PostLayout),
ui_stack_system.in_set(UiSystems::Stack),
update_clipping_system.in_set(UiSystems::PostLayout),
// Potential conflicts: `Assets<Image>`
// They run independently since `widget::image_node_system` will only ever observe
Expand Down Expand Up @@ -261,7 +254,6 @@ fn build_text_interop(app: &mut App) {
// as editable_text_system or related systems could generate focus changes
// which should be processed ASAP.
.before(bevy_input_focus::InputFocusSystems::FocusChangeEvents)
.ambiguous_with(ui_stack_system)
.ambiguous_with(widget::text_system)
.ambiguous_with(bevy_sprite::calculate_bounds_text2d),
),
Expand Down
25 changes: 18 additions & 7 deletions crates/bevy_ui/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@

use crate::{
experimental::{UiChildren, UiRootNodes},
ComputedNode, GlobalZIndex, ZIndex,
GlobalZIndex, ZIndex,
};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{entity::EntityHashSet, prelude::*};
use core::ops::Range;

/// 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.
///
/// Automatically calculated in [`UiSystems::Stack`](`super::UiSystems::Stack`).
#[derive(Component, Default, PartialEq, Eq, Deref, DerefMut)]
pub struct ComputedStackIndex(pub u32);

/// The current UI stack, which contains all UI nodes ordered by their depth (back-to-front).
///
/// The first entry is the furthest node from the camera and is the first one to get rendered
Expand Down Expand Up @@ -46,10 +54,13 @@ 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<ComputedNode>>,
zindex_global_node_query: Query<
(Entity, &GlobalZIndex, Option<&ZIndex>),
With<ComputedStackIndex>,
>,
ui_children: UiChildren,
zindex_query: Query<Option<&ZIndex>, (With<ComputedNode>, Without<GlobalZIndex>)>,
mut update_query: Query<&mut ComputedNode>,
zindex_query: Query<Option<&ZIndex>, (With<ComputedStackIndex>, Without<GlobalZIndex>)>,
mut update_query: Query<&mut ComputedStackIndex>,
) {
ui_stack.partition.clear();
ui_stack.uinodes.clear();
Expand Down Expand Up @@ -96,8 +107,8 @@ pub fn ui_stack_system(
}

for (i, entity) in ui_stack.uinodes.iter().enumerate() {
if let Ok(mut node) = update_query.get_mut(*entity) {
node.bypass_change_detection().stack_index = i as u32;
if let Ok(mut stack_index) = update_query.get_mut(*entity) {
stack_index.0 = i as u32;
}
}
}
Expand All @@ -106,7 +117,7 @@ fn update_uistack_recursive(
cache: &mut ChildBufferCache,
node_entity: Entity,
ui_children: &UiChildren,
zindex_query: &Query<Option<&ZIndex>, (With<ComputedNode>, Without<GlobalZIndex>)>,
zindex_query: &Query<Option<&ZIndex>, (With<ComputedStackIndex>, Without<GlobalZIndex>)>,
ui_stack: &mut Vec<Entity>,
) {
ui_stack.push(node_entity);
Expand Down
18 changes: 3 additions & 15 deletions crates/bevy_ui/src/ui_node.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
ui_transform::{UiGlobalTransform, UiTransform},
ContentSize, FocusPolicy, UiRect, Val,
ComputedStackIndex, ContentSize, FocusPolicy, UiRect, Val,
};
use bevy_camera::{visibility::Visibility, Camera, RenderTarget};
use bevy_color::{Alpha, Color};
Expand All @@ -25,12 +25,8 @@ use tracing::warn;
/// handle size without any delays.
#[derive(Component, Debug, Copy, Clone, PartialEq, Reflect)]
#[reflect(Component, Default, Debug, Clone)]
#[require(ComputedStackIndex)]
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.
///
/// Automatically calculated in [`UiSystems::Stack`](`super::UiSystems::Stack`).
pub stack_index: u32,
/// The size of the node as width and height in physical pixels.
///
/// Automatically calculated by [`ui_layout_system`](`super::layout::ui_layout_system`).
Expand Down Expand Up @@ -108,14 +104,6 @@ impl ComputedNode {
self.size.x <= 0. || self.size.y <= 0.
}

/// 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.
///
/// Automatically calculated in [`UiSystems::Stack`](super::UiSystems::Stack).
pub const fn stack_index(&self) -> u32 {
self.stack_index
}

/// The calculated node size as width and height in physical pixels before rounding.
///
/// Automatically calculated by [`ui_layout_system`](`super::layout::ui_layout_system`).
Expand Down Expand Up @@ -393,7 +381,6 @@ impl ComputedNode {

impl ComputedNode {
pub const DEFAULT: Self = Self {
stack_index: 0,
size: Vec2::ZERO,
content_size: Vec2::ZERO,
scrollbar_size: Vec2::ZERO,
Expand Down Expand Up @@ -481,6 +468,7 @@ impl From<BVec2> for IgnoreScroll {
#[derive(Component, Clone, PartialEq, Debug, Reflect)]
#[require(
ComputedNode,
ComputedStackIndex,
ContentSize,
ComputedUiTargetCamera,
ComputedUiRenderTargetInfo,
Expand Down
9 changes: 5 additions & 4 deletions crates/bevy_ui_render/src/box_shadow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use bevy_render::{
use bevy_render::{GpuResourceAppExt, RenderApp, RenderStartup};
use bevy_shader::{Shader, ShaderDefVal};
use bevy_ui::{
BoxShadow, CalculatedClip, ComputedNode, ComputedUiRenderTargetInfo, ComputedUiTargetCamera,
ResolvedBorderRadius, UiGlobalTransform, Val,
BoxShadow, CalculatedClip, ComputedNode, ComputedStackIndex, ComputedUiRenderTargetInfo,
ComputedUiTargetCamera, ResolvedBorderRadius, UiGlobalTransform, Val,
};
use bevy_utils::default;
use bytemuck::{Pod, Zeroable};
Expand Down Expand Up @@ -210,6 +210,7 @@ pub fn extract_shadows(
Query<(
Entity,
&ComputedNode,
&ComputedStackIndex,
&UiGlobalTransform,
&InheritedVisibility,
&BoxShadow,
Expand All @@ -222,7 +223,7 @@ pub fn extract_shadows(
) {
let mut mapping = camera_map.get_mapper();

for (entity, uinode, transform, visibility, box_shadow, clip, camera, target) in
for (entity, uinode, stack_index, transform, visibility, box_shadow, clip, camera, target) in
&box_shadow_query
{
// Skip if no visible shadows
Expand Down Expand Up @@ -277,7 +278,7 @@ pub fn extract_shadows(

extracted_box_shadows.box_shadows.push(ExtractedBoxShadow {
render_entity: commands.spawn(TemporaryRenderEntity).id(),
stack_index: uinode.stack_index,
stack_index: stack_index.0,
transform: Affine2::from(transform) * Affine2::from_translation(offset),
color: drop_shadow.color.into(),
bounds: shadow_size + 6. * blur_radius,
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_ui_render/src/debug_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use bevy_sprite::BorderRect;
use bevy_ui::ui_transform::UiGlobalTransform;
use bevy_ui::CalculatedClip;
use bevy_ui::ComputedNode;
use bevy_ui::ComputedStackIndex;
use bevy_ui::ComputedUiTargetCamera;
use bevy_ui::ResolvedBorderRadius;
use bevy_ui::UiStack;
Expand Down Expand Up @@ -176,6 +177,7 @@ pub fn extract_debug_overlay(
Query<(
Entity,
&ComputedNode,
&ComputedStackIndex,
&UiGlobalTransform,
&InheritedVisibility,
Option<&CalculatedClip>,
Expand All @@ -188,7 +190,8 @@ pub fn extract_debug_overlay(
) {
let mut camera_mapper = camera_map.get_mapper();

for (entity, uinode, transform, visibility, maybe_clip, computed_target, debug) in &uinode_query
for (entity, uinode, stack_index, transform, visibility, maybe_clip, computed_target, debug) in
&uinode_query
{
let debug_options = debug.copied().unwrap_or((*debug_options.as_ref()).into());
if !debug_options.enabled {
Expand All @@ -205,7 +208,7 @@ pub fn extract_debug_overlay(
let color = debug_options
.line_color_override
.unwrap_or_else(|| Hsla::sequential_dispersed(entity.index_u32()).into());
let z_order = (ui_stack.uinodes.len() as u32 + uinode.stack_index()) as f32;
let z_order = (ui_stack.uinodes.len() as u32 + stack_index.0) as f32;
let border = BorderRect::all(debug_options.line_width / uinode.inverse_scale_factor());
let transform = transform.affine();

Expand Down
15 changes: 9 additions & 6 deletions crates/bevy_ui_render/src/gradient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ use bevy_render::{sync_world::MainEntity, GpuResourceAppExt, RenderStartup};
use bevy_shader::Shader;
use bevy_sprite::BorderRect;
use bevy_ui::{
BackgroundGradient, BorderGradient, ColorStop, ComputedUiRenderTargetInfo, ConicGradient,
Gradient, InterpolationColorSpace, LinearGradient, RadialGradient, ResolvedBorderRadius, Val,
BackgroundGradient, BorderGradient, ColorStop, ComputedStackIndex, ComputedUiRenderTargetInfo,
ConicGradient, Gradient, InterpolationColorSpace, LinearGradient, RadialGradient,
ResolvedBorderRadius, Val,
};
use bevy_utils::default;
use bytemuck::{Pod, Zeroable};
Expand Down Expand Up @@ -343,6 +344,7 @@ pub fn extract_gradients(
Query<(
Entity,
&ComputedNode,
&ComputedStackIndex,
&ComputedUiTargetCamera,
&ComputedUiRenderTargetInfo,
&UiGlobalTransform,
Expand All @@ -359,6 +361,7 @@ pub fn extract_gradients(
for (
entity,
uinode,
stack_index,
camera,
target,
transform,
Expand Down Expand Up @@ -390,7 +393,7 @@ pub fn extract_gradients(
if let Some(color) = gradient.get_single() {
// With a single color stop there's no gradient, fill the node with the color
extracted_uinodes.uinodes.push(ExtractedUiNode {
z_order: uinode.stack_index as f32
z_order: stack_index.0 as f32
+ match node_type {
NodeType::Rect | NodeType::Inverted => stack_z_offsets::GRADIENT,
NodeType::Border(_) => stack_z_offsets::BORDER_GRADIENT,
Expand Down Expand Up @@ -438,7 +441,7 @@ pub fn extract_gradients(

extracted_gradients.items.push(ExtractedGradient {
render_entity: commands.spawn(TemporaryRenderEntity).id(),
stack_index: uinode.stack_index,
stack_index: stack_index.0,
transform: transform.into(),
stops_range: range_start..extracted_color_stops.0.len(),
rect: Rect {
Expand Down Expand Up @@ -488,7 +491,7 @@ pub fn extract_gradients(

extracted_gradients.items.push(ExtractedGradient {
render_entity: commands.spawn(TemporaryRenderEntity).id(),
stack_index: uinode.stack_index,
stack_index: stack_index.0,
transform: transform.into(),
stops_range: range_start..extracted_color_stops.0.len(),
rect: Rect {
Expand Down Expand Up @@ -544,7 +547,7 @@ pub fn extract_gradients(

extracted_gradients.items.push(ExtractedGradient {
render_entity: commands.spawn(TemporaryRenderEntity).id(),
stack_index: uinode.stack_index,
stack_index: stack_index.0,
transform: transform.into(),
stops_range: range_start..extracted_color_stops.0.len(),
rect: Rect {
Expand Down
Loading