feat: Add inventory display popup (#48)

This commit is contained in:
demenik
2025-11-27 23:12:07 +01:00
parent ca1fe7bcfd
commit 8be97265ee
8 changed files with 219 additions and 9 deletions

View File

@@ -14,7 +14,6 @@ pub enum TextType {
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
SavegameDump,
SettingsOpen, SettingsOpen,
SettingsClose, SettingsClose,
SettingsExit, SettingsExit,

View File

@@ -1,3 +1,4 @@
use crate::features::inventory;
use crate::features::phase::components::TimerSettings; use crate::features::phase::components::TimerSettings;
use crate::features::savegame::messages::SavegameDumpMessage; use crate::features::savegame::messages::SavegameDumpMessage;
use crate::prelude::*; use crate::prelude::*;
@@ -50,15 +51,25 @@ fn setup(mut commands: Commands) {
TextFont::from_font_size(16.0), TextFont::from_font_size(16.0),
TextColor(Color::WHITE) TextColor(Color::WHITE)
), ),
(
Button,
inventory::components::ButtonType::InventoryOpen,
Node::default(),
children![(
Text::new("Inventar"),
TextFont::from_font_size(16.0),
TextColor(Color::WHITE)
)]
),
( (
Button, Button,
ButtonType::SettingsOpen, ButtonType::SettingsOpen,
Node::default(), Node::default(),
children![ children![(
Text::new("Einstellungen"), Text::new("Einstellungen"),
TextFont::from_font_size(16.0), TextFont::from_font_size(16.0),
TextColor(Color::WHITE) TextColor(Color::WHITE)
] )]
) )
], ],
)); ));
@@ -115,7 +126,6 @@ fn buttons(
timer_settings.change(timer_type, *amount) timer_settings.change(timer_type, *amount)
} }
}, },
_ => {}
}, },
_ => {} _ => {}
} }

View File

@@ -1,13 +1,33 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(Component)]
pub struct Item;
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub enum ItemType { pub enum ItemType {
Berry, Berry,
} }
impl ItemType {
pub fn singular(&self) -> String {
match self {
ItemType::Berry => "Beere",
}
.into()
}
pub fn plural(&self) -> String {
match self {
ItemType::Berry => "Beeren",
}
.into()
}
pub fn description(&self) -> String {
match self {
ItemType::Berry => "Von Pflanzen erntbar. Kann im Shop zum Einkaufen benutzt werden.",
}
.into()
}
}
#[derive(Component, Serialize, Deserialize, Clone)] #[derive(Component, Serialize, Deserialize, Clone)]
pub struct ItemStack { pub struct ItemStack {
pub item_type: ItemType, pub item_type: ItemType,
@@ -18,3 +38,14 @@ pub struct ItemStack {
pub struct Inventory { pub struct Inventory {
pub items: Vec<Entity>, pub items: Vec<Entity>,
} }
#[derive(Component)]
pub enum RootMarker {
Inventory,
}
#[derive(Component)]
pub enum ButtonType {
InventoryOpen,
InventoryClose,
}

View File

@@ -1,11 +1,40 @@
use crate::prelude::*; use crate::{features::inventory::ui::open_inventory, prelude::*};
use components::*;
pub mod components; pub mod components;
pub mod ui;
pub struct InventoryPlugin; pub struct InventoryPlugin;
impl Plugin for InventoryPlugin { impl Plugin for InventoryPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<Inventory>(); app.init_resource::<Inventory>();
app.add_systems(Update, buttons.run_if(in_state(AppState::GameScreen)));
}
}
fn buttons(
mut commands: Commands,
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
itemstack_query: Query<&ItemStack>,
root_query: Query<(Entity, &RootMarker)>,
) {
for (interaction, button_type) in &mut interaction_query {
match *interaction {
Interaction::Pressed => match button_type {
ButtonType::InventoryOpen => {
open_inventory(&mut commands, itemstack_query);
}
ButtonType::InventoryClose => {
for (entity, root) in root_query.iter() {
match *root {
RootMarker::Inventory => commands.entity(entity).despawn(),
}
}
}
},
_ => {}
}
} }
} }

View File

@@ -0,0 +1,83 @@
use super::super::components::{ButtonType, RootMarker};
use crate::{features::inventory::ui::list_itemstack, prelude::*};
pub fn open_inventory(commands: &mut Commands, items: Query<&ItemStack>) {
commands
.spawn((
RootMarker::Inventory,
Node {
position_type: PositionType::Absolute,
width: percent(100),
height: percent(100),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
ZIndex(1),
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)),
))
.with_children(|parent| {
parent
.spawn((
Node {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
padding: UiRect::all(px(20.0)),
..default()
},
BackgroundColor(Color::srgb(0.2, 0.2, 0.2)),
BorderRadius::all(px(10.0)),
))
.with_children(|parent| {
parent.spawn((
Node {
width: percent(100.0),
justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Center,
margin: UiRect::bottom(px(20.0)),
column_gap: px(20.0),
..default()
},
children![
(
Text::new("Inventar"),
TextFont::from_font_size(40.0),
TextColor(Color::WHITE),
),
(
Button,
ButtonType::InventoryClose,
Node {
width: px(40.0),
height: px(40.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(Color::srgb(0.8, 0.2, 0.2)),
BorderRadius::MAX,
children![(
Text::new("X"),
TextFont::from_font_size(24.0),
TextColor(Color::WHITE),
)]
)
],
));
parent
.spawn(Node {
width: percent(100),
flex_direction: FlexDirection::Column,
margin: UiRect::top(px(10.0)),
row_gap: px(10.0),
..default()
})
.with_children(|parent| {
for itemstack in items.iter() {
parent.spawn(list_itemstack(itemstack));
}
});
});
});
}

View File

@@ -0,0 +1,53 @@
use crate::prelude::*;
pub fn list_itemstack(itemstack: &ItemStack) -> impl Bundle {
let name = match itemstack.amount {
1 => itemstack.item_type.singular(),
_ => itemstack.item_type.plural(),
};
(
Node {
flex_direction: FlexDirection::Row,
column_gap: px(8),
align_items: AlignItems::Center,
padding: UiRect::all(px(4)),
..default()
},
BackgroundColor(NORMAL_BUTTON),
BorderRadius::all(px(10)),
children![
(
// Placeholder for icon
Node {
height: percent(100),
aspect_ratio: Some(1.0),
..default()
},
BackgroundColor(HOVERED_BUTTON),
BorderRadius::all(px(10))
),
(
Node {
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
row_gap: px(4),
padding: UiRect::vertical(px(4)),
..default()
},
children![
(
Text::new(format!("{} ({})", name, itemstack.amount)),
TextFont::from_font_size(14.0),
TextColor(Color::WHITE)
),
(
Text::new(itemstack.item_type.description()),
TextFont::from_font_size(10.0),
TextColor(Color::WHITE)
)
]
)
],
)
}

View File

@@ -0,0 +1,5 @@
pub mod inventory;
pub mod item;
pub use inventory::*;
pub use item::*;

View File

@@ -7,7 +7,7 @@ pub use crate::features::{
consts::TILE_SIZE, consts::TILE_SIZE,
utils::{grid_to_world_coords, world_to_grid_coords}, utils::{grid_to_world_coords, world_to_grid_coords},
}, },
inventory::components::{Inventory, Item, ItemStack, ItemType}, inventory::components::{Inventory, ItemStack, ItemType},
phase::components::{CurrentPhase, Phase}, phase::components::{CurrentPhase, Phase},
pom::{ pom::{
components::{GridPosition, MovingState, Pom}, components::{GridPosition, MovingState, Pom},