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>
- solitaire_data::Settings { sfx_volume, first_run_complete } with
atomic JSON persistence and clamping sanitizer.
- SettingsPlugin (engine): [ / ] adjust SFX volume by 0.1, clamped;
persists on change; emits SettingsChangedEvent. No-op at rails.
- AudioPlugin applies sfx_volume to kira's main track at startup
and on every change so live tweaks take effect without restart.
- Brief "SFX: N%" toast on each change. Help cheat sheet updated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New MoveRejectedEvent fires from end_drag when the cursor is over
a real pile but the placement is illegal. AudioPlugin plays
card_invalid.wav on it.
- New PausePlugin + PausedResource: Esc toggles a full-window
overlay and the flag. tick_elapsed_time and advance_time_attack
skip work while paused. Help cheat sheet updated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New solitaire_assetgen crate with gen_sfx binary: synthesizes
five 44.1kHz mono 16-bit PCM WAVs (flip/place/deal/invalid/fanfare)
from an LCG noise source + sine/square synths. Output committed
under assets/audio/.
- AudioPlugin (engine): embeds the WAVs via include_bytes!, decodes
once with kira::StaticSoundData, plays on Draw / Move / NewGame /
GameWon events. card_invalid is loaded but unused — wiring it
needs a MoveRejectedEvent.
- AudioManager kept on the main thread (NonSend) since cpal is !Send
on some platforms; degrades gracefully if no audio device present.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>