refactor: decouple Application singleton by extracting core subsystems and updating interfaces

- Add `audio::AudioCoordinator` interface and implementation
- Modify `Application` to reduce singleton usage and move controller responsibilities:
  - application.hpp
  - application.cpp
- Update UI and audio headers/sources:
  - game_screen.hpp
  - game_screen.cpp
  - ui_manager.hpp
  - audio_coordinator.hpp
  - audio_coordinator.cpp
- Project config touched:
  - CMakeLists.txt
This commit is contained in:
Paul 2026-04-01 20:38:37 +03:00
parent 9b38e64f84
commit d43397163e
8 changed files with 179 additions and 3 deletions

View file

@ -0,0 +1,66 @@
#pragma once
#include <memory>
namespace wowee {
namespace pipeline { class AssetManager; }
namespace audio {
class MusicManager;
class FootstepManager;
class ActivitySoundManager;
class MountSoundManager;
class NpcVoiceManager;
class AmbientSoundManager;
class UiSoundManager;
class CombatSoundManager;
class SpellSoundManager;
class MovementSoundManager;
/// Coordinates all audio subsystems.
/// Extracted from Renderer to separate audio lifecycle from rendering.
/// Owned by Application; Renderer and UI components access through Application.
class AudioCoordinator {
public:
AudioCoordinator();
~AudioCoordinator();
/// Initialize the audio engine and all managers.
/// @return true if audio is available (engine initialized successfully)
bool initialize();
/// Initialize managers that need AssetManager (music lookups, sound banks).
void initializeWithAssets(pipeline::AssetManager* assetManager);
/// Shutdown all audio managers and engine.
void shutdown();
// Accessors for all audio managers (same interface as Renderer had)
MusicManager* getMusicManager() { return musicManager_.get(); }
FootstepManager* getFootstepManager() { return footstepManager_.get(); }
ActivitySoundManager* getActivitySoundManager() { return activitySoundManager_.get(); }
MountSoundManager* getMountSoundManager() { return mountSoundManager_.get(); }
NpcVoiceManager* getNpcVoiceManager() { return npcVoiceManager_.get(); }
AmbientSoundManager* getAmbientSoundManager() { return ambientSoundManager_.get(); }
UiSoundManager* getUiSoundManager() { return uiSoundManager_.get(); }
CombatSoundManager* getCombatSoundManager() { return combatSoundManager_.get(); }
SpellSoundManager* getSpellSoundManager() { return spellSoundManager_.get(); }
MovementSoundManager* getMovementSoundManager() { return movementSoundManager_.get(); }
private:
std::unique_ptr<MusicManager> musicManager_;
std::unique_ptr<FootstepManager> footstepManager_;
std::unique_ptr<ActivitySoundManager> activitySoundManager_;
std::unique_ptr<MountSoundManager> mountSoundManager_;
std::unique_ptr<NpcVoiceManager> npcVoiceManager_;
std::unique_ptr<AmbientSoundManager> ambientSoundManager_;
std::unique_ptr<UiSoundManager> uiSoundManager_;
std::unique_ptr<CombatSoundManager> combatSoundManager_;
std::unique_ptr<SpellSoundManager> spellSoundManager_;
std::unique_ptr<MovementSoundManager> movementSoundManager_;
bool audioAvailable_ = false;
};
} // namespace audio
} // namespace wowee

View file

@ -29,7 +29,7 @@ namespace ui { class UIManager; }
namespace auth { class AuthHandler; }
namespace game { class GameHandler; class World; class ExpansionRegistry; }
namespace pipeline { class AssetManager; class DBCLayout; struct M2Model; struct WMOModel; }
namespace audio { enum class VoiceType; }
namespace audio { enum class VoiceType; class AudioCoordinator; }
namespace addons { class AddonManager; }
namespace core {
@ -104,6 +104,9 @@ public:
// World loader access
WorldLoader* getWorldLoader() { return worldLoader_.get(); }
// Audio coordinator access (Section 4.1: extracted audio subsystem)
audio::AudioCoordinator* getAudioCoordinator() { return audioCoordinator_.get(); }
private:
void update(float deltaTime);
void render();
@ -129,6 +132,7 @@ private:
std::unique_ptr<EntitySpawner> entitySpawner_;
std::unique_ptr<AppearanceComposer> appearanceComposer_;
std::unique_ptr<WorldLoader> worldLoader_;
std::unique_ptr<audio::AudioCoordinator> audioCoordinator_;
AppState state = AppState::AUTHENTICATION;
bool running = false;

View file

@ -23,6 +23,7 @@
#include <unordered_map>
namespace wowee {
namespace core { class AppearanceComposer; }
namespace pipeline { class AssetManager; }
namespace rendering { class Renderer; }
namespace ui {
@ -50,7 +51,12 @@ public:
void saveSettings();
void loadSettings();
// Dependency injection for extracted classes (Phase A singleton breaking)
void setAppearanceComposer(core::AppearanceComposer* ac) { appearanceComposer_ = ac; }
private:
// Injected dependencies (replaces getInstance() calls)
core::AppearanceComposer* appearanceComposer_ = nullptr;
// Chat panel (extracted from GameScreen — owns all chat state and rendering)
ChatPanel chatPanel_;

View file

@ -13,7 +13,7 @@ union SDL_Event;
namespace wowee {
// Forward declarations
namespace core { class Window; enum class AppState; }
namespace core { class Window; class AppearanceComposer; enum class AppState; }
namespace auth { class AuthHandler; }
namespace game { class GameHandler; }
@ -69,6 +69,11 @@ public:
CharacterScreen& getCharacterScreen() { return *characterScreen; }
GameScreen& getGameScreen() { return *gameScreen; }
// Dependency injection forwarding (Phase A singleton breaking)
void setAppearanceComposer(core::AppearanceComposer* ac) {
if (gameScreen) gameScreen->setAppearanceComposer(ac);
}
private:
core::Window* window = nullptr;