#include "project.hpp" #include "entities.hpp" #include "helpers.hpp" #include #include const long projReadLineLength = 128; char projReadLine[projReadLineLength]; const char *PKE_PROJ_DEFAULT_FILENAME = "project.pptf"; const char *PKE_PROJ_FILE_BEGIN = ":PKPB:"; const char *PKE_PROJ_FILE_END = ":PKPE:"; const char *PKE_PROJ_FILE_VERSION = ":0:"; const char *PKE_PROJ_FILE_OBJ_END = ""; const char *PKE_PROJ_FILE_OBJ_ENTITY_TYPE = "EntityType:"; const char *PKE_PROJ_FILE_ENTITY_TYPE_MODELS_DIR = "ModelsDir: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_MODEL_FILE = "ModelFile: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE = "EntityTypeCode: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE = "EntityHandle: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT = "StartingInstanceCount: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX = "Importer_GLTF::AccessorIndexVertex: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL = "Importer_GLTF::AccessorIndexNormal: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV = "Importer_GLTF::AccessorIndexUV: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX = "Importer_GLTF::AccessorIndexIndex: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS = "BT::StartingMass: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER = "BT::StartingCollisionLayer: "; const char *PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK = "BT::StartingCollisionMask: "; void Proj_SerializeEntityType(std::ofstream &stream, const EntityType &et) { char handleStr[19] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; snprintf(handleStr, 19, "0x%016lX",static_cast(et.entityHandle)); EntityType e{}; if (et.modelsDir != e.modelsDir) stream << PKE_PROJ_FILE_ENTITY_TYPE_MODELS_DIR << et.modelsDir << std::endl; if (et.modelFile != e.modelFile) stream << PKE_PROJ_FILE_ENTITY_TYPE_MODEL_FILE << et.modelFile << std::endl; if (et.entityTypeCode != e.entityTypeCode) stream << PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE << et.entityTypeCode << std::endl; if (et.entityHandle != e.entityHandle) stream << PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE << handleStr << std::endl; if (et.startingInstanceCount != e.startingInstanceCount) stream << PKE_PROJ_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT << et.startingInstanceCount << std::endl; if (et.Importer_GLTF.AccessorIndexVertex != e.Importer_GLTF.AccessorIndexVertex) stream << PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX << et.Importer_GLTF.AccessorIndexVertex << std::endl; if (et.Importer_GLTF.AccessorIndexNormal != e.Importer_GLTF.AccessorIndexNormal) stream << PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL << et.Importer_GLTF.AccessorIndexNormal << std::endl; if (et.Importer_GLTF.AccessorIndexUV != e.Importer_GLTF.AccessorIndexUV) stream << PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV << et.Importer_GLTF.AccessorIndexUV << std::endl; if (et.Importer_GLTF.AccessorIndexIndex != e.Importer_GLTF.AccessorIndexIndex) stream << PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX << et.Importer_GLTF.AccessorIndexIndex << std::endl; if (et.bt.startingMass != e.bt.startingMass) stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS << et.bt.startingMass << std::endl; if (et.bt.startingCollisionLayer != e.bt.startingCollisionLayer) stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER << static_cast(et.bt.startingCollisionLayer) << std::endl; if (et.bt.startingCollisionMask != e.bt.startingCollisionMask) stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK << static_cast(et.bt.startingCollisionMask) << std::endl; } void Proj_ParseEntityType(std::ifstream &stream) { EntityType et{}; while (stream.getline(projReadLine, projReadLineLength)) { if (strcmp(PKE_PROJ_FILE_OBJ_END, projReadLine) == 0) { int64_t existingEntityTypeIndex = EntityType_FindByTypeCode(et.entityTypeCode); if (existingEntityTypeIndex != -1) { continue; } et.entityHandle = ECS_CreateEntity(); EntityType_Load(et); GlobalEntityTypes.Push(et); return; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_MODELS_DIR)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_MODELS_DIR); uint64_t len = strlen(projReadLine + prefixLen) + 1; char *val = Pke_New(len); memset(reinterpret_cast(val), '\0', len); memcpy(val, projReadLine + prefixLen, len); et.modelsDir = val; continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_MODEL_FILE)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_MODEL_FILE); uint64_t len = strlen(projReadLine + prefixLen) + 1; char *val = Pke_New(len); memset(reinterpret_cast(val), '\0', len); memcpy(val, projReadLine + prefixLen, len); et.modelFile = val; continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE); uint64_t len = strlen(projReadLine + prefixLen) + 1; char *val = Pke_New(len); memset(reinterpret_cast(val), '\0', len); memcpy(val, projReadLine + prefixLen, len); et.entityTypeCode = val; continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE); EntityHandle_T handle_t; STR2NUM_ERROR result = str2num(handle_t, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); et.entityHandle = EntityHandle{handle_t}; continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT); STR2NUM_ERROR result = str2num(et.startingInstanceCount, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX); STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexVertex, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL); STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexNormal, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV); STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexUV, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX); STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexIndex, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS); STR2NUM_ERROR result = str2num(et.bt.startingMass, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER); PhysicsCollision_T val = static_cast(et.bt.startingCollisionLayer); STR2NUM_ERROR result = str2num(val, projReadLine + prefixLen); et.bt.startingCollisionLayer = PhysicsCollision{val}; assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK); PhysicsCollision_T val = static_cast(et.bt.startingCollisionMask); STR2NUM_ERROR result = str2num(val, projReadLine + prefixLen); et.bt.startingCollisionMask = PhysicsCollision{val}; assert(result == STR2NUM_ERROR::SUCCESS); continue; } } } void PkeProject_Load(const char *filePath) { const char *safeFilePath = filePath == nullptr ? PKE_PROJ_DEFAULT_FILENAME : filePath; std::ifstream f(safeFilePath); if (!f.is_open()) { fprintf(stderr, "While attempting to load project file, failed to open requested file for reading: %s", safeFilePath); return; } memset(projReadLine, '\0', projReadLineLength); while (f.getline(projReadLine, projReadLineLength)) { if (strcmp(PKE_PROJ_FILE_OBJ_ENTITY_TYPE, projReadLine) == 0) { Proj_ParseEntityType(f); continue; } } f.close(); } void PkeProject_Save(const char *filePath) { const char *safeFilePath = filePath == nullptr ? PKE_PROJ_DEFAULT_FILENAME : filePath; std::ofstream f(safeFilePath); if (!f.is_open()) { fprintf(stderr, "While attempting to save project file, failed to open requested file for writing: %s", safeFilePath); return; } f << PKE_PROJ_FILE_BEGIN << std::endl; f << PKE_PROJ_FILE_VERSION << std::endl; f << "" << std::endl; for (long i = 0; i < GlobalEntityTypes.Count(); ++i) { f << PKE_PROJ_FILE_OBJ_ENTITY_TYPE << std::endl; const auto &et = GlobalEntityTypes[i]; const CompGrBinds *grBinds = ECS_GetGrBinds(et.entityHandle); if (grBinds == nullptr) { continue; } Proj_SerializeEntityType(f, et); f << PKE_PROJ_FILE_OBJ_END << std::endl; } f << PKE_PROJ_FILE_END << std::endl; f.flush(); f.close(); }