Merge branch '68-startscreen-settings-implementation' into 'dev'
StartScreen Settings implementation See merge request softwaregrundprojekt/2025-2026/einzelprojekt/tutorium-moritz/bernroider-dominik/bernroider-dominik!43
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
|
use crate::features::phase::components::TimerSettings;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Markers for main menu UI.
|
/// Markers for main menu UI.
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub enum RootMarker {
|
pub enum RootMarker {
|
||||||
MainMenu,
|
MainMenu,
|
||||||
|
Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Buttons in the main menu.
|
/// Buttons in the main menu.
|
||||||
@@ -13,3 +15,6 @@ pub enum ButtonType {
|
|||||||
NewGame,
|
NewGame,
|
||||||
Settings,
|
Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default, Debug)]
|
||||||
|
pub struct StartScreenTimerSettings(pub Option<TimerSettings>);
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
|
use crate::features::hud::components::{SettingsTimerInput, TimerType};
|
||||||
|
use crate::features::phase::components::TimerSettings;
|
||||||
use crate::features::savegame::ui::spawn_load_popup;
|
use crate::features::savegame::ui::spawn_load_popup;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use components::*;
|
use components::*;
|
||||||
|
use ui::settings::open_settings_menu;
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
|
pub mod ui;
|
||||||
|
|
||||||
/// Plugin for the main menu screen.
|
/// Plugin for the main menu screen.
|
||||||
pub struct StartScreenPlugin;
|
pub struct StartScreenPlugin;
|
||||||
|
|
||||||
impl Plugin for StartScreenPlugin {
|
impl Plugin for StartScreenPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
|
app.init_resource::<StartScreenTimerSettings>();
|
||||||
app.add_systems(OnEnter(AppState::StartScreen), setup);
|
app.add_systems(OnEnter(AppState::StartScreen), setup);
|
||||||
app.add_systems(OnExit(AppState::StartScreen), cleanup);
|
app.add_systems(OnExit(AppState::StartScreen), cleanup);
|
||||||
app.add_systems(Update, menu.run_if(in_state(AppState::StartScreen)));
|
app.add_systems(
|
||||||
|
Update,
|
||||||
|
(menu, handle_settings_buttons, update_timer_settings_display)
|
||||||
|
.run_if(in_state(AppState::StartScreen)),
|
||||||
|
);
|
||||||
|
app.add_systems(
|
||||||
|
PostUpdate,
|
||||||
|
apply_start_screen_settings.run_if(in_state(AppState::GameScreen)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +83,7 @@ fn menu(
|
|||||||
) {
|
) {
|
||||||
for (interaction, button_type) in &mut interaction_query {
|
for (interaction, button_type) in &mut interaction_query {
|
||||||
match *interaction {
|
match *interaction {
|
||||||
Interaction::Pressed => {
|
Interaction::Pressed => match button_type {
|
||||||
match button_type {
|
|
||||||
ButtonType::LoadGame => {
|
ButtonType::LoadGame => {
|
||||||
spawn_load_popup(&mut commands);
|
spawn_load_popup(&mut commands);
|
||||||
}
|
}
|
||||||
@@ -79,9 +91,10 @@ fn menu(
|
|||||||
commands.insert_resource(SavegamePath::next());
|
commands.insert_resource(SavegamePath::next());
|
||||||
next_state.set(AppState::GameScreen);
|
next_state.set(AppState::GameScreen);
|
||||||
}
|
}
|
||||||
ButtonType::Settings => todo!(),
|
ButtonType::Settings => {
|
||||||
};
|
open_settings_menu(&mut commands);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,3 +106,79 @@ fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) {
|
|||||||
commands.entity(entity).despawn();
|
commands.entity(entity).despawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles button interactions within the settings menu.
|
||||||
|
fn handle_settings_buttons(
|
||||||
|
mut interaction_query: Query<
|
||||||
|
(&Interaction, &crate::features::hud::components::ButtonType),
|
||||||
|
(Changed<Interaction>, With<Button>),
|
||||||
|
>,
|
||||||
|
mut timer_settings: ResMut<TimerSettings>,
|
||||||
|
mut ss_timer_settings: ResMut<StartScreenTimerSettings>,
|
||||||
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
|
) {
|
||||||
|
let shift_multiplier = if keys.any_pressed([KeyCode::ShiftLeft, KeyCode::ShiftRight]) {
|
||||||
|
10
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
for (interaction, button_type) in &mut interaction_query {
|
||||||
|
if *interaction == Interaction::Pressed {
|
||||||
|
if let crate::features::hud::components::ButtonType::SettingsTimerChange {
|
||||||
|
input,
|
||||||
|
amount,
|
||||||
|
} = button_type
|
||||||
|
{
|
||||||
|
match input {
|
||||||
|
SettingsTimerInput::Minutes(timer_type) => {
|
||||||
|
timer_settings.change(timer_type, 60 * amount * shift_multiplier)
|
||||||
|
}
|
||||||
|
SettingsTimerInput::Seconds(timer_type) => {
|
||||||
|
timer_settings.change(timer_type, *amount * shift_multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss_timer_settings.0 = Some(timer_settings.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the timer settings display in the settings menu.
|
||||||
|
fn update_timer_settings_display(
|
||||||
|
timer_settings: Res<TimerSettings>,
|
||||||
|
mut query: Query<(&SettingsTimerInput, &mut Text)>,
|
||||||
|
) {
|
||||||
|
for (input_type, mut text) in query.iter_mut() {
|
||||||
|
match input_type {
|
||||||
|
SettingsTimerInput::Minutes(timer_type) => {
|
||||||
|
let value = match timer_type {
|
||||||
|
TimerType::Focus => timer_settings.focus_duration,
|
||||||
|
TimerType::ShortBreak => timer_settings.short_break_duration,
|
||||||
|
TimerType::LongBreak => timer_settings.long_break_duration,
|
||||||
|
} as f32;
|
||||||
|
|
||||||
|
text.0 = format!("{:0>2}", (value / 60.0).floor());
|
||||||
|
}
|
||||||
|
SettingsTimerInput::Seconds(timer_type) => {
|
||||||
|
let value = match timer_type {
|
||||||
|
TimerType::Focus => timer_settings.focus_duration,
|
||||||
|
TimerType::ShortBreak => timer_settings.short_break_duration,
|
||||||
|
TimerType::LongBreak => timer_settings.long_break_duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
text.0 = format!("{:0>2}", (value % 60));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies the timer settings from the start screen once the game screen is entered.
|
||||||
|
fn apply_start_screen_settings(
|
||||||
|
mut settings: ResMut<TimerSettings>,
|
||||||
|
mut ss_settings: ResMut<StartScreenTimerSettings>,
|
||||||
|
) {
|
||||||
|
if let Some(new_settings) = ss_settings.0.take() {
|
||||||
|
*settings = new_settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
1
src/features/start_screen/ui/mod.rs
Normal file
1
src/features/start_screen/ui/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod settings;
|
||||||
71
src/features/start_screen/ui/settings.rs
Normal file
71
src/features/start_screen/ui/settings.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use crate::features::hud::components::TimerType;
|
||||||
|
use crate::features::hud::ui::timer_settings::timer_settings;
|
||||||
|
use crate::features::start_screen::components::RootMarker;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Spawns the settings popup for the start screen.
|
||||||
|
pub fn open_settings_menu(commands: &mut Commands) {
|
||||||
|
spawn_popup(
|
||||||
|
commands,
|
||||||
|
RootMarker::Settings,
|
||||||
|
"Einstellungen",
|
||||||
|
Node {
|
||||||
|
width: px(700),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
|parent| {
|
||||||
|
parent.spawn((
|
||||||
|
Node {
|
||||||
|
justify_content: JustifyContent::Center,
|
||||||
|
..Node::hstack(px(30))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
width: percent(40),
|
||||||
|
..Node::vstack(px(10))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
text("Timer Einstellungen", 18.0, Color::WHITE),
|
||||||
|
text(
|
||||||
|
"Tipp: Benutze [Umschalt] um in 10er Schritten zu inkrementieren oder dekrementieren!",
|
||||||
|
16.0,
|
||||||
|
Color::WHITE
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..Node::vstack(px(10))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
text("Fokus Phase", 12.0, Color::WHITE),
|
||||||
|
timer_settings(TimerType::Focus)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..Node::vstack(px(10))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
text("Kurze Pause", 12.0, Color::WHITE),
|
||||||
|
timer_settings(TimerType::ShortBreak)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Node {
|
||||||
|
align_items: AlignItems::Center,
|
||||||
|
..Node::vstack(px(10))
|
||||||
|
},
|
||||||
|
children![
|
||||||
|
text("Lange Pause", 12.0, Color::WHITE),
|
||||||
|
timer_settings(TimerType::LongBreak)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user