summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-12-07 11:03:38 -0500
committerJonathan Bradley <jcb@pikum.xyz>2023-12-07 11:13:40 -0500
commit8bbe530d7e5162ed47977c0381e61ed68c8f8ada (patch)
treed405a054461a308784efcff2d27392d0e40ed946
parente2e1d4646fa3a196b6247ba2dc04603d393df62f (diff)
Breaking change - add project file - EntityType
-rw-r--r--CMakeLists.txt4
-rw-r--r--editor/editor.cpp82
-rw-r--r--src/game.cpp165
-rw-r--r--src/project-settings.cpp4
-rw-r--r--src/project-settings.hpp10
-rw-r--r--src/project.cpp213
-rw-r--r--src/project.hpp9
7 files changed, 292 insertions, 195 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aaa1314..f1400a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,10 @@ set(PKE_SOURCE_FILES
src/player-input.cpp
src/plugins.hpp
src/plugins.cpp
+ src/project.hpp
+ src/project.cpp
+ src/project-settings.hpp
+ src/project-settings.cpp
src/static/cube.hpp
src/static/cube.cpp
src/thread_pool.hpp
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 1786a18..8107ee3 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -1,6 +1,7 @@
#include "editor.hpp"
+#include "project.hpp"
#include "thread_pool.hpp"
#include "game.hpp"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
@@ -13,6 +14,7 @@
#include "vendor/glm_include.hpp"
#include "vendor/tinyfiledialogs//tinyfiledialogs.h"
#include "imgui.h"
+
#include <future>
const char *dbgCtrl_CameraLeft = "debug-camera-left";
@@ -58,6 +60,7 @@ bool shouldOpenLoadSceneDialog = false;
bool shouldOpenSaveSceneDialog = false;
bool shouldLoadScene = false;
bool shouldSaveScene = false;
+bool shouldSaveProjectFile = false;
glm::vec3 unproject(glm::vec3 windowCoords) {
double xDevNorm = (2.0f * windowCoords.x) / Extent.width - 1.0f;
@@ -82,6 +85,9 @@ void PkeEditor_Tick(double delta) {
if (shouldDisableEditor) {
PkeEditor_Teardown();
}
+ if (shouldSaveProjectFile) {
+ PkeProject_Save();
+ }
if (shouldOpenLoadSceneDialog) {
shouldOpenLoadSceneDialog = false;
PkeThreads_Enqueue(threadPoolHandle, std::packaged_task<void()>( [] {
@@ -727,48 +733,60 @@ void RecordImGui_CompInstPos(bool readonly, CompInstance *component) {
ImGui::Spacing();
}
-void RecordImGuiSceneEditor() {
- {
- if (!ImGui::Begin("SceneEditorEntityTypes", &pkeSettings.editorSettings.isShowingSceneEditor)) {
- ImGui::End();
- return;
- }
- if (ImGui::Button("Create Entity Type")) {
- ImGui::OpenPopup("CreateEntityType");
- }
- if (ImGui::Button("Save")) {
- shouldSaveScene = true;
- }
- if (sceneName) {
- ImGui::SameLine();
- ImGui::Text("%s", sceneName);
- }
- if (ImGui::Button("Save As...")) {
- shouldOpenSaveSceneDialog = true;
- }
- if (ImGui::Button("Load")) {
- shouldOpenLoadSceneDialog = true;
- }
- if (ImGui::Button("Clear Selection")) {
- selectedEntity = EntityHandle_MAX;
- }
-
- ImGui::Spacing();
+void RecordImGuiProjectSettingsEditor() {
+ if (!ImGui::Begin("ProjectSettings")) {
+ ImGui::End();
+ return;
+ }
- if (selectedEntity != EntityHandle_MAX) {
- RecordImGui_CompGrBinds(true, ECS_GetGrBinds(selectedEntity));
- RecordImGui_CompInstPos(false, ECS_GetInstance(selectedEntity));
- }
+ if (ImGui::Button("Save")) {
+ shouldSaveProjectFile = true;
+ }
- RecordImGuiModalCreateEntityType();
+ ImGui::End();
+}
+void RecordImGuiSceneEditor() {
+ if (!ImGui::Begin("SceneEditorEntityTypes", &pkeSettings.editorSettings.isShowingSceneEditor)) {
ImGui::End();
+ return;
+ }
+ if (ImGui::Button("Create Entity Type")) {
+ ImGui::OpenPopup("CreateEntityType");
+ }
+ if (ImGui::Button("Save")) {
+ shouldSaveScene = true;
+ }
+ if (sceneName) {
+ ImGui::SameLine();
+ ImGui::Text("%s", sceneName);
+ }
+ if (ImGui::Button("Save As...")) {
+ shouldOpenSaveSceneDialog = true;
+ }
+ if (ImGui::Button("Load")) {
+ shouldOpenLoadSceneDialog = true;
}
+ if (ImGui::Button("Clear Selection")) {
+ selectedEntity = EntityHandle_MAX;
+ }
+
+ ImGui::Spacing();
+
+ if (selectedEntity != EntityHandle_MAX) {
+ RecordImGui_CompGrBinds(true, ECS_GetGrBinds(selectedEntity));
+ RecordImGui_CompInstPos(false, ECS_GetInstance(selectedEntity));
+ }
+
+ RecordImGuiModalCreateEntityType();
+
+ ImGui::End();
}
void PkeEditor_RecordImGui() {
if (pkeSettings.isShowingEditor) {
RecordImGuiEditorWrapper();
+ RecordImGuiProjectSettingsEditor();
RecordImGuiEntityList();
RecordImGuiSceneEditor();
RecordImGuiUBO();
diff --git a/src/game.cpp b/src/game.cpp
index 6c47381..98962d7 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -12,6 +12,7 @@
#include "physics.hpp"
#include "player-input.hpp"
#include "plugins.hpp"
+#include "project.hpp"
#include "vendor/glm_include.hpp"
#include "window.hpp"
@@ -32,23 +33,9 @@ const char *PKE_FILE_BEGIN = ":PKFB:";
const char *PKE_FILE_END = ":PKFE:";
const char *PKE_FILE_VERSION = ":0:";
const char *PKE_FILE_OBJ_END = "";
-const char *PKE_FILE_OBJ_ENTITY_TYPE = "EntityType:";
const char *PKE_FILE_OBJ_INSTANCE = "Instance:";
const char *PKE_FILE_OBJ_CAMERA = "Camera:";
-const char *PKE_FILE_ENTITY_TYPE_MODELS_DIR = "ModelsDir: ";
-const char *PKE_FILE_ENTITY_TYPE_MODEL_FILE = "ModelFile: ";
-const char *PKE_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE = "EntityTypeCode: ";
-const char *PKE_FILE_ENTITY_TYPE_ENTITY_HANDLE = "EntityHandle: ";
-const char *PKE_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT = "StartingInstanceCount: ";
-const char *PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX = "Importer_GLTF::AccessorIndexVertex: ";
-const char *PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL = "Importer_GLTF::AccessorIndexNormal: ";
-const char *PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV = "Importer_GLTF::AccessorIndexUV: ";
-const char *PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX = "Importer_GLTF::AccessorIndexIndex: ";
-const char *PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS = "BT::StartingMass: ";
-const char *PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER = "BT::StartingCollisionLayer: ";
-const char *PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK = "BT::StartingCollisionMask: ";
-
const char *PKE_FILE_INSTANCE_ENTITY_HANDLE = "EntityHandle: ";
const char *PKE_FILE_INSTANCE_ENTITY_TYPE_CODE = "EntityTypeCode: ";
const char *PKE_FILE_INSTANCE_POS_POS = "InstPos::Pos: ";
@@ -93,36 +80,6 @@ void SerializeCamera(std::ofstream &stream, const PkeCamera &cam) {
}
}
-void 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<EntityHandle_T>(et.entityHandle));
- EntityType e{};
- if (et.modelsDir != e.modelsDir)
- stream << PKE_FILE_ENTITY_TYPE_MODELS_DIR << et.modelsDir << std::endl;
- if (et.modelFile != e.modelFile)
- stream << PKE_FILE_ENTITY_TYPE_MODEL_FILE << et.modelFile << std::endl;
- if (et.entityTypeCode != e.entityTypeCode)
- stream << PKE_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE << et.entityTypeCode << std::endl;
- if (et.entityHandle != e.entityHandle)
- stream << PKE_FILE_ENTITY_TYPE_ENTITY_HANDLE << handleStr << std::endl;
- if (et.startingInstanceCount != e.startingInstanceCount)
- stream << PKE_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT << et.startingInstanceCount << std::endl;
- if (et.Importer_GLTF.AccessorIndexVertex != e.Importer_GLTF.AccessorIndexVertex)
- stream << PKE_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_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_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_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX << et.Importer_GLTF.AccessorIndexIndex << std::endl;
- if (et.bt.startingMass != e.bt.startingMass)
- stream << PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS << et.bt.startingMass << std::endl;
- if (et.bt.startingCollisionLayer != e.bt.startingCollisionLayer)
- stream << PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER << static_cast<PhysicsCollision_T>(et.bt.startingCollisionLayer) << std::endl;
- if (et.bt.startingCollisionMask != e.bt.startingCollisionMask)
- stream << PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK << static_cast<PhysicsCollision_T>(et.bt.startingCollisionMask) << std::endl;
-}
-
void SerializeInstance(std::ofstream &stream, const CompInstance &comp) {
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<EntityHandle_T>(comp.entHandle));
@@ -252,109 +209,6 @@ void ParseCamera(std::ifstream &stream) {
}
}
-void ParseEntityType(std::ifstream &stream) {
- EntityType et{};
- while (stream.getline(readLine, readLineLength)) {
- if (strcmp(PKE_FILE_OBJ_END, readLine) == 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(readLine, PKE_FILE_ENTITY_TYPE_MODELS_DIR)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_MODELS_DIR);
- uint64_t len = strlen(readLine + prefixLen) + 1;
- char *val = Pke_New<char>(len);
- memset(reinterpret_cast<void *>(val), '\0', len);
- memcpy(val, readLine + prefixLen, len);
- et.modelsDir = val;
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_MODEL_FILE)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_MODEL_FILE);
- uint64_t len = strlen(readLine + prefixLen) + 1;
- char *val = Pke_New<char>(len);
- memset(reinterpret_cast<void *>(val), '\0', len);
- memcpy(val, readLine + prefixLen, len);
- et.modelFile = val;
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE);
- uint64_t len = strlen(readLine + prefixLen) + 1;
- char *val = Pke_New<char>(len);
- memset(reinterpret_cast<void *>(val), '\0', len);
- memcpy(val, readLine + prefixLen, len);
- et.entityTypeCode = val;
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_ENTITY_HANDLE)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_ENTITY_HANDLE);
- EntityHandle_T handle_t;
- STR2NUM_ERROR result = str2num(handle_t, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- et.entityHandle = EntityHandle{handle_t};
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_STARTING_INSTANCE_COUNT);
- STR2NUM_ERROR result = str2num(et.startingInstanceCount, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_VERTEX);
- STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexVertex, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_NORMAL);
- STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexNormal, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_UV);
- STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexUV, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_IMPORTER_GLTF_ACCESSOR_INDEX_INDEX);
- STR2NUM_ERROR result = str2num(et.Importer_GLTF.AccessorIndexIndex, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_MASS);
- STR2NUM_ERROR result = str2num(et.bt.startingMass, readLine + prefixLen);
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER);
- PhysicsCollision_T val = static_cast<PhysicsCollision_T>(et.bt.startingCollisionLayer);
- STR2NUM_ERROR result = str2num(val, readLine + prefixLen);
- et.bt.startingCollisionLayer = PhysicsCollision{val};
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- if (strstr(readLine, PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK)) {
- uint64_t prefixLen = strlen(PKE_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK);
- PhysicsCollision_T val = static_cast<PhysicsCollision_T>(et.bt.startingCollisionMask);
- STR2NUM_ERROR result = str2num(val, readLine + prefixLen);
- et.bt.startingCollisionMask = PhysicsCollision{val};
- assert(result == STR2NUM_ERROR::SUCCESS);
- continue;
- }
- }
-}
-
void ParseInstance(std::ifstream &stream) {
CompInstance comp{};
InstPos instPos{};
@@ -507,18 +361,6 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
}
}
- for (long i = 0; i < GlobalEntityTypes.Count(); ++i) {
- f << PKE_FILE_OBJ_ENTITY_TYPE << std::endl;
- const auto &et = GlobalEntityTypes[i];
- const CompGrBinds *grBinds = ECS_GetGrBinds(et.entityHandle);
- // TODO ignore if no instances
- if (grBinds == nullptr) {
- continue;
- }
- SerializeEntityType(f, et);
- f << PKE_FILE_OBJ_END << std::endl;
- }
-
int64_t instanceBucketCount = ECS_GetInstances_BucketCount();
for (long b = 0; b < instanceBucketCount; ++b) {
uint64_t count;
@@ -552,10 +394,6 @@ void Game_LoadSceneFile(const char *sceneFilePath) {
ParseCamera(f);
continue;
}
- if (strcmp(PKE_FILE_OBJ_ENTITY_TYPE, readLine) == 0) {
- ParseEntityType(f);
- continue;
- }
if (strcmp(PKE_FILE_OBJ_INSTANCE, readLine) == 0) {
ParseInstance(f);
continue;
@@ -637,6 +475,7 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
if (pkePlugin.OnInit) {
pkePlugin.OnInit();
}
+ PkeProject_Load();
GameTimePoint lastTimePoint = pkeSettings.steadyClock.now();
double deltaTillNextRender = pkeSettings.deltaPerFrame;
diff --git a/src/project-settings.cpp b/src/project-settings.cpp
new file mode 100644
index 0000000..46d8d61
--- /dev/null
+++ b/src/project-settings.cpp
@@ -0,0 +1,4 @@
+
+#include "project-settings.hpp"
+
+PkeProjectSettings pkeProjectSettings;
diff --git a/src/project-settings.hpp b/src/project-settings.hpp
new file mode 100644
index 0000000..b101372
--- /dev/null
+++ b/src/project-settings.hpp
@@ -0,0 +1,10 @@
+#ifndef PKE_PROJECT_SETTINGS_HPP
+#define PKE_PROJECT_SETTINGS_HPP
+
+struct PkeProjectSettings {
+
+};
+
+extern PkeProjectSettings pkeProjectSettings;
+
+#endif /* PKE_PROJECT_SETTINGS_HPP */
diff --git a/src/project.cpp b/src/project.cpp
new file mode 100644
index 0000000..a71401b
--- /dev/null
+++ b/src/project.cpp
@@ -0,0 +1,213 @@
+
+#include "project.hpp"
+
+#include "entities.hpp"
+#include "helpers.hpp"
+
+#include <ostream>
+#include <iomanip>
+
+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<EntityHandle_T>(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<PhysicsCollision_T>(et.bt.startingCollisionLayer) << std::endl;
+ if (et.bt.startingCollisionMask != e.bt.startingCollisionMask)
+ stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK << static_cast<PhysicsCollision_T>(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<char>(len);
+ memset(reinterpret_cast<void *>(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<char>(len);
+ memset(reinterpret_cast<void *>(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<char>(len);
+ memset(reinterpret_cast<void *>(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<PhysicsCollision_T>(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<PhysicsCollision_T>(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();
+}
diff --git a/src/project.hpp b/src/project.hpp
new file mode 100644
index 0000000..9a5ed4b
--- /dev/null
+++ b/src/project.hpp
@@ -0,0 +1,9 @@
+#ifndef PKE_PROJECT_HPP
+#define PKE_PROJECT_HPP
+
+#include "project-settings.hpp"
+
+void PkeProject_Load(const char *filePath = nullptr);
+void PkeProject_Save(const char *filePath = nullptr);
+
+#endif /* PKE_PROJECT_HPP */