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

Problems with z-index, NodeBundle ignores it? #1948

Closed
DanilaMihailov opened this issue Apr 17, 2021 · 4 comments
Closed

Problems with z-index, NodeBundle ignores it? #1948

DanilaMihailov opened this issue Apr 17, 2021 · 4 comments
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior

Comments

@DanilaMihailov
Copy link

Bevy version

0.5 from cargo

Operating system & version

macOs Big Sur Version: 11.2.2 (20D80)

What you did

Spawn 2 NodeBundles in different systems, one of them is black with z-index 20 and semi-transparent, other one is green with z-index 1

What you expected to happen

Expected Node with z-index 20 be displayed over node with z-index 1

What actually happened

Node with z-index 1 displayed over node with z-index 20

Additional information

Seems like last inserted Node will always be on top. This is simple example, but I have very similar setup in my game. In the game black Node properly overlays all sprites, but not other Nodes. I use it to create pause menu, and to make text more readable I wanted to dim the background, by inserting fullscreen Node with black color and transparency.

I am completely new to gamedev, so I maybe doing something completely wrong. If that the case, can you please point me in the right direction? I looked at examples and other games, and could not find how to deal with this.

screenshot of the example
Screenshot 2021-04-17 at 11 56 40

here is example code

use bevy::prelude::*;

fn setup_camera(mut commands: Commands) {
    commands.spawn_bundle(UiCameraBundle::default());
}

// some game ui
fn setup_bg(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
    commands.spawn_bundle(NodeBundle {
        transform: Transform::from_xyz(0.0, 0.0, 1.0),

        style: Style {
            size: Size::new(Val::Percent(50.0), Val::Percent(50.0)),
            ..Default::default()
        },
        material: materials.add(Color::GREEN.into()),
        ..Default::default()
    });
}

// fullscreen overlay, semitransparent, there will be ui inside of it
fn setup_overlay(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
    commands.spawn_bundle(NodeBundle {
        // z-index 20?
        transform: Transform::from_xyz(0.0, 0.0, 20.0),

        style: Style {
            position_type: PositionType::Absolute,
            size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
            ..Default::default()
        },
        // this transparency works well, and I can see my SpriteBundles behind
        material: materials.add(Color::rgba(0.0, 0.0, 0.0, 0.9).into()),
        ..Default::default()
    });
}
fn main() {
    App::build()
        .insert_resource(WindowDescriptor {
            title: "test".to_string(),
            width: 800.0,
            height: 600.0,
            ..Default::default()
        })
        .insert_resource(ClearColor(Color::WHITE))
        .add_startup_system(setup_camera.system())
        // order matters, last run system will be on top
        .add_startup_system(setup_bg.system().label("bg"))
        .add_startup_system(setup_overlay.system().label("over").after("bg"))
        .add_plugins(DefaultPlugins)
        .run();
}
@DanilaMihailov DanilaMihailov added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Apr 17, 2021
@mockersf
Copy link
Member

For UI nodes, the z-index you provide is overridden to provide a sensible value based on the hierarchy, so that a child of an entity is displayed in front of it.

To achieve this, the root elements get a z-index at 0, it's children 0.001, their children 0.002, and so on...

This may change soon as we rework the UI, you can check #1275 and #1211 for discussions around that.

@mockersf mockersf added A-UI Graphical user interfaces, styles, layouts, and widgets and removed S-Needs-Triage This issue needs to be labelled labels Apr 17, 2021
@DanilaMihailov
Copy link
Author

Great explanation, thank you. I will look out for UI rework, but for now I'll work around it by creating one tree for UI elements and show/hide them when needed.

@tomuxmon
Copy link

tomuxmon commented Jun 16, 2022

As a workaround for the current stable bevy (0.7), I am using a fixed z for UI nodes.

#[derive(Debug, Component)]
pub(crate) struct UiFixedZ {
    pub z: f32,
}

pub(crate) fn ui_apply_fixed_z(
    mut node_query: Query<(&mut Transform, &mut GlobalTransform, &UiFixedZ), With<Node>>,
) {
    for (mut transform, mut global_transform, fixed) in node_query.iter_mut() {
        transform.translation.z = fixed.z;
        global_transform.translation.z = fixed.z;
    }
}

I am placing the system in the last stage just after the bevy's z-order system.

...
app.add_system_to_stage(CoreStage::Last, ui_apply_fixed_z)
...

when inserting UiFixedZ components keep in mind that you need to take care of all the descendants manually.

...
// inserting with manual z order
.insert(UiFixedZ { z: 101. })
...

   // inserting children with increased z order
   .insert(UiFixedZ { z: 102. })

hope the workaround helps someone. I am personally using it for tooltips.

@raymond-chia
Copy link

As a workaround for the current stable bevy (0.7), I am using a fixed z for UI nodes.

#[derive(Debug, Component)]
pub(crate) struct UiFixedZ {
    pub z: f32,
}

pub(crate) fn ui_apply_fixed_z(
    mut node_query: Query<(&mut Transform, &mut GlobalTransform, &UiFixedZ), With<Node>>,
) {
    for (mut transform, mut global_transform, fixed) in node_query.iter_mut() {
        transform.translation.z = fixed.z;
        global_transform.translation.z = fixed.z;
    }
}

I am placing the system in the last stage just after the bevy's z-order system.

...
app.add_system_to_stage(CoreStage::Last, ui_apply_fixed_z)
...

when inserting UiFixedZ components keep in mind that you need to take care of all the descendants manually.

...
// inserting with manual z order
.insert(UiFixedZ { z: 101. })
...

   // inserting children with increased z order
   .insert(UiFixedZ { z: 102. })

hope the workaround helps someone. I am personally using it for tooltips.

If putting the system in PostUpdate stage just after bevy::ui::update::ui_z_system and before bevy::transform::TransformSystem::TransformPropagate, the descendants can be taken care of automatically.
That is you only need to set the z index of the parent node.
Systems run on label TransformPropagate will handle the z indexes of children nodes.

app.add_system_to_stage(
        CoreStage::PostUpdate,
        ui_apply_fixed_z
            .after(bevy::ui::update::ui_z_system)
            .before(bevy::transform::TransformSystem::TransformPropagate),
)

Tested in bevy 0.8.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

No branches or pull requests

4 participants