imgration 14/12/2025
This commit is contained in:
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <span>
|
||||
|
||||
#include <ryml.hpp>
|
||||
#include <ryml_std.hpp>
|
||||
#include <c4/format.hpp>
|
||||
|
||||
struct AssetBase
|
||||
{
|
||||
public:
|
||||
int64_t ID;
|
||||
};
|
||||
|
||||
struct AssetGUID
|
||||
{
|
||||
AssetGUID() = default;
|
||||
AssetGUID(const char* data) : AssetGUID(std::string_view(data, 32)) {};
|
||||
AssetGUID(std::string_view data)
|
||||
{
|
||||
for (size_t i = 0; i < 16; ++i) Data[0] = (Data[0] << 4) | hexToVal(data[i]);
|
||||
for (size_t i = 16; i < 32; ++i) Data[1] = (Data[1] << 4) | hexToVal(data[i]);
|
||||
}
|
||||
|
||||
static uint64_t hexToVal(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);
|
||||
}
|
||||
|
||||
bool operator==(const AssetGUID& other) const
|
||||
{
|
||||
return Data[0] == other.Data[0] && Data[1] == other.Data[1];
|
||||
}
|
||||
|
||||
static constexpr uint64_t DefaultVal = 0xe000000000000000;
|
||||
|
||||
std::array<uint64_t, 2> Data{ 0, DefaultVal };
|
||||
};
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<AssetGUID> {
|
||||
size_t operator()(const AssetGUID& v) const noexcept
|
||||
{
|
||||
auto h1 = std::hash<uint64_t>{}(v.Data[0]);
|
||||
auto h2 = std::hash<uint64_t>{}(v.Data[1]);
|
||||
return h1 ^ (h2 << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* ParseAssetRef(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
T* asset;
|
||||
node["fileID"] >> asset;
|
||||
return asset;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool LinkAssetRef(const std::unordered_map<int64_t, AssetBase*>& assetsMap, T*& asset)
|
||||
{
|
||||
auto it = assetsMap.find(reinterpret_cast<int64_t>(asset));
|
||||
if (it != assetsMap.end())
|
||||
{
|
||||
asset = reinterpret_cast<T*>(it->second);
|
||||
return true;
|
||||
}
|
||||
asset = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline AssetGUID ParseAssetGUID(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
auto guidStringSpan2 = node["guid"].val();
|
||||
|
||||
assert(guidStringSpan2.size() == 32);
|
||||
|
||||
return AssetGUID{std::string_view(guidStringSpan2.data(), guidStringSpan2.size())};
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
struct Drop
|
||||
{
|
||||
int itemId;
|
||||
int minAmount;
|
||||
int maxAmount;
|
||||
int dropChance;
|
||||
};
|
||||
|
||||
struct Interactable_Resource : public AssetBase
|
||||
{
|
||||
int maxHealth;
|
||||
int respawnTime;
|
||||
std::vector<Drop> drops;
|
||||
std::vector<int> requiredTools;
|
||||
int xp;
|
||||
int typeId;
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <ryml_std.hpp>
|
||||
|
||||
#include "asset_base.hpp"
|
||||
#include "transform.hpp"
|
||||
|
||||
struct GameObjectAsset : public AssetBase
|
||||
{
|
||||
std::string name;
|
||||
uint8_t layer{ 0 };
|
||||
uint8_t namMeshLayer{ 0 };
|
||||
std::string tag;
|
||||
|
||||
TransformAsset* transform{ nullptr };
|
||||
std::vector<AssetBase*> Components;
|
||||
};
|
||||
|
||||
inline GameObjectAsset ParseGameObject(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
GameObjectAsset gameObject;
|
||||
|
||||
node["m_Name"] >> gameObject.name;
|
||||
node["m_Layer"] >> gameObject.layer;
|
||||
node["m_TagString"] >> gameObject.tag;
|
||||
|
||||
auto components = node["m_Component"];
|
||||
auto it = components.begin();
|
||||
|
||||
gameObject.transform = ParseAssetRef<TransformAsset>((*it)["component"]);
|
||||
++it;
|
||||
for (; it != components.end(); ++it)
|
||||
{
|
||||
gameObject.Components.push_back(ParseAssetRef<AssetBase>((*it)["component"]));
|
||||
}
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
inline void LinkGameObject(const std::unordered_map<int64_t, AssetBase*>& assetsMap, GameObjectAsset& gameObject)
|
||||
{
|
||||
LinkAssetRef<TransformAsset>(assetsMap, gameObject.transform);
|
||||
for (int i = static_cast<int>(gameObject.Components.size()) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!LinkAssetRef<AssetBase>(assetsMap, gameObject.Components[i]))
|
||||
{
|
||||
std::swap(gameObject.Components[i], gameObject.Components.back());
|
||||
gameObject.Components.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
0
include/assets/image.h
Normal file
0
include/assets/image.h
Normal file
0
include/assets/mesh.h
Normal file
0
include/assets/mesh.h
Normal file
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
|
||||
struct GameObjectAsset;
|
||||
|
||||
struct MeshFilterAsset : AssetBase
|
||||
{
|
||||
AssetGUID Mesh;
|
||||
GameObjectAsset* GameObject{ nullptr };
|
||||
};
|
||||
|
||||
inline MeshFilterAsset ParseMeshFilter(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
MeshFilterAsset meshFilter;
|
||||
|
||||
meshFilter.Mesh = ParseAssetGUID(node["m_Mesh"]);
|
||||
meshFilter.GameObject = ParseAssetRef<GameObjectAsset>(node["m_GameObject"]);
|
||||
|
||||
return meshFilter;
|
||||
}
|
||||
|
||||
inline void LinkMeshFilter(const std::unordered_map<int64_t, AssetBase*>& assetsMap, MeshFilterAsset& meshFilter)
|
||||
{
|
||||
LinkAssetRef<GameObjectAsset>(assetsMap, meshFilter.GameObject);
|
||||
}
|
||||
29
include/assets/prefab.h
Normal file
29
include/assets/prefab.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
#include <ryml_std.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
|
||||
struct Prefab : public AssetBase
|
||||
{
|
||||
public:
|
||||
static constexpr std::array<std::string_view, 1> Extensions = { ".prefab" };
|
||||
|
||||
public:
|
||||
std::unordered_map<int64_t, ryml::Tree> Data;
|
||||
|
||||
public:
|
||||
template <typename ParsedProject>
|
||||
void Parse(ParsedProject& project, std::string& content)
|
||||
{
|
||||
using ObjectTypesT = typename ParsedProject::ObjectTypes;
|
||||
|
||||
auto names = ObjectTypesT::get_names();
|
||||
ParseSceneYaml(content, false, names, [this](std::string_view componentName, int64_t ID, ryml::Tree&& tree)
|
||||
{
|
||||
Data.emplace(ID, std::move(tree));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
//struct PrefabInstanceAsset : AssetBase
|
||||
//{
|
||||
// AssetGUID prefabGUID;
|
||||
// ryml::Tree Data{};
|
||||
//};
|
||||
|
||||
struct PrefabAsset
|
||||
{
|
||||
std::filesystem::path path;
|
||||
std::string name;
|
||||
|
||||
std::unordered_map<int64_t, ryml::Tree> Data;
|
||||
};
|
||||
|
||||
//inline PrefabInstanceAsset ParsePrefabInstance(const ryml::ConstNodeRef& node)
|
||||
//{
|
||||
// PrefabInstanceAsset prefabInstance;
|
||||
// prefabInstance.prefabGUID = ParseAssetGUID(node["m_SourcePrefab"]);
|
||||
// // prefabInstance.Data = node;
|
||||
// return prefabInstance;
|
||||
//}
|
||||
118
include/assets/scene.h
Normal file
118
include/assets/scene.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
|
||||
#include "asset_base.hpp"
|
||||
#include "type_base.hpp"
|
||||
|
||||
struct Scene : public AssetBase
|
||||
{
|
||||
public:
|
||||
static constexpr std::array<std::string_view, 1> Extensions = { ".unity" };
|
||||
|
||||
private:
|
||||
std::unordered_map<int64_t, void*> IDtoAsset;
|
||||
|
||||
public:
|
||||
int64_t GetNewID(int64_t lastID = 0)
|
||||
{
|
||||
for (;; ++lastID)
|
||||
{
|
||||
if (IDtoAsset.find(lastID) == IDtoAsset.end())
|
||||
return lastID;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ParsedProject>
|
||||
void Parse(ParsedProject& project, std::string& content)
|
||||
{
|
||||
using ObjectTypesT = typename ParsedProject::ObjectTypes;
|
||||
|
||||
auto& sceneData = project.CreateSceneData(GUID);
|
||||
|
||||
// Create ParseContext for component parsing
|
||||
ParseContext context(*this, project.Assets);
|
||||
|
||||
auto names = ObjectTypesT::get_names();
|
||||
ParseSceneYaml(content, true, names, [&sceneData, &context](std::string_view componentName, int64_t ID, ryml::Tree&& tree)
|
||||
{
|
||||
sceneData.AddComponent(componentName, ID, std::move(tree), context);
|
||||
});
|
||||
|
||||
// Link all components after parsing
|
||||
LinkAssets(project);
|
||||
}
|
||||
|
||||
template <typename ParsedProject>
|
||||
void LinkAssets(ParsedProject& project)
|
||||
{
|
||||
using ObjectTypesT = typename ParsedProject::ObjectTypes;
|
||||
|
||||
auto& sceneData = project.GetSceneData(GUID);
|
||||
|
||||
// Build the assets map (ID -> pointer)
|
||||
std::unordered_map<int64_t, TypeBase*> assetsMap;
|
||||
ObjectTypesT::ForEachT([&]<typename T>() -> void
|
||||
{
|
||||
auto& components = sceneData.template GetComponents<T>();
|
||||
for (auto& component : components)
|
||||
{
|
||||
assetsMap.emplace(component.ID, &component);
|
||||
}
|
||||
});
|
||||
|
||||
// Link all components
|
||||
ObjectTypesT::ForEachT([&]<typename T>() -> void
|
||||
{
|
||||
auto& components = sceneData.template GetComponents<T>();
|
||||
for (auto& component : components)
|
||||
{
|
||||
component.Link(assetsMap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename ParsedProject>
|
||||
void MergeComponents(const ParsedProject& project, const Scene& otherScene)
|
||||
{
|
||||
using ObjectTypesT = typename ParsedProject::ObjectTypes;
|
||||
|
||||
auto& thisSceneData = project.GetSceneData(GUID);
|
||||
auto& otherSceneData = project.GetSceneData(otherScene.GUID);
|
||||
|
||||
std::unordered_map<int64_t, int64_t> newIDMap{};
|
||||
int64_t lastID = std::random_device{}();
|
||||
|
||||
ObjectTypesT::ForEachT([&]<typename T>() -> void
|
||||
{
|
||||
auto& thisComponents = thisSceneData.template GetComponents<T>();
|
||||
auto& otherComponents = otherSceneData.template GetComponents<T>();
|
||||
|
||||
for (auto otherComponentCopy : otherComponents)
|
||||
{
|
||||
int64_t originalID = otherComponentCopy.ID;
|
||||
lastID = GetNewID(lastID);
|
||||
otherComponentCopy.ID = lastID;
|
||||
|
||||
// register the new ID to the scene
|
||||
newIDMap.emplace(originalID, lastID);
|
||||
|
||||
// add the component to the scene
|
||||
thisComponents.emplace_back(std::move(otherComponentCopy));
|
||||
}
|
||||
});
|
||||
|
||||
auto& IDMapLinked = reinterpret_cast<std::unordered_map<int64_t, TypeBase*>&>(newIDMap);
|
||||
ObjectTypesT::ForEachT([&]<typename T>() -> void
|
||||
{
|
||||
auto& thisComponents = thisSceneData.template GetComponents<T>();
|
||||
for (auto& component : thisComponents)
|
||||
{
|
||||
component.Link(IDMapLinked);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "game_object.hpp"
|
||||
#include "transform.hpp"
|
||||
#include "mesh_filter.hpp"
|
||||
#include "prefab_instance.hpp"
|
||||
|
||||
struct SceneAsset
|
||||
{
|
||||
public:
|
||||
std::filesystem::path path;
|
||||
std::string name;
|
||||
|
||||
std::vector<GameObjectAsset> gameObjects;
|
||||
std::vector<TransformAsset> transforms;
|
||||
std::vector<MeshFilterAsset> meshFilters;
|
||||
// std::vector<PrefabInstanceAsset> prefabInstances;
|
||||
|
||||
std::unordered_map<int64_t, void*> IDtoAsset;
|
||||
|
||||
|
||||
};
|
||||
16
include/assets/scripts.h
Normal file
16
include/assets/scripts.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
struct Scripts : public AssetBase
|
||||
{
|
||||
public:
|
||||
static constexpr std::array<std::string_view, 1> Extensions = { ".cs" };
|
||||
|
||||
public:
|
||||
template <typename ParsedProject>
|
||||
void Parse(const ParsedProject& project, std::string& content)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include "asset_base.hpp"
|
||||
|
||||
struct GameObjectAsset;
|
||||
|
||||
struct TransformAsset : public AssetBase
|
||||
{
|
||||
glm::quat Rotation;
|
||||
glm::vec3 Position;
|
||||
glm::vec3 Scale;
|
||||
|
||||
glm::mat4 GlobalMatrix;
|
||||
|
||||
GameObjectAsset* GameObject{ nullptr };
|
||||
std::vector<TransformAsset*> Children;
|
||||
TransformAsset* Parent{ nullptr };
|
||||
};
|
||||
|
||||
inline glm::vec3 ParseVector3(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
glm::vec3 vector;
|
||||
node["x"] >> vector.x;
|
||||
node["y"] >> vector.y;
|
||||
node["z"] >> vector.z;
|
||||
return vector;
|
||||
}
|
||||
|
||||
inline glm::quat ParseQuaternion(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
glm::quat quaternion;
|
||||
node["x"] >> quaternion.x;
|
||||
node["y"] >> quaternion.y;
|
||||
node["z"] >> quaternion.z;
|
||||
node["w"] >> quaternion.w;
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
inline TransformAsset ParseTransform(const ryml::ConstNodeRef& node)
|
||||
{
|
||||
TransformAsset transform;
|
||||
transform.Rotation = ParseQuaternion(node["m_LocalRotation"]);
|
||||
transform.Position = ParseVector3(node["m_LocalPosition"]);
|
||||
transform.Scale = ParseVector3(node["m_LocalScale"]);
|
||||
|
||||
transform.Parent = ParseAssetRef<TransformAsset>(node["m_Father"]);
|
||||
transform.GameObject = ParseAssetRef<GameObjectAsset>(node["m_GameObject"]);
|
||||
|
||||
auto children = node["m_Children"];
|
||||
for (const auto& child : children)
|
||||
{
|
||||
transform.Children.push_back(ParseAssetRef<TransformAsset>(child));
|
||||
}
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
inline void LinkTransform(const std::unordered_map<int64_t, AssetBase*>& assetsMap, TransformAsset& transform)
|
||||
{
|
||||
LinkAssetRef<TransformAsset>(assetsMap, transform.Parent);
|
||||
for (int i = static_cast<int>(transform.Children.size()) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!LinkAssetRef<TransformAsset>(assetsMap, transform.Children[i]))
|
||||
{
|
||||
std::swap(transform.Children[i], transform.Children.back());
|
||||
transform.Children.pop_back();
|
||||
}
|
||||
}
|
||||
LinkAssetRef<GameObjectAsset>(assetsMap, transform.GameObject);
|
||||
}
|
||||
Reference in New Issue
Block a user