diff --git a/dash-frontend/assets/sound/app_start.mp3 b/dash-frontend/assets/sound/app_start.mp3 index 155f110..1f16600 100644 Binary files a/dash-frontend/assets/sound/app_start.mp3 and b/dash-frontend/assets/sound/app_start.mp3 differ diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index 6e7646e..30cbb2e 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -60,6 +60,7 @@ pub struct Frontend { popup_manager: PopupManager, toast_manager: ToastManager, timestep: Timestep, + sounds_to_play: Vec, window_audio_settings: WguiWindow, view_audio_settings: Option, @@ -72,11 +73,22 @@ pub struct FrontendUpdateParams<'a, T> { pub timestep_alpha: f32, } +pub struct FrontendUpdateResult { + pub layout_result: LayoutUpdateResult, + pub sounds_to_play: Vec, +} + pub struct InitParams { pub settings: Box, pub interface: BoxDashInterface, } +#[derive(Clone)] +pub enum SoundType { + Startup, + Launch, +} + #[derive(Clone)] pub enum FrontendTask { SetTab(TabType), @@ -88,6 +100,7 @@ pub enum FrontendTask { UpdateAudioSettingsView, RecenterPlayspace, PushToast(Translation), + PlaySound(SoundType), } impl Frontend { @@ -153,6 +166,7 @@ impl Frontend { window_audio_settings: WguiWindow::default(), view_audio_settings: None, executor: Rc::new(smol::LocalExecutor::new()), + sounds_to_play: Vec::new(), }; // init some things first @@ -164,20 +178,25 @@ impl Frontend { Ok(frontend) } - pub fn play_startup_sound(&mut self, audio_system: &mut audio::AudioSystem) -> anyhow::Result<()> { - // play startup sound - let mut assets = self.globals.assets_builtin(); + fn queue_play_sound(&mut self, sound_type: SoundType) { + self.sounds_to_play.push(sound_type); + } - let sample_startup = audio::AudioSample::from_mp3(&assets.load_from_path("sound/startup.mp3")?)?; - audio_system.play_sample(&sample_startup); + fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> { + let mut assets = self.globals.assets_builtin(); + let sample = audio::AudioSample::from_mp3(&assets.load_from_path(match sound_type { + SoundType::Startup => "sound/startup.mp3", + SoundType::Launch => "sound/app_start.mp3", + })?)?; + audio_system.play_sample(&sample); Ok(()) } - pub fn update(&mut self, params: FrontendUpdateParams) -> anyhow::Result { + pub fn update(&mut self, mut params: FrontendUpdateParams) -> anyhow::Result { let mut tasks = self.tasks.drain(); while let Some(task) = tasks.pop_front() { - self.process_task(params.data, task)?; + self.process_task(&mut params, task)?; } if let Some(mut tab) = self.current_tab.take() { @@ -190,13 +209,27 @@ impl Frontend { while self.executor.try_tick() {} let res = self.tick(params)?; - self.ticks += 1; Ok(res) } - fn tick(&mut self, params: FrontendUpdateParams) -> anyhow::Result { + pub fn process_update( + &mut self, + res: FrontendUpdateResult, + audio_system: &mut audio::AudioSystem, + audio_sample_player: &mut audio::SamplePlayer, + ) -> anyhow::Result<()> { + for sound_type in res.sounds_to_play { + self.play_sound(audio_system, sound_type)?; + } + + audio_sample_player.play_wgui_samples(audio_system, res.layout_result.sounds_to_play); + + Ok(()) + } + + fn tick(&mut self, params: FrontendUpdateParams) -> anyhow::Result { // fixme: timer events instead of this thing if self.ticks.is_multiple_of(1000) { self.update_time()?; @@ -209,9 +242,14 @@ impl Frontend { } } - self.layout.update(&mut LayoutUpdateParams { + let layout_result = self.layout.update(&mut LayoutUpdateParams { size: Vec2::new(params.width, params.height), timestep_alpha: params.timestep_alpha, + })?; + + Ok(FrontendUpdateResult { + layout_result, + sounds_to_play: std::mem::take(&mut self.sounds_to_play), }) } @@ -283,17 +321,18 @@ impl Frontend { Ok(()) } - fn process_task(&mut self, data: &mut T, task: FrontendTask) -> anyhow::Result<()> { + fn process_task(&mut self, params: &mut FrontendUpdateParams, task: FrontendTask) -> anyhow::Result<()> { match task { - FrontendTask::SetTab(tab_type) => self.set_tab(data, tab_type)?, + FrontendTask::SetTab(tab_type) => self.set_tab(params.data, tab_type)?, FrontendTask::RefreshClock => self.update_time()?, FrontendTask::RefreshBackground => self.update_background()?, FrontendTask::MountPopup(params) => self.mount_popup(params)?, FrontendTask::RefreshPopupManager => self.refresh_popup_manager()?, FrontendTask::ShowAudioSettings => self.action_show_audio_settings()?, FrontendTask::UpdateAudioSettingsView => self.action_update_audio_settings()?, - FrontendTask::RecenterPlayspace => self.action_recenter_playspace(data)?, + FrontendTask::RecenterPlayspace => self.action_recenter_playspace(params.data)?, FrontendTask::PushToast(content) => self.toast_manager.push(content), + FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type), }; Ok(()) } diff --git a/dash-frontend/src/views/app_launcher.rs b/dash-frontend/src/views/app_launcher.rs index 942337c..385ed79 100644 --- a/dash-frontend/src/views/app_launcher.rs +++ b/dash-frontend/src/views/app_launcher.rs @@ -15,7 +15,7 @@ use wgui::{ use wlx_common::{dash_interface::BoxDashInterface, desktop_finder::DesktopEntry}; use crate::{ - frontend::{FrontendTask, FrontendTasks}, + frontend::{FrontendTask, FrontendTasks, SoundType}, settings::SettingsIO, }; @@ -335,6 +335,8 @@ impl View { "APPLICATION_STARTED", ))); + params.frontend_tasks.push(FrontendTask::PlaySound(SoundType::Launch)); + (*params.on_launched)(); // we're done! diff --git a/dash-frontend/src/views/game_launcher.rs b/dash-frontend/src/views/game_launcher.rs index 42fbcdb..2267e06 100644 --- a/dash-frontend/src/views/game_launcher.rs +++ b/dash-frontend/src/views/game_launcher.rs @@ -1,7 +1,7 @@ use std::rc::Rc; use crate::{ - frontend::{FrontendTask, FrontendTasks}, + frontend::{FrontendTask, FrontendTasks, SoundType}, util::{ cached_fetcher::{self, CoverArt}, steam_utils::{self, AppID, AppManifest}, @@ -178,6 +178,7 @@ impl View { .push(FrontendTask::PushToast(Translation::from_translation_key( "GAME_LAUNCHED", ))); + self.frontend_tasks.push(FrontendTask::PlaySound(SoundType::Launch)); } Err(e) => { self diff --git a/uidev/assets/sound/wgui_checkbox_check.mp3 b/uidev/assets/sound/wgui_checkbox_check.mp3 new file mode 120000 index 0000000..d790586 --- /dev/null +++ b/uidev/assets/sound/wgui_checkbox_check.mp3 @@ -0,0 +1 @@ +../../../wlx-overlay-s/src/assets/sound/wgui_checkbox_check.mp3 \ No newline at end of file diff --git a/uidev/assets/sound/wgui_checkbox_uncheck.mp3 b/uidev/assets/sound/wgui_checkbox_uncheck.mp3 new file mode 120000 index 0000000..13da97d --- /dev/null +++ b/uidev/assets/sound/wgui_checkbox_uncheck.mp3 @@ -0,0 +1 @@ +../../../wlx-overlay-s/src/assets/sound/wgui_checkbox_uncheck.mp3 \ No newline at end of file diff --git a/uidev/src/testbed/testbed_dashboard.rs b/uidev/src/testbed/testbed_dashboard.rs index 2a67350..be1ed7e 100644 --- a/uidev/src/testbed/testbed_dashboard.rs +++ b/uidev/src/testbed/testbed_dashboard.rs @@ -70,14 +70,16 @@ impl TestbedDashboard { } impl Testbed for TestbedDashboard { - fn update(&mut self, mut params: TestbedUpdateParams) -> anyhow::Result<()> { + fn update(&mut self, params: TestbedUpdateParams) -> anyhow::Result<()> { let res = self.frontend.update(FrontendUpdateParams { data: &mut (), /* nothing */ width: params.width, height: params.height, timestep_alpha: params.timestep_alpha, })?; - params.process_layout_result(res); + self + .frontend + .process_update(res, params.audio_system, params.audio_sample_player)?; Ok(()) } diff --git a/wgui/src/components/checkbox.rs b/wgui/src/components/checkbox.rs index aea781c..ef9413f 100644 --- a/wgui/src/components/checkbox.rs +++ b/wgui/src/components/checkbox.rs @@ -15,6 +15,7 @@ use crate::{ i18n::Translation, layout::{self, WidgetID, WidgetPair}, renderer_vk::text::{FontWeight, TextStyle}, + sound::WguiSoundType, widget::{ ConstructEssentials, EventResult, label::{WidgetLabel, WidgetLabelParams}, @@ -249,16 +250,21 @@ fn register_event_mouse_release( state.down = false; if let Some(self_ref) = state.self_ref.upgrade() - && let Some(radio) = data.radio_group.as_ref().and_then(|r| r.upgrade()) + && let Some(radio) = data.radio_group.as_ref().and_then(Weak::upgrade) { radio.set_selected_internal(common, &self_ref)?; state.checked = true; // can't uncheck radiobox by clicking the checked box again + common.alterables.play_sound(WguiSoundType::CheckboxCheck); } else { state.checked = !state.checked; + common.alterables.play_sound(if state.checked { + WguiSoundType::CheckboxCheck + } else { + WguiSoundType::CheckboxUncheck + }); } set_box_checked(&common.state.widgets, &data, state.checked); - if state.hovered && let Some(on_toggle) = &state.on_toggle { @@ -383,7 +389,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul id_inner_box: inner_box.id, id_label: label.id, value: params.value, - radio_group: params.radio_group.as_ref().map(|x| Rc::downgrade(x)), + radio_group: params.radio_group.as_ref().map(Rc::downgrade), }); let state = Rc::new(RefCell::new(State { diff --git a/wgui/src/sound.rs b/wgui/src/sound.rs index 389265d..8a4251c 100644 --- a/wgui/src/sound.rs +++ b/wgui/src/sound.rs @@ -3,4 +3,6 @@ pub enum WguiSoundType { ButtonMouseEnter, ButtonPress, ButtonRelease, + CheckboxCheck, + CheckboxUncheck, } diff --git a/wlx-common/src/audio.rs b/wlx-common/src/audio.rs index fcd2864..7a4d5df 100644 --- a/wlx-common/src/audio.rs +++ b/wlx-common/src/audio.rs @@ -21,6 +21,8 @@ fn get_sample_name_from_wgui_sound_type(sound: WguiSoundType) -> &'static str { WguiSoundType::ButtonMouseEnter => "wgui_mouse_enter", WguiSoundType::ButtonPress => "wgui_button_press", WguiSoundType::ButtonRelease => "wgui_button_release", + WguiSoundType::CheckboxCheck => "wgui_checkbox_check", + WguiSoundType::CheckboxUncheck => "wgui_checkbox_uncheck", } } @@ -62,6 +64,8 @@ impl SamplePlayer { load(WguiSoundType::ButtonPress)?; load(WguiSoundType::ButtonRelease)?; load(WguiSoundType::ButtonMouseEnter)?; + load(WguiSoundType::CheckboxCheck)?; + load(WguiSoundType::CheckboxUncheck)?; Ok(()) } diff --git a/wlx-overlay-s/src/assets/sound/wgui_checkbox_check.mp3 b/wlx-overlay-s/src/assets/sound/wgui_checkbox_check.mp3 new file mode 100644 index 0000000..8a42783 Binary files /dev/null and b/wlx-overlay-s/src/assets/sound/wgui_checkbox_check.mp3 differ diff --git a/wlx-overlay-s/src/assets/sound/wgui_checkbox_uncheck.mp3 b/wlx-overlay-s/src/assets/sound/wgui_checkbox_uncheck.mp3 new file mode 100644 index 0000000..87f07cb Binary files /dev/null and b/wlx-overlay-s/src/assets/sound/wgui_checkbox_uncheck.mp3 differ diff --git a/wlx-overlay-s/src/overlays/dashboard.rs b/wlx-overlay-s/src/overlays/dashboard.rs index 65f59bd..d345cb4 100644 --- a/wlx-overlay-s/src/overlays/dashboard.rs +++ b/wlx-overlay-s/src/overlays/dashboard.rs @@ -1,5 +1,5 @@ use dash_frontend::{ - frontend::{self, FrontendUpdateParams}, + frontend::{self, FrontendTask, FrontendUpdateParams}, settings::{self, SettingsIO}, }; use glam::{Affine2, Affine3A, Vec2, vec2, vec3}; @@ -106,12 +106,14 @@ impl DashFrontend { let settings = SimpleSettingsIO::new(); let interface = DashInterfaceLive::new(); - let mut frontend = frontend::Frontend::new(frontend::InitParams { + let frontend = frontend::Frontend::new(frontend::InitParams { settings: Box::new(settings), interface: Box::new(interface), })?; - frontend.play_startup_sound(&mut app.audio_system)?; + frontend + .tasks + .push(FrontendTask::PlaySound(frontend::SoundType::Startup)); let context = WguiContext::new(&mut app.wgui_shared, 1.0)?; Ok(Self { @@ -131,7 +133,8 @@ impl DashFrontend { height: DASH_RES_VEC2.y / GUI_SCALE, timestep_alpha, })?; - app_misc::process_layout_result(app, res); + self.inner + .process_update(res, &mut app.audio_system, &mut app.audio_sample_player)?; Ok(()) }