summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-03-27 11:58:47 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-03-27 11:58:47 -0400
commite4604d5b84a71ac3cc8fe1a148d0a6250c7a715c (patch)
tree0f768c8b5d0b96cb459f92c7795c6c9353710ed1 /src
parent11057d2aa423f9b565f3fead4c260999d1bdb53e (diff)
pke: generate uuid and save to project+scene files
Diffstat (limited to 'src')
-rw-r--r--src/components.hpp2
-rw-r--r--src/ecs.cpp9
-rw-r--r--src/game.cpp41
-rw-r--r--src/project.cpp10
-rw-r--r--src/scene.cpp15
5 files changed, 62 insertions, 15 deletions
diff --git a/src/components.hpp b/src/components.hpp
index 326b0e6..f4e7c7f 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -28,6 +28,7 @@ constexpr LevelHandle LevelHandle_MAX = LevelHandle{ pk_handle_MAX_constexpr };
struct Entity_Base {
EntityHandle handle = EntityHandle_MAX;
EntityHandle parentHandle = EntityHandle_MAX;
+ pk_uuid uuid = pk_uuid_max;
bool isMarkedForRemoval = false;
};
@@ -65,6 +66,7 @@ struct CompInstance {
EntityHandle entHandle = EntityHandle_MAX;
GrBindsHandle grBindsHandle = GrBindsHandle_MAX;
InstanceHandle instanceHandle = InstanceHandle_MAX;
+ pk_uuid uuid = pk_uuid_max;
uint32_t index = ECS_UNSET_VAL_32;
PhysicsCollision physicsLayer = PhysicsCollision{1};
PhysicsCollision physicsMask = PhysicsCollision{1};
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 4174bd0..048669d 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -5,6 +5,7 @@
#include "game-settings.hpp"
#include "math-helpers.hpp"
#include "physics.hpp"
+#include "pk.h"
#include "window.hpp"
#include <btBulletDynamicsCommon.h>
@@ -68,6 +69,10 @@ void ECS_Init() {
}
Entity_Base *ECS_CreateGenericEntity() {
+ /* 2025-03-26 - JCB
+ * The only place this is called immediately calls ECS_CreateEntity afterwards.
+ * There is no need to generate a uuid
+ */
pk_handle newHandle{Buckets_NewHandle(ecs.bc.generics)};
return &ecs.bc.generics.buckets[newHandle.bucketIndex][newHandle.itemIndex];
}
@@ -78,6 +83,7 @@ EntityHandle ECS_CreateEntity(Entity_Base *entity, Entity_Base *parentEntity) {
EntityHandle entityHandle{Buckets_NewHandle(ecs.bc.entityPtrs)};
entity->handle = entityHandle;
if (parentEntity) entity->parentHandle = parentEntity->handle;
+ if (entity->uuid == pk_uuid_max || entity->uuid == pk_uuid_zed) entity->uuid = pk_uuid_new_v7();
ecs.bc.entityPtrs.buckets[entityHandle.bucketIndex][entityHandle.itemIndex] = entity;
return entityHandle;
}
@@ -443,6 +449,9 @@ CompInstance *ECS_CreateInstance(Entity_Base *entity, CompGrBinds *entityTypeGrB
new (comp) CompInstance{};
comp->entHandle = entity->handle;
comp->instanceHandle = instanceHandle;
+ // TODO this should be passed in - currently generating a new one each time
+ // Consider making a Component_Base that has a UUID, and pass in similar to ECS_CreateEntity
+ if (comp->uuid == pk_uuid_zed || comp->uuid == pk_uuid_max) comp->uuid = pk_uuid_new_v7();
if (entityTypeGrBinds != nullptr) {
comp->grBindsHandle = entityTypeGrBinds->grBindsHandle;
diff --git a/src/game.cpp b/src/game.cpp
index 2edea8c..630495a 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -54,6 +54,7 @@ const char *PKE_FILE_OBJ_CAMERA = "Camera:";
const char *PKE_FILE_INSTANCE_HANDLE = "Inst::InstHandle: ";
const char *PKE_FILE_INSTANCE_ENTITY_HANDLE = "EntityHandle: ";
const char *PKE_FILE_INSTANCE_ENTITY_TYPE_CODE = "EntityTypeCode: ";
+const char *PKE_FILE_INSTANCE_UUID = "UUID: ";
const char *PKE_FILE_INSTANCE_POS_POS = "InstPos::Pos: ";
const char *PKE_FILE_INSTANCE_POS_ROT = "InstPos::Rot: ";
const char *PKE_FILE_INSTANCE_POS_SCALE = "InstPos::Scale: ";
@@ -68,6 +69,7 @@ const char *PKE_FILE_CAMERA_POS = "Cam::Pos: ";
const char *PKE_FILE_CAMERA_ROT = "Cam::Rot: ";
const char *PKE_FILE_CAMERA_TARGET = "Cam::Target: ";
const char *PKE_FILE_CAMERA_TYPE = "Cam::Type: ";
+const char *PKE_FILE_CAMERA_UUID = "Cam::UUID: ";
const char *PKE_FILE_CAMERA_ORIENTATION = "Cam::Orientation: ";
const char *PKE_FILE_CAMERA_INSTANCE_HANDLE = "Cam::InstanceHandle: ";
const char *PKE_FILE_CAMERA_TARGET_INSTANCE_HANDLE = "Cam::TargetInstanceHandle: ";
@@ -76,6 +78,9 @@ const char *PKE_FILE_CAMERA_IS_PRIMARY = "Cam::IsPrimary: ";
void SerializeCamera(std::ostream &stream, const PkeCamera &cam) {
NULL_CHAR_ARR(handleStr, 23);
PkeCamera c{};
+ if (cam.uuid != pk_uuid_zed && cam.uuid != pk_uuid_max) {
+ stream << PKE_FILE_CAMERA_UUID << cam.uuid << std::endl;
+ }
if (cam.type != c.type) {
stream << PKE_FILE_CAMERA_TYPE << int(static_cast<PkeCameraType_T>(cam.type)) << std::endl;
}
@@ -115,6 +120,9 @@ void SerializeInstance(std::ostream &stream, const CompInstance &comp) {
snprintf(handleStr, 22, "0x%08X 0x%08X", comp.instanceHandle.bucketIndex, comp.instanceHandle.itemIndex);
stream << PKE_FILE_INSTANCE_HANDLE << handleStr << std::endl;
}
+ if (comp.uuid != pk_uuid_zed && comp.uuid != pk_uuid_max) {
+ stream << PKE_FILE_INSTANCE_UUID << comp.uuid << std::endl;
+ }
if (et != nullptr) {
stream << PKE_FILE_INSTANCE_ENTITY_TYPE_CODE << et->entityTypeCode.val << std::endl;
} else if (PkeCamera_Get(comp.entHandle)) {
@@ -286,8 +294,17 @@ void DeserializeInstance(Entity_Base *parentEntity, std::istream &stream) {
if (skipEntCreate == false) {
if (etPtr != nullptr && etPtr->createInstanceCallback.func != nullptr) {
- typedef Entity_Base *CreateInst();
- entity = reinterpret_cast<CreateInst*>(etPtr->createInstanceCallback.func)();
+ /* TODO 2025-03-27 JCB
+ * We have not yet defined what the appropriate callback signature
+ * for creating an entity instance is.
+ * What should be passed as arguments? What would need to be passed
+ * that couldn't be accessed globally?
+ * Consider changing this callback to trigger after creating a
+ * generic instance, rather than *creating* it.
+ */
+ // typedef Entity_Base *CreateInst();
+ // entity = reinterpret_cast<CreateInst*>(etPtr->createInstanceCallback.func)();
+ fprintf(stderr, "[%s] Attempted to call EntityType::createInstanceCallback and we have not yet defined a valid function signature", __FILE__);
} else {
entity = EntityType_CreateGenericInstance(etPtr, parentEntity, &comp, &mapping.newInstance);
fprintf(stdout ,"[Game::DeserializeInstance] Debug: entTypeCode '%s' does not have a registered callback func to handle instance creation.\n", entTypeCode);
@@ -444,21 +461,23 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
}
stream << PKE_FILE_END << std::endl;
- }
- catch (...) {
- failed = true;
+ } catch (std::exception e) {
+ fprintf(stderr, "[%s][Game_SaveSceneFile] Failed to serialize scene file: %s\n", __FILE__, e.what());
+ failed = false;
+ } catch (...) {
+ fprintf(stderr, "[%s][Game_SaveSceneFile] Failed to serialize scene file, uncaught exception.\n", __FILE__);
+ failed = false;
}
if (failed == false) {
std::ofstream f(sceneFilePath);
- if (f.is_open()) {
- f << stream.str();
-
- f.flush();
- f.close();
- } else {
+ if (!f.is_open()) {
failed = true;
+ } else {
+ f << stream.str();
}
+ f.flush();
+ f.close();
}
if (failed) {
diff --git a/src/project.cpp b/src/project.cpp
index e8679c8..d371f68 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -29,6 +29,7 @@ const char* const PKE_PROJ_FILE_PROJ_SETTINGS_SCENES_END = "PkeSet::Scenes: ]";
const char* const PKE_PROJ_FILE_ENTITY_TYPE_MODEL_ASSET_KEY = "ModelAssetKey: ";
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_UUID = "UUID: ";
const char* const PKE_PROJ_FILE_ENTITY_TYPE_CREATE_INSTANCE_CALLBACK_SIGNATURE = "InstanceCreateCallbackSignature: ";
const char* const PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE = "CollisionCallbackSignature: ";
const char* const PKE_PROJ_FILE_ENTITY_TYPE_DETAILS_BEGIN = "EntityHandleDetails: {";
@@ -77,6 +78,9 @@ void Proj_SerializeEntityType(std::ostream &stream, const EntityType &et) {
stream << PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_TYPE_CODE << et.entityTypeCode.val << std::endl;
if (et.handle != e.handle)
stream << PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE << handleStr << std::endl;
+ if (et.uuid != pk_uuid_zed && et.uuid != pk_uuid_max) {
+ stream << PKE_PROJ_FILE_ENTITY_TYPE_UUID << et.uuid << std::endl;
+ }
if (et.createInstanceCallback.name[0] != '\0') {
stream << PKE_PROJ_FILE_ENTITY_TYPE_CREATE_INSTANCE_CALLBACK_SIGNATURE << et.createInstanceCallback.name << std::endl;
}
@@ -404,7 +408,11 @@ void PkeProject_Save(const char *filePath) {
}
stream << PKE_PROJ_FILE_END << std::endl;
+ } catch (std::exception e) {
+ fprintf(stderr, "[%s][PkeProject_Save] Failed to serialize project file: %s\n", __FILE__, e.what());
+ failed = false;
} catch (...) {
+ fprintf(stderr, "[%s][PkeProject_Save] Failed to serialize project file, uncaught exception.\n", __FILE__);
failed = false;
}
@@ -412,6 +420,8 @@ void PkeProject_Save(const char *filePath) {
std::ofstream f(saveFilePath);
if (!f.is_open()) {
failed = true;
+ } else {
+ f << stream.str();
}
f.flush();
f.close();
diff --git a/src/scene.cpp b/src/scene.cpp
index 0e5a22c..f4df916 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -2,7 +2,10 @@
#include "scene.hpp"
#include "bucketed-array.hpp"
#include "ecs.hpp"
-#include <cstring>
+
+#include <string.h>
+
+#include <filesystem>
struct pke_scene_master {
BucketContainer<pke_scene, SceneHandle> bc;
@@ -17,7 +20,11 @@ void pke_scene_master_teardown() {
}
pke_scene *pke_scene_create(const char *scene_name) {
- struct pke_scene *scene = pke_scene_get_by_name(scene_name);
+ NULL_CHAR_ARR(safe_scene_name, SCENE_NAME_MAX_LEN);
+ size_t offset;
+ std::filesystem::path p(scene_name);
+ sprintf(safe_scene_name, "%.15s", p.stem().c_str());
+ struct pke_scene *scene = pke_scene_get_by_name(safe_scene_name);
if (scene != nullptr) {
fprintf(stderr, "[pke_scene_create] failed to create scene: pke_scene::name already in use.");
return nullptr;
@@ -31,9 +38,9 @@ pke_scene *pke_scene_create(const char *scene_name) {
ECS_CreateEntity(scene);
scene->scene_handle = scene_handle;
- size_t offset = (strlen(scene_name) > SCENE_NAME_MAX_LEN ? strlen(scene_name) - SCENE_NAME_MAX_LEN : 0);
+ offset = (strlen(safe_scene_name) > SCENE_NAME_MAX_LEN ? strlen(safe_scene_name) - SCENE_NAME_MAX_LEN : 0);
for (int i = 0; i < SCENE_NAME_MAX_LEN; ++i) {
- scene->name[i] = scene_name[i + offset];
+ scene->name[i] = safe_scene_name[i + offset];
}
return scene;
}