From 8c9a27f0df6dd1f1812b963e0673b6028d6e5010 Mon Sep 17 00:00:00 2001 From: demenik Date: Thu, 11 Dec 2025 20:20:30 +0100 Subject: [PATCH] feat: Implement achievement menu UI (#47) --- src/features/achievement/mod.rs | 1 + src/features/achievement/ui.rs | 90 +++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/features/achievement/ui.rs diff --git a/src/features/achievement/mod.rs b/src/features/achievement/mod.rs index df4d7a5..3d8d7a0 100644 --- a/src/features/achievement/mod.rs +++ b/src/features/achievement/mod.rs @@ -5,6 +5,7 @@ use components::{AchievementId, AchievementProgress}; use strum::IntoEnumIterator; pub mod components; +pub mod ui; pub struct AchievementPlugin; diff --git a/src/features/achievement/ui.rs b/src/features/achievement/ui.rs new file mode 100644 index 0000000..8dbe75c --- /dev/null +++ b/src/features/achievement/ui.rs @@ -0,0 +1,90 @@ +use crate::features::achievement::components::{AchievementId, AchievementProgress}; +use crate::features::ui::ui::popups::spawn_popup; +use crate::prelude::*; +use strum::IntoEnumIterator; + +#[derive(Component)] +pub enum AchievementRootMarker { + Menu, +} + +pub fn open_achievements_menu(commands: &mut Commands, progress: &AchievementProgress) { + spawn_popup( + commands, + AchievementRootMarker::Menu, + "Erfolge", + Node { + width: px(700), + height: px(500), + ..default() + }, + |parent| { + // Scrollable Content + parent + .spawn((Node { + width: percent(100), + height: percent(100), + flex_direction: FlexDirection::Column, + overflow: Overflow::scroll_y(), + padding: UiRect::all(px(10)), + row_gap: px(10), + ..default() + },)) + .with_children(|list| { + for id in AchievementId::iter() { + let unlocked = progress.is_unlocked(&id); + let color = if unlocked { + Color::WHITE + } else { + Color::srgb(0.5, 0.5, 0.5) + }; + + let bg_color = if unlocked { + Color::srgb(0.2, 0.3, 0.2) // Dark Greenish for unlocked + } else { + Color::srgb(0.1, 0.1, 0.1) // Dark Grey for locked + }; + + list.spawn(( + Node { + width: percent(100), + padding: UiRect::all(px(10)), + flex_direction: FlexDirection::Column, + row_gap: px(5), + border: UiRect::all(px(2)), + ..default() + }, + BackgroundColor(bg_color), + BorderColor::all(if unlocked { + Color::srgb(0.4, 0.8, 0.4) + } else { + Color::BLACK + }), + BorderRadius::all(px(5)), + )) + .with_children(|item| { + // Title + item.spawn(text(id.title(), 20.0, color)); + // Description + item.spawn(text(id.description(), 16.0, color)); + // Status Text + let status = if unlocked { + "Freigeschaltet" + } else { + "Gesperrt" + }; + item.spawn(text( + status, + 12.0, + if unlocked { + Color::srgb(0.6, 1.0, 0.6) + } else { + Color::srgb(0.7, 0.3, 0.3) + }, + )); + }); + } + }); + }, + ); +}