#include "project.hpp" #include "entities.hpp" #include "helpers.hpp" #include #include #include const long projReadLineLength = 128; char projReadLine[projReadLineLength]; const char* const PKE_PROJ_FILE_BEGIN = ":PKPB:"; const char* const PKE_PROJ_FILE_END = ":PKPE:"; const char* const PKE_PROJ_FILE_VERSION = ":0:"; const char* const PKE_PROJ_FILE_OBJ_END = ""; const char* const PKE_PROJ_FILE_OBJ_PROJECT_SETTINGS = "ProjectSettings:"; const char* const PKE_PROJ_FILE_OBJ_ENTITY_TYPE = "EntityType:"; const char* const PKE_PROJ_FILE_PROJ_SETTINGS_DEFAULT_SCENE_NAME = "PkeSet::DefaultSceneName: "; const char* const PKE_PROJ_FILE_PROJ_SETTINGS_SCENE_COUNT = "PkeSet::SceneCount: "; const char* const PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_BEGIN = "PkeSet::Scenes: ["; const char* const PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_END = "PkeSet::Scenes: ]"; const char* const PKE_PROJ_FILE_ENTITY_TYPE_MODELS_DIR = "ModelsDir: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_MODEL_FILE = "ModelFile: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE = "EntityTypeCode: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE = "EntityHandle: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE = "CollisionCallbackSignature: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT = "StartingInstanceCount: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX = "Importer_GLTF::AccessorIndexVertex: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL = "Importer_GLTF::AccessorIndexNormal: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV = "Importer_GLTF::AccessorIndexUV: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX = "Importer_GLTF::AccessorIndexIndex: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS = "BT::StartingMass: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER = "BT::StartingCollisionLayer: "; const char* const PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK = "BT::StartingCollisionMask: "; /* void Proj_SerializeProjectSettings(std::ofstream &stream) { PkeProjectSettings ps{}; if (strncmp(ps.defaultSceneName, pkeProjectSettings.defaultSceneName, strlen(pkeProjectSettings.defaultSceneName)) != 0) { stream << PKE_PROJ_FILE_PROJ_SETTINGS_DEFAULT_SCENE_NAME << ps.defaultSceneName << std::endl; } if (ps.sceneCount != pkeProjectSettings.sceneCount) { stream << PKE_PROJ_FILE_PROJ_SETTINGS_SCENE_COUNT << ps.sceneCount << std::endl; } if (ps.scenes != nullptr) { stream << PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_BEGIN << std::endl; for (long i = 0; i < ps.sceneCount; ++i) { if (ps.scenes[i].length > 0) { stream << ps.scenes[i].val << std::endl; } } stream << PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_END << std::endl; } } */ 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", et.entityHandle.hash); EntityType e{}; CompGrBinds *grBinds = ECS_GetGrBinds(et.entityHandle); 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 (grBinds) { if (grBinds->collisionCallback.name[0] != '\0') { stream << PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE << grBinds->collisionCallback.name << 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_ParseProjectSettings(std::ifstream &stream) { while (stream.getline(projReadLine, projReadLineLength)) { if (strcmp(PKE_PROJ_FILE_OBJ_END, projReadLine) == 0) { return; } if (strncmp(projReadLine, PKE_PROJ_FILE_PROJ_SETTINGS_DEFAULT_SCENE_NAME, strlen(PKE_PROJ_FILE_PROJ_SETTINGS_DEFAULT_SCENE_NAME)) == 0) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_PROJ_SETTINGS_DEFAULT_SCENE_NAME); uint64_t len = strlen(projReadLine + prefixLen) + 1; char *val = Pke_New(len); memset(reinterpret_cast(val), '\0', len); memcpy(val, projReadLine + prefixLen, len); pkeProjectSettings.defaultSceneName = val; continue; } if (strncmp(projReadLine, PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_BEGIN, strlen(PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_BEGIN)) == 0) { DynArray sceneFiles{16}; while (stream.getline(projReadLine, projReadLineLength)) { if (strcmp(PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_END, projReadLine) == 0) { pkeProjectSettings.sceneCount = sceneFiles.Count(); pkeProjectSettings.scenes = Pke_New(sceneFiles.Count()); memcpy(reinterpret_cast(pkeProjectSettings.scenes), reinterpret_cast(sceneFiles.GetPtr()), sizeof(cpkstr) * sceneFiles.Count()); break; } pkeProjectSettings.sceneCount += 1; uint64_t len = strlen(projReadLine) + 1; char *val = Pke_New(len); memset(val, '\0', len); memcpy(val, projReadLine, len - 1); auto &str = sceneFiles.Push(); str.length = len - 1; str.val = val; } } } } */ void Proj_ParseEntityType(std::ifstream &stream) { CallbackSignature collisionSig; collisionSig[0] = '\0'; 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); CompGrBinds *grBinds = ECS_GetGrBinds(et.entityHandle); if (grBinds) { strncpy(grBinds->collisionCallback.name, collisionSig, 16); PkePlugin_SetSignatureFunc(&grBinds->collisionCallback); } 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); STR2NUM_ERROR result = str2num(et.entityHandle.hash, projReadLine + prefixLen); assert(result == STR2NUM_ERROR::SUCCESS); continue; } if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE)) { uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE); memcpy(collisionSig, projReadLine + prefixLen, 16); 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_PROJECT_SETTINGS, projReadLine) == 0) { Proj_ParseProjectSettings(f); continue; } */ 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; /* f << PKE_PROJ_FILE_OBJ_PROJECT_SETTINGS << std::endl; Proj_SerializeProjectSettings(f); f << PKE_PROJ_FILE_OBJ_END << 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(); }