The Mega Snivy Update
Some checks failed
Build / Build Game (push) Has been cancelled

This commit is contained in:
2026-02-28 21:48:00 -05:00
parent 8b2edd1359
commit 17f3348e94
163 changed files with 8725 additions and 13281 deletions

View File

@@ -1,73 +1,119 @@
#include "audio.h"
#include "audio.hpp"
#include <SDL3/SDL_properties.h>
#include <iostream>
#include "../log.hpp"
#include <string>
#include <unordered_map>
using namespace game::util;
namespace game::resource
{
static std::shared_ptr<MIX_Audio> audio_make(MIX_Audio* audio)
{
return std::shared_ptr<MIX_Audio>(audio,
[](MIX_Audio* a)
{
if (a) MIX_DestroyAudio(a);
});
}
static std::unordered_map<std::string, std::weak_ptr<MIX_Audio>> audioCache{};
static std::shared_ptr<MIX_Audio> cache_get(const std::string& key)
{
auto it = audioCache.find(key);
if (it == audioCache.end()) return {};
auto cached = it->second.lock();
if (!cached) audioCache.erase(it);
return cached;
}
static void cache_set(const std::string& key, const std::shared_ptr<MIX_Audio>& audio)
{
if (!audio) return;
audioCache[key] = audio;
}
MIX_Mixer* Audio::mixer_get()
{
static auto mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr);
return mixer;
}
void Audio::set_gain(float gain)
void Audio::volume_set(float volume)
{
auto mixer = mixer_get();
MIX_SetMasterGain(mixer, gain);
}
void Audio::retain()
{
if (refCount) ++(*refCount);
}
void Audio::release()
{
if (refCount)
{
if (--(*refCount) == 0)
{
if (internal) MIX_DestroyAudio(internal);
delete refCount;
}
refCount = nullptr;
}
internal = nullptr;
MIX_SetMasterGain(mixer, volume);
}
Audio::Audio(const std::filesystem::path& path)
{
internal = MIX_LoadAudio(mixer_get(), path.c_str(), true);
auto key = std::string("fs:") + path.string();
internal = cache_get(key);
if (internal)
{
refCount = new int(1);
std::cout << "Initialized audio: '" << path.string() << "'\n";
logger.info(std::format("Using cached audio: {}", path.string()));
return;
}
else
internal = audio_make(MIX_LoadAudio(mixer_get(), path.c_str(), true));
cache_set(key, internal);
if (internal) logger.info(std::format("Initialized audio: {}", path.string()));
if (!internal) logger.info(std::format("Failed to intialize audio: {} ({})", path.string(), SDL_GetError()));
}
Audio::Audio(const physfs::Path& path)
{
if (!path.is_valid())
{
std::cout << "Failed to initialize audio: '" << path.string() << "'\n";
logger.error(
std::format("Failed to initialize audio from PhysicsFS path: {}", path.c_str(), physfs::error_get()));
return;
}
auto key = std::string("physfs:") + path.c_str();
internal = cache_get(key);
if (internal)
{
logger.info(std::format("Using cached audio: {}", path.c_str()));
return;
}
auto buffer = path.read();
if (buffer.empty())
{
logger.error(
std::format("Failed to initialize audio from PhysicsFS path: {} ({})", path.c_str(), physfs::error_get()));
return;
}
auto ioStream = SDL_IOFromConstMem(buffer.data(), buffer.size());
internal = audio_make(MIX_LoadAudio_IO(mixer_get(), ioStream, false, true));
cache_set(key, internal);
if (internal)
logger.info(std::format("Initialized audio: {}", path.c_str()));
else
logger.info(std::format("Failed to intialize audio: {} ({})", path.c_str(), SDL_GetError()));
}
Audio::Audio(const Audio& other)
{
internal = other.internal;
refCount = other.refCount;
retain();
track = nullptr;
}
Audio::Audio(Audio&& other) noexcept
{
internal = other.internal;
internal = std::move(other.internal);
track = other.track;
refCount = other.refCount;
other.internal = nullptr;
other.track = nullptr;
other.refCount = nullptr;
}
Audio& Audio::operator=(const Audio& other)
@@ -76,8 +122,7 @@ namespace game::resource
{
unload();
internal = other.internal;
refCount = other.refCount;
retain();
track = nullptr;
}
return *this;
}
@@ -87,13 +132,10 @@ namespace game::resource
if (this != &other)
{
unload();
internal = other.internal;
internal = std::move(other.internal);
track = other.track;
refCount = other.refCount;
other.internal = nullptr;
other.track = nullptr;
other.refCount = nullptr;
}
return *this;
}
@@ -105,7 +147,7 @@ namespace game::resource
MIX_DestroyTrack(track);
track = nullptr;
}
release();
internal.reset();
}
void Audio::play(bool isLoop)
@@ -126,7 +168,7 @@ namespace game::resource
if (!track) return;
}
MIX_SetTrackAudio(track, internal);
MIX_SetTrackAudio(track, internal.get());
SDL_PropertiesID options = 0;
@@ -149,5 +191,5 @@ namespace game::resource
bool Audio::is_playing() const { return track && MIX_TrackPlaying(track); }
Audio::~Audio() { unload(); }
bool Audio::is_valid() const { return internal != nullptr; }
bool Audio::is_valid() const { return (bool)internal; }
}