use bevy::prelude::*;
use bevy_quickmenu::{
style::{ControlState, StyleEntry, Stylesheet},
ActionTrait, Menu, MenuIcon, MenuItem, MenuOptions, MenuState, QuickMenuPlugin, RichTextEntry,
ScreenTrait,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(BasicPlugin)
.run();
}
#[derive(Debug, Event)]
enum BasicEvent {
Close,
}
#[derive(Debug, Clone, Default)]
struct BasicState {
boolean1: bool,
boolean2: bool,
custom_icon: Handle<Image>,
}
pub struct BasicPlugin;
impl Plugin for BasicPlugin {
fn build(&self, app: &mut App) {
let options = MenuOptions {
font: Some("font.otf"),
..Default::default()
};
app
.add_event::<BasicEvent>()
.add_plugins(QuickMenuPlugin::<Screens>::with_options(options))
.add_systems(Startup, setup)
.add_systems(Update, event_reader);
}
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera3dBundle::default());
let mut button_style = StyleEntry::button();
button_style.size = 25.0;
button_style.selected = ControlState {
fg: Color::YELLOW,
bg: Color::RED,
};
let sheet = Stylesheet {
button: button_style,
..Default::default()
}
.with_background(BackgroundColor(Color::BISQUE));
let state = BasicState {
custom_icon: asset_server.load("Custom.png"),
..Default::default()
};
commands.insert_resource(MenuState::new(state, Screens::Root, Some(sheet)));
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
enum Actions {
Close,
Toggle1,
Toggle2,
}
impl ActionTrait for Actions {
type State = BasicState;
type Event = BasicEvent;
fn handle(&self, state: &mut BasicState, event_writer: &mut EventWriter<BasicEvent>) {
match self {
Actions::Close => event_writer.send(BasicEvent::Close),
Actions::Toggle1 => state.boolean1 = !state.boolean1,
Actions::Toggle2 => state.boolean2 = !state.boolean2,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
enum Screens {
Root,
Booleans,
}
impl ScreenTrait for Screens {
type Action = Actions;
type State = BasicState;
fn resolve(&self, state: &BasicState) -> Menu<Screens> {
match self {
Screens::Root => root_menu(state),
Screens::Booleans => boolean_menu(state),
}
}
}
fn root_menu(state: &BasicState) -> Menu<Screens> {
Menu::new(
"root",
vec![
MenuItem::headline([
RichTextEntry::new("Rich "),
RichTextEntry::new_color("Text ", Color::RED),
RichTextEntry::new_color("!", Color::YELLOW),
]),
MenuItem::action("Close", Actions::Close).with_icon(MenuIcon::Back),
MenuItem::label("Use a custom Icon"),
MenuItem::screen("Boolean", Screens::Booleans)
.with_icon(MenuIcon::Other(state.custom_icon.clone())),
],
)
.with_background(BackgroundColor(Color::BLACK))
}
fn boolean_menu(state: &BasicState) -> Menu<Screens> {
Menu::new(
"boolean",
vec![
MenuItem::label("Right-Align the elements"),
MenuItem::action("Toggle 1", Actions::Toggle1).checked(state.boolean1),
MenuItem::action("Toggle Boolean 2", Actions::Toggle2).checked(state.boolean2),
],
)
.with_background(BackgroundColor(Color::NAVY))
.with_style(Style {
align_items: AlignItems::FlexEnd,
flex_direction: FlexDirection::Column,
..Default::default()
})
}
fn event_reader(mut commands: Commands, mut event_reader: EventReader<BasicEvent>) {
for event in event_reader.iter() {
match event {
BasicEvent::Close => bevy_quickmenu::cleanup(&mut commands),
}
}
}