Added Project Asset Pack file

This commit is contained in:
OusmBlueNinja 2025-05-11 22:54:48 -05:00
parent 6a29c5bdee
commit 86abf8e5b7
12 changed files with 394 additions and 218 deletions

View File

@ -27,12 +27,12 @@ DockId=0x0000000F,0
[Window][Viewport]
Pos=342,19
Size=1185,488
Size=1185,526
Collapsed=0
DockId=0x00000011,0
[Window][##MainMenuBar]
Size=1280,19
Size=1920,19
Collapsed=0
[Window][Performance Info]
@ -42,8 +42,8 @@ Collapsed=0
DockId=0x00000015,0
[Window][Console]
Pos=342,509
Size=1185,273
Pos=342,547
Size=1185,235
Collapsed=0
DockId=0x00000012,0
@ -125,8 +125,8 @@ Collapsed=0
DockId=0x0000000D,0
[Window][Resources]
Pos=0,465
Size=341,712
Pos=0,19
Size=341,701
Collapsed=0
DockId=0x00000003,0
@ -147,7 +147,7 @@ Size=536,391
Collapsed=0
[Window][Create New Project]
Pos=298,22
Pos=505,191
Size=600,209
Collapsed=0
@ -208,8 +208,8 @@ DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,115
DockNode ID=0x0000001D Parent=0x00000017 SizeRef=1208,763 Split=X Selected=0xC450F867
DockNode ID=0x0000000F Parent=0x0000001D SizeRef=340,399 HiddenTabBar=1 Selected=0x12EF0F59
DockNode ID=0x00000010 Parent=0x0000001D SizeRef=1185,399 Split=Y Selected=0xC450F867
DockNode ID=0x00000011 Parent=0x00000010 SizeRef=1185,488 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
DockNode ID=0x00000012 Parent=0x00000010 SizeRef=1185,273 HiddenTabBar=1 Selected=0xEA83D666
DockNode ID=0x00000011 Parent=0x00000010 SizeRef=1185,526 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
DockNode ID=0x00000012 Parent=0x00000010 SizeRef=1185,235 HiddenTabBar=1 Selected=0xEA83D666
DockNode ID=0x0000001E Parent=0x00000017 SizeRef=1208,393 HiddenTabBar=1 Selected=0x9C2B5678
DockNode ID=0x00000018 Parent=0x00000007 SizeRef=391,860 Split=Y Selected=0x36DC96AB
DockNode ID=0x0000001B Parent=0x00000018 SizeRef=367,636 HiddenTabBar=1 Selected=0x36DC96AB

View File

@ -760,6 +760,11 @@ void Engine::Run()
ImGui::Separator();
ImGui::Spacing();
if (ImGui::MenuItem("Save Project"))
{
Logger::LogInfo("Saving Project.");
ProjectManager::SaveCurrentProject();
}
if (ImGui::MenuItem("Load Project"))
{
std::string file = OpenFileDialog(FileDialogType::Project);

View File

@ -16,7 +16,7 @@
#include <string>
#include <cstring>
#define ASSET_MANEFEST_NAME "assets.capk"
@ -184,88 +184,102 @@ void FileExplorer::Show(bool* p_open)
int cols = std::max(1, int(avail / (iconSize + padding)));
ImGui::Columns(cols, nullptr, false);
// Draw each entry
for (auto &e : entries) {
fs::path p = e.path();
std::string pathStr = p.string();
AssetType type = AssetManager::AssetTypeFromPath(pathStr);
fs::path p = e.path();
std::string pathStr = p.string();
AssetType type = AssetManager::AssetTypeFromPath(pathStr);
ImGui::PushID(pathStr.c_str());
ImGui::PushID(pathStr.c_str());
// --- IMAGE THUMBNAIL w/ InvisibleButton for clicks ---
if (type == AssetType::Image) {
if (auto* asset = AssetManager::GetAssetByPath(pathStr))
if (asset->type == AssetType::Image) {
auto* img = dynamic_cast<const ImageAssetInfo*>(asset);
if (img) {
if (ImGui::ImageButton("##Image", (ImTextureID)(intptr_t)img->textureID, ImVec2(iconSize, iconSize)))
{
s_currentDir = p;
}
}
}
}
else if (e.is_directory()) {
if (ImGui::ImageButton("##item",
(ImTextureID)(intptr_t)s_folderIcon,
ImVec2(iconSize, iconSize)))
{
s_currentDir = p;
}
}
else {
std::string label;
switch (type) {
case AssetType::Prefab: label = "Prefab"; break;
case AssetType::Scene: label = "Scene"; break;
case AssetType::Audio: label = "Audio"; break;
case AssetType::Script: label = "Script"; break;
case AssetType::Video: label = "Video"; break;
case AssetType::Font: label = "Font"; break;
case AssetType::Shader: label = "Shader"; break;
default:
// 1) pick thumbnail
ImTextureID thumbID = 0;
if (e.is_directory()) {
thumbID = (ImTextureID)(intptr_t)s_folderIcon;
} else if (type == AssetType::Image) {
if (auto* asset = AssetManager::GetAssetByPath(pathStr))
if (asset->type == AssetType::Image)
if (auto* img = dynamic_cast<const ImageAssetInfo*>(asset))
thumbID = (ImTextureID)(intptr_t)img->textureID;
}
if (!thumbID) {
GLuint iconTex = EngineLoadTextureIfNeeded(
std::string(ICONS_PATH) + IconFileForPath(p));
thumbID = (ImTextureID)(intptr_t)iconTex;
}
// 2) DRAW the single widget with a consistent ID: "##entry"
bool clicked = false;
if (e.is_directory() || type == AssetType::Image) {
clicked = ImGui::ImageButton(
"##entry",
thumbID,
ImVec2(iconSize, iconSize));
} else {
std::string label;
switch (type) {
case AssetType::Prefab: label = "Prefab"; break;
case AssetType::Scene: label = "Scene"; break;
case AssetType::Audio: label = "Audio"; break;
case AssetType::Script: label = "Script"; break;
case AssetType::Video: label = "Video"; break;
case AssetType::Font: label = "Font"; break;
case AssetType::Shader: label = "Shader"; break;
default:
label = p.extension().string();
if (!label.empty() && label.front()=='.')
label.erase(0,1);
break;
}
if (ImGui::Button(label.c_str(),
ImVec2(iconSize, iconSize)))
{
SelectedPath = pathStr;
}
}
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID)) {
if (auto* asset = AssetManager::GetAssetByPath(pathStr)) {
if (type == AssetType::Image)
ImGui::SetDragDropPayload(ASSET_TEXTURE,
&asset->uaid,
sizeof(asset->uaid));
else if (type == AssetType::Prefab)
ImGui::SetDragDropPayload(ASSET_PREFAB,
&asset->uaid,
sizeof(asset->uaid));
ImGui::TextUnformatted(p.filename().string().c_str());
}
ImGui::EndDragDropSource();
}
if (ImGui::BeginPopupContextItem()) {
if (e.is_directory() && ImGui::MenuItem("Open"))
s_currentDir = p;
if (!e.is_directory() && ImGui::MenuItem("Open File"))
SelectedPath = pathStr;
if (ImGui::MenuItem("Copy Path"))
ImGui::SetClipboardText(pathStr.c_str());
ImGui::EndPopup();
}
ImGui::TextWrapped("%s", p.filename().string().c_str());
ImGui::NextColumn();
ImGui::PopID();
clicked = ImGui::Button(
(std::string("##entry") + label).c_str(),
ImVec2(iconSize, iconSize));
}
// 3) handle click/navigation
if (clicked) {
if (e.is_directory())
s_currentDir = p;
else
SelectedPath = pathStr;
}
// 4) context menu tied to the same "##entry" ID
if (ImGui::BeginPopupContextItem("##entry")) {
if (e.is_directory() && ImGui::MenuItem("Open"))
s_currentDir = p;
if (!e.is_directory() && ImGui::MenuItem("Open File"))
SelectedPath = pathStr;
if (ImGui::MenuItem("Copy Path"))
ImGui::SetClipboardText(pathStr.c_str());
ImGui::EndPopup();
}
// 5) drag-drop source also tied to "##entry"
if (!e.is_directory() &&
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
{
if (auto* asset = AssetManager::GetAssetByPath(pathStr)) {
if (type == AssetType::Image)
ImGui::SetDragDropPayload(ASSET_TEXTURE,
&asset->uaid,
sizeof(asset->uaid));
else if (type == AssetType::Prefab)
ImGui::SetDragDropPayload(ASSET_PREFAB,
&asset->uaid,
sizeof(asset->uaid));
}
ImGui::TextUnformatted(p.filename().string().c_str());
ImGui::EndDragDropSource();
}
// 6) label and next column
ImGui::TextWrapped("%s", p.filename().string().c_str());
ImGui::NextColumn();
ImGui::PopID();
}
ImGui::Columns(1);
ImGui::EndChild();
ImGui::End();
@ -536,7 +550,7 @@ bool ProjectManager::LoadProject(const std::string &projectFilePath)
return false;
}
fs::path baseDir = projFile.parent_path();
fs::path baseDir = projFile.parent_path();
std::string projectName = projFile.stem().string();
YAML::Node config;
@ -549,47 +563,62 @@ bool ProjectManager::LoadProject(const std::string &projectFilePath)
return false;
}
// Read settings
std::string savedName = config["Name"].as<std::string>(projectName);
std::string defaultScene = config["s_defaultScene"].as<std::string>("");
Logger::LogInfo("Loading Project: '%s' from '%s'",
savedName.c_str(), projFile.string().c_str());
Logger::LogDebug("Loading '%s'",
savedName.c_str());
// update project pointers
s_currentProjectPath = baseDir.string();
s_currentProjectName = savedName;
// ensure folders
CreateDirectories(baseDir);
// --- Load the asset manifest from Assets/asset_manifest.yaml ---
{
fs::path manifest = baseDir / "Assets" / ASSET_MANEFEST_NAME;
if (fs::exists(manifest)) {
YAML::Node doc = YAML::LoadFile(manifest.string());
if (doc["Assets"]) {
AssetManager::Load(doc["Assets"]);
Logger::LogDebug("Loaded asset manifest: %s",
manifest.string().c_str());
}
} else {
Logger::LogDebug("No asset manifest found at '%s', skipping.",
manifest.string().c_str());
}
}
// finally load the default scene (if any)
if (!defaultScene.empty()) {
s_defaultScene = ResolveResPath(defaultScene);
Logger::LogDebug("Loading Default Scene: %s", s_defaultScene.c_str());
if (!fs::exists(s_defaultScene)) {
Logger::LogError("Default scene does not exist: %s", s_defaultScene.c_str());
return false;
}
SceneLoader::LoadScene(s_defaultScene);
}
Logger::LogInfo("Successfully loaded project '%s'", savedName.c_str());
CreateDirectories(baseDir);
SceneLoader::LoadScene(s_defaultScene);
Logger::LogOk("loaded project '%s'", savedName.c_str());
return true;
}
bool ProjectManager::CreateProject(const std::string &projectPath,
const std::string &projectName)
bool ProjectManager::CreateProject(
const std::string &projectPath,
const std::string &projectName)
{
fs::path baseDir = fs::path(projectPath) / projectName;
fs::path baseDir = fs::path(projectPath) / projectName;
fs::path projFile = baseDir / (projectName + ".cproj");
std::error_code ec;
if (!fs::create_directories(baseDir, ec) && ec)
{
// 1) create project root
if (!fs::create_directories(baseDir, ec) && ec) {
Logger::LogError("Failed to create project directory '%s': %s",
projectPath.c_str(), ec.message().c_str());
return false;
@ -598,113 +627,205 @@ bool ProjectManager::CreateProject(const std::string &projectPath,
s_currentProjectPath = baseDir.string();
s_currentProjectName = projectName;
fs::path scenePath = baseDir / "Assets" / "Scenes" / projectName / ".cene";
CreateDirectories(baseDir);
fs::path sceneDir = baseDir / "Assets" / "Scenes";
fs::path sceneFile = sceneDir / (projectName + ".cene");
s_defaultScene = sceneFile.string();
s_defaultScene = scenePath.string();
// Write .cproj YAML
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << projectName;
out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version;
fs::path relPath = fs::relative(scenePath, baseDir);
out << YAML::Key << "s_defaultScene" << YAML::Value << ("res://" + relPath.generic_string());
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
#if defined(_WIN32)
gmtime_s(&tm, &t);
#else
gmtime_r(&t, &tm);
#endif
char buf[32];
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm);
out << YAML::Key << "CreatedDate" << YAML::Value << buf;
out << YAML::EndMap;
std::ofstream fout(projFile);
if (!fout.is_open())
{
Logger::LogError("Could not open project file for writing: %s",
projFile.string().c_str());
return false;
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << projectName;
out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version;
fs::path rel = fs::relative(sceneFile, baseDir);
out << YAML::Key << "s_defaultScene"
<< YAML::Value << ("res://" + rel.generic_string());
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
#if defined(_WIN32)
gmtime_s(&tm, &t);
#else
gmtime_r(&t, &tm);
#endif
char buf[32];
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm);
out << YAML::Key << "CreatedDate" << YAML::Value << buf;
out << YAML::EndMap;
std::ofstream fout(projFile);
if (!fout.is_open()) {
Logger::LogError("Could not open project file for writing: %s",
projFile.string().c_str());
return false;
}
fout << out.c_str();
}
fout << out.c_str();
fout.close();
Logger::LogOk("Created project '%s' at '%s'",
projectName.c_str(), projectPath.c_str());
CreateDirectories(baseDir);
SceneLoader::SaveScene(scenePath.string());
SceneLoader::LoadScene(scenePath.string());
SceneLoader::SaveScene(sceneFile.string());
SceneLoader::LoadScene(sceneFile.string());
return true;
}
bool ProjectManager::SaveProject(const std::string &projectPath,
const std::string &projectName)
bool ProjectManager::SaveCurrentProject()
{
fs::path baseDir = fs::path(projectPath) / projectName;
if (s_currentProjectPath.empty() || s_currentProjectName.empty())
{
Logger::LogError("Cannot save project: no project loaded");
return false;
}
fs::path baseDir = fs::path(s_currentProjectPath);
fs::path projFile = baseDir / (s_currentProjectName + ".cproj");
{
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << s_currentProjectName;
out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version;
fs::path rel = fs::relative(s_defaultScene, baseDir);
out << YAML::Key << "s_defaultScene"
<< YAML::Value << ("res://" + rel.generic_string());
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
#if defined(_WIN32)
gmtime_s(&tm, &t);
#else
gmtime_r(&t, &tm);
#endif
char buf[32];
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm);
out << YAML::Key << "CreatedDate" << YAML::Value << buf;
out << YAML::EndMap;
std::ofstream fout(projFile);
if (!fout.is_open())
{
Logger::LogError("Could not open project file for writing: %s",
projFile.string().c_str());
return false;
}
fout << out.c_str();
}
Logger::LogOk("Saved project");
CreateDirectories(baseDir);
{
fs::path manifest = baseDir / "Assets" / ASSET_MANEFEST_NAME;
YAML::Emitter manOut;
manOut << YAML::BeginMap;
AssetManager::Save(manOut);
manOut << YAML::EndMap;
std::ofstream mf(manifest);
if (!mf.is_open())
{
Logger::LogError("Failed to write asset manifest: %s",
manifest.string().c_str());
}
else
{
mf << manOut.c_str();
Logger::LogDebug("Wrote asset manifest: %s",
manifest.string().c_str());
}
}
return true;
}
bool ProjectManager::SaveProject(
const std::string &projectPath,
const std::string &projectName)
{
fs::path baseDir = fs::path(projectPath) / projectName;
fs::path projFile = baseDir / (projectName + ".cproj");
std::error_code ec;
if (!fs::create_directories(baseDir, ec) && ec)
{
if (!fs::create_directories(baseDir, ec) && ec) {
Logger::LogError("Failed to create project directory '%s': %s",
projectPath.c_str(), ec.message().c_str());
return false;
}
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Name" << YAML::Value << projectName;
out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version;
fs::path relPath = fs::relative(s_defaultScene,
fs::path(s_currentProjectPath) / s_currentProjectName);
out << YAML::Key << "s_defaultScene" << YAML::Value << ("res://" + relPath.generic_string());
out << YAML::Key << "Name" << YAML::Value << projectName;
out << YAML::Key << "EngineVersion" << YAML::Value << g_engineConfig.version;
fs::path sceneRel = fs::relative(s_defaultScene,
fs::path(s_currentProjectPath) / s_currentProjectName);
out << YAML::Key << "s_defaultScene"
<< YAML::Value << ("res://" + sceneRel.generic_string());
// timestamp
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
#if defined(_WIN32)
#if defined(_WIN32)
gmtime_s(&tm, &t);
#else
#else
gmtime_r(&t, &tm);
#endif
#endif
char buf[32];
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm);
out << YAML::Key << "CreatedDate" << YAML::Value << buf;
out << YAML::EndMap;
std::ofstream fout(projFile);
if (!fout.is_open())
{
if (!fout.is_open()) {
Logger::LogError("Could not open project file for writing: %s",
projFile.string().c_str());
return false;
}
fout << out.c_str();
fout.close();
Logger::LogOk("Saved project '%s' at '%s'",
projectName.c_str(), projectPath.c_str());
Logger::LogOk("Saved project '%s'",
projectName.c_str());
CreateDirectories(baseDir);
{
fs::path manifest = baseDir / "Assets" / ASSET_MANEFEST_NAME;
YAML::Emitter assetOut;
assetOut << YAML::BeginMap;
AssetManager::Save(assetOut);
assetOut << YAML::EndMap;
std::ofstream mf(manifest);
if (!mf.is_open()) {
Logger::LogError("Failed to write asset manifest: %s",
manifest.string().c_str());
} else {
mf << assetOut.c_str();
mf.close();
Logger::LogDebug("Wrote asset manifest: %s",
manifest.string().c_str());
}
}
// update our in-memory project pointers
s_currentProjectPath = projectPath;
s_currentProjectName = projectName;
return true;
}
const std::string &ProjectManager::GetCurrentProjectPath()
{
return s_currentProjectPath;

View File

@ -57,7 +57,6 @@ private:
static std::string IconFileForPath(const fs::path &path);
static void DrawFolderTree(const fs::path &path);
// Initializes file queue by scanning res:// recursively
static void InitLoading();
};
@ -76,6 +75,8 @@ public:
static bool SaveProject(const std::string& projectPath,
const std::string& projectName);
static bool SaveCurrentProject();
// Creates a project at the path with the name
// makes a .cproj file at the path in the name folder
static bool CreateProject(const std::string& projectPath,

View File

@ -38,7 +38,7 @@ bool VerifySceneHash(const YAML::Node &root)
return hashHex.str() == root["scene_hash"].as<std::string>();
}
void SceneLoader::SaveScene(const std::string &path)
void SceneLoader::SaveScene(const std::string &path, bool standalone)
{
YAML::Emitter out;
YAML::Emitter sceneData;
@ -78,7 +78,8 @@ void SceneLoader::SaveScene(const std::string &path)
out << YAML::Key << "threshold" << YAML::Value << Renderer::GetColorCorrection()->threshold;
out << YAML::EndMap;
//AssetManager::Save(out);
if (standalone)
AssetManager::Save(out);
out << YAML::EndMap;
@ -88,7 +89,7 @@ void SceneLoader::SaveScene(const std::string &path)
Logger::LogOk("Scene Saved");
}
void SceneLoader::LoadScene(const std::string &path)
void SceneLoader::LoadScene(const std::string &path, bool standalone)
{
bool legacyLoad = false;
@ -152,16 +153,17 @@ void SceneLoader::LoadScene(const std::string &path)
{
Logger::LogWarning("Scene hash does not match! File may be corrupted or tampered.");
}
if (standalone) {
if (root["Assets"])
{
currentStep = "Loading Assets";
currentDetail = "Parsing asset data...";
loadingUI.Update(currentStep, currentDetail, 0.05f);
//if (root["Assets"])
//{
// currentStep = "Loading Assets";
// currentDetail = "Parsing asset data...";
// loadingUI.Update(currentStep, currentDetail, 0.05f);
//
// Logger::LogDebug("Loading Assets");
// AssetManager::Load(root["Assets"]);
//}
Logger::LogDebug("Loading Assets");
AssetManager::Load(root["Assets"]);
}
}
Logger::LogDebug("Reseting Scene.");
currentStep = "Clearing Previous Scene";

View File

@ -5,7 +5,7 @@
class SceneLoader
{
public:
static void SaveScene(const std::string &path);
static void LoadScene(const std::string &path);
static void SaveScene(const std::string &path, bool standalone = false);
static void LoadScene(const std::string &path, bool standalone = false);
};

View File

@ -9,6 +9,8 @@
#include <stb_image.h>
#include "../../Entitys/Object.h"
#include "../../core/functions/ProjectManager.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -21,6 +23,10 @@ std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID;
uint64_t AssetManager::s_NextUAID = 1;
std::string AssetManager::GetFileExtension(const std::string& filepath)
{
std::string ext = fs::path(filepath).extension().string(); // ".PNG"
@ -600,19 +606,29 @@ void AssetManager::ClearAllAssets()
}
namespace fs = std::filesystem;
void AssetManager::Save(YAML::Emitter &out)
{
// Write out each assets UAID and a res:// path
out << YAML::Key << "Assets" << YAML::BeginSeq;
fs::path projectRoot = fs::path(ProjectManager::GetCurrentProjectPath());
for (const auto &[uaid, asset] : s_Assets)
{
// compute res:// relative path
fs::path fullPath = asset->path;
fs::path rel = fs::relative(fullPath, projectRoot);
std::string resPath = std::string("res://") + rel.generic_string();
out << YAML::BeginMap;
out << YAML::Key << "uaid" << YAML::Value << asset->uaid;
out << YAML::Key << "path" << YAML::Value << asset->path;
out << YAML::Key << "uaid" << YAML::Value << asset->uaid;
out << YAML::Key << "path" << YAML::Value << resPath;
out << YAML::Key << "filename" << YAML::Value << asset->filename;
out << YAML::Key << "filetype" << YAML::Value << asset->filetype;
out << YAML::Key << "type" << YAML::Value << static_cast<int>(asset->type);
out << YAML::Key << "hash" << YAML::Value << asset->hash;
out << YAML::Key << "type" << YAML::Value << static_cast<int>(asset->type);
out << YAML::Key << "hash" << YAML::Value << asset->hash;
out << YAML::Key << "lastModified" << YAML::Value << asset->lastModified;
// let each subclass dump its own data
asset->Save(out);
out << YAML::EndMap;
}
@ -621,66 +637,69 @@ void AssetManager::Save(YAML::Emitter &out)
void AssetManager::Load(const YAML::Node &node)
{
if (!node)
return;
if (!node) return;
LoadingWindow loadingUI;
loadingUI.Create("Loading Assets");
fs::path projectRoot = fs::path(ProjectManager::GetCurrentProjectPath());
const size_t total = node.size();
size_t index = 0;
for (const auto &item : node)
{
// 1) read the res:// path and convert to real FS path
std::string resPath = item["path"].as<std::string>();
std::string fsPath = ProjectManager::ResolveResPath(resPath);
uint64_t uaid = item["uaid"].as<uint64_t>();
std::string path = item["path"].as<std::string>();
AssetType type = static_cast<AssetType>(item["type"].as<int>());
uint64_t uaid = item["uaid"].as<uint64_t>();
AssetType type = static_cast<AssetType>(item["type"].as<int>());
// 2) allocate the right subclass
std::shared_ptr<AssetInfo> asset;
if (type == AssetType::Image)
asset = std::make_shared<ImageAssetInfo>();
else if (type == AssetType::Audio)
asset = std::make_shared<AudioAssetInfo>();
else if (type == AssetType::Prefab)
asset = std::make_shared<PrefabAssetInfo>();
else if (type == AssetType::Font)
asset = std::make_shared<FontAssetInfo>();
else
continue;
switch (type) {
case AssetType::Image: asset = std::make_shared<ImageAssetInfo>(); break;
case AssetType::Audio: asset = std::make_shared<AudioAssetInfo>(); break;
case AssetType::Prefab: asset = std::make_shared<PrefabAssetInfo>(); break;
case AssetType::Font: asset = std::make_shared<FontAssetInfo>(); break;
default: continue;
}
float progress = static_cast<float>(index) / total;
loadingUI.Update("Loading Asset", path, progress);
// 3) progress UI
float progress = static_cast<float>(index++) / total;
loadingUI.Update("Loading Asset", fsPath, progress);
asset->uaid = uaid;
asset->path = path;
asset->filename = item["filename"] ? item["filename"].as<std::string>() : GetFilenameFromPath(path);
asset->filetype = item["filetype"] ? item["filetype"].as<std::string>() : GetFileExtension(path);
asset->hash = item["hash"] ? item["hash"].as<std::string>() : "";
// 4) populate fields
asset->uaid = uaid;
asset->path = fsPath; // now points at real file
asset->filename = item["filename"] ? item["filename"].as<std::string>()
: GetFilenameFromPath(fsPath);
asset->filetype = item["filetype"] ? item["filetype"].as<std::string>()
: GetFileExtension(fsPath);
asset->hash = item["hash"] ? item["hash"].as<std::string>() : "";
asset->lastModified = item["lastModified"] ? item["lastModified"].as<std::time_t>() : 0;
asset->loaded = false;
asset->loaded = false;
// 5) subclassspecific load
asset->Load(item);
s_Assets[uaid] = asset;
s_PathToUAID[path] = uaid;
// 6) insert into maps
s_Assets [uaid] = asset;
s_PathToUAID[asset->path] = uaid;
if (uaid >= s_NextUAID) s_NextUAID = uaid + 1;
if (uaid >= s_NextUAID)
s_NextUAID = uaid + 1;
if (type == AssetType::Image)
LoadImageInternal(path, uaid);
else if (type == AssetType::Audio)
LoadAudioInternal(path, uaid);
else if (type == AssetType::Prefab)
LoadPrefabInternal(path, uaid);
else if (type == AssetType::Font)
LoadFontInternal(path, uaid);
else
Logger::LogError("[Engine Error] Unhandled Internal Asset Loading. %s", AssetTypeToString(type));
++index;
// 7) internal loading
switch (type) {
case AssetType::Image: LoadImageInternal(fsPath, uaid); break;
case AssetType::Audio: LoadAudioInternal(fsPath, uaid); break;
case AssetType::Prefab: LoadPrefabInternal(fsPath, uaid); break;
case AssetType::Font: LoadFontInternal(fsPath, uaid); break;
default:
Logger::LogError("[Engine Error] Unhandled asset type %s",
AssetTypeToString(type));
}
}
loadingUI.Destroy();
}

View File

@ -158,6 +158,10 @@ public:
static uint64_t GenerateUAID();
bool SaveManifest(const std::string &manifestPath);
bool LoadManifest(const std::string &manifestPath);
static std::string GetFileExtension(const std::string& filepath);
static AssetType AssetTypeFromExtension(std::string ext);

View File

@ -25,6 +25,7 @@ static std::unordered_map<FileDialogType, const char*> filters = {
{ FileDialogType::Fonts, "Font Files\0*.ttf;*.otf;*.fnt\0All Files\0*.*\0" },
{ FileDialogType::Models, "3D Models\0*.obj;*.fbx;*.gltf;*.dae\0All Files\0*.*\0" },
{ FileDialogType::Project, "Project File\0*.cproj\0All Files\0*.*\0" },
{ FileDialogType::AssetManifests, "Asset Manifest Files\0*.cmanifest;*.assetmanifest;*.yaml\0All Files\0*.*\0" },
{ FileDialogType::All, "All Files\0*.*\0" }
};

View File

@ -14,6 +14,7 @@ enum class FileDialogType {
Fonts, // .ttf, .otf
Models, // .obj, .fbx, .gltf, etc.
Project,
AssetManifests,
All
};

View File

@ -56,7 +56,7 @@ bool Logger::s_ShowWarning = true;
bool Logger::s_ShowError = true;
bool Logger::s_ShowDebug = false;
bool Logger::s_ShowVerbose = false;
bool Logger::s_PrintToTerminal = true;
bool Logger::s_PrintToTerminal = false;
const char *Logger::ToString(Level level)
{

View File

@ -16,7 +16,29 @@
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
#include <cstdio>
static inline void ImGuiAssertHandler(const char* expr, const char* file, int line)
{
std::fprintf(stderr,
"Assertion failed: (%s), at %s:%d\n",
expr, file, line);
#if defined(_MSC_VER)
__debugbreak(); // MSVC
#elif defined(__GNUC__) || defined(__clang__)
__builtin_trap(); // GCC / Clang
#else
std::abort(); // Fallback
#endif
}
#undef IM_ASSERT
#define IM_ASSERT(_EXPR) \
do { \
if (!(_EXPR)) \
ImGuiAssertHandler(#_EXPR, __FILE__, __LINE__); \
} while (0)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows