|
|
|
@ -1,11 +1,20 @@
|
|
|
|
|
|
|
|
#![feature(iter_intersperse)]
|
|
|
|
|
|
|
|
|
|
|
|
//! This example illustrates scrolling in Bevy UI.
|
|
|
|
//! This example illustrates scrolling in Bevy UI.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use bevy::picking::{
|
|
|
|
|
|
|
|
hover::HoverMap,
|
|
|
|
|
|
|
|
pointer::{PointerId, PointerMap},
|
|
|
|
|
|
|
|
};
|
|
|
|
use games::*;
|
|
|
|
use games::*;
|
|
|
|
|
|
|
|
use lipsum::*;
|
|
|
|
|
|
|
|
use rand::*;
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
|
let mut app = App::new();
|
|
|
|
let mut app = App::new();
|
|
|
|
app.add_plugins(BaseGamePlugin::default())
|
|
|
|
app.add_plugins(BaseGamePlugin::default())
|
|
|
|
.add_systems(Startup, (setup_list, setup_nav_tree));
|
|
|
|
.add_systems(Startup, (setup_list, setup_nav_tree))
|
|
|
|
|
|
|
|
.add_systems(Update, (hide_menu, control_menu.run_if(on_event::<Pointer<Over>>.or(on_event::<Pointer<Out>>))));
|
|
|
|
app.run();
|
|
|
|
app.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -36,12 +45,14 @@ fn setup_nav_tree(mut commands: Commands) {
|
|
|
|
// Nav Tree
|
|
|
|
// Nav Tree
|
|
|
|
commands
|
|
|
|
commands
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
|
|
|
|
Text::new("+"),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
align_self: AlignSelf::Start,
|
|
|
|
right: Val::Px(0.0),
|
|
|
|
justify_self: JustifySelf::End,
|
|
|
|
top: Val::Percent(50.0),
|
|
|
|
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
|
|
|
|
align_content: AlignContent::Center,
|
|
|
|
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BackgroundColor(RED.into()),
|
|
|
|
BackgroundColor(RED.into()),
|
|
|
|
@ -49,26 +60,107 @@ fn setup_nav_tree(mut commands: Commands) {
|
|
|
|
.with_children(|parent| {
|
|
|
|
.with_children(|parent| {
|
|
|
|
parent
|
|
|
|
parent
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
|
|
|
|
Name::new("Buttons"),
|
|
|
|
|
|
|
|
NavState::default(),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
right: Val::Px(25.0),
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
right: Val::Percent(100.0),
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
width: Val::Auto,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Visibility::Hidden,
|
|
|
|
BackgroundColor(ORANGE.into()),
|
|
|
|
BackgroundColor(ORANGE.into()),
|
|
|
|
))
|
|
|
|
))
|
|
|
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
|
|
|
(0..10).for_each(|_| {
|
|
|
|
|
|
|
|
let title: String = lipsum_title_with_rng(thread_rng())
|
|
|
|
|
|
|
|
.split_whitespace()
|
|
|
|
|
|
|
|
.take(2)
|
|
|
|
|
|
|
|
.intersperse(" ")
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
Text::new(title),
|
|
|
|
|
|
|
|
Node {
|
|
|
|
|
|
|
|
width: Val::Auto,
|
|
|
|
|
|
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
BackgroundColor(ORANGE_RED.into()),
|
|
|
|
|
|
|
|
Button,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
})
|
|
|
|
.with_children(|parent| {
|
|
|
|
.with_children(|parent| {
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
Name::new("Preview"),
|
|
|
|
|
|
|
|
NavState::default(),
|
|
|
|
|
|
|
|
Text::new(lipsum_with_rng(thread_rng(), 50)),
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
right: Val::Px(25.0),
|
|
|
|
right: Val::Percent(100.0),
|
|
|
|
min_width: Val::Px(25.0),
|
|
|
|
|
|
|
|
min_height: Val::Px(25.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BackgroundColor(YELLOW.into()),
|
|
|
|
BackgroundColor(YELLOW.into()),
|
|
|
|
|
|
|
|
Visibility::Hidden,
|
|
|
|
));
|
|
|
|
));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// When you pointer over the '+' make the entire menu visible
|
|
|
|
|
|
|
|
fn hide_menu(
|
|
|
|
|
|
|
|
mut nodes: Query<(Entity, &mut Visibility, &NavState), Changed<NavState>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
nodes.iter_mut().for_each(|(e, mut v, n)| {
|
|
|
|
|
|
|
|
*v = match n {
|
|
|
|
|
|
|
|
NavState::Open => Visibility::Inherited,
|
|
|
|
|
|
|
|
NavState::Closed => Visibility::Hidden,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// When you pointer goes off of the '+' or any of it's children make the entire menu invisible
|
|
|
|
|
|
|
|
fn control_menu(
|
|
|
|
|
|
|
|
mut over_events: EventReader<Pointer<Over>>,
|
|
|
|
|
|
|
|
mut out_events: EventReader<Pointer<Out>>,
|
|
|
|
|
|
|
|
children: Query<&ChildOf>,
|
|
|
|
|
|
|
|
parents: Query<&Children>,
|
|
|
|
|
|
|
|
mut nav: Query<&mut NavState>,
|
|
|
|
|
|
|
|
hover_map: Res<HoverMap>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
over_events.read().for_each(|over| {
|
|
|
|
|
|
|
|
let root = children.root_ancestor(over.target);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parents.iter_descendants(root).for_each(|child| {
|
|
|
|
|
|
|
|
if let Ok(mut n) = nav.get_mut(child) {
|
|
|
|
|
|
|
|
*n = NavState::Open;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gives us the entiies covered by the HoverMap
|
|
|
|
|
|
|
|
let is_hovered: Vec<&Entity> = hover_map.iter().flat_map(|(_, submap)| {
|
|
|
|
|
|
|
|
let x: Vec<&Entity> = submap.iter().map(|(node, _)| {
|
|
|
|
|
|
|
|
node
|
|
|
|
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
x
|
|
|
|
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// For all pointer out events
|
|
|
|
|
|
|
|
out_events.read().for_each(|out| {
|
|
|
|
|
|
|
|
// If a relative of out.target is hovered, do nothing
|
|
|
|
|
|
|
|
// Otherwise set to closed
|
|
|
|
|
|
|
|
let root = children.root_ancestor(out.target);
|
|
|
|
|
|
|
|
let tree_still_hovered = parents.iter_descendants(root).any(|child| {
|
|
|
|
|
|
|
|
is_hovered.contains(&&child)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if !tree_still_hovered {
|
|
|
|
|
|
|
|
parents.iter_descendants(root).for_each(|child| {
|
|
|
|
|
|
|
|
if let Ok(mut n) = nav.get_mut(child) {
|
|
|
|
|
|
|
|
*n = NavState::Closed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|