mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Smooth login music start and lower auth-screen volume
Add configurable fade-in support to MusicManager playback paths and use it for auth/login intro tracks to avoid abrupt starts. Apply a login-only 20% music attenuation while the auth screen is active, then restore the previous music volume when leaving login so in-game volume remains unchanged.
This commit is contained in:
parent
3368dbb9ec
commit
44a947163d
4 changed files with 90 additions and 20 deletions
|
|
@ -18,8 +18,8 @@ public:
|
|||
bool initialize(pipeline::AssetManager* assets);
|
||||
void shutdown();
|
||||
|
||||
void playMusic(const std::string& mpqPath, bool loop = true);
|
||||
void playFilePath(const std::string& filePath, bool loop = true);
|
||||
void playMusic(const std::string& mpqPath, bool loop = true, float fadeInMs = 0.0f);
|
||||
void playFilePath(const std::string& filePath, bool loop = true, float fadeInMs = 0.0f);
|
||||
void stopMusic(float fadeMs = 2000.0f);
|
||||
void crossfadeTo(const std::string& mpqPath, float fadeMs = 3000.0f);
|
||||
void crossfadeToFile(const std::string& filePath, float fadeMs = 3000.0f);
|
||||
|
|
@ -34,6 +34,7 @@ public:
|
|||
const std::string& getCurrentTrack() const { return currentTrack; }
|
||||
|
||||
private:
|
||||
float effectiveMusicVolume() const;
|
||||
pipeline::AssetManager* assetManager = nullptr;
|
||||
std::string currentTrack;
|
||||
bool currentTrackIsFile = false;
|
||||
|
|
@ -47,6 +48,10 @@ private:
|
|||
bool pendingIsFile = false;
|
||||
float fadeTimer = 0.0f;
|
||||
float fadeDuration = 0.0f;
|
||||
bool fadingIn = false;
|
||||
float fadeInTimer = 0.0f;
|
||||
float fadeInDuration = 0.0f;
|
||||
float fadeInTargetVolume = 0.0f;
|
||||
|
||||
std::unordered_map<std::string, std::vector<uint8_t>> musicDataCache_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ private:
|
|||
|
||||
bool musicInitAttempted = false;
|
||||
bool musicPlaying = false;
|
||||
bool loginMusicVolumeAdjusted_ = false;
|
||||
int savedMusicVolume_ = 30;
|
||||
};
|
||||
|
||||
}} // namespace wowee::ui
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "audio/audio_engine.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
|
|
@ -20,9 +21,21 @@ bool MusicManager::initialize(pipeline::AssetManager* assets) {
|
|||
return true;
|
||||
}
|
||||
|
||||
float MusicManager::effectiveMusicVolume() const {
|
||||
float vol = volumePercent / 100.0f;
|
||||
if (underwaterMode) {
|
||||
vol *= 0.3f;
|
||||
}
|
||||
return vol;
|
||||
}
|
||||
|
||||
void MusicManager::shutdown() {
|
||||
AudioEngine::instance().stopMusic();
|
||||
playing = false;
|
||||
fadingIn = false;
|
||||
fadeInTimer = 0.0f;
|
||||
fadeInDuration = 0.0f;
|
||||
fadeInTargetVolume = 0.0f;
|
||||
currentTrack.clear();
|
||||
musicDataCache_.clear();
|
||||
}
|
||||
|
|
@ -37,7 +50,7 @@ void MusicManager::preloadMusic(const std::string& mpqPath) {
|
|||
}
|
||||
}
|
||||
|
||||
void MusicManager::playMusic(const std::string& mpqPath, bool loop) {
|
||||
void MusicManager::playMusic(const std::string& mpqPath, bool loop, float fadeInMs) {
|
||||
if (!assetManager) return;
|
||||
if (mpqPath == currentTrack && playing) return;
|
||||
|
||||
|
|
@ -59,9 +72,18 @@ void MusicManager::playMusic(const std::string& mpqPath, bool loop) {
|
|||
}
|
||||
|
||||
// Play with AudioEngine (non-blocking, streams from memory)
|
||||
float volume = volumePercent / 100.0f;
|
||||
if (AudioEngine::instance().playMusic(cacheIt->second, volume, loop)) {
|
||||
float targetVolume = effectiveMusicVolume();
|
||||
float startVolume = (fadeInMs > 0.0f) ? 0.0f : targetVolume;
|
||||
if (AudioEngine::instance().playMusic(cacheIt->second, startVolume, loop)) {
|
||||
playing = true;
|
||||
fadingIn = false;
|
||||
if (fadeInMs > 0.0f) {
|
||||
fadingIn = true;
|
||||
fadeInTimer = 0.0f;
|
||||
fadeInDuration = std::max(0.05f, fadeInMs / 1000.0f);
|
||||
fadeInTargetVolume = targetVolume;
|
||||
AudioEngine::instance().setMusicVolume(0.0f);
|
||||
}
|
||||
currentTrack = mpqPath;
|
||||
currentTrackIsFile = false;
|
||||
LOG_INFO("Music: Playing ", mpqPath);
|
||||
|
|
@ -70,7 +92,7 @@ void MusicManager::playMusic(const std::string& mpqPath, bool loop) {
|
|||
}
|
||||
}
|
||||
|
||||
void MusicManager::playFilePath(const std::string& filePath, bool loop) {
|
||||
void MusicManager::playFilePath(const std::string& filePath, bool loop, float fadeInMs) {
|
||||
if (filePath.empty()) return;
|
||||
if (filePath == currentTrack && playing) return;
|
||||
if (!std::filesystem::exists(filePath)) {
|
||||
|
|
@ -101,9 +123,18 @@ void MusicManager::playFilePath(const std::string& filePath, bool loop) {
|
|||
}
|
||||
|
||||
// Play with AudioEngine
|
||||
float volume = volumePercent / 100.0f;
|
||||
if (AudioEngine::instance().playMusic(data, volume, loop)) {
|
||||
float targetVolume = effectiveMusicVolume();
|
||||
float startVolume = (fadeInMs > 0.0f) ? 0.0f : targetVolume;
|
||||
if (AudioEngine::instance().playMusic(data, startVolume, loop)) {
|
||||
playing = true;
|
||||
fadingIn = false;
|
||||
if (fadeInMs > 0.0f) {
|
||||
fadingIn = true;
|
||||
fadeInTimer = 0.0f;
|
||||
fadeInDuration = std::max(0.05f, fadeInMs / 1000.0f);
|
||||
fadeInTargetVolume = targetVolume;
|
||||
AudioEngine::instance().setMusicVolume(0.0f);
|
||||
}
|
||||
currentTrack = filePath;
|
||||
currentTrackIsFile = true;
|
||||
LOG_INFO("Music: Playing file ", filePath);
|
||||
|
|
@ -116,6 +147,10 @@ void MusicManager::stopMusic(float fadeMs) {
|
|||
(void)fadeMs; // Fade not implemented yet
|
||||
AudioEngine::instance().stopMusic();
|
||||
playing = false;
|
||||
fadingIn = false;
|
||||
fadeInTimer = 0.0f;
|
||||
fadeInDuration = 0.0f;
|
||||
fadeInTargetVolume = 0.0f;
|
||||
currentTrack.clear();
|
||||
currentTrackIsFile = false;
|
||||
}
|
||||
|
|
@ -127,11 +162,14 @@ void MusicManager::setVolume(int volume) {
|
|||
volumePercent = volume;
|
||||
|
||||
// Update AudioEngine music volume directly (no restart needed!)
|
||||
float vol = volumePercent / 100.0f;
|
||||
if (underwaterMode) {
|
||||
vol *= 0.3f; // 30% volume underwater
|
||||
float vol = effectiveMusicVolume();
|
||||
if (fadingIn) {
|
||||
fadeInTargetVolume = vol;
|
||||
float t = std::clamp(fadeInTimer / std::max(fadeInDuration, 0.001f), 0.0f, 1.0f);
|
||||
AudioEngine::instance().setMusicVolume(fadeInTargetVolume * t);
|
||||
} else {
|
||||
AudioEngine::instance().setMusicVolume(vol);
|
||||
}
|
||||
AudioEngine::instance().setMusicVolume(vol);
|
||||
}
|
||||
|
||||
void MusicManager::setUnderwaterMode(bool underwater) {
|
||||
|
|
@ -139,11 +177,14 @@ void MusicManager::setUnderwaterMode(bool underwater) {
|
|||
underwaterMode = underwater;
|
||||
|
||||
// Apply volume change immediately
|
||||
float vol = volumePercent / 100.0f;
|
||||
if (underwaterMode) {
|
||||
vol *= 0.3f; // Fade to 30% underwater
|
||||
float vol = effectiveMusicVolume();
|
||||
if (fadingIn) {
|
||||
fadeInTargetVolume = vol;
|
||||
float t = std::clamp(fadeInTimer / std::max(fadeInDuration, 0.001f), 0.0f, 1.0f);
|
||||
AudioEngine::instance().setMusicVolume(fadeInTargetVolume * t);
|
||||
} else {
|
||||
AudioEngine::instance().setMusicVolume(vol);
|
||||
}
|
||||
AudioEngine::instance().setMusicVolume(vol);
|
||||
}
|
||||
|
||||
void MusicManager::crossfadeTo(const std::string& mpqPath, float fadeMs) {
|
||||
|
|
@ -183,6 +224,15 @@ void MusicManager::update(float deltaTime) {
|
|||
playing = false;
|
||||
}
|
||||
|
||||
if (fadingIn) {
|
||||
fadeInTimer += deltaTime;
|
||||
float t = std::clamp(fadeInTimer / std::max(fadeInDuration, 0.001f), 0.0f, 1.0f);
|
||||
AudioEngine::instance().setMusicVolume(fadeInTargetVolume * t);
|
||||
if (t >= 1.0f) {
|
||||
fadingIn = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle crossfade
|
||||
if (crossfading) {
|
||||
fadeTimer += deltaTime;
|
||||
|
|
|
|||
|
|
@ -211,6 +211,14 @@ void AuthScreen::render(auth::AuthHandler& authHandler) {
|
|||
if (renderer) {
|
||||
auto* music = renderer->getMusicManager();
|
||||
if (music) {
|
||||
if (!loginMusicVolumeAdjusted_) {
|
||||
savedMusicVolume_ = music->getVolume();
|
||||
int loginVolume = (savedMusicVolume_ * 80) / 100; // reduce auth music by 20%
|
||||
if (loginVolume < 0) loginVolume = 0;
|
||||
if (loginVolume > 100) loginVolume = 100;
|
||||
music->setVolume(loginVolume);
|
||||
loginMusicVolumeAdjusted_ = true;
|
||||
}
|
||||
music->update(ImGui::GetIO().DeltaTime);
|
||||
if (!music->isPlaying()) {
|
||||
static std::mt19937 rng(std::random_device{}());
|
||||
|
|
@ -253,7 +261,7 @@ void AuthScreen::render(auth::AuthHandler& authHandler) {
|
|||
if (!availableTracks.empty()) {
|
||||
std::uniform_int_distribution<size_t> pick(0, availableTracks.size() - 1);
|
||||
const std::string& path = availableTracks[pick(rng)];
|
||||
music->playFilePath(path, true);
|
||||
music->playFilePath(path, true, 1800.0f);
|
||||
LOG_INFO("AuthScreen: Playing login intro track: ", path);
|
||||
musicPlaying = music->isPlaying();
|
||||
} else {
|
||||
|
|
@ -477,14 +485,19 @@ void AuthScreen::render(auth::AuthHandler& authHandler) {
|
|||
}
|
||||
|
||||
void AuthScreen::stopLoginMusic() {
|
||||
if (!musicPlaying) return;
|
||||
auto& app = core::Application::getInstance();
|
||||
auto* renderer = app.getRenderer();
|
||||
if (!renderer) return;
|
||||
auto* music = renderer->getMusicManager();
|
||||
if (!music) return;
|
||||
music->stopMusic(500.0f);
|
||||
musicPlaying = false;
|
||||
if (musicPlaying) {
|
||||
music->stopMusic(500.0f);
|
||||
musicPlaying = false;
|
||||
}
|
||||
if (loginMusicVolumeAdjusted_) {
|
||||
music->setVolume(savedMusicVolume_);
|
||||
loginMusicVolumeAdjusted_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AuthScreen::attemptAuth(auth::AuthHandler& authHandler) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue