From 886f1e70401bef5b2845f23dd75850fd4c053000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lex=20Rom=C3=A1n=20N=C3=BA=C3=B1ez?= Date: Sun, 20 Sep 2026 13:13:51 +0200 Subject: [PATCH] Add stocks UI --- src/ui/fighter_info.rs | 60 +++++++++++++++++++++++++++++++++++++----- src/ui/mod.rs | 23 ++++++++++++++-- src/ui/stock_icon.rs | 17 ++++++++++++ 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 src/ui/stock_icon.rs diff --git a/src/ui/fighter_info.rs b/src/ui/fighter_info.rs index f1b8681..409a9e3 100644 --- a/src/ui/fighter_info.rs +++ b/src/ui/fighter_info.rs @@ -1,13 +1,17 @@ use bevy::prelude::*; -use crate::{fighter::{attack::FighterDamage, manifest::{FighterManifest}}, match_loading::MatchPlayer, player::Player}; +use crate::{ + fighter::{attack::FighterDamage, manifest::FighterManifest}, match_loading::{MatchPlayer}, match_runtime::MatchState, player::Player, ui::stock_icon::BattleUIStockIcon, +}; #[derive(Component, FromTemplate)] pub struct FighterInfoUI { percentage_text: Entity, + stock_icon_container: Entity, _name_text: Entity, player_handle: usize, visible_damage: FighterDamage, + visible_stocks: u8, } impl FighterInfoUI { @@ -16,6 +20,7 @@ impl FighterInfoUI { bsn! { FighterInfoUI { percentage_text: #PercentageText, + stock_icon_container: #StockIconContainer, _name_text: #NameText, player_handle: {match_player.handle} } @@ -25,6 +30,10 @@ impl FighterInfoUI { justify_content: JustifyContent::Center, } Children [ + ( + #StockIconContainer + Node + ) ( #PercentageText Text("0.00%") @@ -41,17 +50,54 @@ impl FighterInfoUI { } } -pub fn update_fighter_info_damage(fighters: Query<(&Player, &FighterDamage)>, ui_elements: Query<&mut FighterInfoUI>, mut commands: Commands) { +pub fn update_fighter_info_damage( + fighters: Query<(&Player, &FighterDamage)>, + ui_elements: Query<&mut FighterInfoUI>, + mut commands: Commands, +) { for mut ui_element in ui_elements { - let Some((_, damage)) = fighters.iter().find(|(player, _)| { - player.handle == ui_element.player_handle - }) else { + let Some((_, damage)) = fighters + .iter() + .find(|(player, _)| player.handle == ui_element.player_handle) + else { continue; }; if *damage != ui_element.visible_damage { - commands.entity(ui_element.percentage_text).insert(Text(format!("{}%", damage))); + commands + .entity(ui_element.percentage_text) + .insert(Text(format!("{}%", damage))); ui_element.visible_damage = damage.clone(); } } -} \ No newline at end of file +} + +pub fn update_fighter_info_stocks( + match_state: Res, + ui_elements: Query<&mut FighterInfoUI>, + mut commands: Commands, +) { + + for mut ui_element in ui_elements { + let handle = ui_element.player_handle; + let Some(match_player) = match_state.players.get(handle) else { + continue; + }; + + let Some(stocks) = match_player.stocks_remaining else { + continue; + }; + + if stocks != ui_element.visible_stocks { + commands + .entity(ui_element.stock_icon_container) + .despawn_children() + .with_children(|spawner| { + for _ in 0..stocks { + spawner.spawn_empty().apply_scene(BattleUIStockIcon::scene()); + } + }); + ui_element.visible_stocks = stocks; + } + } +} diff --git a/src/ui/mod.rs b/src/ui/mod.rs index f393c32..2b7c6b9 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,10 +1,15 @@ use bevy::prelude::*; -use crate::AppState; +use crate::{ + AppState, + match_loading::{MatchConfig, MatchRules}, + match_runtime::MatchState, +}; pub mod battle_ui; pub mod errors; pub mod fighter_info; +pub mod stock_icon; #[derive(Default)] pub struct InGameUIPlugin; @@ -13,6 +18,20 @@ impl Plugin for InGameUIPlugin { fn build(&self, app: &mut App) { app.add_systems(OnEnter(AppState::InMatch), battle_ui::spawn_battle_ui) .add_systems(OnExit(AppState::InMatch), battle_ui::cleanup_battle_ui) - .add_systems(PostUpdate, fighter_info::update_fighter_info_damage); + .add_systems(PostUpdate, fighter_info::update_fighter_info_damage) + .add_systems( + PostUpdate, + fighter_info::update_fighter_info_stocks.run_if( + resource_exists:: + .and_then(resource_exists::) + .and_then(|match_config: Res| { + if let MatchRules::Stock { .. } = match_config.rules { + true + } else { + false + } + }), + ), + ); } } diff --git a/src/ui/stock_icon.rs b/src/ui/stock_icon.rs new file mode 100644 index 0000000..ef8fbfb --- /dev/null +++ b/src/ui/stock_icon.rs @@ -0,0 +1,17 @@ +use bevy::prelude::*; + +#[derive(SceneComponent, Clone, FromTemplate)] +pub struct BattleUIStockIcon; + +impl BattleUIStockIcon { + pub fn scene() -> impl Scene { + bsn! { + Node { + width: px(32), + height: px(32), + border_radius: BorderRadius::MAX, + } + BackgroundColor({bevy::color::palettes::css::RED}) + } + } +} \ No newline at end of file