diff --git a/src/main.rs b/src/main.rs index 7d919c7..86746fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ +#![feature(iter_collect_into)] use bevy::prelude::*; mod camera; mod cleanup; mod debugging; mod game; +mod menus; #[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash, Reflect)] #[allow(unused)] diff --git a/src/menus.rs b/src/menus.rs new file mode 100644 index 0000000..d7dd07a --- /dev/null +++ b/src/menus.rs @@ -0,0 +1,50 @@ +use bevy::{input::ButtonState, prelude::*}; +use lib::{ItemPosition, Menu, MenuItemType, Menus, OnPressAction}; + +mod lib; + +#[derive(States, Debug, Clone, PartialEq, Eq, Hash)] +enum CurrentMenu { + NotInMenus, + MainMenu, + Settings, + HighScores, + StartGame, +} +pub fn todo_meow() { + let plugin = Menus::::new() + .add_menu( + CurrentMenu::MainMenu, + Menu::new().add_items(&[ + &MenuItemType::Text(String::from("Hello, World!")), + &( + MenuItemType::Button(String::from("Start Game")), + OnPressAction::SampleAction, + ), + &( + MenuItemType::Button(String::from("Settings")), + OnPressAction::NavigateTo(CurrentMenu::Settings), + ), + ]), + ) + .add_menu( + CurrentMenu::Settings, + Menu::new() + .add_items(&[ + &MenuItemType::Text(String::from("Hello, World!")), + &( + MenuItemType::Button(String::from("Sample setting")), + OnPressAction::SampleAction, + ), + ]) + .add_items_positioned( + ItemPosition::SouthEast, + &[&( + MenuItemType::Button(String::from("Back")), + OnPressAction::NavigateTo(CurrentMenu::MainMenu), + )], + ), + ); + + dbg!(plugin); +} diff --git a/src/menus/lib.rs b/src/menus/lib.rs new file mode 100644 index 0000000..5319c31 --- /dev/null +++ b/src/menus/lib.rs @@ -0,0 +1,62 @@ +#![allow(unused, reason = "Temporary.")] +//! goal is a custom ui/menu library that allows simple and declarative menus. +//! bevy ui is annoying. + +use std::marker::PhantomData; + +use bevy::{platform::collections::HashMap, prelude::*}; + +type ToDo = (); + +#[derive(Debug)] +pub struct Menus { + menus: HashMap>, +} + +#[derive(Debug)] +pub struct Menu { + menu_items: Vec>, +} + +pub use item::types::*; +pub use item::*; + +mod item; + +impl Menus { + pub fn new() -> Self { + Self { + menus: HashMap::new(), + } + } + + pub fn add_menu(mut self, state: NavState, menu: Menu) -> Self { + self.menus.insert(state, menu); + self + } +} + +impl Menu { + pub fn new() -> Self { + Self { + menu_items: Vec::new(), + } + } + + /// Adds `items` in the default `ItemPosition::MainView`. + pub fn add_items(mut self, items: &[&dyn MenuItem]) -> Self { + self.add_items_positioned(ItemPosition::MainView, items) + } + + pub fn add_items_positioned( + mut self, + position: ItemPosition, + items: &[&dyn MenuItem], + ) -> Self { + items + .iter() + .map(|it| (*it).item()) + .collect_into(&mut self.menu_items); + self + } +} diff --git a/src/menus/lib/item.rs b/src/menus/lib/item.rs new file mode 100644 index 0000000..f7f1547 --- /dev/null +++ b/src/menus/lib/item.rs @@ -0,0 +1,59 @@ +use bevy::state::state::States; +use types::{ItemPosition, MenuItemType, OnPressAction}; + +pub mod types; + +#[derive(Debug)] +pub(super) struct MenuItemInternal { + r#type: MenuItemType, + pos: ItemPosition, + action: Option>, +} + +pub(super) trait IntoMenuItemInternal { + fn item(&self) -> MenuItemInternal; +} + +impl> IntoMenuItemInternal for T { + fn item(&self) -> MenuItemInternal { + MenuItemInternal { + r#type: self.item_type(), + pos: self.pos(), + action: self.action(), + } + } +} + +pub trait MenuItem { + fn item_type(&self) -> MenuItemType; + fn pos(&self) -> ItemPosition; + fn action(&self) -> Option>; +} + +impl MenuItem for MenuItemType { + fn item_type(&self) -> MenuItemType { + self.clone() + } + + fn pos(&self) -> ItemPosition { + ItemPosition::default() + } + + fn action(&self) -> Option> { + None + } +} + +impl MenuItem for (MenuItemType, OnPressAction) { + fn item_type(&self) -> MenuItemType { + self.0.clone() + } + + fn pos(&self) -> ItemPosition { + ItemPosition::default() + } + + fn action(&self) -> Option> { + Some(self.1.clone()) + } +} diff --git a/src/menus/lib/item/types.rs b/src/menus/lib/item/types.rs new file mode 100644 index 0000000..c72db23 --- /dev/null +++ b/src/menus/lib/item/types.rs @@ -0,0 +1,33 @@ +use bevy::state::state::States; + +use crate::menus::lib::ToDo; + +/// positions the item in the menu +#[derive(Default, Debug)] +pub enum ItemPosition { + #[default] + MainView, + North, + NorthWest, + West, + SouthWest, + South, + SouthEast, + East, + NorthEast, +} + +// TODO: replace strings with custom "content"? +#[derive(Clone, Debug)] +pub enum MenuItemType { + Text(String), + Button(String), + Subsection(Vec), +} + +#[derive(Clone, Debug)] +pub enum OnPressAction { + NavigateTo(NavState), + RunSystem(ToDo), + SampleAction, +}