Skip to content

Commit

Permalink
Use System Chains to handle Buttons (#12)
Browse files Browse the repository at this point in the history
* Use System Chains to handle Buttons

* cargo fmt
  • Loading branch information
inodentry authored Feb 15, 2021
1 parent ba240d1 commit c567084
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 28 deletions.
22 changes: 20 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,23 @@ fn main() {
.on_state_update(
APPSTATES,
AppState::MainMenu,
menu::button_interact.system(),
menu::button_interact::<menu::button::ExitApp>
.system()
.chain(menu::main_menu::button_exit_app.system()),
)
.on_state_update(
APPSTATES,
AppState::MainMenu,
menu::button_interact::<menu::button::EnterGame>
.system()
.chain(menu::main_menu::button_enter_game.system()),
)
.on_state_update(
APPSTATES,
AppState::MainMenu,
menu::button_interact::<menu::button::OpenSettingsMenu>
.system()
.chain(menu::main_menu::button_open_settings_menu.system()),
)
.on_state_exit(
APPSTATES,
Expand All @@ -73,7 +89,9 @@ fn main() {
.on_state_update(
APPSTATES,
AppState::SettingsMenu,
menu::button_interact.system(),
menu::button_interact::<menu::button::ExitSettingsMenu>
.system()
.chain(menu::settings::button_exit_settings_menu.system()),
)
.on_state_exit(
APPSTATES,
Expand Down
27 changes: 23 additions & 4 deletions src/menu/main_menu.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
use bevy::app::AppExit;
use bevy::prelude::*;

use crate::menu::{ClickAction, MenuAssets};
use crate::menu::{button, MenuAssets};
use crate::AppState;

/// Marker for despawning when exiting `AppState::MainMenu`
pub struct StateCleanup;

pub fn button_exit_app(In(clicked): In<bool>, mut app_exit: ResMut<Events<AppExit>>) {
if clicked {
app_exit.send(AppExit);
}
}

pub fn button_enter_game(In(clicked): In<bool>, mut state: ResMut<State<AppState>>) {
if clicked {
state.set_next(AppState::Overworld).unwrap();
}
}

pub fn button_open_settings_menu(In(clicked): In<bool>, mut state: ResMut<State<AppState>>) {
if clicked {
state.set_next(AppState::SettingsMenu).unwrap();
}
}

pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
let button_style = Style {
size: Size::new(Val::Auto, Val::Auto),
Expand Down Expand Up @@ -98,7 +117,7 @@ pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
style: button_style.clone(),
..Default::default()
})
.with(ClickAction::ChangeState(AppState::Overworld))
.with(button::EnterGame)
.with_children(|button| {
button.spawn(TextBundle {
text: Text::with_section(
Expand All @@ -124,7 +143,7 @@ pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
style: button_style.clone(),
..Default::default()
})
.with(ClickAction::ChangeState(AppState::SettingsMenu))
.with(button::OpenSettingsMenu)
.with_children(|button| {
button.spawn(TextBundle {
text: Text::with_section(
Expand All @@ -141,7 +160,7 @@ pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
style: button_style.clone(),
..Default::default()
})
.with(ClickAction::Exit)
.with(button::ExitApp)
.with_children(|button| {
button.spawn(TextBundle {
text: Text::with_section(
Expand Down
40 changes: 20 additions & 20 deletions src/menu/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use bevy::app::AppExit;
use bevy::prelude::*;

use crate::AppState;

pub mod main_menu;
pub mod settings;

/// Every logical action for which we can have a UI button
///
/// Use as marker components to identify the buttons.
pub mod button {
pub struct EnterGame;
pub struct ExitApp;
pub struct OpenSettingsMenu;
pub struct ExitSettingsMenu;
}

pub struct MenuAssets {
button_normal: Handle<ColorMaterial>,
button_hover: Handle<ColorMaterial>,
Expand Down Expand Up @@ -47,32 +54,25 @@ impl FromResources for MenuAssets {
}
}

pub enum ClickAction {
ChangeState(AppState),
Exit,
}

pub fn button_interact(
mut state: ResMut<State<AppState>>,
mut app_exit: ResMut<Events<AppExit>>,
pub fn button_interact<B: Component>(
materials: Res<MenuAssets>,
mut query: Query<
(&Interaction, &mut Handle<ColorMaterial>, &ClickAction),
(Mutated<Interaction>, With<Button>),
(&Interaction, &mut Handle<ColorMaterial>),
(Mutated<Interaction>, With<Button>, With<B>),
>,
) {
for (interaction, mut material, action) in query.iter_mut() {
) -> bool {
let mut clicked = false;

for (interaction, mut material) in query.iter_mut() {
match interaction {
Interaction::Clicked => {
*material = materials.button_active.clone();

match action {
ClickAction::ChangeState(next) => state.set_next(*next).unwrap(),
ClickAction::Exit => app_exit.send(AppExit),
}
clicked = true;
}
Interaction::Hovered => *material = materials.button_hover.clone(),
Interaction::None => *material = materials.button_normal.clone(),
}
}

clicked
}
10 changes: 8 additions & 2 deletions src/menu/settings.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use bevy::prelude::*;

use crate::menu::{ClickAction, MenuAssets};
use crate::menu::{button, MenuAssets};
use crate::AppState;

/// Marker for despawning when exiting `AppState::SettingsMenu`
pub struct StateCleanup;

pub fn button_exit_settings_menu(In(clicked): In<bool>, mut state: ResMut<State<AppState>>) {
if clicked {
state.set_next(AppState::MainMenu).unwrap();
}
}

pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
let button_style = Style {
size: Size::new(Val::Auto, Val::Auto),
Expand Down Expand Up @@ -121,7 +127,7 @@ pub fn setup(commands: &mut Commands, assets: Res<MenuAssets>) {
style: button_style.clone(),
..Default::default()
})
.with(ClickAction::ChangeState(AppState::MainMenu))
.with(button::ExitSettingsMenu)
.with_children(|button| {
button.spawn(TextBundle {
text: Text::with_section(
Expand Down

0 comments on commit c567084

Please sign in to comment.