From 011b33c7f876f16856e79f7c7ca4c6f2e722edde Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 9 Feb 2026 16:30:47 -0800 Subject: [PATCH] Add comprehensive UI sound manager for interface interactions Implemented complete UI sound system with 32+ interface sounds: Window sounds (10 types): - Bag open/close (backpack, containers) - Quest log open/close - Character sheet open/close - Auction house open/close - Guild bank open/close Button sounds (2 types): - Interface button clicks - Main menu button clicks Quest sounds (4 types): - Quest activate (new quest accepted) - Quest complete (quest turned in) - Quest failed - Quest update (progress notification) Loot sounds (3 types): - Coin pickup (small/large amounts) - Item loot from creatures Item sounds (6 types): - Drop item on ground - Pickup sounds by item type: bags, books, cloth, food, gems Eating/Drinking (2 types): - Eating food sound - Drinking potion/water sound Special sounds: - Level up fanfare - Error/invalid action feedback - Target select/deselect Technical details: - Loads 32 sound files from Sound\Interface directory - Volume at 0.7 with global scale control - Simple API: playBagOpen(), playQuestComplete(), etc. - Ready for integration with UI systems and game events - Can be hooked to ImGui windows, inventory actions, quest system --- CMakeLists.txt | 1 + include/audio/ui_sound_manager.hpp | 131 +++++++++++++++++ src/audio/ui_sound_manager.cpp | 219 +++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 include/audio/ui_sound_manager.hpp create mode 100644 src/audio/ui_sound_manager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c69e2e2..56985b60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ set(WOWEE_SOURCES src/audio/mount_sound_manager.cpp src/audio/npc_voice_manager.cpp src/audio/ambient_sound_manager.cpp + src/audio/ui_sound_manager.cpp # Pipeline (asset loaders) src/pipeline/mpq_manager.cpp diff --git a/include/audio/ui_sound_manager.hpp b/include/audio/ui_sound_manager.hpp new file mode 100644 index 00000000..5d314a68 --- /dev/null +++ b/include/audio/ui_sound_manager.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include +#include +#include +#include + +namespace wowee { +namespace pipeline { +class AssetManager; +} + +namespace audio { + +class UISoundManager { +public: + UISoundManager() = default; + ~UISoundManager() = default; + + // Initialization + bool initialize(pipeline::AssetManager* assets); + void shutdown(); + + // Volume control + void setVolumeScale(float scale); + + // Window sounds + void playBagOpen(); + void playBagClose(); + void playQuestLogOpen(); + void playQuestLogClose(); + void playCharacterSheetOpen(); + void playCharacterSheetClose(); + void playAuctionHouseOpen(); + void playAuctionHouseClose(); + void playGuildBankOpen(); + void playGuildBankClose(); + + // Button sounds + void playButtonClick(); + void playMenuButtonClick(); + + // Quest sounds + void playQuestActivate(); + void playQuestComplete(); + void playQuestFailed(); + void playQuestUpdate(); + + // Loot sounds + void playLootCoinSmall(); + void playLootCoinLarge(); + void playLootItem(); + + // Item sounds + void playDropOnGround(); + void playPickupBag(); + void playPickupBook(); + void playPickupCloth(); + void playPickupFood(); + void playPickupGem(); + + // Eating/drinking + void playEating(); + void playDrinking(); + + // Level up + void playLevelUp(); + + // Error/feedback + void playError(); + void playTargetSelect(); + void playTargetDeselect(); + +private: + struct UISample { + std::string path; + std::vector data; + bool loaded; + }; + + // Sound libraries + std::vector bagOpenSounds_; + std::vector bagCloseSounds_; + std::vector questLogOpenSounds_; + std::vector questLogCloseSounds_; + std::vector characterSheetOpenSounds_; + std::vector characterSheetCloseSounds_; + std::vector auctionOpenSounds_; + std::vector auctionCloseSounds_; + std::vector guildBankOpenSounds_; + std::vector guildBankCloseSounds_; + + std::vector buttonClickSounds_; + std::vector menuButtonSounds_; + + std::vector questActivateSounds_; + std::vector questCompleteSounds_; + std::vector questFailedSounds_; + std::vector questUpdateSounds_; + + std::vector lootCoinSmallSounds_; + std::vector lootCoinLargeSounds_; + std::vector lootItemSounds_; + + std::vector dropSounds_; + std::vector pickupBagSounds_; + std::vector pickupBookSounds_; + std::vector pickupClothSounds_; + std::vector pickupFoodSounds_; + std::vector pickupGemSounds_; + + std::vector eatingSounds_; + std::vector drinkingSounds_; + + std::vector levelUpSounds_; + + std::vector errorSounds_; + std::vector selectTargetSounds_; + std::vector deselectTargetSounds_; + + // State tracking + float volumeScale_ = 1.0f; + bool initialized_ = false; + + // Helper methods + bool loadSound(const std::string& path, UISample& sample, pipeline::AssetManager* assets); + void playSound(const std::vector& library); +}; + +} // namespace audio +} // namespace wowee diff --git a/src/audio/ui_sound_manager.cpp b/src/audio/ui_sound_manager.cpp new file mode 100644 index 00000000..cdc12975 --- /dev/null +++ b/src/audio/ui_sound_manager.cpp @@ -0,0 +1,219 @@ +#include "audio/ui_sound_manager.hpp" +#include "audio/audio_engine.hpp" +#include "pipeline/asset_manager.hpp" +#include "core/logger.hpp" + +namespace wowee { +namespace audio { + +bool UISoundManager::initialize(pipeline::AssetManager* assets) { + if (!assets) { + LOG_ERROR("UISoundManager: AssetManager is null"); + return false; + } + + LOG_INFO("UISoundManager: Initializing..."); + + // Load window sounds + bagOpenSounds_.resize(1); + bool bagOpenLoaded = loadSound("Sound\\Interface\\iBackPackOpen.wav", bagOpenSounds_[0], assets); + + bagCloseSounds_.resize(1); + bool bagCloseLoaded = loadSound("Sound\\Interface\\iBackPackClose.wav", bagCloseSounds_[0], assets); + + questLogOpenSounds_.resize(1); + bool questLogOpenLoaded = loadSound("Sound\\Interface\\iQuestLogOpenA.wav", questLogOpenSounds_[0], assets); + + questLogCloseSounds_.resize(1); + bool questLogCloseLoaded = loadSound("Sound\\Interface\\iQuestLogCloseA.wav", questLogCloseSounds_[0], assets); + + characterSheetOpenSounds_.resize(1); + bool charSheetOpenLoaded = loadSound("Sound\\Interface\\iAbilitiesOpenA.wav", characterSheetOpenSounds_[0], assets); + + characterSheetCloseSounds_.resize(1); + bool charSheetCloseLoaded = loadSound("Sound\\Interface\\iAbilitiesCloseA.wav", characterSheetCloseSounds_[0], assets); + + auctionOpenSounds_.resize(1); + bool auctionOpenLoaded = loadSound("Sound\\Interface\\AuctionWindowOpen.wav", auctionOpenSounds_[0], assets); + + auctionCloseSounds_.resize(1); + bool auctionCloseLoaded = loadSound("Sound\\Interface\\AuctionWindowClose.wav", auctionCloseSounds_[0], assets); + + guildBankOpenSounds_.resize(1); + bool guildBankOpenLoaded = loadSound("Sound\\Interface\\GuildVaultOpen.wav", guildBankOpenSounds_[0], assets); + + guildBankCloseSounds_.resize(1); + bool guildBankCloseLoaded = loadSound("Sound\\Interface\\GuildVaultClose.wav", guildBankCloseSounds_[0], assets); + + // Load button sounds + buttonClickSounds_.resize(1); + bool buttonClickLoaded = loadSound("Sound\\Interface\\iUiInterfaceButtonA.wav", buttonClickSounds_[0], assets); + + menuButtonSounds_.resize(1); + bool menuButtonLoaded = loadSound("Sound\\Interface\\iUIMainMenuButtonA.wav", menuButtonSounds_[0], assets); + + // Load quest sounds + questActivateSounds_.resize(1); + bool questActivateLoaded = loadSound("Sound\\Interface\\iQuestActivate.wav", questActivateSounds_[0], assets); + + questCompleteSounds_.resize(1); + bool questCompleteLoaded = loadSound("Sound\\Interface\\iQuestComplete.wav", questCompleteSounds_[0], assets); + + questFailedSounds_.resize(1); + bool questFailedLoaded = loadSound("Sound\\Interface\\igQuestFailed.wav", questFailedSounds_[0], assets); + + questUpdateSounds_.resize(1); + bool questUpdateLoaded = loadSound("Sound\\Interface\\iQuestUpdate.wav", questUpdateSounds_[0], assets); + + // Load loot sounds + lootCoinSmallSounds_.resize(1); + bool lootCoinSmallLoaded = loadSound("Sound\\Interface\\LootCoinSmall.wav", lootCoinSmallSounds_[0], assets); + + lootCoinLargeSounds_.resize(1); + bool lootCoinLargeLoaded = loadSound("Sound\\Interface\\LootCoinLarge.wav", lootCoinLargeSounds_[0], assets); + + lootItemSounds_.resize(1); + bool lootItemLoaded = loadSound("Sound\\Interface\\igLootCreature.wav", lootItemSounds_[0], assets); + + // Load item pickup sounds + dropSounds_.resize(1); + bool dropLoaded = loadSound("Sound\\Interface\\DropOnGround.wav", dropSounds_[0], assets); + + pickupBagSounds_.resize(1); + bool pickupBagLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpBag.wav", pickupBagSounds_[0], assets); + + pickupBookSounds_.resize(1); + bool pickupBookLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpBook.wav", pickupBookSounds_[0], assets); + + pickupClothSounds_.resize(1); + bool pickupClothLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpCloth_Leather01.wav", pickupClothSounds_[0], assets); + + pickupFoodSounds_.resize(1); + bool pickupFoodLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpFoodGeneric.wav", pickupFoodSounds_[0], assets); + + pickupGemSounds_.resize(1); + bool pickupGemLoaded = loadSound("Sound\\Interface\\PickUp\\PickUpGems.wav", pickupGemSounds_[0], assets); + + // Load eating/drinking sounds + eatingSounds_.resize(1); + bool eatingLoaded = loadSound("Sound\\Interface\\iEating1.wav", eatingSounds_[0], assets); + + drinkingSounds_.resize(1); + bool drinkingLoaded = loadSound("Sound\\Interface\\iDrinking1.wav", drinkingSounds_[0], assets); + + // Load level up sound + levelUpSounds_.resize(1); + bool levelUpLoaded = loadSound("Sound\\Interface\\LevelUp.wav", levelUpSounds_[0], assets); + + // Load error/feedback sounds + errorSounds_.resize(1); + bool errorLoaded = loadSound("Sound\\Interface\\Error.wav", errorSounds_[0], assets); + + selectTargetSounds_.resize(1); + bool selectTargetLoaded = loadSound("Sound\\Interface\\iSelectTarget.wav", selectTargetSounds_[0], assets); + + deselectTargetSounds_.resize(1); + bool deselectTargetLoaded = loadSound("Sound\\Interface\\iDeselectTarget.wav", deselectTargetSounds_[0], assets); + + LOG_INFO("UISoundManager: Window sounds - Bag: ", (bagOpenLoaded && bagCloseLoaded) ? "YES" : "NO", + ", QuestLog: ", (questLogOpenLoaded && questLogCloseLoaded) ? "YES" : "NO", + ", CharSheet: ", (charSheetOpenLoaded && charSheetCloseLoaded) ? "YES" : "NO"); + LOG_INFO("UISoundManager: Button sounds - Click: ", buttonClickLoaded ? "YES" : "NO", + ", Menu: ", menuButtonLoaded ? "YES" : "NO"); + LOG_INFO("UISoundManager: Quest sounds - Activate: ", questActivateLoaded ? "YES" : "NO", + ", Complete: ", questCompleteLoaded ? "YES" : "NO", + ", Failed: ", questFailedLoaded ? "YES" : "NO"); + LOG_INFO("UISoundManager: Loot sounds - Coins: ", (lootCoinSmallLoaded && lootCoinLargeLoaded) ? "YES" : "NO", + ", Items: ", lootItemLoaded ? "YES" : "NO"); + LOG_INFO("UISoundManager: Item sounds - Pickup: ", (pickupBagLoaded && pickupBookLoaded) ? "YES" : "NO", + ", Drop: ", dropLoaded ? "YES" : "NO"); + LOG_INFO("UISoundManager: Misc sounds - Eating: ", eatingLoaded ? "YES" : "NO", + ", Drinking: ", drinkingLoaded ? "YES" : "NO", + ", LevelUp: ", levelUpLoaded ? "YES" : "NO"); + + initialized_ = true; + LOG_INFO("UISoundManager: Initialization complete"); + return true; +} + +void UISoundManager::shutdown() { + initialized_ = false; +} + +bool UISoundManager::loadSound(const std::string& path, UISample& sample, pipeline::AssetManager* assets) { + sample.path = path; + sample.loaded = false; + + try { + sample.data = assets->readFile(path); + if (!sample.data.empty()) { + sample.loaded = true; + return true; + } + } catch (const std::exception& e) { + LOG_ERROR("UISoundManager: Failed to load ", path, ": ", e.what()); + } + + return false; +} + +void UISoundManager::playSound(const std::vector& library) { + if (!initialized_ || library.empty() || !library[0].loaded) return; + + float volume = 0.7f * volumeScale_; + AudioEngine::instance().playSound2D(library[0].data, volume, 1.0f); +} + +void UISoundManager::setVolumeScale(float scale) { + volumeScale_ = std::max(0.0f, std::min(1.0f, scale)); +} + +// Window sounds +void UISoundManager::playBagOpen() { playSound(bagOpenSounds_); } +void UISoundManager::playBagClose() { playSound(bagCloseSounds_); } +void UISoundManager::playQuestLogOpen() { playSound(questLogOpenSounds_); } +void UISoundManager::playQuestLogClose() { playSound(questLogCloseSounds_); } +void UISoundManager::playCharacterSheetOpen() { playSound(characterSheetOpenSounds_); } +void UISoundManager::playCharacterSheetClose() { playSound(characterSheetCloseSounds_); } +void UISoundManager::playAuctionHouseOpen() { playSound(auctionOpenSounds_); } +void UISoundManager::playAuctionHouseClose() { playSound(auctionCloseSounds_); } +void UISoundManager::playGuildBankOpen() { playSound(guildBankOpenSounds_); } +void UISoundManager::playGuildBankClose() { playSound(guildBankCloseSounds_); } + +// Button sounds +void UISoundManager::playButtonClick() { playSound(buttonClickSounds_); } +void UISoundManager::playMenuButtonClick() { playSound(menuButtonSounds_); } + +// Quest sounds +void UISoundManager::playQuestActivate() { playSound(questActivateSounds_); } +void UISoundManager::playQuestComplete() { playSound(questCompleteSounds_); } +void UISoundManager::playQuestFailed() { playSound(questFailedSounds_); } +void UISoundManager::playQuestUpdate() { playSound(questUpdateSounds_); } + +// Loot sounds +void UISoundManager::playLootCoinSmall() { playSound(lootCoinSmallSounds_); } +void UISoundManager::playLootCoinLarge() { playSound(lootCoinLargeSounds_); } +void UISoundManager::playLootItem() { playSound(lootItemSounds_); } + +// Item sounds +void UISoundManager::playDropOnGround() { playSound(dropSounds_); } +void UISoundManager::playPickupBag() { playSound(pickupBagSounds_); } +void UISoundManager::playPickupBook() { playSound(pickupBookSounds_); } +void UISoundManager::playPickupCloth() { playSound(pickupClothSounds_); } +void UISoundManager::playPickupFood() { playSound(pickupFoodSounds_); } +void UISoundManager::playPickupGem() { playSound(pickupGemSounds_); } + +// Eating/drinking +void UISoundManager::playEating() { playSound(eatingSounds_); } +void UISoundManager::playDrinking() { playSound(drinkingSounds_); } + +// Level up +void UISoundManager::playLevelUp() { playSound(levelUpSounds_); } + +// Error/feedback +void UISoundManager::playError() { playSound(errorSounds_); } +void UISoundManager::playTargetSelect() { playSound(selectTargetSounds_); } +void UISoundManager::playTargetDeselect() { playSound(deselectTargetSounds_); } + +} // namespace audio +} // namespace wowee