Assets system refactor, Save Asset

This commit is contained in:
legatt 2026-01-28 19:41:07 +03:00
parent 49affdcc38
commit 9d5a41b02d
24 changed files with 477 additions and 176 deletions

View File

@ -11,7 +11,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project (EtrediaEmpires) project (EtrediaEmpires)
add_subdirectory(sdk/map) add_subdirectory(sdk/map)
add_subdirectory(sdk/materials) add_subdirectory(sdk/assets)
add_subdirectory(utils) add_subdirectory(utils)
add_subdirectory(p7lib) add_subdirectory(p7lib)
add_subdirectory(server) add_subdirectory(server)

BIN
assets/map/_states.map Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,32 +1,57 @@
#pragma once #pragma once
#include "GameData.hpp"
#include "Map.hpp" #include "Map.hpp"
#include <concepts> #include <concepts>
#include <cstdint> #include <cstdint>
#include <vector>
namespace ee_assets namespace ee_assets
{ {
struct AssetData {}; struct AssetData {};
template<typename T> concept Asset = std::derived_from<T, AssetData>; template<typename T> concept Asset = std::derived_from<T, AssetData>;
struct AssetBinary : AssetData enum AssetType
{
BINARY,
MAP_MESH,
SAVE,
SHADER,
MATERIAL,
IMAGE
};
struct AssetBinary : public AssetData
{ {
uint8_t* content = nullptr; uint8_t* content = nullptr;
size_t size = 0; size_t size = 0;
AssetBinary(uint8_t* &source, const size_t &sourceSize); AssetBinary(uint8_t* &source, const size_t sourceSize);
~AssetBinary(); ~AssetBinary();
}; };
struct AssetMapMesh : AssetData struct AssetMapMesh : public AssetData
{ {
ee_engine::MapMesh content; ee_engine::MapMesh content;
AssetMapMesh(uint8_t* &source, const size_t &sourceSize); uint8_t* Serialize(size_t &size);
AssetMapMesh() {};
AssetMapMesh(uint8_t* &source, const size_t sourceSize);
};
struct AssetSave : public AssetData
{
std::vector<ee_data::Subject> subjects;
uint8_t* Serialize(size_t &size);
AssetSave() {};
AssetSave(uint8_t* &source, const size_t sourceSize);
}; };
#define AssetShader AssetBinary #define AssetShader AssetBinary
struct AssetMaterial : AssetData struct AssetMaterial : public AssetData
{ {
uint32_t vertexShaderAssetID; uint32_t vertexShaderAssetID;
uint32_t fragmentShaderAssetID; uint32_t fragmentShaderAssetID;

View File

@ -0,0 +1,13 @@
#pragma once
#include <cstdint>
#include <vector>
namespace ee_data
{
struct Subject
{
uint32_t tag;
uint32_t color;
std::vector<uint32_t> regions;
};
}

View File

@ -9,9 +9,12 @@ YOU CAN PREVENT SOURCE BUFFER FROM CLOSING.
IT CAN BE USED FOR STORING ASSET DATA WITHOUT COPY. IT CAN BE USED FOR STORING ASSET DATA WITHOUT COPY.
IN THIS CASE, YOU MUST SET SOURCE TO NULLPTR AND FREE BUFFER YOURSELF. IN THIS CASE, YOU MUST SET SOURCE TO NULLPTR AND FREE BUFFER YOURSELF.
TODO: make binary format describing for common functions instead of individual serialize/deserialize functions
TODO: parallelize convertion loops
*/ */
ee_assets::AssetBinary::AssetBinary(uint8_t* &source, const size_t &sourceSize) ee_assets::AssetBinary::AssetBinary(uint8_t* &source, const size_t sourceSize)
{ {
content = source; content = source;
size = sourceSize; size = sourceSize;
@ -26,7 +29,7 @@ ee_assets::AssetBinary::~AssetBinary()
ee_assets::AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t &sourceSize) ee_assets::AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t sourceSize)
{ {
uint8_t* buffer = source; uint8_t* buffer = source;
uint8_t* pointer = source; uint8_t* pointer = source;
@ -87,3 +90,78 @@ ee_assets::AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t &sourceSize
DeallocateArray(buffer); DeallocateArray(buffer);
} }
ee_assets::AssetSave::AssetSave(uint8_t* &source, const size_t sourceSize)
{
uint8_t* buffer = source;
uint8_t* pointer = source;
size_t leftoverSize = sourceSize;
source = nullptr;
uint16_t subjectsCount = static_cast<uint16_t>(subjects.size());
ee_utils::readNext(&subjectsCount, pointer, leftoverSize, sizeof(uint16_t));
for (uint16_t i = 0; i < subjectsCount; i++)
{
ee_data::Subject subject;
ee_utils::readNext(&subject.tag, pointer, leftoverSize, sizeof(subject.tag));
ee_utils::readNext(&subject.color, pointer, leftoverSize, sizeof(subject.color));
uint16_t regionsCount = 0;
ee_utils::readNext(&regionsCount, pointer, leftoverSize, sizeof(uint16_t));
subject.regions.resize(regionsCount);
ee_utils::readNext(
subject.regions.data(),
pointer,
leftoverSize,
subject.regions.size() * sizeof(uint32_t)
);
subjects.push_back(subject);
}
DeallocateArray(buffer);
}
// SERIALIZERS
uint8_t* ee_assets::AssetSave::Serialize(size_t &size)
{
size = sizeof(uint16_t);
for (ee_data::Subject &subject : subjects)
{
size += sizeof(subject.tag);
size += sizeof(subject.color);
size += sizeof(uint16_t) + subject.regions.size() * sizeof(uint32_t);
}
size_t leftover = size;
uint8_t *result = AllocateArray<uint8_t>(size);
uint8_t *pointer = result;
uint16_t subjectsCount = static_cast<uint16_t>(subjects.size());
ee_utils::writeNext(pointer, &subjectsCount, leftover, sizeof(uint16_t));
for (ee_data::Subject &subject : subjects)
{
ee_utils::writeNext(pointer, &subject.tag, leftover, sizeof(subject.tag));
ee_utils::writeNext(pointer, &subject.color, leftover, sizeof(subject.color));
uint16_t regionsCount = static_cast<uint16_t>(subject.regions.size());
ee_utils::writeNext(pointer, &regionsCount, leftover, sizeof(uint16_t));
ee_utils::writeNext(
pointer,
subject.regions.data(),
leftover,
subject.regions.size() * sizeof(uint32_t)
);
}
return result;
}

View File

@ -2,6 +2,7 @@
#include "FileSystem.hpp" #include "FileSystem.hpp"
#include <ee_engine_api/AssetData.hpp> #include <ee_engine_api/AssetData.hpp>
#include "Logger.h"
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <filesystem> #include <filesystem>
@ -26,16 +27,7 @@ struct AssetHandle
class AssetInfo class AssetInfo
{ {
public: public:
enum Type ee_assets::AssetType type = ee_assets::BINARY;
{
BINARY,
MAP_MESH,
SHADER,
MATERIAL,
IMAGE
} type = BINARY;
std::atomic<bool> isReady; std::atomic<bool> isReady;
AssetAddress* resourceAddress; AssetAddress* resourceAddress;
@ -72,7 +64,7 @@ struct AssetStreamCommand
AssetHandle target; AssetHandle target;
uint32_t targetId = INVALID_ASSET_ID; uint32_t targetId = INVALID_ASSET_ID;
std::filesystem::path targetPath; std::filesystem::path targetPath;
AssetInfo::Type targetType = AssetInfo::BINARY; ee_assets::AssetType targetType = ee_assets::BINARY;
std::atomic<void*>* out; std::atomic<void*>* out;
}; };
@ -87,9 +79,9 @@ public:
void Start(); void Start();
void Shutdown(); void Shutdown();
void LoadDir(AssetInfo::Type type, const std::filesystem::path &path); void LoadDir(ee_assets::AssetType type, const std::filesystem::path &path);
void LoadAsync(AssetInfo::Type type, const std::filesystem::path &path); void LoadAsync(ee_assets::AssetType type, const std::filesystem::path &path);
AssetHandle& Find(const std::filesystem::path &path); AssetHandle& Find(const std::filesystem::path &path);
AssetHandle& Find(const uint32_t &id); AssetHandle& Find(const uint32_t &id);
template <ee_assets::Asset T> T& FindOnce(const std::filesystem::path &path); template <ee_assets::Asset T> T& FindOnce(const std::filesystem::path &path);
@ -112,6 +104,7 @@ private:
std::vector<AssetLoadingEntry> loadingEntries; std::vector<AssetLoadingEntry> loadingEntries;
std::vector<ee_assets::AssetBinary*> binaryStorage; std::vector<ee_assets::AssetBinary*> binaryStorage;
std::vector<ee_assets::AssetSave*> savesStorage;
std::vector<ee_assets::AssetMapMesh*> mapMeshesStorage; std::vector<ee_assets::AssetMapMesh*> mapMeshesStorage;
std::vector<ee_assets::AssetShader*> shadersStorage; std::vector<ee_assets::AssetShader*> shadersStorage;
std::vector<ee_assets::AssetMaterial*> materialsStorage; std::vector<ee_assets::AssetMaterial*> materialsStorage;
@ -123,6 +116,8 @@ private:
void ProcessCommand(AssetStreamCommand &command); void ProcessCommand(AssetStreamCommand &command);
void Release(); void Release();
template<ee_assets::Asset T> void FinishLoadConstruct(AssetLoadingEntry &loaded, std::vector<T*> &storage);
template<ee_assets::Asset T> void FinishLoadPlain(AssetLoadingEntry &loaded, std::vector<T*> &storage);
template<ee_assets::Asset T> void ClearStorage(std::vector<T*> &storage); template<ee_assets::Asset T> void ClearStorage(std::vector<T*> &storage);
}; };
@ -149,6 +144,23 @@ template <ee_assets::Asset T> T& AssetManager::FindOnce(const uint32_t &id)
return Get<T>(Find(id)); return Get<T>(Find(id));
} }
template<ee_assets::Asset T> void AssetManager::FinishLoadConstruct(AssetLoadingEntry &loaded, std::vector<T*> &storage)
{
T* resource = Allocate<T>(loaded.file->data, loaded.file->size);
storage.push_back(resource);
Redirect(loaded.handle, storage.back());
}
template<ee_assets::Asset T> void AssetManager::FinishLoadPlain(AssetLoadingEntry &loaded, std::vector<T*> &storage)
{
T* resource = Allocate<T>();
if (loaded.file->size < sizeof(T))
LOG(CRITICAL, "File size is less than needed for asset of type: %d", typeid(T).name());
std::memcpy(resource, loaded.file->data, sizeof(T));
storage.push_back(resource);
Redirect(loaded.handle, storage.back());
}
template<ee_assets::Asset T> void AssetManager::ClearStorage(std::vector<T*> &storage) template<ee_assets::Asset T> void AssetManager::ClearStorage(std::vector<T*> &storage)
{ {
for (T* &resource : storage) for (T* &resource : storage)

View File

@ -87,7 +87,7 @@ void AssetManager::Request(const AssetStreamCommand::Type &type)
commands.push(AssetStreamCommand {.type = type}); commands.push(AssetStreamCommand {.type = type});
} }
void AssetManager::LoadAsync(AssetInfo::Type type, const std::filesystem::path &path) void AssetManager::LoadAsync(ee_assets::AssetType type, const std::filesystem::path &path)
{ {
AssetStreamCommand command { AssetStreamCommand command {
.type = AssetStreamCommand::LOAD, .type = AssetStreamCommand::LOAD,
@ -166,6 +166,7 @@ void AssetManager::Loop()
} }
incompleteCommands.clear(); incompleteCommands.clear();
// TODO: FinishLoadTasks()
for (AssetLoadingEntry &entry : loadingEntries) for (AssetLoadingEntry &entry : loadingEntries)
{ {
bool isReady = entry.fileOwner->PollReady(*entry.file); bool isReady = entry.fileOwner->PollReady(*entry.file);
@ -175,48 +176,27 @@ void AssetManager::Loop()
switch (asset.type) switch (asset.type)
{ {
case AssetInfo::MAP_MESH: case ee_assets::MAP_MESH:
{ FinishLoadConstruct(entry, mapMeshesStorage);
ee_assets::AssetMapMesh* mesh = Allocate<ee_assets::AssetMapMesh>(entry.file->data, entry.file->size);
mapMeshesStorage.push_back(mesh);
Redirect(entry.handle, mapMeshesStorage.back());
break; break;
} case ee_assets::SAVE:
FinishLoadConstruct(entry, savesStorage);
case AssetInfo::SHADER:
{
ee_assets::AssetShader* shader = Allocate<ee_assets::AssetShader>(entry.file->data, entry.file->size);
shadersStorage.push_back(shader);
Redirect(entry.handle, shadersStorage.back());
break; break;
}
case AssetInfo::MATERIAL: case ee_assets::SHADER:
{ FinishLoadConstruct(entry, shadersStorage);
ee_assets::AssetMaterial* material = Allocate<ee_assets::AssetMaterial>();
if (entry.file->size < sizeof(ee_assets::AssetMaterial))
LOG(CRITICAL, "File size is less than needed for material");
std::memcpy(material, entry.file->data, sizeof(ee_assets::AssetMaterial));
materialsStorage.push_back(material);
Redirect(entry.handle, materialsStorage.back());
break; break;
} case ee_assets::MATERIAL:
FinishLoadPlain(entry, materialsStorage);
case AssetInfo::IMAGE: break;
{ case ee_assets::IMAGE:
break; break;
}
case AssetInfo::BINARY: case ee_assets::BINARY:
default: default:
{ FinishLoadConstruct(entry, binaryStorage);
ee_assets::AssetBinary* data = Allocate<ee_assets::AssetBinary>(entry.file->data, entry.file->size);
binaryStorage.push_back(data);
Redirect(entry.handle, binaryStorage.back());
break; break;
} }
}
entry.fileOwner->Close(*entry.file); entry.fileOwner->Close(*entry.file);
#ifndef NDEBUG #ifndef NDEBUG
@ -234,6 +214,7 @@ void AssetManager::Loop()
} }
void AssetManager::ProcessCommand(AssetStreamCommand &command) void AssetManager::ProcessCommand(AssetStreamCommand &command)
{ {
// TODO: method for each command
switch(command.type) switch(command.type)
{ {
case AssetStreamCommand::LOAD: case AssetStreamCommand::LOAD:
@ -353,7 +334,7 @@ void AssetManager::Release()
isRunning.store(false); isRunning.store(false);
} }
void AssetManager::LoadDir(AssetInfo::Type type, const std::filesystem::path &path) void AssetManager::LoadDir(ee_assets::AssetType type, const std::filesystem::path &path)
{ {
for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(path)) for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(path))
{ {

View File

@ -40,11 +40,12 @@ int main(int argc, char **argv)
// Setup Asset Manager // Setup Asset Manager
Engine::assetManager = Allocate<AssetManager>(); Engine::assetManager = Allocate<AssetManager>();
Engine::assetManager->Start(); Engine::assetManager->Start();
Engine::assetManager->LoadDir(AssetInfo::SHADER, "assets/shaders"); Engine::assetManager->LoadDir(ee_assets::SHADER, "assets/shaders");
Engine::assetManager->LoadDir(AssetInfo::MATERIAL, "assets/materials"); Engine::assetManager->LoadDir(ee_assets::MATERIAL, "assets/materials");
// Load assets // Load assets
Engine::assetManager->LoadAsync(AssetInfo::MAP_MESH, "assets/map/states.map"); Engine::assetManager->LoadAsync(ee_assets::MAP_MESH, "assets/map/states.map");
Engine::assetManager->LoadAsync(ee_assets::SAVE, "assets/scenarios/empires.save");
// Setup input manager TODO: builder // Setup input manager TODO: builder
Engine::input = Allocate<GLFWInput>(Actions::mappings); Engine::input = Allocate<GLFWInput>(Actions::mappings);

23
sdk/assets/CMakeLists.txt Normal file
View File

@ -0,0 +1,23 @@
cmake_minimum_required (VERSION 3.8)
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project (compile_assets)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(xxHash CONFIG REQUIRED)
add_executable(${PROJECT_NAME} compile_assets.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
target_link_libraries(${PROJECT_NAME} PUBLIC engine-api)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

View File

@ -0,0 +1,23 @@
{
"type": "object",
"title": "Etredia Empires savegame data",
"description": "Contains initial state of a game (e.g. scenarios, saves)",
"properties": {
"subjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"tag": {"type": "string"},
"color": {"type": "string"},
"regions": {
"type": "array",
"items": {"type": "string"}
}
}
}
}
}
}

View File

@ -0,0 +1,177 @@
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <xxhash.h>
#include <string>
#include <charconv>
#include <functional>
#include <ee_engine_api/AssetData.hpp>
using json = nlohmann::json;
#define bytes(value) reinterpret_cast<const char*>(value)
namespace ee_data
{
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
Subject,
tag,
color,
regions
)
}
namespace ee_assets
{
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
AssetSave,
subjects
)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
AssetMaterial,
vertexShaderAssetID,
fragmentShaderAssetID
)
}
struct MappingEntry
{
std::string_view name;
uint32_t value;
};
static constexpr MappingEntry mappings[] = {
#define MAP(name, value) {#name, ((value & 0x0000FF) << 16) | ( value & 0x00FF00) | ((value & 0xFF0000) >> 16)},
#include "define/regions.def"
#undef MAP
};
void CompileRecursive(json &obj, std::function<void(const std::basic_string<char> &key, json &value)> callback)
{
if (obj.is_array()) {for (auto &element : obj) CompileRecursive(element, callback); return;}
if (!obj.is_object()) {callback("", obj); return;}
for (auto &[key, value] : obj.items())
{
if (value.is_object())
CompileRecursive(value, callback);
else if (value.is_array())
for (auto &element : value)
CompileRecursive(element, callback);
else callback(key, value);
}
}
int main(int argc, char **argv)
{
try
{
std::filesystem::path in = argv[1];
std::filesystem::path out = argv[2];
char* assetTypeStr = argv[3];
std::ifstream fin(in);
std::ofstream fout(out);
ee_assets::AssetType assetType = static_cast<ee_assets::AssetType>(atoi(assetTypeStr));
if (!fin.is_open()) {
std::cout << "Error: Could not open input file: " << in << std::endl;
return 1;
}
if (!fout.is_open()) {
std::cout << "Error: Could not open output file: " << out << std::endl;
return 1;
}
json data = json::parse(fin);
// Compile hashes
CompileRecursive(data, [](const std::basic_string<char> &key, json &value) {
if (!value.is_string()) return;
if (
!(key == "tag") &&
!key.ends_with("AssetID") &&
!key.ends_with("Type")
) return;
std::filesystem::path linkPath = value;
auto linkPath8 = linkPath.generic_u8string();
uint32_t assetId = XXH32(linkPath8.data(), linkPath8.size(), 0);
std::cout << "Replace string [" << value << "] with [" << assetId << "]" << std::endl;
value = assetId;
});
// Compile mappings
CompileRecursive(data, [](const std::basic_string<char> &key, json &value) {
if (!value.is_string()) return;
const std::string& value_string = value.get_ref<const std::string&>();
for (const MappingEntry &map : mappings)
{
if (value_string == map.name)
{
std::cout << "Replace string [" << value << "] with [" << map.value << "]" << std::endl;
value = map.value;
break;
}
}
});
// Compile colors
CompileRecursive(data, [](const std::basic_string<char> &key, json &value) {
if (!value.is_string()) return;
const char* color_str = value.get_ref<const std::string&>().c_str() + 1;
uint8_t b = 0, g = 0, r = 0;
uint32_t hex = 0;
std::from_chars(color_str, color_str + 2, r, 16); color_str += 2;
std::from_chars(color_str, color_str + 2, g, 16); color_str += 2;
std::from_chars(color_str, color_str + 2, b, 16); color_str += 2;
hex = static_cast<uint32_t>(r) << 16 |
static_cast<uint32_t>(g) << 8 |
static_cast<uint32_t>(b);
std::cout << "Replace string [" << value << "] with [" << (int)r << "," << (int)g << "," << (int)b << "]" << std::endl;
value = hex;
});
switch (assetType)
{
case ee_assets::MATERIAL:
{
ee_assets::AssetMaterial material = data.get<ee_assets::AssetMaterial>();
fout.write(bytes(&material), sizeof(material));
break;
}
case ee_assets::SAVE:
{
ee_assets::AssetSave save = data.get<ee_assets::AssetSave>();
size_t size = 0;
const char* data = bytes(save.Serialize(size));
fout.write(data, size);
break;
}
default:
break;
}
fin.close();
fout.close();
}
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}

View File

@ -0,0 +1,19 @@
#ifndef MAP
#define MAP(name, color)
#endif
MAP(elnia, 0xFF0000)
MAP(south_hleria, 0xFFD800)
MAP(siburia_central, 0xFF00DC)
MAP(siburia, 0xFF0000)
MAP(savatia, 0xFF0000)
MAP(east_monfua, 0xFF0000)
MAP(dineria, 0x0400FF)
MAP(perdania, 0xFF6A00)
MAP(arstinia, 0xFF0000)
MAP(ortostan, 0xFF0000)
MAP(zerandia, 0xFF0000)
MAP(mgahvatia, 0xFF0000)
#undef MAP

10
sdk/assets/run.cmd Normal file
View File

@ -0,0 +1,10 @@
@echo off
set ASSETS=../../assets
set COMPILE=%CD%/../../out/build/DEBUG/sdk/assets/compile_assets.exe
set MATERIAL=4
set SAVE=2
for %%F in (materials/*) do %COMPILE% "materials/%%~nF.json" "%ASSETS%/materials/%%~nF" %MATERIAL% && echo "Compiled: %%~nF"
for %%F in (saves/*) do %COMPILE% "saves/%%~nF.json" "%ASSETS%/scenarios/%%~nF" %SAVE% && echo "Compiled: %%~nF"

View File

@ -0,0 +1,33 @@
{
"subjects": [
{
"tag": "ESH",
"color": "#FF0000",
"regions": [
"elnia",
"south_hleria",
"siburia_central",
"siburia",
"savatia",
"east_monfua"
]
},
{
"tag": "UCB",
"color": "#00FF00",
"regions": [
"dineria",
"perdania",
"arstinia",
"ortostan",
"zerandia",
"mgahvatia"
]
}
]
}

View File

@ -1,4 +1,3 @@
#include <filesystem>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <cstdint> #include <cstdint>
@ -40,7 +39,9 @@ struct vertex { float x,y; };
struct BGRHash { struct BGRHash {
size_t operator()(const BGR& c) const noexcept { size_t operator()(const BGR& c) const noexcept {
return (c.r<<16)|(c.g<<8)|c.b; return static_cast<uint32_t>(c.r) << 16 |
static_cast<uint32_t>(c.g) << 8 |
static_cast<uint32_t>(c.b);
} }
}; };

View File

@ -1,46 +0,0 @@
cmake_minimum_required (VERSION 3.8)
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project (compile_materials)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(xxHash CONFIG REQUIRED)
add_executable(${PROJECT_NAME} compile_materials.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/engine-api/include/)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()
file(GLOB MATERIAL_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.mat.json")
set(COMPILED_DIR "${CMAKE_SOURCE_DIR}/assets/materials")
foreach(MAT ${MATERIAL_FILES})
get_filename_component(MAT_NAME ${MAT} NAME_WE)
set(OUT_FILE "${COMPILED_DIR}/${MAT_NAME}.mat")
add_custom_command(
OUTPUT ${OUT_FILE}
COMMAND ${PROJECT_NAME} ${MAT} ${OUT_FILE}
DEPENDS ${MAT}
COMMENT "Compiling material ${MAT_NAME}"
VERBATIM
)
list(APPEND COMPILED_BINARIES ${OUT_FILE})
endforeach()
add_custom_target(compile_material_assets ALL
DEPENDS ${COMPILED_BINARIES}
)

View File

@ -1,66 +0,0 @@
#include <filesystem>
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <xxhash.h>
#include <string>
#include <ee_engine_api/AssetData.hpp>
using json = nlohmann::json;
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
AssetMaterial,
vertexShaderAssetID,
fragmentShaderAssetID
)
int main(int argc, char **argv)
{
try
{
std::filesystem::path in = argv[1];
std::filesystem::path out = argv[2];
std::ifstream fin(in);
std::ofstream fout(out);
if (!fin.is_open()) {
std::cout << "Error: Could not open input file." << std::endl;
return 1;
}
if (!fout.is_open()) {
std::cout << "Error: Could not open output file." << std::endl;
return 1;
}
json data = json::parse(fin);
for (auto &[key, value] : data.items())
{
if (
!key.ends_with("AssetID") &&
!key.ends_with("Type")
) continue;
std::filesystem::path linkPath = data[key];
auto linkPath8 = linkPath.generic_u8string();
uint32_t assetId = XXH32(linkPath8.data(), linkPath8.size(), 0);
data[key] = assetId;
}
AssetMaterial material = data.get<AssetMaterial>();
fout.write(reinterpret_cast<const char*>(&material), sizeof(material));
fin.close();
fout.close();
}
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#define as_bytes(value) reinterpret_cast<const char*>(value)
namespace ee_utils namespace ee_utils
{ {
bool readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize); bool readNext(void* dst, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize);
bool writeNext(uint8_t* &dstPointer, void* src, size_t &dstLeftoverSize, const size_t &writeSize);
} }

View File

@ -1,12 +1,12 @@
#include <ee_utils/buffers.hpp> #include <ee_utils/buffers.hpp>
#include <cstring> #include <cstring>
bool ee_utils::readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize) bool ee_utils::readNext(void* dst, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize)
{ {
if (srcLeftoverSize >= readSize) if (srcLeftoverSize >= readSize)
{ {
srcLeftoverSize -= readSize; srcLeftoverSize -= readSize;
std::memcpy(dist, srcPointer, readSize); std::memcpy(dst, srcPointer, readSize);
srcPointer += readSize; srcPointer += readSize;
return true; return true;
@ -14,3 +14,17 @@ bool ee_utils::readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSiz
return false; return false;
} }
bool ee_utils::writeNext(uint8_t* &dstPointer, void* src, size_t &dstLeftoverSize, const size_t &writeSize)
{
if (dstLeftoverSize >= writeSize)
{
dstLeftoverSize -= writeSize;
std::memcpy(dstPointer, src, writeSize);
dstPointer += writeSize;
return true;
}
return false;
}