Skip to content

Commit

Permalink
Simplify the z_index example
Browse files Browse the repository at this point in the history
  • Loading branch information
oceantume committed Sep 7, 2022
1 parent 12cc199 commit 0c1bbab
Showing 1 changed file with 102 additions and 193 deletions.
295 changes: 102 additions & 193 deletions examples/ui/z_index.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Demonstrates how to use z-index
//! Shows two colored buttons with transparent text.
//!
//! It uses colored boxes with different z-index values to demonstrate how it can affect the order of
//! depth of nodes compared to their siblings, but also compared to the entire UI.
use bevy::prelude::*;

Expand All @@ -8,216 +10,123 @@ fn main() {
.insert_resource(ClearColor(Color::BLACK))
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.add_system(grab)
.add_system(update_z_index_text)
.add_system_to_stage(CoreStage::PreUpdate, grabbed_move)
.run();
}

#[derive(Component)]
struct ZIndexText;

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
fn setup(mut commands: Commands) {
commands.spawn_bundle(Camera2dBundle::default());

let font_handle = asset_server.load("fonts/FiraSans-Bold.ttf");

// prepare a stack node at the root that's above the stack container
spawn_stack_node(
&mut commands,
font_handle.clone(),
Color::DARK_GREEN,
Some(ZIndex::Global(1)),
UiRect {
left: Val::Px(20.0),
bottom: Val::Px(80.0),
..default()
},
);

// prepare a stack node at the root that's under the stack container
spawn_stack_node(
&mut commands,
font_handle.clone(),
Color::ORANGE,
Some(ZIndex::Global(-1)),
UiRect {
left: Val::Px(20.0),
bottom: Val::Px(20.0),
..default()
},
);

// prepare a stack of nodes that can be moved around inside their container.
let mut stacked_nodes = (0..9)
.map(|i| {
spawn_stack_node(
&mut commands,
font_handle.clone(),
Color::rgb(0.1 + i as f32 * 0.1, 0.0, 0.0),
Some(ZIndex::Local(-4 + i)),
UiRect {
left: Val::Px(10.0 + (i as f32 * 47.5)),
bottom: Val::Px(10.0 + (i as f32 * 22.5)),
..default()
},
)
})
.collect::<Vec<_>>();

// add a node that has no z-index
stacked_nodes.push(spawn_stack_node(
&mut commands,
font_handle.clone(),
Color::PURPLE,
None,
UiRect {
left: Val::Px(10.0),
bottom: Val::Px(120.0),
..default()
},
));

// add a node with a global z-index
stacked_nodes.push(spawn_stack_node(
&mut commands,
font_handle,
Color::PINK,
Some(ZIndex::Global(2)),
UiRect {
left: Val::Px(10.0),
bottom: Val::Px(180.0),
..default()
},
));

// spawn the stack container
// spawn the container with default z-index.
// ommiting the z-index component is equivalent to inserting `ZIndex::Local(0)`.
// because this is a root UI node, it is also equivalent to inserting `ZIndex::Global(0)`.
commands
.spawn_bundle(NodeBundle {
color: Color::GRAY.into(),
style: Style {
size: Size::new(Val::Px(500.0), Val::Px(250.0)),
overflow: Overflow::Hidden,
size: Size::new(Val::Px(180.0), Val::Px(100.0)),
margin: UiRect::all(Val::Auto),
..default()
},
..default()
})
.push_children(&stacked_nodes);
}

fn spawn_stack_node(
commands: &mut Commands,
font_handle: Handle<Font>,
color: Color,
z_index: Option<ZIndex>,
position: UiRect,
) -> Entity {
let text = commands
.spawn_bundle(TextBundle::from_section(
"",
TextStyle {
color: Color::WHITE,
font: font_handle,
font_size: 20.0,
},
))
.insert(ZIndexText)
.id();

let node = commands
.spawn_bundle(ButtonBundle {
color: color.into(),
style: Style {
position_type: PositionType::Absolute,
position,
size: Size::new(Val::Px(100.0), Val::Px(50.0)),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
.with_children(|parent| {
// spawn a node with no z-index.
// this has the same result as using `ZIndex::Local(0)`.
// this uses the default depth ordering which is based on where this node is in the hierarchy.
parent.spawn_bundle(ButtonBundle {
color: Color::RED.into(),
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Px(10.0),
bottom: Val::Px(40.0),
..default()
},
size: Size::new(Val::Px(100.0), Val::Px(50.0)),
..default()
},
..default()
},
..default()
})
.insert(Grab)
.add_child(text)
.id();

if let Some(z_index) = z_index {
commands.entity(node).insert(z_index);
}

node
}

fn update_z_index_text(
mut text_query: Query<(&Parent, &mut Text), With<ZIndexText>>,
zindex_query: Query<&ZIndex>,
) {
for (parent, mut text) in &mut text_query {
let new_text = zindex_query
.get(parent.get())
.map_or("No ZIndex".to_string(), |zindex| match zindex {
ZIndex::Local(value) => format!("Local({value})"),
ZIndex::Global(value) => format!("Global({value})"),
});

if text.sections[0].value != new_text {
text.sections[0].value = new_text;
}
}
}

#[derive(Component, Copy, Clone, Debug)]
pub struct Grab;

#[derive(Component, Copy, Clone, Debug)]
pub struct Grabbed {
pub cursor_position: Vec2,
pub cursor_offset: Vec2,
}

fn grab(
mut commands: Commands,
query: Query<(Entity, &Interaction, Option<&Grabbed>), With<Grab>>,
windows: Res<Windows>,
) {
for (entity, interaction, grabbed) in query.iter() {
match interaction {
Interaction::Clicked => {
if grabbed.is_none() {
if let Some(cursor_position) = windows
.get_primary()
.and_then(|window| window.cursor_position())
{
commands.entity(entity).insert(Grabbed {
cursor_position,
cursor_offset: Vec2::new(0.0, 0.0),
});
}
}
}
_ => {
if grabbed.is_some() {
commands.entity(entity).remove::<Grabbed>();
}
}
};
}
}

fn grabbed_move(mut query: Query<(&mut Grabbed, &mut Style), With<Grab>>, windows: Res<Windows>) {
for (mut grabbed, mut style) in query.iter_mut() {
if let Some(cursor_position) = windows
.get_primary()
.and_then(|window| window.cursor_position())
{
let offset = cursor_position - grabbed.cursor_position;
if grabbed.cursor_offset != offset {
style.position.left += offset.x - grabbed.cursor_offset.x;
style.position.bottom += offset.y - grabbed.cursor_offset.y;

grabbed.cursor_offset = offset;
}
}
}
// spawn a node with a positive local z-index of 2.
// it will show above other nodes in the grey container.
parent
.spawn_bundle(ButtonBundle {
color: Color::BLUE.into(),
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Px(45.0),
bottom: Val::Px(30.0),
..default()
},
size: Size::new(Val::Px(100.0), Val::Px(50.0)),
..default()
},
..default()
})
.insert(ZIndex::Local(2));

// spawn a node with a negative local z-index.
// it will show under all other nodes in the grey container.
parent
.spawn_bundle(ButtonBundle {
color: Color::GREEN.into(),
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Px(70.0),
bottom: Val::Px(20.0),
..default()
},
size: Size::new(Val::Px(100.0), Val::Px(75.0)),
..default()
},
..default()
})
.insert(ZIndex::Local(-1));

// spawn a node with a positive global z-index of 1.
// it will show above all other nodes, because it's the highest global z-index in this example app.
// by default, boxes all share the global z-index of 0 that the grey container is implicitly added to.
parent
.spawn_bundle(ButtonBundle {
color: Color::PINK.into(),
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Px(15.0),
bottom: Val::Px(-5.0),
..default()
},
size: Size::new(Val::Px(100.0), Val::Px(60.0)),
..default()
},
..default()
})
.insert(ZIndex::Global(1));

// spawn a node with a negative global z-index.
// this will show under all other nodes, including its parent, because -1 is the lowest global z-index
// in this example app.
parent
.spawn_bundle(ButtonBundle {
color: Color::YELLOW.into(),
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
left: Val::Px(-10.0),
bottom: Val::Px(-10.0),
..default()
},
size: Size::new(Val::Px(100.0), Val::Px(50.0)),
..default()
},
..default()
})
.insert(ZIndex::Global(-1));
});
}

0 comments on commit 0c1bbab

Please sign in to comment.