Still need to fix asset loading

This commit is contained in:
OusmBlueNinja 2025-04-29 14:10:29 -05:00
parent d70c04e57e
commit 4bdae7213d
16 changed files with 94185 additions and 311 deletions

View File

@ -10,24 +10,24 @@ Collapsed=1
[Window][WindowOverViewport_11111111] [Window][WindowOverViewport_11111111]
Pos=0,19 Pos=0,19
Size=1920,1158 Size=1280,701
Collapsed=0 Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1402,19 Pos=774,19
Size=518,1158 Size=506,701
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Scene Tree] [Window][Scene Tree]
Pos=0,19 Pos=0,19
Size=342,575 Size=342,348
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][Viewport] [Window][Viewport]
Pos=344,19 Pos=344,19
Size=1056,847 Size=428,390
Collapsed=0 Collapsed=0
DockId=0x00000007,0 DockId=0x00000007,0
@ -36,14 +36,14 @@ Size=1280,19
Collapsed=0 Collapsed=0
[Window][Performance Info] [Window][Performance Info]
Pos=344,868 Pos=344,411
Size=1056,309 Size=428,309
Collapsed=0 Collapsed=0
DockId=0x00000008,2 DockId=0x00000008,2
[Window][Console] [Window][Console]
Pos=344,868 Pos=344,411
Size=1056,309 Size=428,309
Collapsed=0 Collapsed=0
DockId=0x00000008,0 DockId=0x00000008,0
@ -54,8 +54,8 @@ Collapsed=0
DockId=0x00000007,1 DockId=0x00000007,1
[Window][Profiler] [Window][Profiler]
Pos=344,868 Pos=344,411
Size=1056,309 Size=428,309
Collapsed=0 Collapsed=0
DockId=0x00000008,3 DockId=0x00000008,3
@ -78,14 +78,14 @@ Collapsed=0
DockId=0x00000008,1 DockId=0x00000008,1
[Window][Color Correction] [Window][Color Correction]
Pos=344,868 Pos=344,411
Size=1056,309 Size=428,309
Collapsed=0 Collapsed=0
DockId=0x00000008,1 DockId=0x00000008,1
[Window][Asset Browser] [Window][Asset Browser]
Pos=0,596 Pos=0,369
Size=342,581 Size=342,351
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@ -95,13 +95,13 @@ Size=325,75
Collapsed=0 Collapsed=0
[Docking][Data] [Docking][Data]
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1400,1158 Split=X DockNode ID=0x00000005 Parent=0x11111111 SizeRef=772,1158 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1056,701 Split=Y Selected=0xC450F867 DockNode ID=0x00000002 Parent=0x00000005 SizeRef=428,701 Split=Y Selected=0xC450F867
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,847 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,847 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,309 Selected=0x9B5D3198 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,309 Selected=0x9B5D3198
DockNode ID=0x00000006 Parent=0x11111111 SizeRef=518,1158 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000006 Parent=0x11111111 SizeRef=506,1158 HiddenTabBar=1 Selected=0x36DC96AB

View File

@ -16,6 +16,7 @@ include_dirs:
- src/vendor/imgui - src/vendor/imgui
- src/vendor/box2d - src/vendor/box2d
- src/vendor/xxhash - src/vendor/xxhash
- src/vendor/miniaudio
- C:/msys64/mingw64/include - C:/msys64/mingw64/include

View File

@ -1,2 +1,2 @@
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto [LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\audio\AudioEngine.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
[RUN] Executed app.exe successfully. [RUN] Executed app.exe successfully.

View File

@ -0,0 +1,56 @@
engine_version: 0.1.0
scene_name: updated_asset_manager
scene_hash: 0293966521aa0692590ed25b05d9076fc6d206e07484422d814d7ee33ac235b4
format_version: 1
objects:
- name: Hello, Create
uid: 4afb134ba5a84d3d837374e314ca9adb
id: 0
position: [0, 0]
rotation: 0
layer: 0
visable: true
components: []
children: []
color_correction:
brightness: 1
saturation: 1
gamma: 1
bloom: true
intensity: 1.20000005
threshold: 1
Assets:
- uaid: 4
path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png
filename: ganges_river_pebbles_nor_gl_1k.png
filetype: png
type: 0
hash: 6711b00700d4c94a
lastModified: 1744565594
size: [1024, 1024]
channels: 4
format: GL_RGBA
- uaid: 3
path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png
filename: ganges_river_pebbles_diff_1k.png
filetype: png
type: 0
hash: 0349580fcbf62155
lastModified: 1744565605
size: [1024, 1024]
channels: 4
format: GL_RGBA
- uaid: 2
path: C:\Users\spenc\Music\simple-notification-152054.mp3
filename: simple-notification-152054.mp3
filetype: mp3
type: 1
hash: 3e57c2530f08c1ab
lastModified: 1745951639
- uaid: 1
path: C:\Users\spenc\Music\simple-notification-152054.wav
filename: simple-notification-152054.wav
filetype: wav
type: 1
hash: 0f5adca8b95e7494
lastModified: 1745952999

View File

@ -15,15 +15,22 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
{ {
textureUAID = uaid; textureUAID = uaid;
const auto *asset = AssetManager::GetAssetByID(uaid); const auto* asset = AssetManager::GetAssetByID(uaid);
if (!asset || !asset->loaded) if (!asset || !asset->loaded)
{ {
Logger::LogError("SetTextureAtlas: Asset not found or not loaded (UAID: %llu)", uaid); Logger::LogError("SetTextureAtlas: Asset not found or not loaded (UAID: %llu)", uaid);
return; return;
} }
int texWidth = static_cast<int>(asset->size.x); const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset);
int texHeight = static_cast<int>(asset->size.y); if (!imageAsset)
{
Logger::LogError("SetTextureAtlas: Asset with UAID %llu is not an image", uaid);
return;
}
int texWidth = static_cast<int>(imageAsset->size.x);
int texHeight = static_cast<int>(imageAsset->size.y);
if (texelWidth <= 0 || texelHeight <= 0 || texWidth < texelWidth || texHeight < texelHeight) if (texelWidth <= 0 || texelHeight <= 0 || texWidth < texelWidth || texHeight < texelHeight)
{ {
@ -37,7 +44,7 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
Logger::LogWarning("SetTextureAtlas: Texture size is not cleanly divisible by texel size (UAID: %llu)", uaid); Logger::LogWarning("SetTextureAtlas: Texture size is not cleanly divisible by texel size (UAID: %llu)", uaid);
} }
texture = std::make_shared<Texture>(asset->uaid); texture = std::make_shared<Texture>(imageAsset->uaid);
atlas.texture = texture; atlas.texture = texture;
atlas.SetTexelSize(texelWidth, texelHeight); atlas.SetTexelSize(texelWidth, texelHeight);
@ -50,14 +57,10 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
endFrame = totalFrames > 0 ? totalFrames - 1 : 0; endFrame = totalFrames > 0 ? totalFrames - 1 : 0;
if (start != 0) if (start != 0)
{
startFrame = start; startFrame = start;
}
if (end != 0) if (end != 0)
{
endFrame = end; endFrame = end;
}
frameDuration = duration; frameDuration = duration;
currentFrame = startFrame; currentFrame = startFrame;
@ -65,6 +68,7 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
renderType = RenderType::Unlit; renderType = RenderType::Unlit;
} }
void AnimationComponent::Play() { playing = true; } void AnimationComponent::Play() { playing = true; }
void AnimationComponent::Stop() { playing = false; } void AnimationComponent::Stop() { playing = false; }
void AnimationComponent::SetLooping(bool loop_) { loop = loop_; } void AnimationComponent::SetLooping(bool loop_) { loop = loop_; }

View File

@ -44,26 +44,42 @@ void SpriteComponent::SetTexture(uint64_t uaid)
const auto* asset = AssetManager::GetAssetByID(uaid); const auto* asset = AssetManager::GetAssetByID(uaid);
if (asset && asset->loaded) if (asset && asset->loaded)
{ {
textureID = asset->textureID; if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
size = asset->size; {
textureID = imageAsset->textureID;
size = imageAsset->size;
texture_loaded = true; texture_loaded = true;
} }
else
{
Logger::LogError("[SpriteComponent] Asset with UAID '%llu' is not an image!", uaid);
}
}
} }
void SpriteComponent::SetNormalMap(uint64_t uaid) void SpriteComponent::SetNormalMap(uint64_t uaid)
{ {
normalMapUAID = uaid; normalMapUAID = uaid;
const auto* asset = AssetManager::GetAssetByID(uaid); const auto* asset = AssetManager::GetAssetByID(uaid);
if (asset && asset->loaded) if (asset && asset->loaded)
{ {
normalMapID = asset->textureID; if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
{
normalMapID = imageAsset->textureID;
}
else
{
Logger::LogError("[SpriteComponent] Asset with UAID '%llu' is not an image!", uaid);
}
} }
} }
unsigned int SpriteComponent::GetTextureID() const unsigned int SpriteComponent::GetTextureID() const
{ {
return textureID; return textureID;

View File

@ -40,18 +40,26 @@ void TilemapComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texelH
return; return;
} }
texture = std::make_shared<Texture>(uaid); const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset);
if (!imageAsset)
{
Logger::LogError("TilemapComponent: Asset with UAID %llu is not an image", uaid);
return;
}
texture = std::make_shared<Texture>(imageAsset->uaid);
atlas.texture = texture; atlas.texture = texture;
atlas.SetTexelSize(texelWidth, texelHeight); atlas.SetTexelSize(texelWidth, texelHeight);
int texWidth = static_cast<int>(asset->size.x); int texWidth = static_cast<int>(imageAsset->size.x);
int texHeight = static_cast<int>(asset->size.y); int texHeight = static_cast<int>(imageAsset->size.y);
atlasColumns = texWidth / texelWidth; atlasColumns = texWidth / texelWidth;
atlasRows = texHeight / texelHeight; atlasRows = texHeight / texelHeight;
} }
void TilemapComponent::SetTile(int x, int y, int index) void TilemapComponent::SetTile(int x, int y, int index)
{ {
uint64_t key = PackCoord(x, y); uint64_t key = PackCoord(x, y);

View File

@ -13,6 +13,9 @@
#include "core/utils/FileDialog.h" #include "core/utils/FileDialog.h"
#include "core/utils/Logging.h" #include "core/utils/Logging.h"
#include "core/audio/AudioEngine.h"
#include "core/utils/EngineConfig.h" #include "core/utils/EngineConfig.h"
#include "utils/GameObjectsList.h" #include "utils/GameObjectsList.h"
#include "core/utils/Profiler.h" #include "core/utils/Profiler.h"
@ -510,6 +513,12 @@ void Engine::Init()
// } // }
//} //}
Logger::LogVerbose("Init Sound Core");
AudioEngine::Init();
Logger::LogVerbose("Resverving Objects"); Logger::LogVerbose("Resverving Objects");
// These values were AI Generated. // These values were AI Generated.
@ -985,7 +994,6 @@ void Engine::Run()
profiler.EndSection(); profiler.EndSection();
} }
} }
profiler.EndSection(); profiler.EndSection();
@ -1022,9 +1030,11 @@ void Engine::Run()
const auto *asset = AssetManager::GetAssetByID(uaid); const auto *asset = AssetManager::GetAssetByID(uaid);
if (asset && asset->loaded) if (asset && asset->loaded)
{
if (const auto *imageAsset = dynamic_cast<const ImageAssetInfo *>(asset))
{ {
auto *drawList = ImGui::GetWindowDrawList(); auto *drawList = ImGui::GetWindowDrawList();
const auto texSize = asset->size; const auto texSize = imageAsset->size;
int maxCols = static_cast<int>(texSize.x / tileSize.x); int maxCols = static_cast<int>(texSize.x / tileSize.x);
int maxRows = static_cast<int>(texSize.y / tileSize.y); int maxRows = static_cast<int>(texSize.y / tileSize.y);
@ -1125,6 +1135,7 @@ void Engine::Run()
} }
} }
} }
}
if (ImGui::BeginDragDropTarget()) if (ImGui::BeginDragDropTarget())
{ {
@ -1550,5 +1561,8 @@ void Engine::Shutdown()
glfwDestroyWindow(window); glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
AudioEngine::Shutdown();
std::filesystem::remove(tempScenePath); std::filesystem::remove(tempScenePath);
} }

View File

@ -0,0 +1,81 @@
#define MA_ENABLE_MP3
#define MA_ENABLE_WAV
#define MA_ENABLE_FLAC
#define MA_ENABLE_VORBIS
#include "AudioEngine.h"
#include "../utils/AssetManager.h"
#include "../utils/Logging.h"
ma_engine AudioEngine::s_Engine{};
std::unordered_map<uint64_t, ma_sound> AudioEngine::s_SoundMap;
bool AudioEngine::Init()
{
ma_result result = ma_engine_init(nullptr, &s_Engine);
if (result != MA_SUCCESS)
{
Logger::LogError("Failed to start AudioCore: %s", MiniaudioResultToString(result));
return false;
}
Logger::LogVerbose("AudioCore initialized successfully.");
return true;
}
void AudioEngine::Shutdown()
{
for (auto& [_, sound] : s_SoundMap)
ma_sound_uninit(&sound);
s_SoundMap.clear();
ma_engine_uninit(&s_Engine);
}
void AudioEngine::Play(uint64_t uaid, bool loop)
{
if (s_SoundMap.find(uaid) == s_SoundMap.end())
{
const auto* asset = AssetManager::GetAssetByID(uaid);
if (!asset || !asset->loaded || asset->type != AssetType::Audio)
{
Logger::LogError("[AudioEngine] Invalid or unloaded audio asset: %llu", uaid);
return;
}
ma_sound sound;
if (ma_sound_init_from_file(&s_Engine, asset->path.c_str(), 0, NULL, NULL, &sound) != MA_SUCCESS)
{
Logger::LogError("[AudioEngine] Failed to initialize sound from: %s", asset->path.c_str());
return;
}
s_SoundMap[uaid] = sound;
}
auto& sound = s_SoundMap[uaid];
ma_sound_set_looping(&sound, loop);
ma_sound_start(&sound);
}
void AudioEngine::Stop(uint64_t uaid)
{
auto it = s_SoundMap.find(uaid);
if (it != s_SoundMap.end())
ma_sound_stop(&it->second);
}
void AudioEngine::StopAll()
{
for (auto& [_, sound] : s_SoundMap)
ma_sound_stop(&sound);
}
void AudioEngine::Unload(uint64_t uaid)
{
auto it = s_SoundMap.find(uaid);
if (it != s_SoundMap.end())
{
ma_sound_uninit(&it->second);
s_SoundMap.erase(it);
}
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <unordered_map>
#include <string>
#include "miniaudio.h"
#include <cstdint>
class AudioEngine
{
public:
static bool Init();
static void Shutdown();
static void Play(uint64_t uaid, bool loop = false);
static void Stop(uint64_t uaid);
static void StopAll();
static void Unload(uint64_t uaid);
static ma_engine* GetEngine() { return &s_Engine; }
private:
static ma_engine s_Engine;
static std::unordered_map<uint64_t, ma_sound> s_SoundMap;
};

View File

@ -1,81 +1,178 @@
// AssetManager.cpp
#include "AssetManager.h" #include "AssetManager.h"
#include "utils.h" #include "utils.h"
#include <GL/glew.h> #include <fstream>
#include <iostream>
#include "../audio/AudioEngine.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h> #include <stb_image.h>
#include <future>
#include <iostream>
// Static definitions #define MINIAUDIO_IMPLEMENTATION
std::unordered_map<uint64_t, AssetInfo> AssetManager::s_Assets; #define MA_ENABLE_MP3
#define MA_ENABLE_WAV
#define MA_ENABLE_FLAC
#define MA_ENABLE_VORBIS
#include "miniaudio.h"
std::unordered_map<uint64_t, std::shared_ptr<AssetInfo>> AssetManager::s_Assets;
std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID; std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID;
uint64_t AssetManager::s_NextUAID = 1; uint64_t AssetManager::s_NextUAID = 1;
void AssetManager::Init() {}
const char* MiniaudioResultToString(ma_result result)
{
switch (result)
{
case MA_SUCCESS: return "Success";
case MA_ERROR: return "Generic error";
case MA_INVALID_ARGS: return "Invalid arguments";
case MA_INVALID_OPERATION: return "Invalid operation";
case MA_OUT_OF_MEMORY: return "Out of memory";
case MA_OUT_OF_RANGE: return "Out of range";
case MA_ACCESS_DENIED: return "Access denied";
case MA_DOES_NOT_EXIST: return "File does not exist";
case MA_ALREADY_EXISTS: return "File already exists";
case MA_TOO_MANY_OPEN_FILES: return "Too many open files";
case MA_INVALID_FILE: return "Invalid or corrupted file";
case MA_TOO_BIG: return "File too big";
case MA_PATH_TOO_LONG: return "Path too long";
case MA_NAME_TOO_LONG: return "Name too long";
case MA_NOT_DIRECTORY: return "Not a directory";
case MA_IS_DIRECTORY: return "Is a directory";
case MA_DIRECTORY_NOT_EMPTY: return "Directory not empty";
case MA_AT_END: return "End of file or stream";
case MA_NO_SPACE: return "No space left on device";
case MA_BUSY: return "Resource busy";
case MA_IO_ERROR: return "I/O error";
case MA_INTERRUPT: return "Operation interrupted";
case MA_UNAVAILABLE: return "Resource unavailable";
case MA_ALREADY_IN_USE: return "Already in use";
case MA_BAD_ADDRESS: return "Bad memory address";
case MA_BAD_SEEK: return "Bad seek operation";
case MA_BAD_PIPE: return "Bad pipe";
case MA_DEADLOCK: return "Deadlock detected";
case MA_TOO_MANY_LINKS: return "Too many symbolic links";
case MA_NOT_IMPLEMENTED: return "Not implemented";
case MA_NO_MESSAGE: return "No message available";
case MA_BAD_MESSAGE: return "Bad message format";
case MA_NO_DATA_AVAILABLE: return "No data available";
case MA_INVALID_DATA: return "Invalid data";
case MA_TIMEOUT: return "Operation timed out";
case MA_NO_NETWORK: return "Network unavailable";
case MA_NOT_UNIQUE: return "Not unique";
case MA_NOT_SOCKET: return "Not a socket";
case MA_NO_ADDRESS: return "No address available";
case MA_BAD_PROTOCOL: return "Bad protocol";
case MA_PROTOCOL_UNAVAILABLE: return "Protocol unavailable";
case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
case MA_SOCKET_NOT_SUPPORTED: return "Socket not supported";
case MA_CONNECTION_RESET: return "Connection reset";
case MA_ALREADY_CONNECTED: return "Already connected";
case MA_NOT_CONNECTED: return "Not connected";
case MA_CONNECTION_REFUSED: return "Connection refused";
case MA_NO_HOST: return "Host not found";
case MA_IN_PROGRESS: return "Operation in progress";
case MA_CANCELLED: return "Operation cancelled";
case MA_MEMORY_ALREADY_MAPPED: return "Memory already mapped";
case MA_CRC_MISMATCH: return "CRC mismatch";
case MA_FORMAT_NOT_SUPPORTED: return "Audio format not supported";
case MA_DEVICE_TYPE_NOT_SUPPORTED: return "Device type not supported";
case MA_SHARE_MODE_NOT_SUPPORTED: return "Share mode not supported";
case MA_NO_BACKEND: return "No backend available";
case MA_NO_DEVICE: return "No device available";
case MA_API_NOT_FOUND: return "API not found";
case MA_INVALID_DEVICE_CONFIG: return "Invalid device configuration";
case MA_LOOP: return "Loop detected";
case MA_BACKEND_NOT_ENABLED: return "Backend not enabled";
case MA_DEVICE_NOT_INITIALIZED: return "Device not initialized";
case MA_DEVICE_ALREADY_INITIALIZED: return "Device already initialized";
case MA_DEVICE_NOT_STARTED: return "Device not started";
case MA_DEVICE_NOT_STOPPED: return "Device not stopped";
case MA_FAILED_TO_INIT_BACKEND: return "Failed to initialize backend";
case MA_FAILED_TO_OPEN_BACKEND_DEVICE: return "Failed to open backend device";
case MA_FAILED_TO_START_BACKEND_DEVICE: return "Failed to start backend device";
case MA_FAILED_TO_STOP_BACKEND_DEVICE: return "Failed to stop backend device";
default: return "Unknown error code";
}
}
void AssetManager::Init()
{
}
uint64_t AssetManager::GenerateUAID() uint64_t AssetManager::GenerateUAID()
{ {
return s_NextUAID++; return s_NextUAID++;
} }
void AssetManager::LoadAssetAsync(const std::string &path, AssetType type) void AssetManager::LoadAssetAsync(const std::string& path, AssetType type)
{ {
if (auto itPath = s_PathToUAID.find(path); itPath != s_PathToUAID.end() && s_Assets[itPath->second]->loaded)
{ {
Logger::LogVerbose("[AssetManager] Skipping already-loaded asset: %s (UAID: %llu)", path.c_str(), itPath->second);
auto itPath = s_PathToUAID.find(path);
if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded)
{
Logger::LogVerbose("[AssetManager] Skipping already-loaded image: %s (UAID: %llu)", path.c_str(), itPath->second);
return; return;
} }
}
uint64_t uaid = GenerateUAID(); uint64_t uaid = GenerateUAID();
{ std::shared_ptr<AssetInfo> asset;
AssetInfo info;
info.uaid = uaid;
info.path = path;
info.filename = GetFilenameFromPath(path);
info.filetype = ::GetFileExtension(path);
info.type = type;
s_Assets[uaid] = info;
s_PathToUAID[path] = uaid;
}
if (type == AssetType::Image) if (type == AssetType::Image)
{ asset = std::make_shared<ImageAssetInfo>();
Logger::LogVerbose("[AssetManager] Scheduling load: %s (UAID: %llu)", path.c_str(), uaid); else if (type == AssetType::Audio)
AssetManager::LoadImageInternal(path, uaid); asset = std::make_shared<AudioAssetInfo>();
}
else else
{ {
Logger::LogWarning("[AssetManager] Unknown Asset Type: '%d'", static_cast<int>(type)); Logger::LogWarning("[AssetManager] Unknown Asset Type: '%d'", static_cast<int>(type));
return;
} }
asset->uaid = uaid;
asset->path = path;
asset->filename = GetFilenameFromPath(path);
asset->filetype = ::GetFileExtension(path);
asset->type = type;
s_Assets[uaid] = asset;
s_PathToUAID[path] = uaid;
if (type == AssetType::Image)
LoadImageInternal(path, uaid);
else if (type == AssetType::Audio)
LoadAudioInternal(path, uaid);
} }
void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid) void AssetManager::LoadImageInternal(const std::string& path, uint64_t uaid)
{ {
{
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
if (it != s_Assets.end() && it->second.loaded) if (it == s_Assets.end())
return; return;
auto itPath = s_PathToUAID.find(path); auto image = std::dynamic_pointer_cast<ImageAssetInfo>(it->second);
if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded) if (!image)
return;
stbi_set_flip_vertically_on_load(false);
std::ifstream file(path, std::ios::binary);
if (!file)
{
Logger::LogError("[AssetManager] Failed to open image file: %s", path.c_str());
return; return;
} }
Logger::LogVerbose("[AssetManager] Begin loading image: %s (UAID: %llu)", path.c_str(), uaid); std::vector<unsigned char> fileData((std::istreambuf_iterator<char>(file)), {});
stbi_set_flip_vertically_on_load(false);
int w, h, channels; int w, h, channels;
stbi_uc *pixels = stbi_load(path.c_str(), &w, &h, &channels, STBI_rgb_alpha); stbi_uc* pixels = stbi_load_from_memory(fileData.data(), static_cast<int>(fileData.size()), &w, &h, &channels, STBI_rgb_alpha);
if (!pixels) if (!pixels)
{ {
Logger::LogError("[AssetManager] Failed to load image: %s", path.c_str()); Logger::LogError("[AssetManager] Failed to decode image: %s", path.c_str());
return; return;
} }
@ -92,125 +189,171 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
if (texID == 0) if (texID == 0)
{ {
Logger::LogError("[AssetManager] Failed to Load asset."); Logger::LogError("[AssetManager] Failed to create GL texture.");
return; return;
} }
auto &asset = s_Assets[uaid]; image->size = {static_cast<float>(w), static_cast<float>(h)};
asset.size = {static_cast<float>(w), static_cast<float>(h)}; image->textureID = texID;
asset.textureID = texID; image->channels = channels;
asset.loaded = true; image->format = "GL_RGBA";
asset.channels = channels; image->loaded = true;
asset.format = "GL_RGBA"; image->lastModified = GetFileLastWrite(path);
asset.lastModified = GetFileLastWrite(path); image->hash = GetFileHash(path);
asset.hash = GetFileHash(path);
Logger::LogVerbose("[AssetManager] Finished loading image: %s (%dx%d) (UAID: %llu, Texture ID: %u)", path.c_str(), w, h, uaid, texID); Logger::LogVerbose("[AssetManager] Loaded image: %s (%dx%d)", path.c_str(), w, h);
} }
const AssetInfo *AssetManager::GetAssetByID(uint64_t uaid) void AssetManager::LoadAudioInternal(const std::string& path, uint64_t uaid)
{ {
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
return it != s_Assets.end() ? &it->second : nullptr; if (it == s_Assets.end())
return;
auto audio = std::dynamic_pointer_cast<AudioAssetInfo>(it->second);
if (!audio)
return;
audio->sound = new ma_sound();
ma_result result = ma_sound_init_from_file(AudioEngine::GetEngine(), path.c_str(), 0, nullptr, nullptr, audio->sound);
if (result != MA_SUCCESS)
{
Logger::LogError("[AssetManager] Failed to load audio file: %s (Reason: %s)", path.c_str(), MiniaudioResultToString(result));
delete audio->sound;
audio->sound = nullptr;
return;
}
audio->loaded = true;
audio->lastModified = GetFileLastWrite(path);
audio->hash = GetFileHash(path);
Logger::LogVerbose("[AssetManager] Loaded audio: %s", path.c_str());
} }
const AssetInfo *AssetManager::GetAssetByPath(const std::string &path)
const AssetInfo* AssetManager::GetAssetByID(uint64_t uaid)
{ {
auto it = s_Assets.find(uaid);
auto it = s_PathToUAID.find(path); return it != s_Assets.end() ? it->second.get() : nullptr;
return it != s_PathToUAID.end() ? &s_Assets[it->second] : nullptr;
} }
const std::unordered_map<uint64_t, AssetInfo> &AssetManager::GetAllAssets() const AssetInfo* AssetManager::GetAssetByPath(const std::string& path)
{
auto it = s_PathToUAID.find(path);
return it != s_PathToUAID.end() ? s_Assets[it->second].get() : nullptr;
}
const std::unordered_map<uint64_t, std::shared_ptr<AssetInfo>>& AssetManager::GetAllAssets()
{ {
return s_Assets; return s_Assets;
} }
void AssetManager::UnloadAsset(uint64_t uaid) void AssetManager::UnloadAsset(uint64_t uaid)
{ {
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
if (it != s_Assets.end()) if (it != s_Assets.end())
{ {
if (it->second.textureID) if (auto img = std::dynamic_pointer_cast<ImageAssetInfo>(it->second); img && img->textureID)
glDeleteTextures(1, &it->second.textureID); glDeleteTextures(1, &img->textureID);
s_PathToUAID.erase(it->second.path); if (auto audio = std::dynamic_pointer_cast<AudioAssetInfo>(it->second); audio && audio->sound)
{
ma_sound_uninit(audio->sound);
delete audio->sound;
}
s_PathToUAID.erase(it->second->path);
s_Assets.erase(it); s_Assets.erase(it);
} }
} }
void AssetManager::ClearAllAssets() void AssetManager::ClearAllAssets()
{ {
for (auto& [id, asset] : s_Assets)
UnloadAsset(id);
for (auto &kv : s_Assets)
if (kv.second.textureID)
glDeleteTextures(1, &kv.second.textureID);
s_Assets.clear(); s_Assets.clear();
s_PathToUAID.clear(); s_PathToUAID.clear();
} }
void AssetManager::Save(YAML::Emitter &out) void AssetManager::Save(YAML::Emitter& out)
{ {
out << YAML::Key << "Assets" << YAML::BeginSeq; out << YAML::Key << "Assets" << YAML::BeginSeq;
for (const auto &kv : s_Assets) for (const auto& [uaid, asset] : s_Assets)
{ {
const auto &a = kv.second; out << YAML::BeginMap;
out << YAML::BeginMap out << YAML::Key << "uaid" << YAML::Value << asset->uaid;
<< YAML::Key << "uaid" << YAML::Value << a.uaid out << YAML::Key << "path" << YAML::Value << asset->path;
<< YAML::Key << "path" << YAML::Value << a.path out << YAML::Key << "filename" << YAML::Value << asset->filename;
<< YAML::Key << "filename" << YAML::Value << a.filename out << YAML::Key << "filetype" << YAML::Value << asset->filetype;
<< YAML::Key << "filetype" << YAML::Value << a.filetype out << YAML::Key << "type" << YAML::Value << static_cast<int>(asset->type);
<< YAML::Key << "type" << YAML::Value << static_cast<int>(a.type) out << YAML::Key << "hash" << YAML::Value << asset->hash;
<< YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << a.size.x << a.size.y << YAML::EndSeq out << YAML::Key << "lastModified" << YAML::Value << asset->lastModified;
<< YAML::Key << "hash" << YAML::Value << a.hash asset->Save(out);
<< YAML::Key << "channels" << YAML::Value << a.channels out << YAML::EndMap;
<< YAML::Key << "format" << YAML::Value << a.format
<< YAML::Key << "lastModified" << YAML::Value << a.lastModified
<< YAML::EndMap;
} }
out << YAML::EndSeq; out << YAML::EndSeq;
} }
void AssetManager::Load(const YAML::Node &node) void AssetManager::Load(const YAML::Node& node)
{ {
if (!node) if (!node)
return; return;
for (const auto &item : node) for (const auto& item : node)
{ {
uint64_t uaid = item["uaid"].as<uint64_t>(); uint64_t uaid = item["uaid"].as<uint64_t>();
std::string path = item["path"].as<std::string>(); std::string path = item["path"].as<std::string>();
AssetType type = static_cast<AssetType>(item["type"].as<int>()); AssetType type = static_cast<AssetType>(item["type"].as<int>());
float sx = item["size"][0].as<float>();
float sy = item["size"][1].as<float>();
AssetInfo asset; std::shared_ptr<AssetInfo> asset;
asset.uaid = uaid; if (type == AssetType::Image)
asset.path = path; asset = std::make_shared<ImageAssetInfo>();
asset.filename = item["filename"] ? item["filename"].as<std::string>() : GetFilenameFromPath(path); else if (type == AssetType::Audio)
asset.filetype = item["filetype"] ? item["filetype"].as<std::string>() : ::GetFileExtension(path); asset = std::make_shared<AudioAssetInfo>();
asset.type = type; else
asset.size = {sx, sy}; continue;
asset.hash = item["hash"] ? item["hash"].as<std::string>() : "";
asset.channels = item["channels"] ? item["channels"].as<int>() : 4; asset->uaid = uaid;
asset.format = item["format"] ? item["format"].as<std::string>() : "GL_RGBA"; asset->path = path;
asset.lastModified = item["lastModified"] ? item["lastModified"].as<std::time_t>() : 0; asset->filename = item["filename"] ? item["filename"].as<std::string>() : GetFilenameFromPath(path);
asset.loaded = false; asset->filetype = item["filetype"] ? item["filetype"].as<std::string>() : GetFileExtension(path);
asset.textureID = 0; asset->hash = item["hash"] ? item["hash"].as<std::string>() : "";
asset->lastModified = item["lastModified"] ? item["lastModified"].as<std::time_t>() : 0;
asset->loaded = false;
asset->Load(item);
s_Assets[uaid] = asset; s_Assets[uaid] = asset;
s_PathToUAID[path] = uaid; s_PathToUAID[path] = uaid;
if (uaid >= s_NextUAID) if (uaid >= s_NextUAID)
s_NextUAID = uaid + 1; s_NextUAID = uaid + 1;
if (type == AssetType::Image)
{
Logger::LogVerbose("[AssetManager] Reloading from file: %s (UAID: %llu)", path.c_str(), uaid);
LoadImageInternal(path, uaid);
} }
}
} }
void ImageAssetInfo::Save(YAML::Emitter& out) const
{
out << YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << size.x << size.y << YAML::EndSeq;
out << YAML::Key << "channels" << YAML::Value << channels;
out << YAML::Key << "format" << YAML::Value << format;
}
void ImageAssetInfo::Load(const YAML::Node& node)
{
if (node["size"])
{
size.x = node["size"][0].as<float>();
size.y = node["size"][1].as<float>();
}
channels = node["channels"] ? node["channels"].as<int>() : 4;
format = node["format"] ? node["format"].as<std::string>() : "GL_RGBA";
}
void AudioAssetInfo::Save(YAML::Emitter& out) const {}
void AudioAssetInfo::Load(const YAML::Node& node) {}

View File

@ -1,35 +1,59 @@
#pragma once #pragma once
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <mutex> #include <memory>
#include <vector>
#include <future> #include <future>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "../types/vec2.h" #include "../types/vec2.h"
#include <GL/glew.h> #include <GL/glew.h>
#include "miniaudio.h"
enum class AssetType { Image, Audio }; enum class AssetType { Image, Audio };
struct AssetInfo struct AssetInfo
{ {
uint64_t uaid; uint64_t uaid = 0;
std::string path; std::string path;
std::string filename; std::string filename;
std::string filetype; std::string filetype;
AssetType type; AssetType type = AssetType::Image;
core::types::Vec2 size;
std::string hash; std::string hash;
int channels = 4;
std::string format;
std::time_t lastModified = 0; std::time_t lastModified = 0;
bool loaded = false; bool loaded = false;
GLuint textureID = 0;
virtual ~AssetInfo() = default;
virtual void Save(YAML::Emitter& out) const = 0;
virtual void Load(const YAML::Node& node) = 0;
}; };
struct ImageAssetInfo : public AssetInfo
{
core::types::Vec2 size = {0, 0};
int channels = 4;
std::string format = "GL_RGBA";
GLuint textureID = 0;
ImageAssetInfo() { type = AssetType::Image; }
void Save(YAML::Emitter& out) const override;
void Load(const YAML::Node& node) override;
};
struct AudioAssetInfo : public AssetInfo
{
ma_sound* sound = nullptr;
AudioAssetInfo() { type = AssetType::Audio; }
void Save(YAML::Emitter& out) const override;
void Load(const YAML::Node& node) override;
};
const char* MiniaudioResultToString(ma_result result);
class AssetManager class AssetManager
{ {
public: public:
@ -37,20 +61,18 @@ public:
static void LoadAssetAsync(const std::string& path, AssetType type); static void LoadAssetAsync(const std::string& path, AssetType type);
static const AssetInfo* GetAssetByID(uint64_t uaid); static const AssetInfo* GetAssetByID(uint64_t uaid);
static const AssetInfo* GetAssetByPath(const std::string& path); static const AssetInfo* GetAssetByPath(const std::string& path);
static const std::unordered_map<uint64_t, AssetInfo>& GetAllAssets(); static const std::unordered_map<uint64_t, std::shared_ptr<AssetInfo>>& GetAllAssets();
static void UnloadAsset(uint64_t uaid); static void UnloadAsset(uint64_t uaid);
static void ClearAllAssets(); static void ClearAllAssets();
static void Save(YAML::Emitter& out); static void Save(YAML::Emitter& out);
static void Load(const YAML::Node& node); static void Load(const YAML::Node& node);
private: private:
static std::unordered_map<uint64_t, AssetInfo> s_Assets; static std::unordered_map<uint64_t, std::shared_ptr<AssetInfo>> s_Assets;
static std::unordered_map<std::string, uint64_t> s_PathToUAID; static std::unordered_map<std::string, uint64_t> s_PathToUAID;
static uint64_t s_NextUAID; static uint64_t s_NextUAID;
static uint64_t GenerateUAID(); static uint64_t GenerateUAID();
static void LoadImageInternal(const std::string& path, uint64_t uaid); static void LoadImageInternal(const std::string& path, uint64_t uaid);
static void LoadAudioInternal(const std::string& path, uint64_t uaid);
}; };

View File

@ -2,16 +2,23 @@
#include "AssetManager.h" #include "AssetManager.h"
#include "Logging.h" #include "Logging.h"
Texture::Texture(const std::string &path) Texture::Texture(const std::string& path)
{ {
if (!path.empty()) if (!path.empty())
{ {
AssetManager::LoadAssetAsync(path, AssetType::Image); AssetManager::LoadAssetAsync(path, AssetType::Image);
const auto *asset = AssetManager::GetAssetByPath(path); const auto* asset = AssetManager::GetAssetByPath(path);
if (asset && asset->loaded) if (asset && asset->loaded)
{ {
id = asset->textureID; if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
size = asset->size; {
id = imageAsset->textureID;
size = imageAsset->size;
}
else
{
Logger::LogError("[Texture] Asset at path '%s' is not an image!", path.c_str());
}
} }
else else
{ {
@ -20,15 +27,20 @@ Texture::Texture(const std::string &path)
} }
} }
Texture::Texture(uint64_t uaid) Texture::Texture(uint64_t uaid)
{ {
const auto *asset = AssetManager::GetAssetByID(uaid); const auto* asset = AssetManager::GetAssetByID(uaid);
if (asset && asset->loaded) if (asset && asset->loaded)
{ {
id = asset->textureID; if (const auto* imageAsset = dynamic_cast<const ImageAssetInfo*>(asset))
size = asset->size; {
id = imageAsset->textureID;
size = imageAsset->size;
}
else
{
Logger::LogError("[Texture] Asset with UAID '%llu' is not an image!", uaid);
}
} }
else else
{ {

View File

@ -25,41 +25,20 @@ std::unordered_map<std::string, ImageCacheEntry> engineTextureCache;
ImageCacheEntry LoadImageCache(const std::string& path) ImageCacheEntry LoadImageCache(const std::string& path)
{ {
auto [it, inserted] = textureCache.try_emplace(path, ImageCacheEntry{}); Logger::LogWarning(
"[LoadImageCache] This function is **deprecated**.\n"
"Please use one of the following AssetManager functions instead:\n"
" - AssetManager::LoadAssetAsync(path, AssetType::Image)\n"
" - AssetManager::GetAssetByID(uaid)\n"
" - AssetManager::GetAssetByPath(path)\n"
);
if (!inserted) return ImageCacheEntry{};
{
return it->second;
}
int w, h, channels;
stbi_set_flip_vertically_on_load(false);
unsigned char* data = stbi_load(path.c_str(), &w, &h, &channels, 4);
if (!data)
{
Logger::LogError("Failed to load image: '%s'", path.c_str());
return {};
}
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
stbi_image_free(data);
glm::vec2 imageSize(w, h);
ImageCacheEntry entry{ id, imageSize };
it->second = entry;
Logger::LogVerbose("Loaded Image: (%d, %d) '%s'",w,h, path.c_str());
Logger::LogWarning("Loaded Image Via Depricated Function: '%s'", path.c_str());
return entry;
} }
GLuint LoadTextureIfNeeded(const std::string &path) GLuint LoadTextureIfNeeded(const std::string &path)
{ {
auto [it, inserted] = textureCache.try_emplace(path, ImageCacheEntry{}); auto [it, inserted] = textureCache.try_emplace(path, ImageCacheEntry{});

View File

@ -17,13 +17,20 @@ void ShowAssetBrowser()
ImGui::Begin("Asset Browser"); ImGui::Begin("Asset Browser");
if (ImGui::Button("Load Asset")) if (ImGui::Button("Load Image"))
{ {
std::string path = OpenFileDialog(FileDialogType::Images); std::string path = OpenFileDialog(FileDialogType::Images);
if (!path.empty()) if (!path.empty())
{
AssetManager::LoadAssetAsync(path, AssetType::Image); AssetManager::LoadAssetAsync(path, AssetType::Image);
} }
ImGui::SameLine();
if (ImGui::Button("Load Audio"))
{
std::string path = OpenFileDialog(FileDialogType::Audio);
if (!path.empty())
AssetManager::LoadAssetAsync(path, AssetType::Audio);
} }
ImGui::Separator(); ImGui::Separator();
@ -50,42 +57,82 @@ void ShowAssetBrowser()
ImGui::Columns(columns, nullptr, false); ImGui::Columns(columns, nullptr, false);
int idx = 0; int idx = 0;
for (const auto &[uaid, asset] : AssetManager::GetAllAssets()) for (const auto &[uaid, baseAsset] : AssetManager::GetAllAssets())
{ {
if (asset.type != AssetType::Image || !asset.loaded) if (!baseAsset || !baseAsset->loaded)
continue; continue;
if (!assetSearchQuery.empty() && if (!assetSearchQuery.empty() &&
asset.filename.find(assetSearchQuery) == std::string::npos && baseAsset->filename.find(assetSearchQuery) == std::string::npos &&
asset.path.find(assetSearchQuery) == std::string::npos) baseAsset->path.find(assetSearchQuery) == std::string::npos)
{ {
continue; continue;
} }
ImGui::PushID(idx++); ImGui::PushID(idx++);
std::string displayName = GetFilenameFromPath(asset.path); std::string displayName = GetFilenameFromPath(baseAsset->path);
ImGui::Image((ImTextureID)(intptr_t)asset.textureID, if (baseAsset->type == AssetType::Image)
{
const auto *imageAsset = dynamic_cast<const ImageAssetInfo *>(baseAsset.get());
if (!imageAsset)
{
ImGui::PopID();
continue;
}
ImGui::Image((ImTextureID)(intptr_t)imageAsset->textureID,
ImVec2(thumbnailSize, thumbnailSize)); ImVec2(thumbnailSize, thumbnailSize));
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID)) if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
{ {
ImGui::SetDragDropPayload("ASSET_TEXTURE", &uaid, sizeof(uint64_t)); ImGui::SetDragDropPayload("ASSET_TEXTURE", &uaid, sizeof(uint64_t));
ImGui::Image((ImTextureID)(intptr_t)imageAsset->textureID,
ImGui::Image((ImTextureID)(intptr_t)asset.textureID,
ImVec2(thumbnailSize * 2, thumbnailSize * 2)); ImVec2(thumbnailSize * 2, thumbnailSize * 2));
ImGui::Text("%s", displayName.c_str()); ImGui::Text("%s", displayName.c_str());
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
}
else if (baseAsset->type == AssetType::Audio)
{
std::string buttonLabel = baseAsset->filetype.empty() ? "Audio" : (baseAsset->filetype);
ImGui::Button(buttonLabel.c_str(), ImVec2(thumbnailSize, thumbnailSize));
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
{
ImGui::SetDragDropPayload("ASSET_AUDIO", &uaid, sizeof(uint64_t));
ImGui::Text("Audio: %s", displayName.c_str());
ImGui::EndDragDropSource();
}
}
else
{
ImGui::PopID();
continue;
}
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::Text("Path: %s", asset.path.c_str()); ImGui::Text("Path: %s", baseAsset->path.c_str());
ImGui::Text("UAID: %llu", asset.uaid); ImGui::Text("UAID: %llu", baseAsset->uaid);
ImGui::Text("Texture ID: %u", asset.textureID);
ImGui::Text("Size: (%.0f, %.0f)", asset.size.x, asset.size.y); if (baseAsset->type == AssetType::Image)
{
const auto *imageAsset = dynamic_cast<const ImageAssetInfo *>(baseAsset.get());
if (imageAsset)
{
ImGui::Text("Texture ID: %u", imageAsset->textureID);
ImGui::Text("Size: (%.0f, %.0f)", imageAsset->size.x, imageAsset->size.y);
}
}
else if (baseAsset->type == AssetType::Audio)
{
ImGui::Text("Audio file");
}
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
@ -93,7 +140,7 @@ void ShowAssetBrowser()
{ {
if (ImGui::MenuItem("Unload")) if (ImGui::MenuItem("Unload"))
{ {
Logger::LogInfo("[AssetBrowser] Unloaded: %s", asset.path.c_str()); Logger::LogInfo("[AssetBrowser] Unloaded: %s", baseAsset->path.c_str());
AssetManager::UnloadAsset(uaid); AssetManager::UnloadAsset(uaid);
ImGui::EndPopup(); ImGui::EndPopup();
ImGui::PopID(); ImGui::PopID();
@ -102,12 +149,12 @@ void ShowAssetBrowser()
if (ImGui::MenuItem("Copy Path")) if (ImGui::MenuItem("Copy Path"))
{ {
ImGui::SetClipboardText(asset.path.c_str()); ImGui::SetClipboardText(baseAsset->path.c_str());
} }
if (ImGui::MenuItem("Copy UAID")) if (ImGui::MenuItem("Copy UAID"))
{ {
ImGui::SetClipboardText(std::to_string(asset.uaid).c_str()); ImGui::SetClipboardText(std::to_string(baseAsset->uaid).c_str());
} }
ImGui::EndPopup(); ImGui::EndPopup();

93468
src/vendor/miniaudio/miniaudio.h vendored Normal file

File diff suppressed because it is too large Load Diff