Compare commits
No commits in common. "dd4ee9732c2263ddc64877168d64bf895c4f1f7c" and "d466ef13317db30b0b51f004021611d4948459f2" have entirely different histories.
dd4ee9732c
...
d466ef1331
14 changed files with 0 additions and 5726 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,7 +0,0 @@
|
||||||
.envrc
|
|
||||||
.direnv
|
|
||||||
|
|
||||||
|
|
||||||
# Added by cargo
|
|
||||||
|
|
||||||
/target
|
|
5087
Cargo.lock
generated
5087
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,7 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "s10e-bevy-menus"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bevy = "0.16.1"
|
|
|
@ -1,4 +0,0 @@
|
||||||
# (TODO: Name)
|
|
||||||
|
|
||||||
This is a simple bevy menu library, that's supposed to abstract away a lot of the annoying parts of making bevy uis.
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
use s10e_bevy_menus::{
|
|
||||||
MenuItemType,
|
|
||||||
menus::{FakeTrigger, Menu, Menus, SimpleMenus},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(States, Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Reflect)]
|
|
||||||
pub enum CurrentMenu {
|
|
||||||
NotInMenus,
|
|
||||||
#[default]
|
|
||||||
MainMenu,
|
|
||||||
MenuA,
|
|
||||||
MenuB,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let menus = SimpleMenus::new(CurrentMenu::NotInMenus, None).add_menu(
|
|
||||||
CurrentMenu::MainMenu,
|
|
||||||
Menu::new().add_items(&[
|
|
||||||
&MenuItemType::Text("Hello world".to_owned()),
|
|
||||||
&MenuItemType::Button("Meoww".to_owned()),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
|
|
||||||
App::new()
|
|
||||||
.add_plugins(DefaultPlugins)
|
|
||||||
.init_state::<CurrentMenu>()
|
|
||||||
.add_plugins(menus)
|
|
||||||
.run();
|
|
||||||
}
|
|
100
flake.lock
generated
100
flake.lock
generated
|
@ -1,100 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"fenix": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-analyzer-src": "rust-analyzer-src"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1756622179,
|
|
||||||
"narHash": "sha256-K3CimrAcMhdDYkErd3oiWPZNaoyaGZEuvGrFuDPFMZY=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"rev": "0abcb15ae6279dcb40a8ae7c1ed980705245cb79",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1756636162,
|
|
||||||
"narHash": "sha256-mBecwgUTWRgClJYqcF+y4O1bY8PQHqeDpB+zsAn+/zA=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "37ff64b7108517f8b6ba5705ee5085eac636a249",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"fenix": "fenix",
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-analyzer-src": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1756597274,
|
|
||||||
"narHash": "sha256-wfaKRKsEVQDB7pQtAt04vRgFphkVscGRpSx3wG1l50E=",
|
|
||||||
"owner": "rust-lang",
|
|
||||||
"repo": "rust-analyzer",
|
|
||||||
"rev": "21614ed2d3279a9aa1f15c88d293e65a98991b30",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "rust-lang",
|
|
||||||
"ref": "nightly",
|
|
||||||
"repo": "rust-analyzer",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
66
flake.nix
66
flake.nix
|
@ -1,66 +0,0 @@
|
||||||
{
|
|
||||||
description = "Build a cargo project without extra checks";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
|
||||||
|
|
||||||
fenix = {
|
|
||||||
url = "github:nix-community/fenix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs =
|
|
||||||
{
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
fenix,
|
|
||||||
flake-utils,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
flake-utils.lib.eachDefaultSystem (
|
|
||||||
system:
|
|
||||||
let
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
|
|
||||||
rs-toolchain =
|
|
||||||
with fenix.packages.${system};
|
|
||||||
combine [
|
|
||||||
complete.toolchain
|
|
||||||
];
|
|
||||||
in
|
|
||||||
{
|
|
||||||
devShells.default = pkgs.mkShell rec {
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
cargo-watch
|
|
||||||
pkg-config
|
|
||||||
rs-toolchain
|
|
||||||
udev
|
|
||||||
alsa-lib
|
|
||||||
glfw
|
|
||||||
freetype
|
|
||||||
vulkan-headers
|
|
||||||
vulkan-loader
|
|
||||||
vulkan-validation-layers
|
|
||||||
vulkan-tools # vulkaninfo
|
|
||||||
shaderc # GLSL to SPIRV compiler - glslc
|
|
||||||
renderdoc # Graphics debugger
|
|
||||||
tracy # Graphics profiler
|
|
||||||
vulkan-tools-lunarg
|
|
||||||
xorg.libX11
|
|
||||||
xorg.libXcursor
|
|
||||||
xorg.libXi
|
|
||||||
xorg.libXrandr # To use the x11 feature
|
|
||||||
libxkbcommon
|
|
||||||
wayland
|
|
||||||
clang
|
|
||||||
llvmPackages.bintools
|
|
||||||
];
|
|
||||||
|
|
||||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
/// Despawn/cleanup every entity with `T`.
|
|
||||||
/// See the [bevy cheatbook's cleanup example](https://bevy-cheatbook.github.io/patterns/generic-systems.html#example-cleanup).
|
|
||||||
pub fn despawn<T: Component>(mut c: Commands, q: Query<Entity, With<T>>) {
|
|
||||||
for e in q {
|
|
||||||
c.entity(e).despawn();
|
|
||||||
}
|
|
||||||
}
|
|
59
src/item.rs
59
src/item.rs
|
@ -1,59 +0,0 @@
|
||||||
use bevy::state::state::States;
|
|
||||||
use types::{ItemPosition, MenuItemType, OnPressAction};
|
|
||||||
|
|
||||||
pub mod types;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub(super) struct MenuItemInternal<NavState: States> {
|
|
||||||
pub(super) r#type: MenuItemType,
|
|
||||||
pub(super) pos: ItemPosition,
|
|
||||||
pub(super) 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())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use bevy::{
|
|
||||||
ecs::{
|
|
||||||
event::Event,
|
|
||||||
system::{Commands, SystemId},
|
|
||||||
},
|
|
||||||
state::state::{FreelyMutableState, NextState, States},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// positions the item in the menu
|
|
||||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
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),
|
|
||||||
DispatchSystem(SystemId),
|
|
||||||
Multiple(Vec<OnPressAction<NavState>>),
|
|
||||||
Close,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: States + FreelyMutableState> OnPressAction<S> {
|
|
||||||
pub fn run(&self, c: &mut Commands, mut nav_state: &mut NextState<S>, closed_state: &S) {
|
|
||||||
dbg!(self);
|
|
||||||
match self {
|
|
||||||
OnPressAction::NavigateTo(to) => nav_state.set(to.clone()),
|
|
||||||
OnPressAction::DispatchSystem(system_id) => c.run_system(*system_id),
|
|
||||||
OnPressAction::Multiple(actions) => {
|
|
||||||
let mut actions = actions.clone();
|
|
||||||
while let Some(action) = actions.pop() {
|
|
||||||
action.run(c, nav_state, closed_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OnPressAction::Close => nav_state.set(closed_state.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
25
src/lib.rs
25
src/lib.rs
|
@ -1,25 +0,0 @@
|
||||||
#![allow(unused, reason = "Temporary.")]
|
|
||||||
#![feature(iter_collect_into)]
|
|
||||||
//! goal is a custom ui/menu library that allows simple and declarative menus.
|
|
||||||
//! bevy ui is annoying.
|
|
||||||
//!
|
|
||||||
//! TODOs:
|
|
||||||
//! - [ ] cleanup
|
|
||||||
//! - [ ] trigger game events (trigger or normal eventwriter?)
|
|
||||||
//! - [ ] styling
|
|
||||||
//! - [ ] more components
|
|
||||||
//! - [ ] more shorthands
|
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use bevy::{platform::collections::HashMap, prelude::*};
|
|
||||||
|
|
||||||
mod item;
|
|
||||||
pub mod plugin;
|
|
||||||
|
|
||||||
mod cleanup;
|
|
||||||
pub mod menus;
|
|
||||||
pub use item::types::*;
|
|
||||||
pub use item::*;
|
|
||||||
|
|
||||||
type ToDo = ();
|
|
77
src/menus.rs
77
src/menus.rs
|
@ -1,77 +0,0 @@
|
||||||
use bevy::{platform::collections::HashMap, prelude::*};
|
|
||||||
|
|
||||||
use super::{IntoMenuItemInternal, ItemPosition, MenuItem, MenuItemInternal};
|
|
||||||
|
|
||||||
#[derive(States, Clone, Eq, PartialEq, Hash, Debug, Copy, Default)]
|
|
||||||
pub struct FakeTrigger;
|
|
||||||
|
|
||||||
pub type SimpleMenus<S> = Menus<FakeTrigger, S>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Menus<TriggerState, NavState>
|
|
||||||
where
|
|
||||||
TriggerState: States,
|
|
||||||
NavState: States,
|
|
||||||
{
|
|
||||||
pub(super) start: NavState,
|
|
||||||
pub(super) closed_when: NavState,
|
|
||||||
/// The state needed to trigger this set of menus
|
|
||||||
pub(super) trigger: Option<TriggerState>,
|
|
||||||
pub(super) menus: HashMap<NavState, Menu<NavState>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Menu<ParentNavState: States> {
|
|
||||||
pub(super) menu_items: Vec<MenuItemInternal<ParentNavState>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<TriggerState, NavState> Menus<TriggerState, NavState>
|
|
||||||
where
|
|
||||||
TriggerState: States,
|
|
||||||
NavState: States + Default,
|
|
||||||
{
|
|
||||||
pub fn new(closed_when: NavState, trigger: Option<TriggerState>) -> Self {
|
|
||||||
Self {
|
|
||||||
trigger,
|
|
||||||
closed_when,
|
|
||||||
start: NavState::default(),
|
|
||||||
menus: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, NavState> Menus<T, NavState>
|
|
||||||
where
|
|
||||||
T: States,
|
|
||||||
NavState: States,
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
161
src/plugin.rs
161
src/plugin.rs
|
@ -1,161 +0,0 @@
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use bevy::{
|
|
||||||
ecs::spawn::SpawnIter, platform::collections::HashMap, prelude::*,
|
|
||||||
state::state::FreelyMutableState,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::cleanup::despawn;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
ItemPosition, MenuItemInternal, MenuItemType, OnPressAction,
|
|
||||||
menus::{Menu, Menus},
|
|
||||||
};
|
|
||||||
|
|
||||||
mod components;
|
|
||||||
|
|
||||||
impl<TriggerState, NavState> Plugin for Menus<TriggerState, NavState>
|
|
||||||
where
|
|
||||||
TriggerState: States + Copy,
|
|
||||||
NavState: States + FreelyMutableState + Copy,
|
|
||||||
{
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.insert_state(self.start)
|
|
||||||
.insert_resource(self.get_store())
|
|
||||||
.insert_resource(MenusClosedWhen(self.closed_when))
|
|
||||||
.add_observer(build_ui::<NavState>)
|
|
||||||
.add_observer(destroy_ui::<NavState>)
|
|
||||||
// .add_observer(destroy_ui::<NavStates>)
|
|
||||||
.add_systems(Update, (update_ui_trigger::<NavState>,));
|
|
||||||
|
|
||||||
if let Some(trigger) = &self.trigger {
|
|
||||||
app.add_systems(
|
|
||||||
Update,
|
|
||||||
handle_press_actions::<NavState>.run_if(in_state(*trigger)),
|
|
||||||
)
|
|
||||||
.add_systems(OnExit(*trigger), close_menu::<NavState>);
|
|
||||||
} else {
|
|
||||||
app.add_systems(Update, handle_press_actions::<NavState>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Event)]
|
|
||||||
struct DestroyUi<S: States>(PhantomData<S>);
|
|
||||||
#[derive(Event)]
|
|
||||||
struct BuildUi<S: States>(S);
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
struct UiParent<S: States>(PhantomData<S>);
|
|
||||||
#[derive(Component)]
|
|
||||||
struct UiComponent;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
struct Action<S: States>(OnPressAction<S>);
|
|
||||||
|
|
||||||
impl<T: States, S: States> Menus<T, S> {
|
|
||||||
fn get_store(&self) -> MenusStore<S> {
|
|
||||||
MenusStore(self.menus.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close_menu<S: States + FreelyMutableState>(
|
|
||||||
mut c: Commands,
|
|
||||||
mut nav_state: ResMut<NextState<S>>,
|
|
||||||
closed_when: Res<MenusClosedWhen<S>>,
|
|
||||||
) {
|
|
||||||
c.run_system_cached(despawn::<UiParent<S>>);
|
|
||||||
nav_state.set(closed_when.0.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
|
||||||
struct MenusStore<S: States>(HashMap<S, Menu<S>>);
|
|
||||||
#[derive(Resource)]
|
|
||||||
struct MenusClosedWhen<S: States>(S);
|
|
||||||
|
|
||||||
fn destroy_ui<S: States>(
|
|
||||||
trigger: Trigger<DestroyUi<S>>,
|
|
||||||
ui_parent: Query<Entity, With<UiParent<S>>>,
|
|
||||||
mut c: Commands,
|
|
||||||
) {
|
|
||||||
trace!("destroy_ui called");
|
|
||||||
if let Ok(parent) = ui_parent.single_inner() {
|
|
||||||
c.entity(parent).despawn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_ui<S: States>(
|
|
||||||
trigger: Trigger<BuildUi<S>>,
|
|
||||||
ui_parent: Query<Entity, With<UiParent<S>>>,
|
|
||||||
mut c: Commands,
|
|
||||||
menus_data: Res<MenusStore<S>>,
|
|
||||||
) {
|
|
||||||
let e = trigger.event();
|
|
||||||
let Some(menu_structure) = menus_data.0.get(&e.0) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let items = menu_structure
|
|
||||||
.menu_items
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
// TODO: implement other item positions
|
|
||||||
.filter(|it| ItemPosition::MainView == it.pos);
|
|
||||||
|
|
||||||
c.spawn((
|
|
||||||
UiParent(PhantomData::<S>),
|
|
||||||
Node {
|
|
||||||
width: Val::Percent(100.0),
|
|
||||||
height: Val::Percent(100.0),
|
|
||||||
align_items: AlignItems::Center,
|
|
||||||
justify_content: JustifyContent::Center,
|
|
||||||
flex_direction: FlexDirection::Column,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
))
|
|
||||||
.with_children(|parent| {
|
|
||||||
for MenuItemInternal { r#type, action, .. } in items {
|
|
||||||
let mut e = match r#type {
|
|
||||||
MenuItemType::Text(s) => parent.spawn(components::text(s)),
|
|
||||||
MenuItemType::Button(s) => parent.spawn(components::button(s)),
|
|
||||||
};
|
|
||||||
e.insert(UiComponent);
|
|
||||||
|
|
||||||
if let Some(action) = action {
|
|
||||||
e.insert(Action(action));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_press_actions<S: States + FreelyMutableState>(
|
|
||||||
mut c: Commands,
|
|
||||||
mut interaction_query: Query<(&Interaction, &Action<S>), Changed<Interaction>>,
|
|
||||||
mut nav_state: ResMut<NextState<S>>,
|
|
||||||
closed_when: Res<MenusClosedWhen<S>>,
|
|
||||||
) {
|
|
||||||
for (interaction, Action(action)) in interaction_query {
|
|
||||||
if *interaction != Interaction::Pressed {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
action.run(&mut c, &mut nav_state, &closed_when.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_ui_trigger<S: States + PartialEq>(
|
|
||||||
mut c: Commands,
|
|
||||||
mut trans_reader: EventReader<StateTransitionEvent<S>>,
|
|
||||||
menus_data: Res<MenusStore<S>>,
|
|
||||||
closed_when: Res<MenusClosedWhen<S>>,
|
|
||||||
) {
|
|
||||||
for trans in trans_reader.read() {
|
|
||||||
info!("{trans:?}");
|
|
||||||
|
|
||||||
c.trigger(DestroyUi(PhantomData::<S>));
|
|
||||||
if let Some(to_build) = trans.entered.clone() {
|
|
||||||
if to_build != closed_when.0 {
|
|
||||||
c.trigger(BuildUi(to_build));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use crate::OnPressAction;
|
|
||||||
|
|
||||||
use super::Action;
|
|
||||||
|
|
||||||
pub fn text(t: String) -> impl Bundle {
|
|
||||||
(
|
|
||||||
Text::new(t),
|
|
||||||
TextFont {
|
|
||||||
// font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
|
||||||
font_size: 33.0,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
TextColor(Color::srgb(0.9, 0.9, 0.9)),
|
|
||||||
TextShadow::default(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn button(t: String) -> impl Bundle {
|
|
||||||
(
|
|
||||||
Button,
|
|
||||||
Node {
|
|
||||||
border: UiRect::all(Val::Px(5.0)),
|
|
||||||
// horizontally center child text
|
|
||||||
justify_content: JustifyContent::Center,
|
|
||||||
// vertically center child text
|
|
||||||
align_items: AlignItems::Center,
|
|
||||||
padding: UiRect::all(Val::Px(10.0)),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
BorderColor(Color::BLACK),
|
|
||||||
BorderRadius::MAX,
|
|
||||||
BackgroundColor(Color::srgb(0.2, 0.2, 0.2)),
|
|
||||||
children![text(t)],
|
|
||||||
)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue