Ok the UI actually feels pretty nice... saving my place before I fuck it up

main
Elijah Voigt 2 years ago
parent fd1ee92d5f
commit cc05c7c434

@ -36,6 +36,7 @@ use bevy::{
asset::{AssetLoader, LoadContext, LoadedAsset},
audio::PlaybackMode,
gltf::Gltf,
input::{keyboard::KeyboardInput, ButtonState},
prelude::*,
utils::BoxedFuture,
};
@ -60,7 +61,7 @@ fn main() {
.init_asset_loader::<MonologueLoader>()
.add_event::<CustomAssetEvent<Scene>>()
.add_event::<CustomAssetEvent<AnimationClip>>()
.add_systems(Startup, initialize_ui)
.add_systems(Startup, (initialize_ui, welcome_message))
.add_systems(
Update,
(
@ -116,7 +117,7 @@ fn initialize_ui(mut commands: Commands) {
let base_style = Style {
border: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(1.0)),
overflow: Overflow::clip(),
flex_direction: FlexDirection::Column,
..default()
@ -125,9 +126,12 @@ fn initialize_ui(mut commands: Commands) {
commands
.spawn(NodeBundle {
style: Style {
top: Val::Px(0.0),
left: Val::Px(0.0),
position_type: PositionType::Absolute,
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Column,
overflow: Overflow::clip(),
..default()
@ -141,8 +145,8 @@ fn initialize_ui(mut commands: Commands) {
.spawn((NodeBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Row,
overflow: Overflow::clip(),
..default()
@ -161,8 +165,8 @@ fn initialize_ui(mut commands: Commands) {
NodeBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Column,
overflow: Overflow::clip(),
justify_content: JustifyContent::FlexStart,
@ -178,37 +182,31 @@ fn initialize_ui(mut commands: Commands) {
content_containers.push(spawn_tab_container::<FontWidget>(
"Font",
parent,
&base_style,
ui::Select::Single,
));
content_containers.push(spawn_tab_container::<AudioWidget>(
"Audio",
parent,
&base_style,
ui::Select::Multi,
));
content_containers.push(spawn_tab_container::<GltfWidget>(
"Gltf",
parent,
&base_style,
ui::Select::Single,
));
content_containers.push(spawn_tab_container::<SceneWidget>(
"Scene",
parent,
&base_style,
ui::Select::Single,
));
content_containers.push(spawn_tab_container::<AnimationWidget>(
"Animation",
parent,
&base_style,
ui::Select::Multi,
));
content_containers.push(spawn_tab_container::<CameraWidget>(
"Camera",
parent,
&base_style,
ui::Select::Single,
));
});
@ -219,8 +217,8 @@ fn initialize_ui(mut commands: Commands) {
NodeBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Column,
overflow: Overflow::clip(),
..default()
@ -246,7 +244,6 @@ fn initialize_ui(mut commands: Commands) {
b.clone(),
ui::Title { text: name.clone() },
ui::Collapse { target: *target },
ui::Active,
));
});
});
@ -256,10 +253,13 @@ fn initialize_ui(mut commands: Commands) {
NodeBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Row,
overflow: Overflow::clip(),
align_items: AlignItems::Center,
align_content: AlignContent::Center,
justify_content: JustifyContent::SpaceBetween,
..default()
},
background_color: Color::ALICE_BLUE.into(),
@ -275,28 +275,47 @@ fn initialize_ui(mut commands: Commands) {
});
}
fn welcome_message(mut writer: EventWriter<ui::Alert>) {
writer.send(ui::Alert::Info(
"Welcome to the Monologue Trees editor!".into(),
));
writer.send(ui::Alert::Info(
[
"Import assets by dragging and dropping files into the editor",
"",
"Supported file types (for now):",
"* 3D: .gltf, .glb",
"* Audio: .ogg",
"* Font: .ttf, .otf",
]
.join("\n")
.into(),
));
}
fn spawn_tab_container<T: Default + Component>(
title: &'static str,
parent: &mut ChildBuilder,
base_style: &Style,
select: ui::Select,
) -> (String, Entity) {
(
title.into(),
// Content node
parent
.spawn((
NodeBundle {
style: Style {
display: Display::None,
top: Val::Px(0.0),
..base_style.clone()
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Column,
..default()
},
background_color: Color::WHITE.into(),
border_color: Color::BLACK.into(),
z_index: ZIndex::Local(100),
..default()
},
ui::Title { text: title.into() },
T::default(),
ui::Scroll,
Interaction::default(),
@ -461,8 +480,8 @@ mod assets {
ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
..default()
},
border_color: Color::BLACK.into(),
@ -486,8 +505,8 @@ mod assets {
ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
..default()
},
border_color: Color::BLACK.into(),

@ -29,10 +29,12 @@ pub struct GameUiPlugin;
impl Plugin for GameUiPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
app.add_event::<Alert>()
.add_systems(Startup, init_alerts)
.add_systems(
Update,
(
init_titles,
create_titles,
manage_titles,
manage_button_interaction,
manage_select_active,
@ -42,8 +44,10 @@ impl Plugin for GameUiPlugin {
manage_collapse_active,
show_child_number,
manage_sort,
spawn_alert,
),
);
)
.add_systems(PostUpdate, close_window);
}
}
@ -69,11 +73,25 @@ mod title {
pub target: Entity,
}
pub fn init_titles(
events: Query<(Entity, &Title, Option<&Note>, Option<&Minimize>), Added<Title>>,
#[derive(Debug, Component)]
pub struct Close {
pub target: Entity,
}
pub fn create_titles(
events: Query<
(
Entity,
&Title,
Option<&Note>,
Option<&Minimize>,
Option<&Close>,
),
Added<Title>,
>,
mut commands: Commands,
) {
events.for_each(|(entity, title, note, minimize)| {
events.for_each(|(entity, title, note, minimize, close)| {
commands.entity(entity).with_children(|parent| {
parent.spawn((
TextBundle {
@ -102,8 +120,9 @@ mod title {
..default()
},
style: Style {
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(3.0)),
padding: UiRect::all(Val::Px(3.0)),
left: Val::Px(0.0),
..default()
},
..default()
@ -111,31 +130,82 @@ mod title {
Sorting(0),
TitleText,
));
if let Some(target) = minimize {
parent.spawn((
if minimize.is_some() || close.is_some() {
parent
.spawn(NodeBundle {
style: Style {
// border: UiRect::all(Val::Px(1.0)),
// margin: UiRect::all(Val::Px(1.0)),
// padding: UiRect::all(Val::Px(1.0)),
right: Val::Px(0.0),
..default()
},
background_color: Color::WHITE.into(),
border_color: Color::BLACK.into(),
..default()
})
.with_children(|parent| {
if let Some(Minimize { target }) = minimize {
parent
.spawn((
ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(5.0)),
padding: UiRect::all(Val::Px(5.0)),
right: Val::Px(0.0),
// margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
..default()
},
background_color: Color::WHITE.into(),
border_color: Color::BLACK.into(),
..default()
},
Collapse { target: *target },
Active,
))
.with_children(|parent| {
parent.spawn(TextBundle::from_section(
"-",
TextStyle {
color: Color::BLACK,
..default()
},
));
});
}
if let Some(Close { target }) = close {
parent
.spawn((
ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
// margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
..default()
},
background_color: Color::WHITE.into(),
border_color: Color::BLACK.into(),
..default()
},
Collapse {
target: target.target,
Close { target: *target },
))
.with_children(|parent| {
parent.spawn(TextBundle::from_section(
"x",
TextStyle {
color: Color::BLACK,
..default()
},
));
});
}
});
}
});
});
}
pub fn manage_titles(
events: Query<(&Title, Option<&Note>, &Children), Changed<Title>>,
events: Query<(&Title, Option<&Note>, &Children), Or<(Changed<Title>, Changed<Note>)>>,
mut texts: Query<&mut Text, With<TitleText>>,
) {
events.iter().for_each(|(title, note, children)| {
@ -169,6 +239,18 @@ mod title {
})
})
}
pub fn close_window(
events: Query<(&Interaction, &Close), (With<Button>, Changed<Interaction>)>,
mut commands: Commands,
) {
events
.iter()
.filter(|(&interaction, _)| interaction == Interaction::Pressed)
.for_each(|(_, Close { target })| {
commands.entity(*target).despawn_recursive();
});
}
}
pub use collapse::*;
@ -426,3 +508,98 @@ mod sort {
})
}
}
pub use alert::*;
pub mod alert {
use super::*;
#[derive(Debug, Event)]
pub enum Alert {
Info(String),
Warn(String),
Danger(String),
}
#[derive(Debug, Component)]
pub struct AlertsWidget;
pub fn init_alerts(mut commands: Commands) {
commands.spawn((
NodeBundle {
style: Style {
top: Val::Px(0.0),
right: Val::Px(0.0),
position_type: PositionType::Absolute,
width: Val::Percent(33.0),
padding: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(1.0)),
border: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Column,
justify_items: JustifyItems::Center,
..default()
},
border_color: Color::WHITE.into(),
..default()
},
AlertsWidget,
));
}
pub fn spawn_alert(
mut events: EventReader<Alert>,
root: Query<Entity, With<AlertsWidget>>,
mut commands: Commands,
) {
events.iter().for_each(|alert| {
info!("Processing alert {:?}", alert);
let (color, text) = match alert {
Alert::Info(text) => (Color::BLUE, text),
Alert::Warn(text) => (Color::ORANGE, text),
Alert::Danger(text) => (Color::RED, text),
};
commands.entity(root.single()).with_children(|parent| {
parent
.spawn(NodeBundle {
style: Style {
width: Val::Percent(100.0),
padding: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(1.0)),
border: UiRect::all(Val::Px(2.0)),
flex_direction: FlexDirection::Column,
justify_self: JustifySelf::Center,
..default()
},
border_color: color.into(),
..default()
})
.with_children(|parent| {
parent.spawn((
NodeBundle {
style: Style {
padding: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(1.0)),
border: UiRect::all(Val::Px(1.0)),
flex_direction: FlexDirection::Row,
align_items: AlignItems::Center,
align_content: AlignContent::Center,
justify_content: JustifyContent::SpaceBetween,
..default()
},
background_color: color.into(),
..default()
},
Title {
text: "Alert".into(),
},
Close {
target: parent.parent_entity(),
},
Sorting(0),
));
parent.spawn(TextBundle::from_section(text, TextStyle { ..default() }));
});
});
});
}
}

Loading…
Cancel
Save