Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI borders "randomly" do not render #10069

Closed
rparrett opened this issue Oct 9, 2023 · 2 comments · Fixed by #10078
Closed

UI borders "randomly" do not render #10069

rparrett opened this issue Oct 9, 2023 · 2 comments · Fixed by #10078
Labels
A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior D-Trivial Nice and easy! A great choice to get started with Bevy P-Regression Functionality that used to work but no longer does. Add a test for this!
Milestone

Comments

@rparrett
Copy link
Contributor

rparrett commented Oct 9, 2023

Bevy version

First started misbehaving after #9903.

Relevant system information

AdapterInfo { name: "Apple M1 Max", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }
SystemInfo { os: "MacOS 13.5.1 ", kernel: "22.6.0", cpu: "Apple M1 Max", core_count: "10", memory: "64.0 GiB" }

What you did

I noticed this while updating bevy_simple_text_input to work with Bevy's main branch. It's possible to reproduce there by running either example.

Here's a minimal reproduction. This is basically bevy's button example but trimmed town.

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            parent
                .spawn((NodeBundle {
                    style: Style {
                        width: Val::Px(200.0),
                        border: UiRect::all(Val::Px(5.0)),
                        padding: UiRect::all(Val::Px(5.0)),
                        ..default()
                    },
                    border_color: BorderColor(Color::BLACK),
                    background_color: Color::RED.into(),
                    ..default()
                },))
                .with_children(|parent| {
                    parent.spawn(TextBundle::from_section("a", TextStyle::default()));
                });
        });
}

What went wrong

Only one of the borders is shown. The exact presentation depends on the contents of the text node. aa seems even weirder. aaaaa seems fine.

image
@rparrett rparrett added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets and removed S-Needs-Triage This issue needs to be labelled labels Oct 9, 2023
@rparrett rparrett added this to the 0.12 milestone Oct 9, 2023
@rparrett
Copy link
Contributor Author

rparrett commented Oct 10, 2023

There's probably a bit more going on than what's described in the issue title.

Here's another repro with the button example mashed onto the 3d_scene example. The button now behaves differently from the button example where it seems to behave properly.

image

@rparrett rparrett added the P-Regression Functionality that used to work but no longer does. Add a test for this! label Oct 10, 2023
@rparrett
Copy link
Contributor Author

This patch seems to fix things and makes sense on the surface to me:

diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs
index 5c5aca45d..c852122e6 100644
--- a/crates/bevy_ui/src/render/mod.rs
+++ b/crates/bevy_ui/src/render/mod.rs
@@ -759,7 +759,10 @@ pub fn queue_uinodes(
                 draw_function,
                 pipeline,
                 entity: *entity,
-                sort_key: FloatOrd(extracted_uinode.stack_index as f32),
+                sort_key: (
+                    FloatOrd(extracted_uinode.stack_index as f32),
+                    entity.index(),
+                ),
                 // batch_range will be calculated in prepare_uinodes
                 batch_range: 0..0,
                 dynamic_offset: None,
diff --git a/crates/bevy_ui/src/render/render_pass.rs b/crates/bevy_ui/src/render/render_pass.rs
index f483c8cf0..bde289853 100644
--- a/crates/bevy_ui/src/render/render_pass.rs
+++ b/crates/bevy_ui/src/render/render_pass.rs
@@ -88,7 +88,7 @@ impl Node for UiPassNode {
 }
 
 pub struct TransparentUi {
-    pub sort_key: FloatOrd,
+    pub sort_key: (FloatOrd, u32),
     pub entity: Entity,
     pub pipeline: CachedRenderPipelineId,
     pub draw_function: DrawFunctionId,
@@ -97,7 +97,7 @@ pub struct TransparentUi {
 }
 
 impl PhaseItem for TransparentUi {
-    type SortKey = FloatOrd;
+    type SortKey = (FloatOrd, u32);
 
     #[inline]
     fn entity(&self) -> Entity {

@alice-i-cecile alice-i-cecile added the D-Trivial Nice and easy! A great choice to get started with Bevy label Oct 10, 2023
@rparrett rparrett changed the title UI borders do not render with inner text node UI borders "randomly" do not render Oct 10, 2023
github-merge-queue bot pushed a commit that referenced this issue Oct 13, 2023
# Objective

Fixes #10069

## Solution

Extracted UI nodes were previously stored in a `SparseSet` and had a
predictable iteration order. UI borders and outlines relied on this. Now
they are stored in a HashMap and that is no longer true.

This adds `entity.index()` to the sort key for `TransparentUi` so that
the iteration order is predictable and the "border entities" that get
spawned during extraction are guaranteed to get drawn after their
respective container nodes again.

I **think** that everything still works for overlapping ui nodes etc,
because the z value / primary sort is still controlled by the "ui
stack."

Text above is just my current understanding. A rendering expert should
check this out.

I will do some more testing when I can.
ameknite pushed a commit to ameknite/bevy that referenced this issue Nov 6, 2023
# Objective

Fixes bevyengine#10069

## Solution

Extracted UI nodes were previously stored in a `SparseSet` and had a
predictable iteration order. UI borders and outlines relied on this. Now
they are stored in a HashMap and that is no longer true.

This adds `entity.index()` to the sort key for `TransparentUi` so that
the iteration order is predictable and the "border entities" that get
spawned during extraction are guaranteed to get drawn after their
respective container nodes again.

I **think** that everything still works for overlapping ui nodes etc,
because the z value / primary sort is still controlled by the "ui
stack."

Text above is just my current understanding. A rendering expert should
check this out.

I will do some more testing when I can.
rdrpenguin04 pushed a commit to rdrpenguin04/bevy that referenced this issue Jan 9, 2024
# Objective

Fixes bevyengine#10069

## Solution

Extracted UI nodes were previously stored in a `SparseSet` and had a
predictable iteration order. UI borders and outlines relied on this. Now
they are stored in a HashMap and that is no longer true.

This adds `entity.index()` to the sort key for `TransparentUi` so that
the iteration order is predictable and the "border entities" that get
spawned during extraction are guaranteed to get drawn after their
respective container nodes again.

I **think** that everything still works for overlapping ui nodes etc,
because the z value / primary sort is still controlled by the "ui
stack."

Text above is just my current understanding. A rendering expert should
check this out.

I will do some more testing when I can.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior D-Trivial Nice and easy! A great choice to get started with Bevy P-Regression Functionality that used to work but no longer does. Add a test for this!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants