feat(engine): implement Draw Mode, Theme, and Music Volume settings
Settings panel "coming soon" stubs replaced with live controls: - Draw Mode toggle (Draw 1 / Draw 3): new games read draw_mode from SettingsResource instead of the previous game's mode. Falls back to the current game's mode in headless/test contexts where SettingsPlugin is absent. - Theme selector (Green → Blue → Dark → Green): SettingsChangedEvent drives TablePlugin's background Sprite colour so the table re-colours immediately without a restart. - Music Volume [−]/[+]: dedicated kira sub-tracks created for SFX and music on startup. SFX sounds are routed to the SFX track; the music track exists for future ambient audio. Both volumes are set on SettingsChangedEvent and at startup. Also fixed: time_attack timer_expiry test double-fires when MinimalPlugins time delta is nonzero — removed the intermediate 0.001-remaining update step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,10 @@ use bevy::prelude::*;
|
||||
use bevy::window::WindowResized;
|
||||
use solitaire_core::card::Suit;
|
||||
use solitaire_core::pile::PileType;
|
||||
use solitaire_data::settings::Theme;
|
||||
|
||||
use crate::layout::{compute_layout, Layout, LayoutResource, TABLE_COLOUR};
|
||||
use crate::settings_plugin::SettingsChangedEvent;
|
||||
|
||||
/// Z-depth used for the background — below everything.
|
||||
const Z_BACKGROUND: f32 = -10.0;
|
||||
@@ -34,8 +36,18 @@ impl Plugin for TablePlugin {
|
||||
// tests. Under DefaultPlugins, bevy_window has already registered it
|
||||
// and this call is a no-op.
|
||||
app.add_event::<WindowResized>()
|
||||
.add_event::<SettingsChangedEvent>()
|
||||
.add_systems(Startup, setup_table)
|
||||
.add_systems(Update, on_window_resized);
|
||||
.add_systems(Update, (on_window_resized, apply_theme_on_settings_change));
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the felt colour for a given theme.
|
||||
fn theme_colour(theme: &Theme) -> Color {
|
||||
match theme {
|
||||
Theme::Green => Color::srgb(TABLE_COLOUR[0], TABLE_COLOUR[1], TABLE_COLOUR[2]),
|
||||
Theme::Blue => Color::srgb(0.059, 0.196, 0.322),
|
||||
Theme::Dark => Color::srgb(0.08, 0.08, 0.10),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +59,7 @@ fn setup_table(
|
||||
mut commands: Commands,
|
||||
windows: Query<&Window>,
|
||||
existing_camera: Query<(), With<Camera>>,
|
||||
settings: Option<Res<crate::settings_plugin::SettingsResource>>,
|
||||
) {
|
||||
// Only spawn a camera if one does not already exist (e.g. a parent app
|
||||
// may have added one in tests).
|
||||
@@ -61,18 +74,23 @@ fn setup_table(
|
||||
.unwrap_or(Vec2::new(1280.0, 800.0));
|
||||
let layout = compute_layout(window_size);
|
||||
|
||||
spawn_background(&mut commands, window_size);
|
||||
let initial_colour = settings
|
||||
.as_ref()
|
||||
.map(|s| theme_colour(&s.0.theme))
|
||||
.unwrap_or_else(|| Color::srgb(TABLE_COLOUR[0], TABLE_COLOUR[1], TABLE_COLOUR[2]));
|
||||
|
||||
spawn_background(&mut commands, window_size, initial_colour);
|
||||
spawn_pile_markers(&mut commands, &layout);
|
||||
commands.insert_resource(LayoutResource(layout));
|
||||
}
|
||||
|
||||
fn spawn_background(commands: &mut Commands, window_size: Vec2) {
|
||||
fn spawn_background(commands: &mut Commands, window_size: Vec2, color: Color) {
|
||||
// Spawn a felt-coloured rectangle that always covers the window. We give
|
||||
// it the window size plus headroom so resizing up doesn't expose edges
|
||||
// before the resize handler runs.
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
color: Color::srgb(TABLE_COLOUR[0], TABLE_COLOUR[1], TABLE_COLOUR[2]),
|
||||
color,
|
||||
custom_size: Some(window_size * 2.0),
|
||||
..default()
|
||||
},
|
||||
@@ -81,6 +99,19 @@ fn spawn_background(commands: &mut Commands, window_size: Vec2) {
|
||||
));
|
||||
}
|
||||
|
||||
fn apply_theme_on_settings_change(
|
||||
mut events: EventReader<SettingsChangedEvent>,
|
||||
mut backgrounds: Query<&mut Sprite, With<TableBackground>>,
|
||||
) {
|
||||
let Some(ev) = events.read().last() else {
|
||||
return;
|
||||
};
|
||||
let colour = theme_colour(&ev.0.theme);
|
||||
for mut sprite in &mut backgrounds {
|
||||
sprite.color = colour;
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_pile_markers(commands: &mut Commands, layout: &Layout) {
|
||||
let marker_colour = Color::srgba(1.0, 1.0, 1.0, 0.08);
|
||||
let marker_size = layout.card_size;
|
||||
|
||||
Reference in New Issue
Block a user