Files
cursebreaker-parser/include/asset_base.hpp
2025-12-24 16:51:01 +09:00

120 lines
3.0 KiB
C++

#pragma once
#include <filesystem>
#include <array>
#include <unordered_map>
#include <vector>
#include <string>
#include <string_view>
#include <ryml.hpp>
#include "type_info.hpp"
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 };
};
struct AssetPath
{
std::filesystem::path path{};
AssetGUID GUID{};
};
template <typename T>
using unordered_map_guid = std::unordered_map<AssetGUID, T>;
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);
}
};
}
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())};
}
struct AssetBase
{
std::filesystem::path Path{};
AssetGUID GUID{};
// static std::span<std::string_view> GetExtensions();
};
struct AssetCollectionBase
{
std::vector<std::unordered_map<AssetGUID, AssetBase*>*> AssetsInterface{};
std::vector<std::string_view> AssetNames{};
template <typename AssetType>
AssetType* GetAsset(AssetGUID guid)
{
for (size_t i = 0; i < AssetNames.size(); i++)
if (AssetNames[i] == type_name<AssetType>())
{
auto& assetMap = (*AssetsInterface[i]);
auto it = assetMap.find(guid);
if (it != assetMap.end())
{
return static_cast<AssetType*>(it->second);
}
return nullptr;
}
return nullptr;
}
};
template <typename AssetTypes = TypeCollection<>>
struct AssetCollection : public AssetCollectionBase
{
using AssetsT = typename AssetTypes::template AsContainedType<unordered_map_guid>;
AssetsT Assets;
AssetCollection(AssetsT&& assets)
: AssetNames(AssetTypes::get_names())
, AssetsInterface(sizeof...(AssetTypes))
, Assets(std::move(assets))
{
size_t index = 0;
AssetTypes::ForEachT([this, &index]<typename AssetT>()
{
AssetsInterface[index++] = &std::get<std::unordered_map<AssetGUID, AssetT>>(Assets);
});
}
};