Added Prefab instatiation

This commit is contained in:
OusmBlueNinja 2025-05-07 10:39:48 -05:00
parent dd29a6bfdf
commit d645875322
9 changed files with 1653 additions and 1375 deletions

View File

@ -21,13 +21,13 @@ DockId=0x00000018,0
[Window][Scene Tree] [Window][Scene Tree]
Pos=0,19 Pos=0,19
Size=342,579 Size=347,579
Collapsed=0 Collapsed=0
DockId=0x0000000F,0 DockId=0x0000000F,0
[Window][Viewport] [Window][Viewport]
Pos=344,19 Pos=349,19
Size=1207,659 Size=1202,659
Collapsed=0 Collapsed=0
DockId=0x00000017,0 DockId=0x00000017,0
@ -42,8 +42,8 @@ Collapsed=0
DockId=0x00000016,0 DockId=0x00000016,0
[Window][Console] [Window][Console]
Pos=344,680 Pos=349,680
Size=1206,273 Size=1201,273
Collapsed=0 Collapsed=0
DockId=0x00000013,0 DockId=0x00000013,0
@ -54,8 +54,8 @@ Collapsed=0
DockId=0x00000017,1 DockId=0x00000017,1
[Window][Profiler] [Window][Profiler]
Pos=344,955 Pos=349,955
Size=1206,222 Size=1201,222
Collapsed=0 Collapsed=0
DockId=0x00000014,0 DockId=0x00000014,0
@ -125,13 +125,13 @@ DockId=0x0000000D,0
[Window][Resources] [Window][Resources]
Pos=0,600 Pos=0,600
Size=342,577 Size=347,577
Collapsed=0 Collapsed=0
DockId=0x00000010,0 DockId=0x00000010,0
[Window][Import Preview] [Window][Import Preview]
Pos=351,22 Pos=351,22
Size=550,1152 Size=536,391
Collapsed=0 Collapsed=0
[Table][0x96376740,2] [Table][0x96376740,2]
@ -142,18 +142,18 @@ Column 1 Width=120
[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=1920,1158 Split=X
DockNode ID=0x00000005 Parent=0x11111111 SizeRef=989,1158 Split=X DockNode ID=0x00000005 Parent=0x11111111 SizeRef=989,1158 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 DockNode ID=0x00000001 Parent=0x00000005 SizeRef=347,701 Split=Y Selected=0x12EF0F59
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,637 Split=Y Selected=0x12EF0F59 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,637 Split=Y Selected=0x12EF0F59
DockNode ID=0x0000000F Parent=0x00000003 SizeRef=342,579 HiddenTabBar=1 Selected=0x12EF0F59 DockNode ID=0x0000000F Parent=0x00000003 SizeRef=342,579 HiddenTabBar=1 Selected=0x12EF0F59
DockNode ID=0x00000010 Parent=0x00000003 SizeRef=342,577 HiddenTabBar=1 Selected=0x30401527 DockNode ID=0x00000010 Parent=0x00000003 SizeRef=342,577 HiddenTabBar=1 Selected=0x30401527
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,519 HiddenTabBar=1 Selected=0x36AF052B DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,519 HiddenTabBar=1 Selected=0x36AF052B
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1576,701 Split=Y Selected=0xC450F867 DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1571,701 Split=Y Selected=0xC450F867
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,659 Split=X Selected=0xC450F867 DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,659 Split=X Selected=0xC450F867
DockNode ID=0x00000017 Parent=0x00000007 SizeRef=1207,860 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 DockNode ID=0x00000017 Parent=0x00000007 SizeRef=1202,860 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
DockNode ID=0x00000018 Parent=0x00000007 SizeRef=367,860 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000018 Parent=0x00000007 SizeRef=367,860 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,497 Split=X Selected=0xEA83D666 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,497 Split=X Selected=0xEA83D666
DockNode ID=0x00000015 Parent=0x00000008 SizeRef=1260,172 Split=X Selected=0xEA83D666 DockNode ID=0x00000015 Parent=0x00000008 SizeRef=1255,172 Split=X Selected=0xEA83D666
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=1206,168 Split=Y Selected=0x9B5D3198 DockNode ID=0x00000011 Parent=0x00000015 SizeRef=1201,168 Split=Y Selected=0x9B5D3198
DockNode ID=0x00000013 Parent=0x00000011 SizeRef=1449,273 HiddenTabBar=1 Selected=0xEA83D666 DockNode ID=0x00000013 Parent=0x00000011 SizeRef=1449,273 HiddenTabBar=1 Selected=0xEA83D666
DockNode ID=0x00000014 Parent=0x00000011 SizeRef=1449,222 HiddenTabBar=1 Selected=0x9B5D3198 DockNode ID=0x00000014 Parent=0x00000011 SizeRef=1449,222 HiddenTabBar=1 Selected=0x9B5D3198
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=52,168 HiddenTabBar=1 Selected=0x56009A08 DockNode ID=0x00000012 Parent=0x00000015 SizeRef=52,168 HiddenTabBar=1 Selected=0x56009A08

View File

@ -1,3 +1,3 @@
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o [COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\editor\windows\AssetBrowser.cpp -o src\build\editor\windows\AssetBrowser.o
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -Isrc/vendor/miniaudio -Isrc/vendor/imguizmo -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\core\utils\AssetManager.cpp -o src\build\core\utils\AssetManager.o
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.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\functions\Prefab.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\Popup.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\AudioInfo.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 src\build\miniaudio.o src\build\ImGuizmo.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp [LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\AudioPlayerComponent.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\functions\Prefab.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\Popup.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\AudioInfo.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 src\build\miniaudio.o src\build\ImGuizmo.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -ldbghelp
[RUN] Executed app.exe successfully.

File diff suppressed because it is too large Load Diff

View File

@ -1220,6 +1220,48 @@ void Engine::Run()
} }
} }
{
const ImGuiPayload *payload = ImGui::GetDragDropPayload();
bool draggingPrefab = payload && payload->IsDataType("ASSET_PREFAB") && payload->DataSize == sizeof(uint64_t);
bool hoveringViewport = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
bool mouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left);
if (draggingPrefab && hoveringViewport && mouseReleased)
{
uint64_t uaid = *(const uint64_t *)payload->Data;
const auto *asset = AssetManager::GetAssetByID(uaid);
if (!asset || asset->type != AssetType::Prefab)
return;
auto prefabInfo = dynamic_cast<const PrefabAssetInfo *>(asset);
if (!prefabInfo)
{
Logger::LogError("[AssetManager] Asset is not a PrefabAssetInfo");
return;
}
std::shared_ptr<Object> newObj = prefabInfo->Instantiate();
if (!newObj)
{
Logger::LogError("[Editor] Failed to instantiate prefab.");
return;
}
ImVec2 mousePos = ImGui::GetMousePos();
ImVec2 screenMin = ImGui::GetWindowPos();
ImVec2 localPos = ImVec2(mousePos.x - screenMin.x, mousePos.y - screenMin.y);
core::types::Vec2 worldPos = ScreenToWorld(core::types::Vec2(localPos), size, cameraPos, cameraZoom);
newObj->SetWorldPosition(worldPos);
objects.push_back(newObj);
Logger::LogInfo("[Editor] Instantiated prefab at (%.2f, %.2f)", worldPos.x, worldPos.y);
}
}
static std::shared_ptr<Object> previewObj = nullptr; static std::shared_ptr<Object> previewObj = nullptr;
static uint64_t previewUAID = 0; static uint64_t previewUAID = 0;
@ -1229,7 +1271,6 @@ void Engine::Run()
bool mouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); bool mouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left);
bool hoveringViewport = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); bool hoveringViewport = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
// While dragging and hovering viewport
if (draggingTexture && mouseHeld && hoveringViewport) if (draggingTexture && mouseHeld && hoveringViewport)
{ {
uint64_t uaid = *(const uint64_t *)payload->Data; uint64_t uaid = *(const uint64_t *)payload->Data;

View File

@ -11,60 +11,62 @@
#include <ctime> #include <ctime>
#include <sstream> #include <sstream>
std::string Prefab::CreatePrefab(const std::shared_ptr<Object>& obj, const std::string& outputDir) std::string Prefab::CreatePrefab(const std::shared_ptr<Object>& obj, const std::string& outputDir)
{ {
if (!obj) if (!obj)
{
Logger::LogError("[Prefab] Cannot create prefab from null object.");
return ""; return "";
}
std::string name = obj->GetName().empty() ? "Unnamed" : obj->GetName(); // Clean filename
for (char& c : name) std::string filename = obj->GetName().empty() ? "Unnamed" : obj->GetName();
{ for (auto& ch : filename)
if (!std::isalnum(c) && c != '_' && c != '-' && c != ' ') if (ch == '/' || ch == '\\' || ch == ':' || ch == '*' || ch == '?' || ch == '\"' || ch == '<' || ch == '>' || ch == '|')
c = '_'; ch = '_';
}
// Emit object YAML std::string path = outputDir + "/" + filename + ".cpfb";
// Serialize Object to string
YAML::Emitter objectOut; YAML::Emitter objectOut;
objectOut.SetIndent(2); objectOut.SetIndent(2);
obj->Save(objectOut); obj->Save(objectOut);
// Wrap metadata // Parse the object YAML string back into a real node
YAML::Node objectNode;
try {
objectNode = YAML::Load(objectOut.c_str());
} catch (const YAML::Exception& e) {
Logger::LogError("[Prefab] Failed to parse object YAML for prefab: %s", e.what());
return "";
}
// Write the outer asset structure
YAML::Emitter out; YAML::Emitter out;
out.SetIndent(2); out.SetIndent(2);
std::string hash = HashString(objectOut.c_str());
std::time_t now = std::time(nullptr);
out << YAML::BeginMap; out << YAML::BeginMap;
out << YAML::Key << "uaid" << YAML::Value << AssetManager::GenerateUAID();
out << YAML::Key << "filename" << YAML::Value << name + ".cpfb"; out << YAML::Key << "uaid" << YAML::Value << AssetManager::GenerateUAID();
out << YAML::Key << "filetype" << YAML::Value << "cpfb"; out << YAML::Key << "filename" << YAML::Value << filename + ".cpfb";
out << YAML::Key << "type" << YAML::Value << "Prefab"; out << YAML::Key << "filetype" << YAML::Value << "cpfb";
out << YAML::Key << "prefabName" << YAML::Value << name; out << YAML::Key << "type" << YAML::Value << "Prefab";
out << YAML::Key << "hash" << YAML::Value << hash; out << YAML::Key << "prefabName" << YAML::Value << obj->GetName();
out << YAML::Key << "lastModified" << YAML::Value << now; out << YAML::Key << "hash" << YAML::Value << "";
out << YAML::Key << "loaded" << YAML::Value << true; out << YAML::Key << "lastModified" << YAML::Value << GetFileLastWrite(path);
out << YAML::Key << "prefabYAML" << YAML::Value << objectOut.c_str(); out << YAML::Key << "prefabYAML" << YAML::Value << objectNode;
out << YAML::EndMap; out << YAML::EndMap;
// Output file std::ofstream file(path);
std::filesystem::create_directories(outputDir);
std::string fullPath = outputDir + "/" + name + ".cpfb";
std::ofstream file(fullPath);
if (file.is_open()) if (file.is_open())
{ {
file << out.c_str(); file << out.c_str();
file.close(); file.close();
Logger::LogInfo("[Prefab] Saved prefab: %s", fullPath.c_str()); Logger::LogInfo("[Prefab] Saved prefab: %s", path.c_str());
return fullPath;
} }
else else
{ {
Logger::LogError("[Prefab] Failed to save prefab: %s (%s)", fullPath.c_str(), std::strerror(errno)); Logger::LogError("[Prefab] Failed to write prefab file: %s (%s)", path.c_str(), std::strerror(errno));
return "";
} }
return path;
} }

View File

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <ostream> #include <ostream>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <imgui.h>
namespace core namespace core
{ {
@ -16,10 +17,11 @@ namespace core
float x{0}, y{0}; float x{0}, y{0};
Vec2() = default; Vec2() = default;
Vec2(float x, float y) : x(x), y(y) {} Vec2(float x, float y) : x(x), y(y) {}
Vec2(float v) : x(v), y(v) {} Vec2(float v) : x(v), y(v) {}
Vec2(const glm::vec2 &v) : x(v.x), y(v.y) {} Vec2(const glm::vec2 &v) : x(v.x), y(v.y) {}
Vec2(const Vec2i &v); Vec2(const Vec2i &v);
Vec2(const ImVec2 &v) : x(v.x), y(v.y) {}
operator glm::vec2() const { return {x, y}; } operator glm::vec2() const { return {x, y}; }
@ -30,10 +32,30 @@ namespace core
Vec2 operator*(const Vec2 &rhs) const { return {x * rhs.x, y * rhs.y}; } Vec2 operator*(const Vec2 &rhs) const { return {x * rhs.x, y * rhs.y}; }
Vec2 &operator+=(const Vec2 &rhs) { x += rhs.x; y += rhs.y; return *this; } Vec2 &operator+=(const Vec2 &rhs)
Vec2 &operator-=(const Vec2 &rhs) { x -= rhs.x; y -= rhs.y; return *this; } {
Vec2 &operator*=(float scalar) { x *= scalar; y *= scalar; return *this; } x += rhs.x;
Vec2 &operator/=(float scalar) { x /= scalar; y /= scalar; return *this; } y += rhs.y;
return *this;
}
Vec2 &operator-=(const Vec2 &rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
Vec2 &operator*=(float scalar)
{
x *= scalar;
y *= scalar;
return *this;
}
Vec2 &operator/=(float scalar)
{
x /= scalar;
y /= scalar;
return *this;
}
Vec2 operator-() const { return {-x, -y}; } Vec2 operator-() const { return {-x, -y}; }
@ -99,10 +121,30 @@ namespace core
Vec2 operator*(const Vec2 &rhs) const { return Vec2(x * rhs.x, y * rhs.y); } Vec2 operator*(const Vec2 &rhs) const { return Vec2(x * rhs.x, y * rhs.y); }
Vec2i &operator+=(const Vec2i &rhs) { x += rhs.x; y += rhs.y; return *this; } Vec2i &operator+=(const Vec2i &rhs)
Vec2i &operator-=(const Vec2i &rhs) { x -= rhs.x; y -= rhs.y; return *this; } {
Vec2i &operator*=(int scalar) { x *= scalar; y *= scalar; return *this; } x += rhs.x;
Vec2i &operator/=(int scalar) { x /= scalar; y /= scalar; return *this; } y += rhs.y;
return *this;
}
Vec2i &operator-=(const Vec2i &rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
Vec2i &operator*=(int scalar)
{
x *= scalar;
y *= scalar;
return *this;
}
Vec2i &operator/=(int scalar)
{
x /= scalar;
y /= scalar;
return *this;
}
bool operator==(const Vec2i &rhs) const { return x == rhs.x && y == rhs.y; } bool operator==(const Vec2i &rhs) const { return x == rhs.x && y == rhs.y; }
bool operator!=(const Vec2i &rhs) const { return !(*this == rhs); } bool operator!=(const Vec2i &rhs) const { return !(*this == rhs); }

View File

@ -8,8 +8,6 @@
#include <stb_image.h> #include <stb_image.h>
#include "../../Entitys/Object.h" #include "../../Entitys/Object.h"
std::unordered_map<uint64_t, std::shared_ptr<AssetInfo>> AssetManager::s_Assets; 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;
@ -169,77 +167,9 @@ const char *MiniaudioResultToString(ma_result result)
} }
} }
// PrefabAssetInfo.cpp
PrefabAssetInfo::PrefabAssetInfo() {
type = AssetType::Prefab;
}
void PrefabAssetInfo::Save(YAML::Emitter& out) const {
out << YAML::BeginMap;
out << YAML::Key << "uaid" << YAML::Value << uaid;
out << YAML::Key << "path" << YAML::Value << path;
out << YAML::Key << "filename" << YAML::Value << filename;
out << YAML::Key << "filetype" << YAML::Value << filetype;
out << YAML::Key << "type" << YAML::Value << "Prefab";
out << YAML::Key << "hash" << YAML::Value << hash;
out << YAML::Key << "lastModified" << YAML::Value << lastModified;
out << YAML::Key << "loaded" << YAML::Value << loaded;
out << YAML::Key << "prefabYAML" << YAML::Value << prefabYAML;
// Prefab metadata
out << YAML::Key << "prefabName" << YAML::Value << prefabName;
out << YAML::EndMap;
}
void PrefabAssetInfo::Load(const YAML::Node& node) {
uaid = node["uaid"].as<uint64_t>();
path = node["path"].as<std::string>();
filename = node["filename"].as<std::string>();
filetype = node["filetype"].as<std::string>();
hash = node["hash"].as<std::string>();
lastModified = node["lastModified"].as<std::time_t>();
loaded = node["loaded"].as<bool>();
prefabYAML = node["prefabYAML"] ? node["prefabYAML"].as<std::string>() : "";
if (node["prefabName"])
prefabName = node["prefabName"].as<std::string>();
ReloadFromYAML();
}
void PrefabAssetInfo::ReloadFromYAML()
{
if (prefabYAML.empty())
return;
YAML::Node root;
try {
root = YAML::Load(prefabYAML);
}
catch (const std::exception& e) {
Logger::LogError("[Prefab] YAML parse error: %s", e.what());
return;
}
prefabRoot = std::make_shared<Object>("PrefabRoot");
prefabRoot->Load(root);
}
void AssetManager::Init() void AssetManager::Init()
{ {
Logger::LogOk("AssetManager Core"); Logger::LogOk("AssetManager Core");
} }
uint64_t AssetManager::GenerateUAID() uint64_t AssetManager::GenerateUAID()
@ -262,6 +192,8 @@ void AssetManager::LoadAssetAsync(const std::string &path, AssetType type)
asset = std::make_shared<ImageAssetInfo>(); asset = std::make_shared<ImageAssetInfo>();
else if (type == AssetType::Audio) else if (type == AssetType::Audio)
asset = std::make_shared<AudioAssetInfo>(); asset = std::make_shared<AudioAssetInfo>();
else if (type == AssetType::Prefab)
asset = std::make_shared<PrefabAssetInfo>();
else else
{ {
Logger::LogWarning("[AssetManager] Unknown Asset Type: '%d'", static_cast<int>(type)); Logger::LogWarning("[AssetManager] Unknown Asset Type: '%d'", static_cast<int>(type));
@ -282,7 +214,6 @@ void AssetManager::LoadAssetAsync(const std::string &path, AssetType type)
LoadAudioInternal(path, uaid); LoadAudioInternal(path, uaid);
else if (type == AssetType::Prefab) else if (type == AssetType::Prefab)
LoadPrefabInternal(path, uaid); LoadPrefabInternal(path, uaid);
} }
void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid) void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
@ -342,9 +273,6 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
Logger::LogVerbose("[AssetManager] Loaded image: %s (%dx%d)", path.c_str(), w, h); Logger::LogVerbose("[AssetManager] Loaded image: %s (%dx%d)", path.c_str(), w, h);
} }
void AssetManager::LoadAudioInternal(const std::string &path, 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);
@ -374,13 +302,9 @@ void AssetManager::LoadAudioInternal(const std::string &path, uint64_t uaid)
Logger::LogVerbose("[AssetManager] Loaded audio: %s", path.c_str()); Logger::LogVerbose("[AssetManager] Loaded audio: %s", path.c_str());
} }
void AssetManager::LoadPrefabInternal(const std::string &path, uint64_t uaid)
void AssetManager::LoadPrefabInternal(const std::string& path, uint64_t uaid)
{ {
// Skip if already loaded and not dirty if (auto it = s_Assets.find(uaid); it != s_Assets.end() && it->second->loaded)
auto it = s_Assets.find(uaid);
if (it != s_Assets.end() && it->second->loaded)
return; return;
if (!FileExists(path)) if (!FileExists(path))
@ -389,40 +313,55 @@ void AssetManager::LoadPrefabInternal(const std::string& path, uint64_t uaid)
return; return;
} }
std::string yamlContent; std::string fileContent;
if (!ReadTextFile(path, yamlContent)) if (!ReadTextFile(path, fileContent))
{ {
Logger::LogError("[AssetManager] Failed to read prefab file: %s", path.c_str()); Logger::LogError("[AssetManager] Failed to read prefab file: %s", path.c_str());
return; return;
} }
YAML::Node root;
try
{
root = YAML::Load(fileContent);
}
catch (const YAML::Exception &e)
{
Logger::LogError("[AssetManager] YAML parse error in %s: %s", path.c_str(), e.what());
return;
}
YAML::Node inner = root["prefabYAML"];
if (!inner || !inner.IsMap())
{
Logger::LogError("[AssetManager] Missing or invalid 'prefabYAML' in: %s", path.c_str());
return;
}
std::string prefabName = root["prefabName"] ? root["prefabName"].as<std::string>() : "Unnamed Prefab";
auto prefab = std::make_shared<PrefabAssetInfo>(); auto prefab = std::make_shared<PrefabAssetInfo>();
prefab->uaid = uaid; prefab->uaid = uaid;
prefab->path = path; prefab->path = path;
prefab->filename = GetFilenameFromPath(path); prefab->filename = GetFilenameFromPath(path);
prefab->filetype = GetFileExtension(path); prefab->filetype = GetFileExtension(path);
prefab->type = AssetType::Prefab; prefab->type = AssetType::Prefab;
prefab->prefabYAML = yamlContent; prefab->prefabYAML = inner;
prefab->prefabName = prefabName;
prefab->lastModified = GetFileLastWrite(path); prefab->lastModified = GetFileLastWrite(path);
prefab->hash = GetFileHash(path); prefab->hash = GetFileHash(path);
prefab->loaded = true; prefab->loaded = true;
prefab->ReloadFromYAML(); // Create and load root object
prefab->prefabRoot = std::make_shared<Object>(prefabName);
if (!prefab->prefabRoot) prefab->prefabRoot->Load(inner);
{
Logger::LogError("[AssetManager] Failed to deserialize prefab object: %s", path.c_str());
return;
}
// Register asset
s_Assets[uaid] = prefab; s_Assets[uaid] = prefab;
Logger::LogVerbose("[AssetManager] Loaded prefab: %s (UAID: %llu)", path.c_str(), uaid); Logger::LogVerbose("[AssetManager] Loaded prefab: %s (UAID: %llu)", path.c_str(), uaid);
} }
const AssetInfo *AssetManager::GetAssetByID(uint64_t uaid) const AssetInfo *AssetManager::GetAssetByID(uint64_t uaid)
{ {
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
@ -490,15 +429,12 @@ void AssetManager::Load(const YAML::Node &node)
if (!node) if (!node)
return; return;
LoadingWindow loadingUI; LoadingWindow loadingUI;
loadingUI.Create("Loading Assets"); loadingUI.Create("Loading Assets");
const size_t total = node.size(); const size_t total = node.size();
size_t index = 0; size_t index = 0;
for (const auto &item : node) for (const auto &item : node)
{ {
@ -539,7 +475,6 @@ void AssetManager::Load(const YAML::Node &node)
LoadAudioInternal(path, uaid); LoadAudioInternal(path, uaid);
++index; ++index;
} }
loadingUI.Destroy(); loadingUI.Destroy();
} }
@ -564,3 +499,99 @@ void ImageAssetInfo::Load(const YAML::Node &node)
void AudioAssetInfo::Save(YAML::Emitter &out) const {} void AudioAssetInfo::Save(YAML::Emitter &out) const {}
void AudioAssetInfo::Load(const YAML::Node &node) {} void AudioAssetInfo::Load(const YAML::Node &node) {}
PrefabAssetInfo::PrefabAssetInfo()
{
type = AssetType::Prefab;
}
void PrefabAssetInfo::Save(YAML::Emitter &out) const
{
out << YAML::Key << "uaid" << YAML::Value << uaid;
out << YAML::Key << "filename" << YAML::Value << filename;
out << YAML::Key << "filetype" << YAML::Value << filetype;
out << YAML::Key << "type" << YAML::Value << "Prefab";
out << YAML::Key << "prefabName" << YAML::Value << prefabName;
out << YAML::Key << "hash" << YAML::Value << hash;
out << YAML::Key << "lastModified" << YAML::Value << lastModified;
out << YAML::Key << "prefabYAML";
if (prefabRoot)
{
YAML::Emitter innerOut;
innerOut.SetIndent(2);
prefabRoot->Save(innerOut);
YAML::Node parsedInner;
try
{
parsedInner = YAML::Load(innerOut.c_str());
}
catch (const YAML::Exception &e)
{
Logger::LogError("[PrefabAssetInfo] Failed to parse prefabRoot YAML for saving: %s", e.what());
}
out << parsedInner;
}
else
{
out << prefabYAML;
}
}
void PrefabAssetInfo::Load(const YAML::Node &node)
{
uaid = node["uaid"] ? node["uaid"].as<uint64_t>() : 0;
filename = node["filename"] ? node["filename"].as<std::string>() : "unknown.cpfb";
filetype = node["filetype"] ? node["filetype"].as<std::string>() : "cpfb";
type = AssetType::Prefab;
prefabName = node["prefabName"] ? node["prefabName"].as<std::string>() : "Unnamed Prefab";
hash = node["hash"] ? node["hash"].as<std::string>() : "";
lastModified = node["lastModified"] ? node["lastModified"].as<uint64_t>() : 0;
if (!node["prefabYAML"] || !node["prefabYAML"].IsMap())
{
Logger::LogError("[PrefabAssetInfo] Missing or invalid 'prefabYAML' node in prefab file.");
prefabYAML = YAML::Node();
prefabRoot = nullptr;
return;
}
prefabYAML = node["prefabYAML"];
ReloadFromYAML();
}
void PrefabAssetInfo::ReloadFromYAML()
{
if (!prefabYAML || !prefabYAML.IsMap())
{
Logger::LogError("[PrefabAsset] Invalid or missing prefab YAML node.");
prefabRoot = nullptr;
return;
}
prefabRoot = std::make_shared<Object>(prefabName);
prefabRoot->Load(prefabYAML);
}
std::shared_ptr<Object> PrefabAssetInfo::Instantiate() const
{
if (!prefabYAML || !prefabYAML.IsMap())
{
Logger::LogError("[PrefabAsset] Cannot instantiate: prefab YAML is invalid.");
return nullptr;
}
auto newObj = std::make_shared<Object>(prefabName);
newObj->Load(prefabYAML);
return newObj;
}

View File

@ -11,13 +11,46 @@
class Object; class Object;
#pragma once
#include <string>
#include <unordered_map>
#include <string_view>
#define ASSET_TYPE_LIST \
X(Image) \
X(Audio) \
X(Prefab) \
X(Unknown)
enum class AssetType { enum class AssetType {
Image, #define X(name) name,
Audio, ASSET_TYPE_LIST
Prefab, #undef X
Unknown
}; };
inline const char* AssetTypeToString(AssetType type) {
switch (type) {
#define X(name) case AssetType::name: return #name;
ASSET_TYPE_LIST
#undef X
default: return "Unknown";
}
}
inline AssetType StringToAssetType(const std::string_view str) {
static const std::unordered_map<std::string_view, AssetType> map = {
#define X(name) {#name, AssetType::name},
ASSET_TYPE_LIST
#undef X
};
auto it = map.find(str);
return it != map.end() ? it->second : AssetType::Unknown;
}
struct AssetInfo struct AssetInfo
{ {
@ -63,21 +96,23 @@ struct AudioAssetInfo : public AssetInfo
struct PrefabAssetInfo : public AssetInfo struct PrefabAssetInfo : public AssetInfo
{ {
std::string prefabYAML; YAML::Node prefabYAML;
std::shared_ptr<Object> prefabRoot = nullptr; std::shared_ptr<Object> prefabRoot = nullptr;
std::string prefabName = "Unnamed Prefab"; std::string prefabName = "Unnamed Prefab";
PrefabAssetInfo(); PrefabAssetInfo();
std::shared_ptr<Object> Instantiate() const;
void Save(YAML::Emitter& out) const override; void Save(YAML::Emitter& out) const override;
void Load(const YAML::Node& node) override; void Load(const YAML::Node& node) override;
void ReloadFromYAML(); // reparses prefabYAML into prefabRoot void ReloadFromYAML();
}; };
const char* MiniaudioResultToString(ma_result result); const char* MiniaudioResultToString(ma_result result);

View File

@ -156,6 +156,25 @@ void ShowAssetBrowser()
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
} }
else if (asset->type == AssetType::Prefab)
{
const auto *prefab = dynamic_cast<const PrefabAssetInfo *>(asset);
if (ImGui::Button(prefab->prefabName.empty() ? "##Prefab" : ("##" + prefab->prefabName).c_str(), ImVec2(thumbnailSize, thumbnailSize)))
{
}
ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + thumbnailSize);
ImGui::TextWrapped("%s", prefab->prefabName.empty() ? "Prefab" : prefab->prefabName.c_str());
ImGui::PopTextWrapPos();
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
{
ImGui::SetDragDropPayload("ASSET_PREFAB", &prefab->uaid, sizeof(uint64_t));
ImGui::Text("%s", displayName.c_str());
ImGui::EndDragDropSource();
}
}
else else
{ {
ImGui::PopID(); ImGui::PopID();