use crate::prelude::*; /// Menu Plugin; empty struct for Plugin impl pub(crate) struct UiPlugin; impl Plugin for UiPlugin { fn build(&self, app: &mut App) { app.add_systems( Update, button_interaction.run_if(any_component_changed::), ); } } fn button_interaction(mut query: Query<(&mut BackgroundColor, &Interaction)>) { query.iter_mut().for_each(|(mut bg, i)| match i { Interaction::Hovered => bg.0 = Color::ORANGE, Interaction::Pressed => bg.0 = Color::GREEN, Interaction::None => bg.0 = Color::WHITE, }); } /// Component for marking a button as a "Set State" action #[derive(Component)] pub(crate) struct SetState(pub S); pub(crate) fn button_state_action( q: Query<(&SetState, &Interaction), Changed>, mut n: ResMut>, ) { q.iter() .for_each(|(SetState(s), interaction)| match interaction { Interaction::Pressed => { n.set(s.clone()); } _ => (), }); } #[derive(Component)] pub(crate) struct EmitEvent(pub E); pub(crate) fn button_emit_event( q: Query<(&EmitEvent, &Interaction), Changed>, mut w: EventWriter, ) { q.iter() .for_each(|(EmitEvent(e), interaction)| match interaction { Interaction::Pressed => { w.send(e.clone()); } _ => (), }) } pub(crate) mod button { use super::*; pub(crate) struct UiButton { pub label: &'static str, } impl EntityCommand for UiButton { fn apply(self, id: Entity, world: &mut World) { let button_text_style = TextStyle { color: Color::BLACK, font_size: 16.0, ..default() }; world .entity_mut(id) .insert(ButtonBundle { style: Style { margin: UiRect::all(Val::Px(5.0)), padding: UiRect::all(Val::Px(5.0)), border: UiRect::all(Val::Px(1.0)), ..default() }, border_color: BorderColor(Color::BLACK), z_index: ZIndex::Local(-1), ..default() }) .with_children(|parent| { parent.spawn(TextBundle { text: Text::from_section(self.label, button_text_style), ..default() }); }); } } } pub(crate) mod title { use super::*; pub(crate) struct UiTitle { pub text: &'static str, pub color: Color, } impl Default for UiTitle { fn default() -> UiTitle { UiTitle { text: "", color: Color::BLACK, } } } impl EntityCommand for UiTitle { fn apply(self, id: Entity, world: &mut World) { let title_text_style = TextStyle { color: self.color, font_size: 32.0, ..default() }; world.entity_mut(id).insert(TextBundle { text: Text::from_section(self.text, title_text_style), style: Style { margin: UiRect::all(Val::Px(5.0)), ..default() }, z_index: ZIndex::Local(-2), ..default() }); } } } pub(crate) mod container { use super::*; pub(crate) struct UiContainer; impl EntityCommand for UiContainer { fn apply(self, id: Entity, world: &mut World) { world.entity_mut(id).insert(NodeBundle { style: Style { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, align_content: AlignContent::Center, justify_items: JustifyItems::Center, justify_content: JustifyContent::Center, flex_direction: FlexDirection::Column, position_type: PositionType::Absolute, ..default() }, border_color: BorderColor(Color::BLACK), z_index: ZIndex::Local(-3), ..default() }); } } } pub(crate) mod style { use super::*; pub(crate) struct UiStyle(pub Style); impl EntityCommand for UiStyle { fn apply(self, id: Entity, world: &mut World) { if let Some(mut s) = world.entity_mut(id).get_mut::