Files
2025-12-24 16:51:01 +09:00

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);
}
});
}
};