menu system: beginnings

This commit is contained in:
Schrottkatze 2025-05-21 20:48:21 +02:00
parent 2e7de9f296
commit 2b18cdea38
Signed by: schrottkatze
SSH key fingerprint: SHA256:FPOYVeBy3QP20FEM42uWF1Wa/Qhlk+L3S2+Wuau/Auo
5 changed files with 206 additions and 0 deletions

View file

@ -1,9 +1,11 @@
#![feature(iter_collect_into)]
use bevy::prelude::*; use bevy::prelude::*;
mod camera; mod camera;
mod cleanup; mod cleanup;
mod debugging; mod debugging;
mod game; mod game;
mod menus;
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash, Reflect)] #[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash, Reflect)]
#[allow(unused)] #[allow(unused)]

50
src/menus.rs Normal file
View file

@ -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::<CurrentMenu>::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);
}

62
src/menus/lib.rs Normal file
View file

@ -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<NavState: States> {
menus: HashMap<NavState, Menu<NavState>>,
}
#[derive(Debug)]
pub struct Menu<ParentNavState: States> {
menu_items: Vec<MenuItemInternal<ParentNavState>>,
}
pub use item::types::*;
pub use item::*;
mod item;
impl<NavState: States> Menus<NavState> {
pub fn new() -> Self {
Self {
menus: HashMap::new(),
}
}
pub fn add_menu(mut self, state: NavState, menu: Menu<NavState>) -> Self {
self.menus.insert(state, menu);
self
}
}
impl<ParentNavState: States> Menu<ParentNavState> {
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<ParentNavState>]) -> Self {
self.add_items_positioned(ItemPosition::MainView, items)
}
pub fn add_items_positioned(
mut self,
position: ItemPosition,
items: &[&dyn MenuItem<ParentNavState>],
) -> Self {
items
.iter()
.map(|it| (*it).item())
.collect_into(&mut self.menu_items);
self
}
}

59
src/menus/lib/item.rs Normal file
View file

@ -0,0 +1,59 @@
use bevy::state::state::States;
use types::{ItemPosition, MenuItemType, OnPressAction};
pub mod types;
#[derive(Debug)]
pub(super) struct MenuItemInternal<NavState: States> {
r#type: MenuItemType,
pos: ItemPosition,
action: Option<OnPressAction<NavState>>,
}
pub(super) trait IntoMenuItemInternal<NavState: States> {
fn item(&self) -> MenuItemInternal<NavState>;
}
impl<S: States, T: ?Sized + MenuItem<S>> IntoMenuItemInternal<S> for T {
fn item(&self) -> MenuItemInternal<S> {
MenuItemInternal {
r#type: self.item_type(),
pos: self.pos(),
action: self.action(),
}
}
}
pub trait MenuItem<NavState: States> {
fn item_type(&self) -> MenuItemType;
fn pos(&self) -> ItemPosition;
fn action(&self) -> Option<OnPressAction<NavState>>;
}
impl<NavState: States> MenuItem<NavState> for MenuItemType {
fn item_type(&self) -> MenuItemType {
self.clone()
}
fn pos(&self) -> ItemPosition {
ItemPosition::default()
}
fn action(&self) -> Option<OnPressAction<NavState>> {
None
}
}
impl<NavState: States> MenuItem<NavState> for (MenuItemType, OnPressAction<NavState>) {
fn item_type(&self) -> MenuItemType {
self.0.clone()
}
fn pos(&self) -> ItemPosition {
ItemPosition::default()
}
fn action(&self) -> Option<OnPressAction<NavState>> {
Some(self.1.clone())
}
}

View file

@ -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<MenuItemType>),
}
#[derive(Clone, Debug)]
pub enum OnPressAction<NavState: States> {
NavigateTo(NavState),
RunSystem(ToDo),
SampleAction,
}