From 45514ae2f448b8bf2bdcd239b751f39eed9c360d Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 29 Apr 2026 20:27:01 +0200 Subject: [PATCH] =?UTF-8?q?feat(menu):=20sons=20de=20navegaci=C3=B3=20i=20?= =?UTF-8?q?acceptaci=C3=B3=20al=20men=C3=BA=20de=20servei?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/sounds/menu_accept.wav | Bin 0 -> 2806 bytes data/sounds/menu_select.wav | Bin 0 -> 1978 bytes data/ui.yaml | 7 +++++++ source/core/system/director.cpp | 8 ++++++++ source/core/ui/ui_config.cpp | 8 ++++++++ source/core/ui/ui_config.hpp | 8 ++++++++ source/game/ui/service_menu.cpp | 19 +++++++++++++++++++ source/game/ui/service_menu.hpp | 6 ++++++ source/utils/defaults.hpp | 6 ++++++ 9 files changed, 62 insertions(+) create mode 100644 data/sounds/menu_accept.wav create mode 100644 data/sounds/menu_select.wav diff --git a/data/sounds/menu_accept.wav b/data/sounds/menu_accept.wav new file mode 100644 index 0000000000000000000000000000000000000000..3cebb3e32a8378deac9ad642d3fe9f50ea359bb1 GIT binary patch literal 2806 zcmeHJ*HT(R7(U)*a+OEOdnB=gihvXWV?;z0YzV>;Q4mpzf~c_}3W|V=1xv736bsf@ z$us2NbJRgS%*2^Yu2_b-`$T_M5q7$h+(1}Ax*BtKYzk7ECYV|5sdg}U>~p= zDK5Q*ZxR>r*wMl6_U6Xg%2IePI6Li~oERJVIp}iq+AQ5&ordJ%W&HH`aBpYx*Lq|*JRh2!@l8#Pj}8yHoPBm{ zkJ)7G(CcuGx*2d3wKA!svZB09B;fNnY*ukmA)S_&lb!j^eVafy2MA{^vJ{>V&dvaz z@loJI;vhaxIC6v|1{|S)&*iY02qz!mXzy>XF3w^{`@7rGjn$RKg}H!#+Us$Hu7Unn zx*F>hNLMB35(!Ir+!7X(QCL7jx;PIc9YWR<9p4K&$+A+?IlQ~RIzKxBI$P28)#b&7 zP{8k-^0>hrL?_7|l@jRG%79J<&=HjKI3=uNL?xPpB2?j2s$QCGGPFO3l}Z)o;qLnK{Pg5-e`gD2zBnHWK;|Bl`9S}x%n4OeP*o19 z$jliib5M13cavn!V^(0!*a%_Hiy1^PDY7EWdDkez=)4_eN^{;H`M)&h;&F1G2RXGl zsRsGcoMXy!?xZ^Be`5|Db2y%9bI42Z)#RkjNq!;H=8(^4`dE?OB7Nt;Qy!1~#|s&n z1yll5Eub;My9ech4`qkVViq&X$X6V?30VQ*8Al~&7)lrP3cJB2tEwcDO0n1^?`($fPl zCR3-;Xz1u@*X!HbbUIyYD~{t@tyTl8g(s4ts?Ir%A8TvR%Yv}6>i*7RnU$}CAS~hcZ7eANCE<$@3TA>bzUe#x z?RNVScmVE!zrY{hj?e-e4yV((zV33l+-~;<;PH68Ua!yR`w95{{!L&D2m}J#z|ElF z@ArDWe?Yg}?R4~4=o$T$ltQ(DNude?JAf$W$D`43I2;T#a$;A>i5(>nxvUE#We`Tn zG+`W_D2gFqG8vD}#F}g?@s3`r9Y#r#t|l6-MKGr~kM`M6Ng_kwl#Zs;`K)@6Z{K(V zODvV6lWOG(DeHn%ZNUt!I%||S`W?~=N#z=gI9MGk@}zot$a2kdv(m)WP6IyHQ;FT# zk(#w*loBU0N@C{*>HMxX7S&IY=bU2m>o*OVXh-U6rX+T4k&59mM%S1DMAaB4nkU|W z%9N>oMD_iwBC4~u#~l9=RW((kMSDPvs?9ltRi>!UunL=tmdl%{^7X%3rTV`hswS&u z)o&S9y{XEi{(n)$0^qE&-h CurveFn; + // Sons del menú de servei. Claus de Resource::Cache::loadSound (els + // fitxers viuen a `data/sounds/`). + [[nodiscard]] auto menuSelectSound() const -> const std::string& { return menu_select_sound_; } + [[nodiscard]] auto menuAcceptSound() const -> const std::string& { return menu_accept_sound_; } + // Fonts de UI. [[nodiscard]] auto hudFont() const -> const Font& { return hud_font_; } [[nodiscard]] auto placeholderFont() const -> const Font& { return placeholder_font_; } @@ -121,6 +126,9 @@ class UiConfig { CurveFn pause_enter_curve_; CurveFn pause_exit_curve_; + std::string menu_select_sound_; + std::string menu_accept_sound_; + Font hud_font_; Font placeholder_font_; Font room_text_font_; diff --git a/source/game/ui/service_menu.cpp b/source/game/ui/service_menu.cpp index d872ac0..6dfefaa 100644 --- a/source/game/ui/service_menu.cpp +++ b/source/game/ui/service_menu.cpp @@ -459,6 +459,14 @@ namespace { } // namespace +void ServiceMenu::playSelectSound() { + Audio::get()->playSound(UiConfig::get().menuSelectSound(), Audio::Group::INTERFACE); +} + +void ServiceMenu::playAcceptSound() { + Audio::get()->playSound(UiConfig::get().menuAcceptSound(), Audio::Group::INTERFACE); +} + void ServiceMenu::handleGamepadButtonDown(const SDL_GamepadButtonEvent& ev) { // El botó SERVICE (per defecte BACK; remapejable per dispositiu via // `GamepadBindings`) tanca el menú sencer. Cada mando pot tenir el @@ -466,26 +474,32 @@ void ServiceMenu::handleGamepadButtonDown(const SDL_GamepadButtonEvent& ev) { const int SERVICE_BTN = serviceButtonForEvent(ev.which); if (SERVICE_BTN >= 0 && static_cast(ev.button) == SERVICE_BTN) { close(); + playSelectSound(); return; } switch (ev.button) { case SDL_GAMEPAD_BUTTON_DPAD_UP: moveCursor(-1); + playSelectSound(); break; case SDL_GAMEPAD_BUTTON_DPAD_DOWN: moveCursor(+1); + playSelectSound(); break; case SDL_GAMEPAD_BUTTON_DPAD_LEFT: activateCurrent(-1); + playAcceptSound(); break; case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: case SDL_GAMEPAD_BUTTON_EAST: case SDL_GAMEPAD_BUTTON_NORTH: activateCurrent(+1); + playAcceptSound(); break; case SDL_GAMEPAD_BUTTON_WEST: case SDL_GAMEPAD_BUTTON_SOUTH: popPage(); + playSelectSound(); break; default: break; @@ -567,21 +581,26 @@ auto ServiceMenu::handleEvent(const SDL_Event& ev) -> bool { switch (SC) { case SDL_SCANCODE_UP: moveCursor(-1); + playSelectSound(); break; case SDL_SCANCODE_DOWN: moveCursor(+1); + playSelectSound(); break; case SDL_SCANCODE_LEFT: activateCurrent(-1); + playAcceptSound(); break; case SDL_SCANCODE_RIGHT: case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: activateCurrent(+1); + playAcceptSound(); break; case SDL_SCANCODE_BACKSPACE: case SDL_SCANCODE_ESCAPE: popPage(); + playSelectSound(); break; default: break; diff --git a/source/game/ui/service_menu.hpp b/source/game/ui/service_menu.hpp index 669f7f0..8bd0d22 100644 --- a/source/game/ui/service_menu.hpp +++ b/source/game/ui/service_menu.hpp @@ -207,6 +207,12 @@ class ServiceMenu { // mètode propi per a mantenir la complexitat cognitiva d'`handleEvent` // sota el llindar de clang-tidy. void handleGamepadButtonDown(const SDL_GamepadButtonEvent& ev); + + // Sons d'UI: SELECT acompanya navegació (amunt/avall) i back; ACCEPT + // acompanya modificació d'opció (esquerra/dreta/retorn). Els noms de + // recurs venen d'`UiConfig` i el preload el fa el Director. + static void playSelectSound(); + static void playAcceptSound(); [[nodiscard]] auto top() -> Page&; [[nodiscard]] auto topConst() const -> const Page&; [[nodiscard]] static auto isItemVisible(const Item& item) -> bool; diff --git a/source/utils/defaults.hpp b/source/utils/defaults.hpp index f182fa1..411444d 100644 --- a/source/utils/defaults.hpp +++ b/source/utils/defaults.hpp @@ -216,6 +216,12 @@ namespace Defaults { constexpr int PAUSE_EXIT_MS = 250; constexpr const char* PAUSE_ENTER_CURVE = "outCubic"; constexpr const char* PAUSE_EXIT_CURVE = "inCubic"; + + // Sons del menú de servei. SELECT acompanya navegació (amunt/avall) + // i back; ACCEPT acompanya modificació d'opció (esq/dret/retorn). + // Els fitxers viuen a `data/sounds/`; només es referencia el nom. + constexpr const char* MENU_SELECT_SOUND = "menu_select.wav"; + constexpr const char* MENU_ACCEPT_SOUND = "menu_accept.wav"; } // namespace UI #ifdef _DEBUG