it actually completely fully works praise jesus

main
Elijah Voigt 2 years ago
parent fc02df8638
commit dd912f420f

@ -18,175 +18,11 @@ fn main() {
)) ))
// .init_resource::<Icon>() // .init_resource::<Icon>()
.add_systems(Startup, init_ui2) .add_systems(Startup, init_ui2)
.add_systems(Update, toggle)
.add_systems(PostUpdate, selection)
// .add_systems(Startup, init_ui) // .add_systems(Startup, init_ui)
// .add_systems(Update, (cursors, container)) // .add_systems(Update, (cursors, container))
.run(); .run();
} }
#[derive(Debug, Bundle)]
struct UiKitContainer {
node_bundle: NodeBundle,
select: Select,
}
#[derive(Copy, Clone)]
enum UiKitPosition {
Top,
Left,
Right,
}
impl UiKitContainer {
fn new(position: UiKitPosition) -> Self {
let style = match position {
UiKitPosition::Top => Style {
border: UiRect::all(Val::Px(1.0)),
top: Val::Percent(102.0),
left: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
align_items: AlignItems::FlexStart,
display: Display::None,
..default()
},
UiKitPosition::Left => Style {
border: UiRect::all(Val::Px(1.0)),
left: Val::Percent(100.0),
top: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
justify_items: JustifyItems::Start,
display: Display::None,
..default()
},
UiKitPosition::Right => Style {
border: UiRect::all(Val::Px(1.0)),
right: Val::Percent(104.0),
top: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
justify_items: JustifyItems::Start,
display: Display::None,
..default()
},
};
UiKitContainer {
node_bundle: NodeBundle {
style,
background_color: BackgroundColor(Color::PURPLE),
border_color: BorderColor(Color::BLACK),
..default()
},
select: Select::None,
}
}
}
#[derive(Debug, Bundle)]
struct UiKitButton {
button_bundle: ButtonBundle,
select: Select,
}
impl UiKitButton {
fn new(color: Color) -> Self {
UiKitButton {
button_bundle: ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
width: Val::Px(100.0),
height: Val::Px(50.0),
flex_direction: FlexDirection::Column,
..default()
},
background_color: BackgroundColor(color),
border_color: BorderColor(Color::BLACK),
..default()
},
select: Select::None,
}
}
}
#[derive(Debug, Component, Copy, Clone)]
enum Select {
Active,
None,
}
/// When an item is selected/de-selected change it's display accordingly
fn selection(
mut events: Query<(&mut BackgroundColor, &Select, &Children), (Changed<Select>, With<Button>)>,
mut styles: Query<&mut Style>,
) {
events
.iter_mut()
.for_each(|(mut bg_color, select, children)| {
bg_color.0 = match select {
Select::Active => Color::RED,
Select::None => Color::WHITE,
};
children.iter().for_each(|&child| {
if let Ok(mut style) = styles.get_mut(child) {
style.display = match select {
Select::Active => Display::Flex,
Select::None => Display::None,
}
}
});
});
}
/// Toggle a UI Nav tree open/closed
///
/// PERF: This is hella not performant, we just usually don't have many elements to iterate over so
/// it's tolerable.
///
// TODO: Should not be able to select multiple children in branch of tree
// TODO: Port to ui.rs
fn toggle(
events: Query<Entity, (Changed<Interaction>, With<Button>)>,
interactions: Query<&Interaction>,
mut selects: Query<&mut Select>,
children: Query<&Children>,
) {
events.iter().for_each(|entity| {
// If all interactions are inactive, set all selections to None
if interactions
.iter()
.all(|&interaction| interaction == Interaction::None)
{
selects.iter_mut().for_each(|mut select| {
*select = Select::None;
});
// Otherwise change this item's selection
} else {
let mut select = selects
.get_mut(entity)
.expect("Entity has Select component");
let interaction = interactions
.get(entity)
.expect("Entity has Interaction component");
*select = match interaction {
Interaction::Pressed | Interaction::Hovered => Select::Active,
Interaction::None => {
let children_inactive = children.iter_descendants(entity).all(|child| {
if let Ok(&c) = interactions.get(child) {
c == Interaction::None
} else {
true
}
});
if children_inactive {
Select::None
} else {
Select::Active
}
}
}
}
});
}
// const CURSORS: [CursorIcon; 35] = [ // const CURSORS: [CursorIcon; 35] = [
// CursorIcon::Default, // CursorIcon::Default,
// CursorIcon::Crosshair, // CursorIcon::Crosshair,

@ -1,15 +1,232 @@
/// TODO: /// TODO:
/// * Titles on top left of window/tab /// * Text box w/ clear button
/// * /// * Names/Labels management
/// * Button color management
/// * Move code to submodules
///
/// BUGS:
/// * When selecting one tree, possible to select another without the first closing.
///
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{prelude::*, window::PrimaryWindow};
pub struct GameUiPlugin; pub struct GameUiPlugin;
impl Plugin for GameUiPlugin { impl Plugin for GameUiPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app; app.add_systems(Update, toggle)
// .add_systems(PreUpdate, ) .add_systems(PostUpdate, selection);
// .add_systems(Update,)
// .add_systems(PostUpdate, );
} }
} }
#[derive(Debug, Bundle)]
pub struct UiKitContainer {
node_bundle: NodeBundle,
select: UiKitSelect,
}
#[derive(Copy, Clone)]
pub enum UiKitPosition {
Top,
Left,
Right,
}
impl UiKitContainer {
pub fn new(position: UiKitPosition) -> Self {
let style = match position {
UiKitPosition::Top => Style {
border: UiRect::all(Val::Px(1.0)),
top: Val::Percent(102.0),
left: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
align_items: AlignItems::FlexStart,
display: Display::None,
..default()
},
UiKitPosition::Left => Style {
border: UiRect::all(Val::Px(1.0)),
left: Val::Percent(100.0),
top: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
justify_items: JustifyItems::Start,
display: Display::None,
..default()
},
UiKitPosition::Right => Style {
border: UiRect::all(Val::Px(1.0)),
right: Val::Percent(104.0),
top: Val::Px(-2.0),
flex_direction: FlexDirection::Column,
justify_items: JustifyItems::Start,
display: Display::None,
..default()
},
};
UiKitContainer {
node_bundle: NodeBundle {
style,
background_color: BackgroundColor(Color::PURPLE),
border_color: BorderColor(Color::BLACK),
..default()
},
select: UiKitSelect::None,
}
}
}
#[derive(Debug, Bundle)]
pub struct UiKitButton {
button_bundle: ButtonBundle,
select: UiKitSelect,
}
impl UiKitButton {
pub fn new(color: Color) -> Self {
UiKitButton {
button_bundle: ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
width: Val::Px(100.0),
height: Val::Px(50.0),
flex_direction: FlexDirection::Column,
..default()
},
background_color: BackgroundColor(color),
border_color: BorderColor(Color::BLACK),
..default()
},
select: UiKitSelect::None,
}
}
}
#[derive(Debug, Component, Copy, Clone)]
pub enum UiKitSelect {
Active,
None,
}
#[derive(Debug, Bundle)]
pub struct UiKitTextInput {
text_bundle: TextBundle,
}
impl UiKitTextInput {
pub fn new() -> Self {
UiKitTextInput {
text_bundle: TextBundle { ..default() },
}
}
}
/// When an item is selected/de-selected change it's display accordingly
fn selection(
mut events: Query<
(&mut BackgroundColor, &UiKitSelect, &Children),
(Changed<UiKitSelect>, With<Button>),
>,
mut styles: Query<&mut Style>,
) {
events
.iter_mut()
.for_each(|(mut bg_color, select, children)| {
bg_color.0 = match select {
UiKitSelect::Active => Color::RED,
UiKitSelect::None => Color::WHITE,
};
children.iter().for_each(|&child| {
if let Ok(mut style) = styles.get_mut(child) {
style.display = match select {
UiKitSelect::Active => Display::Flex,
UiKitSelect::None => Display::None,
}
}
});
});
}
/// Toggle a UI Nav tree open/closed
///
/// PERF: This is hella not performant, we just usually don't have many elements to iterate over so
/// it's tolerable.
///
// TODO: Should not be able to select multiple children in branch of tree
// TODO: Port to ui.rs
fn toggle(
events: Query<Entity, (Changed<Interaction>, With<Button>)>,
interactions: Query<&Interaction, With<Button>>,
mut selects: Query<&mut UiKitSelect>,
parents: Query<&Parent>,
children: Query<&Children>,
) {
events.iter().for_each(|entity| {
// Otherwise, update nav tree(s)
if let Ok(interaction) = interactions.get(entity) {
match interaction {
Interaction::Pressed | Interaction::Hovered => {
{
let parent = parents.get(entity).expect("entity has parent");
children
.get(parent.get())
.expect("parent has children")
.iter()
.filter(|&e| *e != entity)
.for_each(|sibling| {
if let Ok(mut select) = selects.get_mut(*sibling) {
*select = UiKitSelect::None
}
});
}
if let Ok(mut select) = selects.get_mut(entity) {
*select = UiKitSelect::Active
}
}
Interaction::None => {
// Find the ancestor which does not have a parent
let root_parent = parents
.iter_ancestors(entity)
.find(|&e| parents.get(e).is_err())
.expect("entity has root parent");
let family: Vec<Entity> = children.iter_descendants(root_parent).collect();
let family_inactive = family
.iter()
.filter_map(|member| interactions.get(*member).ok())
.all(|&interaction| interaction == Interaction::None);
// Zero out children
let descendants: Vec<Entity> = children.iter_descendants(entity).collect();
let descendants_inactive = descendants
.iter()
.filter_map(|child| interactions.get(*child).ok())
.all(|&interaction| interaction == Interaction::None);
// The entire tree is inactive
if family_inactive {
family.iter().for_each(|member| {
if let Ok(mut select) = selects.get_mut(*member) {
*select = UiKitSelect::None
}
});
if let Ok(mut select) = selects.get_mut(entity) {
*select = UiKitSelect::None
}
// Just the sub-tree is inactive
} else if descendants_inactive {
descendants.iter().for_each(|child| {
if let Ok(mut select) = selects.get_mut(*child) {
*select = UiKitSelect::None
}
});
if let Ok(mut select) = selects.get_mut(entity) {
*select = UiKitSelect::None
}
// This node is active (usually a parent of an active child)
} else if let Ok(mut select) = selects.get_mut(entity) {
*select = UiKitSelect::Active
}
}
}
}
});
}

Loading…
Cancel
Save