119 lines
3.6 KiB
C++
119 lines
3.6 KiB
C++
#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);
|
|
}
|
|
});
|
|
}
|
|
};
|