summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-05-09 20:40:56 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-05-09 20:40:56 -0400
commitecf91229fb5c9150f2d60d97652bf0024a5c3435 (patch)
treed8fcffa8d436222c4304d9f4d538165ddd734055
parent9693ff2d4be85d356e07e3192baaa2262a7140ff (diff)
pke-test-serialization: add more complex tests
-rw-r--r--src/camera.cpp2
-rw-r--r--src/components.hpp1
-rw-r--r--src/ecs.cpp22
-rw-r--r--src/ecs.hpp2
-rw-r--r--src/entities.cpp5
-rw-r--r--src/serialization-camera.cpp78
-rw-r--r--src/serialization-component.cpp147
-rw-r--r--src/serialization.cpp49
-rw-r--r--src/serialization.hpp18
-rw-r--r--tests/pke-test-serialization.cpp274
10 files changed, 453 insertions, 145 deletions
diff --git a/src/camera.cpp b/src/camera.cpp
index 8b7abe9..e734994 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -55,7 +55,7 @@ PkeCamera &PkeCamera_Register(pk_uuid uuid, const InstPos &instPos) {
cam.uuid = uuid;
ECS_CreateEntity(&cam, nullptr);
cam.camHandle = cameraHandle;
- inst = ECS_CreateInstance(&cam, pk_uuid_zed, nullptr);
+ inst = ECS_CreateInstance(&cam, pk_uuid_zed, nullptr, nullptr);
return PkeCamera_Register_Inner(cam, *inst, instPos);
}
diff --git a/src/components.hpp b/src/components.hpp
index 968cd23..eebe43b 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -71,6 +71,7 @@ struct InstPos {
btScalar mass;
};
struct InstBt {
+ btCollisionShape *collision_shape = nullptr;
btDefaultMotionState *motionState = nullptr;
btRigidBody *rigidBody = nullptr;
};
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 4f81ac0..9de7866 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -439,7 +439,7 @@ CompGrBinds *ECS_GetGrBinds(pk_handle_bucket_index_T bucketIndex, pk_handle_item
return ecs.bc.grBinds.buckets[bucketIndex];
}
-CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds) {
+CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds, InstPos *inst_pos) {
assert(entity != nullptr && entity != CAFE_BABE(Entity_Base));
InstanceHandle instanceHandle{Buckets_NewHandle(ecs.bc.instances)};
@@ -461,6 +461,26 @@ CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds
if (entityTypeGrBinds->instanceCounter > entityTypeGrBinds->instanceBufferMaxCount) {
EntitiesWithExcessInstances.Push(ECS_GetEntity(entityTypeGrBinds->entHandle));
}
+ } else if (inst_pos != nullptr) {
+ // TODO leaky
+ comp->bt.collision_shape = pk_new<btSphereShape>(MemBkt_Bullet);
+ new (comp->bt.collision_shape) btSphereShape(1.0);
+
+ btVector3 localInertia(0, 0, 0);
+ comp->bt.collision_shape->calculateLocalInertia(inst_pos->mass, localInertia);
+ comp->bt.motionState = pk_new<btDefaultMotionState>(MemBkt_Bullet);
+ new (comp->bt.motionState) btDefaultMotionState(inst_pos->posRot);
+
+ comp->bt.rigidBody = pk_new<btRigidBody>(MemBkt_Bullet);
+ new (comp->bt.rigidBody) btRigidBody(inst_pos->mass, comp->bt.motionState, comp->bt.collision_shape, localInertia);
+
+ comp->bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
+ comp->bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
+ comp->bt.rigidBody->getCollisionShape()->setLocalScaling(inst_pos->scale);
+ BtDynamicsWorld->addRigidBody(comp->bt.rigidBody);
+ comp->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(comp->physicsLayer);
+ comp->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(comp->physicsMask);
+ comp->bt.rigidBody->setUserPointer(reinterpret_cast<void *>(comp));
}
return comp;
diff --git a/src/ecs.hpp b/src/ecs.hpp
index e086ab6..b25fdb7 100644
--- a/src/ecs.hpp
+++ b/src/ecs.hpp
@@ -27,7 +27,7 @@ void ECS_GetGrBinds(Entity_Base *entity, pk_arr_t<CompGrBinds *> &arr);
uint64_t ECS_GetGrBinds_BucketCount();
CompGrBinds *ECS_GetGrBinds(pk_handle_bucket_index_T bucketIndex, pk_handle_item_index_T &itemCount);
-CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds);
+CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds, InstPos *instance_pos);
CompInstance *ECS_GetInstance(InstanceHandle instanceHandle);
void ECS_GetInstances(Entity_Base *entity, pk_arr_t<CompInstance *> &arr);
void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics = false);
diff --git a/src/entities.cpp b/src/entities.cpp
index 0ab040c..860907c 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -52,7 +52,7 @@ Entity_Base *EntityType_CreateGenericInstance(EntityType *et, Entity_Base *level
for (int64_t i = 0; i < et->detailsCount; ++i) {
auto &etd = et->details[i];
- auto *compInst = ECS_CreateInstance(genericEntity, uuid, etd.grBinds);
+ auto *compInst = ECS_CreateInstance(genericEntity, uuid, etd.grBinds, nullptr);
btVector3 scaling{1.f,1.f,1.f};
btTransform posRot{};
@@ -65,17 +65,18 @@ Entity_Base *EntityType_CreateGenericInstance(EntityType *et, Entity_Base *level
}
compInst->physicsLayer = srcInstance->physicsLayer;
compInst->physicsMask = srcInstance->physicsMask;
- posRot = instPos->posRot;
} else {
compInst->physicsLayer = etd.bt.startingCollisionLayer;
compInst->physicsMask = etd.bt.startingCollisionMask;
posRot.setIdentity();
}
if (instPos != nullptr) {
+ posRot = instPos->posRot;
mass = instPos->mass;
scaling = instPos->scale;
} else {
mass = etd.bt.startingMass;
+ posRot.setIdentity();
}
btVector3 localInertia(0, 0, 0);
diff --git a/src/serialization-camera.cpp b/src/serialization-camera.cpp
index 963853e..d6563b7 100644
--- a/src/serialization-camera.cpp
+++ b/src/serialization-camera.cpp
@@ -26,6 +26,15 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam)
glm::quat quat_rot;
glm::vec3 glm_scale;
+ kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA);
+ kvec.bkt = h->bkt;
+ kvec.arr.bkt = h->bkt;
+ kvec.children.bkt = h->bkt;
+ kvec.child_handles.bkt = h->bkt;
+ pk_arr_reset(&kvec.arr);
+ pk_arr_reset(&kvec.children);
+ pk_arr_reset(&kvec.child_handles);
+
if (PK_HAS_FLAG(cam->entity_flags, ENTITY_FLAG_DO_NOT_SERIALIZE)) {
return PK_HANDLE_MAX;
}
@@ -44,13 +53,8 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam)
inst_pos_handle = pke_serialize_inst_pos(h, glm_pos, quat_rot, glm_scale);
kvec.srlztn_handle = h->handle_head;
- kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA);
- kvec.bkt = h->bkt;
- kvec.arr.bkt = h->bkt;
- kvec.children.bkt = h->bkt;
- kvec.child_handles.bkt = h->bkt;
h->handle_head.itemIndex++;
- pk_arr_append_t(&kvec.child_handles, inst_pos_handle);
+ pk_arr_append_t<pk_handle>(&kvec.child_handles, inst_pos_handle);
if (cam->uuid != pk_uuid_zed && cam->uuid != pk_uuid_max) {
kve.key = SRLZTN_CAMERA_UUID;
@@ -94,6 +98,9 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam)
}
pk_arr_append_t(&h->kvp_containers, kvec);
+ kvec.arr.data = nullptr;
+ kvec.children.data = nullptr;
+ kvec.child_handles.data = nullptr;
return kvec.srlztn_handle;
}
@@ -120,37 +127,6 @@ void pke_deserialize_camera(srlztn_deserialize_helper *h, pke_kve_container *kve
}
for (i = 0; i < kvec->arr.next; ++i) {
- if (strcmp(kvec->arr[i].key, SRLZTN_OBJ_END) == 0) {
-
- uint32_t targetInstanceIndex = -1;
- if (target_uuid != pk_uuid_zed) {
- targetInstanceIndex = pk_arr_find_first_index(&h->mapping, &target_uuid, srlztn_mapping_find_first_handle_by_uuid);
- if (targetInstanceIndex == uint32_t(-1)) {
- fprintf(stderr, "[pke_deserialize_camera] Camera has target instance uuid '" pk_uuid_printf_format "', but failed to find target instance.", pk_uuid_printf_var(target_uuid));
- }
- }
-
- btVector3 bt_pos;
- btQuaternion bt_rot;
- GlmToBullet(pos, bt_pos);
- GlmToBullet(scale, instPos.scale);
- GlmToBullet(quat_rot, bt_rot);
- instPos.posRot.setOrigin(bt_pos);
- instPos.posRot.setRotation(bt_rot);
- auto &rCam = PkeCamera_Register(cam.uuid, instPos);
- rCam.type = cam.type;
- rCam.view = cam.view;
- rCam.isPrimary = cam.isPrimary;
- pke_scene_register_camera(h->scene->scene_handle, rCam.camHandle);
- if (targetInstanceIndex != uint32_t(-1)) {
- rCam.phys.target_inst_handle = h->mapping[targetInstanceIndex].created_instance->instanceHandle;
- PkeCamera_TargetInstance(rCam.camHandle, h->mapping[targetInstanceIndex].created_instance);
- }
- if (rCam.isPrimary == true) {
- ActiveCamera = &rCam;
- }
- return;
- }
if (strncmp(kvec->arr[i].key, SRLZTN_CAMERA_UUID, strlen(SRLZTN_CAMERA_TYPE)) == 0) {
kvec->arr[i].val >> cam.uuid;
continue;
@@ -185,5 +161,33 @@ void pke_deserialize_camera(srlztn_deserialize_helper *h, pke_kve_container *kve
continue;
}
}
+
+ uint32_t targetInstanceIndex = -1;
+ if (target_uuid != pk_uuid_zed) {
+ targetInstanceIndex = pk_arr_find_first_index(&h->mapping, &target_uuid, srlztn_mapping_find_first_handle_by_uuid);
+ if (targetInstanceIndex == uint32_t(-1)) {
+ fprintf(stderr, "[pke_deserialize_camera] Camera has target instance uuid '" pk_uuid_printf_format "', but failed to find target instance.", pk_uuid_printf_var(target_uuid));
+ }
+ }
+
+ btVector3 bt_pos;
+ btQuaternion bt_rot;
+ GlmToBullet(pos, bt_pos);
+ GlmToBullet(scale, instPos.scale);
+ GlmToBullet(quat_rot, bt_rot);
+ instPos.posRot.setOrigin(bt_pos);
+ instPos.posRot.setRotation(bt_rot);
+ auto &rCam = PkeCamera_Register(cam.uuid, instPos);
+ rCam.type = cam.type;
+ rCam.view = cam.view;
+ rCam.isPrimary = cam.isPrimary;
+ pke_scene_register_camera(h->scene->scene_handle, rCam.camHandle);
+ if (targetInstanceIndex != uint32_t(-1)) {
+ rCam.phys.target_inst_handle = h->mapping[targetInstanceIndex].created_instance->instanceHandle;
+ PkeCamera_TargetInstance(rCam.camHandle, h->mapping[targetInstanceIndex].created_instance);
+ }
+ if (rCam.isPrimary == true) {
+ ActiveCamera = &rCam;
+ }
return;
}
diff --git a/src/serialization-component.cpp b/src/serialization-component.cpp
index 7514a14..afa3b89 100644
--- a/src/serialization-component.cpp
+++ b/src/serialization-component.cpp
@@ -50,6 +50,12 @@ pk_handle pke_serialize_inst_pos(srlztn_serialize_helper *h, const glm::vec3 pos
pk_arr_append_t(&kvec.arr, kve);
}
pk_arr_append_t(&h->kvp_containers, kvec);
+ // 2025-05-08 JCB
+ // this is dead code, but it's here as a reminder to not call pk_arr_reset
+ // so that the underlying data is not freed.
+ kvec.child_handles.data = nullptr;
+ kvec.children.data = nullptr;
+ kvec.arr.data = nullptr;
return kvec.srlztn_handle;
}
@@ -58,10 +64,12 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k
char *pEnd = nullptr;
uint32_t i, index;
const char *starting_char;
+ pke_kve *kve;
PK_STN_RES stn_res;
for (i = 0; i < kvec->arr.next; ++i) {
- if (strstr(kvec->arr[i].key, SRLZTN_POSROT_POS)) {
- starting_char = kvec->arr[i].val;
+ kve = &kvec->arr[i];
+ if (strstr(kve->key, SRLZTN_POSROT_POS)) {
+ starting_char = kve->val;
index = 0;
do {
assert(index < 3);
@@ -70,9 +78,10 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k
starting_char = pEnd + 1;
++index;
} while (*pEnd != '\0');
+ continue;
}
- if (strstr(kvec->arr[i].key, SRLZTN_POSROT_ROT)) {
- starting_char = kvec->arr[i].val;
+ if (strstr(kve->key, SRLZTN_POSROT_ROT)) {
+ starting_char = kve->val;
index = 0;
do {
assert(index < 4);
@@ -81,9 +90,10 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k
starting_char = pEnd + 1;
++index;
} while (*pEnd != '\0');
+ continue;
}
- if (strstr(kvec->arr[i].key, SRLZTN_POSROT_SCALE)) {
- starting_char = kvec->arr[i].val;
+ if (strstr(kve->key, SRLZTN_POSROT_SCALE)) {
+ starting_char = kve->val;
index = 0;
do {
assert(index < 3);
@@ -92,6 +102,7 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k
starting_char = pEnd + 1;
++index;
} while (*pEnd != '\0');
+ continue;
}
}
}
@@ -103,10 +114,9 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance
pk_handle inst_pos_handle;
pke_kve kve{};
pke_kve_container kvec{};
- CompInstance c{};
- glm::vec3 pos;
- glm::quat quat_rot;
- glm::vec3 scale;
+ glm::vec3 pos = glm::vec3(0,0,0);
+ glm::quat quat_rot = glm::quat(1,0,0,0);
+ glm::vec3 scale = glm::vec3(1,1,1);
float mass;
PhysicsCollision collisionLayer;
PhysicsCollision collisionMask;
@@ -120,7 +130,12 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance
comp->bt.motionState->getWorldTransform(trans);
BulletToGlm(trans.getOrigin(), pos);
BulletToGlm(trans.getRotation(), quat_rot);
- BulletToGlm(comp->bt.rigidBody->getCollisionShape()->getLocalScaling(), scale);
+ if (comp->bt.rigidBody != nullptr) {
+ auto a1 = comp->bt.rigidBody;
+ auto a2 = a1 != nullptr ? a1->getCollisionShape() : nullptr;
+ auto a3 = a2 != nullptr ? a2->getLocalScaling() : btVector3(1,1,1);
+ BulletToGlm(a3, scale);
+ }
}
inst_pos_handle = pke_serialize_inst_pos(h, pos, quat_rot, scale);
@@ -154,7 +169,7 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance
kve.end = SRLZTN_KVE_END;
pk_arr_append_t(&kvec.arr, kve);
}
- if (mass != 1) {
+ {
kve.key = SRLZTN_INSTANCE_COMPONENT_MASS;
len = snprintf(NULL, 0, "%f", mass);
s = pk_new<char>(len+1, h->bkt);
@@ -163,20 +178,20 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance
kve.end = SRLZTN_KVE_END;
pk_arr_append_t(&kvec.arr, kve);
}
- if (collisionLayer != c.physicsLayer) {
+ {
kve.key = SRLZTN_INSTANCE_COMPONENT_COLLISION_LAYER;
- len = snprintf(NULL, 0, "%lu", static_cast<PhysicsCollision_T>(collisionLayer));
+ len = snprintf(NULL, 0, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionLayer));
s = pk_new<char>(len+1, h->bkt);
- sprintf(s, "%lu", static_cast<PhysicsCollision_T>(collisionLayer));
+ sprintf(s, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionLayer));
kve.val = s;
kve.end = SRLZTN_KVE_END;
pk_arr_append_t(&kvec.arr, kve);
}
- if (collisionMask != c.physicsMask) {
+ {
kve.key = SRLZTN_INSTANCE_COMPONENT_COLLISION_MASK;
- len = snprintf(NULL, 0, "%lu", static_cast<PhysicsCollision_T>(collisionMask));
+ len = snprintf(NULL, 0, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionMask));
s = pk_new<char>(len+1, h->bkt);
- sprintf(s, "%lu", static_cast<PhysicsCollision_T>(collisionMask));
+ sprintf(s, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionMask));
kve.val = s;
kve.end = SRLZTN_KVE_END;
pk_arr_append_t(&kvec.arr, kve);
@@ -214,53 +229,6 @@ void pke_deserialize_instance(srlztn_deserialize_helper *h, pke_kve_container *k
}
for (i = 0; i < kvec->arr.next; ++i) {
- if (strstr(SRLZTN_OBJ_END, kvec->arr[i].key)) {
- if (et_ptr == nullptr) {
- fprintf(stdout, "[Game::DeserializeInstance] Unknown EntityTypeCode, skipping instance.\n");
- break;
- }
- btVector3 bt_pos;
- btQuaternion bt_quat;
- GlmToBullet(pos, bt_pos);
- GlmToBullet(quat_rot, bt_quat);
- GlmToBullet(scale, inst_pos.scale);
- inst_pos.mass = mass;
- inst_pos.posRot.setIdentity();
- inst_pos.posRot.setOrigin(bt_pos);
- inst_pos.posRot.setRotation(bt_quat);
- if (et_ptr->createInstanceCallback.func != nullptr) {
- /* 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.
- * Also consider just requiring a generic instance for any given
- * EntityType.
- */
- // typedef Entity_Base *CreateInst();
- // entity = reinterpret_cast<CreateInst*>(et_ptr->createInstanceCallback.func)();
- fprintf(stderr, "[%s] Attempted to call EntityType::createInstanceCallback and we have not yet defined a valid function signature", __FILE__);
- } else {
- srlztn_instance_mapping map{};
- map.serialized_uuid = comp.uuid;
- map.created_entity = EntityType_CreateGenericInstance(et_ptr, h->scene, &comp, &inst_pos);
- // TODO gross
- pk_arr_t<CompInstance *> instances;
- ECS_GetInstances(map.created_entity, instances);
- for (uint32_t i = 0; i < instances.next; ++i) {
- if (comp.uuid == instances[i]->uuid) {
- map.created_instance = instances[i];
- }
- }
- if (map.created_instance == nullptr) {
- fprintf(stderr, "[pke_deserialize_instance] Failed to find created instance for creating mapping");
- } else {
- pk_arr_append(&h->mapping, &map);
- }
- }
- }
if (strstr(kvec->arr[i].key, SRLZTN_INSTANCE_COMPONENT_UUID)) {
kvec->arr[i].val >> comp.uuid ;
continue;
@@ -295,5 +263,54 @@ void pke_deserialize_instance(srlztn_deserialize_helper *h, pke_kve_container *k
continue;
}
}
+ if (et_ptr == nullptr) {
+ fprintf(stdout, "[Game::DeserializeInstance] Unknown EntityTypeCode, skipping instance.\n");
+ }
+ btVector3 bt_pos;
+ btQuaternion bt_quat;
+ GlmToBullet(pos, bt_pos);
+ GlmToBullet(quat_rot, bt_quat);
+ GlmToBullet(scale, inst_pos.scale);
+ inst_pos.mass = mass;
+ inst_pos.posRot.setIdentity();
+ inst_pos.posRot.setOrigin(bt_pos);
+ inst_pos.posRot.setRotation(bt_quat);
+ pk_arr_t<CompInstance *> instances;
+ srlztn_instance_mapping map{};
+ map.serialized_uuid = comp.uuid;
+ if (et_ptr != nullptr) {
+ if (et_ptr->createInstanceCallback.func != nullptr) {
+ /* 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.
+ * Also consider just requiring a generic instance for any given
+ * EntityType.
+ */
+ // typedef Entity_Base *CreateInst();
+ // entity = reinterpret_cast<CreateInst*>(et_ptr->createInstanceCallback.func)();
+ fprintf(stderr, "[%s] Attempted to call EntityType::createInstanceCallback and we have not yet defined a valid function signature", __FILE__);
+ } else {
+ map.created_entity = EntityType_CreateGenericInstance(et_ptr, h->scene, &comp, &inst_pos);
+ }
+ } else {
+ map.created_entity = ECS_CreateGenericEntity();
+ map.created_instance = ECS_CreateInstance(map.created_entity, comp.uuid, nullptr, &inst_pos);
+ }
+ ECS_GetInstances(map.created_entity, instances);
+ for (uint32_t i = 0; i < instances.next; ++i) {
+ if (comp.uuid == instances[i]->uuid) {
+ map.created_instance = instances[i];
+ }
+ }
+ pk_arr_reset(&instances);
+ if (map.created_instance == nullptr) {
+ fprintf(stderr, "[pke_deserialize_instance] Failed to find created instance for creating mapping");
+ } else {
+ pk_arr_append(&h->mapping, &map);
+ }
return;
}
diff --git a/src/serialization.cpp b/src/serialization.cpp
index bc5fb44..ce2dbd3 100644
--- a/src/serialization.cpp
+++ b/src/serialization.cpp
@@ -17,20 +17,22 @@ bool srlztn_kvec_find_first_by_handle(void *handle, void *container) {
srlztn_serialize_helper *pke_serialize_init(pk_membucket *bkt) {
srlztn_serialize_helper *helper = pk_new<srlztn_serialize_helper>(bkt);
- // TODO custom allocator
- // helper->o = {};
helper->bkt = bkt;
helper->kvp_containers.bkt = bkt;
+ pk_arr_reserve(&helper->kvp_containers, 1);
+ pk_arr_reset(&helper->kvp_containers);
return helper;
}
srlztn_deserialize_helper *pke_deserialize_init(pk_membucket *bkt) {
srlztn_deserialize_helper *helper = pk_new<srlztn_deserialize_helper>(bkt);
helper->bkt = bkt;
- // helper->read_line = nullptr;
- // TODO custom allocator
- // helper->mapping = {bkt};
helper->kvp_containers.bkt = bkt;
+ helper->mapping.bkt = bkt;
+ pk_arr_reset(&helper->kvp_containers);
+ pk_arr_reset(&helper->mapping);
+ pk_arr_reserve(&helper->kvp_containers, 1);
+ pk_arr_reserve(&helper->mapping, 1);
return helper;
}
@@ -58,28 +60,19 @@ void pke_deserialize_project_from_stream(std::istream &i, srlztn_deserialize_hel
}
void pke_serialize_scene(srlztn_serialize_helper *h) {
- pke_kve_container kvec = {};
- kvec.bkt = h->bkt;
- kvec.arr.bkt = h->bkt;
- kvec.children.bkt = h->bkt;
- kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_INSTANCE);
pk_handle_bucket_index_T instanceBucketCount = ECS_GetInstances_BucketCount();
for (pk_handle_bucket_index_T b = 0; b < instanceBucketCount; ++b) {
pk_handle_item_index_T count;
auto *instances = ECS_GetInstances(b, count);
for (pk_handle_item_index_T i = 0; i < count; ++i) {
const auto &instance = instances[i];
- if (instance.entHandle == EntityHandle_MAX)
- continue;
if (PK_HAS_FLAG(instance.comp_instance_flags, COMPONENT_INSTANCE_FLAG_DO_NOT_SERIALIZE)) {
continue;
}
pke_serialize_instance(h, &instance);
- pk_arr_append_t(&h->kvp_containers, kvec);
}
}
- kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA);
pk_handle_bucket_index_T cameraBucketCount = PkeCamera_GetBucketCount();
for (pk_handle_bucket_index_T b = 0; b < cameraBucketCount; ++b) {
pk_handle_item_index_T count;
@@ -89,7 +82,6 @@ void pke_serialize_scene(srlztn_serialize_helper *h) {
if (cam.handle == CameraHandle_MAX)
continue;
pke_serialize_camera(h, &cam);
- pk_arr_append_t(&h->kvp_containers, kvec);
}
}
}
@@ -99,11 +91,11 @@ void pke_deserialize_scene(srlztn_deserialize_helper *h) {
for (i = 0; i < h->kvp_containers.next; ++i) {
kvec = &h->kvp_containers[i];
- if (strcmp(SRLZTN_OBJ_INSTANCE, kvec->type_code.val) == 0) {
+ if (strstr(kvec->type_code.val, SRLZTN_OBJ_INSTANCE) != nullptr) {
pke_deserialize_instance(h, kvec);
continue;
}
- if (strcmp(SRLZTN_OBJ_CAMERA, kvec->type_code.val) == 0) {
+ if (strstr(kvec->type_code.val, SRLZTN_OBJ_CAMERA) != nullptr) {
pke_deserialize_camera(h, kvec);
continue;
}
@@ -120,16 +112,16 @@ void pke_serialize_scene_to_stream(std::ostream &o, srlztn_serialize_helper *h)
for (i = 0; i < h->kvp_containers.next; ++i) {
kvec = &h->kvp_containers[i];
- o << kvec->type_code.val;
+ o << kvec->type_code.val << ":";
o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.bucketIndex;
o << SRLZTN_HANDLE_SEPARATOR;
o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.itemIndex;
o << std::setbase(0) << std::setw(0) << std::endl;
for (k = 0; k < kvec->child_handles.next; ++k) {
o << SRLZTN_CHILD_ID;
- o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.bucketIndex;
+ o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->child_handles[k].bucketIndex;
o << SRLZTN_HANDLE_SEPARATOR;
- o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.itemIndex;
+ o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->child_handles[k].itemIndex;
o << std::setbase(0) << std::setw(0) << std::endl;
}
for (k = 0; k < kvec->arr.next; ++k) {
@@ -139,7 +131,7 @@ void pke_serialize_scene_to_stream(std::ostream &o, srlztn_serialize_helper *h)
o << SRLZTN_OBJ_END << std::endl;
}
- o << SRLZTN_FILE_END << std::endl;
+ o << SRLZTN_FILE_END;
}
void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helper *h) {
// 0: new object
@@ -159,6 +151,7 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe
kvec.bkt = h->bkt;
kvec.arr.bkt = h->bkt;
kvec.children.bkt = h->bkt;
+ kvec.child_handles.bkt = h->bkt;
i.getline(read_line, read_line_len);
assert(strstr(read_line, SRLZTN_FILE_BEGIN) != 0);
@@ -248,8 +241,15 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe
kvec.type_code.val = nullptr;
kvec.type_code.length = 0;
kvec.type_code.reserved = 0;
- pk_arr_reset(&kvec.arr);
- pk_arr_reset(&kvec.children);
+ kvec.children.next = 0;
+ kvec.children.reserved = 0;
+ kvec.children.data = nullptr;
+ kvec.arr.next = 0;
+ kvec.arr.reserved = 0;
+ kvec.arr.data = nullptr;
+ kvec.child_handles.next = 0;
+ kvec.child_handles.reserved = 0;
+ kvec.child_handles.data = nullptr;
}
}
@@ -269,6 +269,9 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe
}
}
+ kvec.arr.data = nullptr;
+ kvec.children.data = nullptr;
+ kvec.child_handles.data = nullptr;
pk_delete<char>(read_line, read_line_len, h->bkt);
}
diff --git a/src/serialization.hpp b/src/serialization.hpp
index 3b74428..93fd92a 100644
--- a/src/serialization.hpp
+++ b/src/serialization.hpp
@@ -19,13 +19,13 @@ iccsc SRLZTN_MULTILINE_END = ":MULTILINE_END:";
iccsc SRLZTN_CHILD_ID = "ChildId:";
iccsc SRLZTN_OBJ_END = "";
-iccsc SRLZTN_OBJ_INSTANCE_POSITION = "InstPos:";
-iccsc SRLZTN_OBJ_INSTANCE = "Instance:";
-iccsc SRLZTN_OBJ_CAMERA = "Camera:";
-iccsc SRLZTN_OBJ_UI_BOX = "UIBox:";
-iccsc SRLZTN_OBJ_FONT_RENDER = "FontRender:";
-iccsc SRLZTN_OBJ_FONT_RENDER_SETTINGS = "FontRenderSettings:";
-iccsc SRLZTN_OBJ_UI_BOX_TYPE_DATA = "UIBoxTypeData:";
+iccsc SRLZTN_OBJ_INSTANCE_POSITION = "InstPos";
+iccsc SRLZTN_OBJ_INSTANCE = "Instance";
+iccsc SRLZTN_OBJ_CAMERA = "Camera";
+iccsc SRLZTN_OBJ_UI_BOX = "UIBox";
+iccsc SRLZTN_OBJ_FONT_RENDER = "FontRender";
+iccsc SRLZTN_OBJ_FONT_RENDER_SETTINGS = "FontRenderSettings";
+iccsc SRLZTN_OBJ_UI_BOX_TYPE_DATA = "UIBoxTypeData";
iccsc SRLZTN_POSROT_POS = "Position:";
iccsc SRLZTN_POSROT_ROT = "Rotation:";
@@ -78,17 +78,13 @@ struct srlztn_instance_mapping {
struct srlztn_serialize_helper {
pk_membucket *bkt;
- // std::ostringstream o;
pk_arr_t<pke_kve_container> kvp_containers;
pk_handle handle_head;
};
struct srlztn_deserialize_helper {
pk_membucket *bkt;
- // std::istream *i;
- // size_t read_line_len = 256;
pke_scene *scene;
- // char *read_line;
pk_arr_t<srlztn_instance_mapping> mapping;
pk_arr_t<pke_kve_container> kvp_containers;
};
diff --git a/tests/pke-test-serialization.cpp b/tests/pke-test-serialization.cpp
index 64523d8..c514578 100644
--- a/tests/pke-test-serialization.cpp
+++ b/tests/pke-test-serialization.cpp
@@ -1,14 +1,85 @@
#include "./pke-test-serialization.h"
+#include "game-settings.hpp"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "camera.hpp"
+#include "ecs.hpp"
+#include "physics.hpp"
#include "pk.h"
+#include "scene.hpp"
+#include "serialization-camera.hpp"
#include "serialization-component.hpp"
#include "serialization.hpp"
#include <cstring>
#include <sstream>
-pk_membucket *bkt;
+pk_membucket *bkt = nullptr;
+const char *test_scene_name = "srlztn_test_scene";
+pke_scene *test_scene = nullptr;
+
+void pke_test_serialization_spinup() {
+ pkeSettings.isSimulationPaused = true;
+ Physics_Init();
+ ECS_Init();
+ PkeCamera_Init();
+ pke_scene_master_init();
+ test_scene = pke_scene_create(test_scene_name);
+};
+
+void pke_test_serialization_teardown() {
+ // pke_scene_remove(test_scene->scene_handle); // TODO this doesn't work?
+ test_scene = nullptr;
+ pke_scene_master_teardown();
+ PkeCamera_Teardown();
+ ECS_Teardown();
+ Physics_Teardown();
+};
+
+int pke_test_serialization_999() {
+ int64_t err_index = 0;
+ pke_kve_container kvec{};
+ pke_kve kve{};
+ const pk_handle zed_handle = {0,0};
+ PKE_TEST_ASSERT(kvec.srlztn_handle == zed_handle, err_index);
+
+ PKE_TEST_ASSERT(kvec.type_code.length == 0, err_index);
+ PKE_TEST_ASSERT(kvec.type_code.reserved == 0, err_index);
+ PKE_TEST_ASSERT(kvec.type_code.val == nullptr, err_index);
+
+ PKE_TEST_ASSERT(kvec.bkt == nullptr, err_index);
+
+ // 6
+ PKE_TEST_ASSERT(kvec.child_handles.next == 0, err_index);
+ PKE_TEST_ASSERT(kvec.child_handles.reserved == 0, err_index);
+ PKE_TEST_ASSERT(kvec.child_handles.stride == sizeof(pk_handle), err_index);
+ PKE_TEST_ASSERT(kvec.child_handles.alignment == alignof(pk_handle), err_index);
+ PKE_TEST_ASSERT(kvec.child_handles.bkt == nullptr, err_index);
+ PKE_TEST_ASSERT(kvec.child_handles.data == nullptr, err_index);
+
+ // 12
+ PKE_TEST_ASSERT(kvec.children.next == 0, err_index);
+ PKE_TEST_ASSERT(kvec.children.reserved == 0, err_index);
+ PKE_TEST_ASSERT(kvec.children.stride == sizeof(pke_kve_container*), err_index);
+ PKE_TEST_ASSERT(kvec.children.alignment == alignof(pke_kve_container*), err_index);
+ PKE_TEST_ASSERT(kvec.children.bkt == nullptr, err_index);
+ PKE_TEST_ASSERT(kvec.children.data == nullptr, err_index);
+
+ // 18
+ PKE_TEST_ASSERT(kvec.arr.next == 0, err_index);
+ PKE_TEST_ASSERT(kvec.arr.reserved == 0, err_index);
+ PKE_TEST_ASSERT(kvec.arr.stride == sizeof(pke_kve), err_index);
+ PKE_TEST_ASSERT(kvec.arr.alignment == alignof(pke_kve), err_index);
+ PKE_TEST_ASSERT(kvec.arr.bkt == nullptr, err_index);
+ PKE_TEST_ASSERT(kvec.arr.data == nullptr, err_index);
+
+ // 24
+ PKE_TEST_ASSERT(kve.key == nullptr, err_index);
+ PKE_TEST_ASSERT(kve.val == nullptr, err_index);
+ PKE_TEST_ASSERT(kve.end == nullptr, err_index);
+ return 0;
+}
const char *const test_001_str = R"VOGON(:PKFB:
:0:
@@ -18,8 +89,7 @@ Position:0.000000;1.000000;2.000000
Rotation:7.000000;8.000000;9.000000;6.000000
Scale:5.000000;4.000000;3.000000
-:PKFE:
-)VOGON";
+:PKFE:)VOGON";
int pke_test_serialization_001() {
int64_t err_index = 0, i;
srlztn_serialize_helper *h;
@@ -103,10 +173,192 @@ int pke_test_deserialization_101() {
return 0;
}
+const char *const test_002_str = R"VOGON(:PKFB:
+:0:
+
+InstPos:00000000!00000000
+Rotation:0.000000;0.000000;0.000000;1.000000
+
+Instance:00000000!00000001
+ChildId:00000000!00000000
+UUID:67eec271-ab64-78d2-a38e-1f2946e87ccd
+Mass:1.000000
+CollisionLayer:0x0000000000000001
+CollisionMask:0x0000000000000001
+
+InstPos:00000000!00000002
+Position:0.000000;-10.000000;-10.000000
+Rotation:0.000000;0.000000;0.000000;1.000000
+Scale:5.000000;4.000000;3.000000
+
+Camera:00000000!00000003
+ChildId:00000000!00000002
+UUID:67eec26e-56c4-7aeb-a43c-986966334873
+Type:0x01
+Orientation:0x01
+TargetUUID:67eec271-ab64-78d2-a38e-1f2946e87ccd
+IsPrimary:1
+
+:PKFE:)VOGON";
+int pke_test_serialization_002() {
+ int64_t err_index = 0;
+ uint32_t i, k;
+ srlztn_serialize_helper *h = nullptr;
+ pke_kve *kve = nullptr;
+ std::stringstream ss;
+ try {
+ bkt = pk_bucket_create("pke_test_serialization", PK_DEFAULT_BUCKET_SIZE, false);
+ h = pke_serialize_init(bkt);
+ const pk_uuid camera_uuid = { .uuid = { 0x67,0xEE,0xC2,0x6E,0x56,0xC4,0x7A,0xEB,0xA4,0x3C,0x98,0x69,0x66,0x33,0x48,0x73 } };
+ const pk_uuid target_uuid = { .uuid = { 0x67,0xEE,0xC2,0x71,0xAB,0x64,0x78,0xD2,0xA3,0x8E,0x1F,0x29,0x46,0xE8,0x7C,0xCD } };
+
+ // reminder that 'targeting' moves and rotates the camera, so we shouldn't see these values in the output
+ InstPos cam_inst_pos{};
+ cam_inst_pos.posRot.setIdentity();
+ cam_inst_pos.posRot.setOrigin(btVector3(0,0,0));
+ cam_inst_pos.posRot.setRotation(btQuaternion(0.f,0.f,0.f,1));
+ cam_inst_pos.scale = btVector3(1,1,1);
+ cam_inst_pos.mass = 1.f;
+
+ Entity_Base *target_ent = ECS_CreateGenericEntity();
+ CompInstance *target_ent_comp_inst = ECS_CreateInstance(target_ent, target_uuid, nullptr, &cam_inst_pos);
+
+ cam_inst_pos.scale = btVector3(5,4,3);
+ PkeCamera &cam = PkeCamera_Register(camera_uuid, cam_inst_pos);
+ cam.type = PKE_CAMERA_TYPE_PERSPECTIVE;
+ cam.view = PKE_CAMERA_VIEW_TARGET;
+ PkeCamera_SetPrimary(cam.camHandle);
+ PkeCamera_TargetInstance(cam.camHandle, target_ent_comp_inst);
+
+ pke_serialize_scene(h);
+ pke_serialize_scene_to_stream(ss, h);
+ std::string s = ss.str();
+
+ PKE_TEST_ASSERT(h->bkt == bkt, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers.bkt == bkt, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers.next == 4, err_index);
+ // instpos
+ PKE_TEST_ASSERT(h->kvp_containers[0].child_handles.next == 0, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[0].arr.next == 1, err_index);
+ // instance
+ PKE_TEST_ASSERT(h->kvp_containers[1].child_handles.next == 1, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[1].arr.next == 4, err_index);
+ // instpos
+ PKE_TEST_ASSERT(h->kvp_containers[2].child_handles.next == 0, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[2].arr.next == 3, err_index);
+ // camera
+ PKE_TEST_ASSERT(h->kvp_containers[3].child_handles.next == 1, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[3].arr.next == 5, err_index);
+
+ // 12
+ for (k = 0; k < h->kvp_containers.next; ++k) {
+ for (i = 0; i < h->kvp_containers[k].arr.next; ++i) {
+ // 12 + (3 * (1 + 4 + 3 + 5))
+ kve = &h->kvp_containers[k].arr[i];
+ PKE_TEST_ASSERT(kve->key != nullptr, err_index);
+ PKE_TEST_ASSERT(kve->val != nullptr, err_index);
+ PKE_TEST_ASSERT(kve->end != nullptr, err_index);
+ }
+ }
+
+ // 51
+ PKE_TEST_ASSERT(strstr(test_002_str, s.c_str()) != nullptr, err_index);
+
+ pke_serialize_teardown(h);
+
+ } catch (const std::exception &ex) {
+ pk_bucket_destroy(bkt);
+ throw;
+ }
+ pk_bucket_destroy(bkt);
+ return 0;
+}
+
+int pke_test_deserialization_102() {
+ int64_t err_index = 0;
+ uint32_t i, k;
+ pke_kve *kve;
+ srlztn_deserialize_helper *h;
+ std::stringstream ss(test_002_str);
+ try {
+ bkt = pk_bucket_create("pke_test_serialization", PK_DEFAULT_BUCKET_SIZE, false);
+ h = pke_deserialize_init(bkt);
+ h->scene = test_scene;
+ const pk_uuid camera_uuid = { .uuid = { 0x67,0xEE,0xC2,0x6E,0x56,0xC4,0x7A,0xEB,0xA4,0x3C,0x98,0x69,0x66,0x33,0x48,0x73 } };
+ const pk_uuid target_uuid = { .uuid = { 0x67,0xEE,0xC2,0x71,0xAB,0x64,0x78,0xD2,0xA3,0x8E,0x1F,0x29,0x46,0xE8,0x7C,0xCD } };
+
+ pke_deserialize_scene_from_stream(ss, h);
+
+ PKE_TEST_ASSERT(h->bkt == bkt, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers.bkt == bkt, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers.next == 4, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[0].child_handles.next == 0, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[1].child_handles.next == 1, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[2].child_handles.next == 0, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[3].child_handles.next == 1, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[0].arr.next == 1, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[1].arr.next == 4, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[2].arr.next == 3, err_index);
+ PKE_TEST_ASSERT(h->kvp_containers[3].arr.next == 5, err_index);
+
+ // 12
+ for (k = 0; k < h->kvp_containers.next; ++k) {
+ for (i = 0; i < h->kvp_containers[k].arr.next; ++i) {
+ // 12 + (3 * (1 + 4 + 3 + 5))
+ kve = &h->kvp_containers[k].arr[i];
+ PKE_TEST_ASSERT(kve->key != nullptr, err_index);
+ PKE_TEST_ASSERT(kve->val != nullptr, err_index);
+ PKE_TEST_ASSERT(kve->end != nullptr, err_index);
+ }
+ }
+
+ glm::vec3 pos = glm::vec3(0,0,0);
+ glm::quat rot = glm::quat(1,0,0,0);
+ glm::vec3 scale = glm::vec3(1,1,1);
+
+ pke_deserialize_inst_pos(h, &h->kvp_containers[0], pos, rot, scale);
+ // 51
+ PKE_TEST_ASSERT(pos == glm::vec3(0,0,0), err_index);
+ PKE_TEST_ASSERT(rot == glm::quat(1,0,0,0), err_index);
+ PKE_TEST_ASSERT(scale == glm::vec3(1,1,1), err_index);
+
+ pke_deserialize_inst_pos(h, &h->kvp_containers[2], pos, rot, scale);
+ // 54
+ PKE_TEST_ASSERT(pos == glm::vec3(0,-10,-10), err_index);
+ PKE_TEST_ASSERT(rot == glm::quat(1,0,0,0), err_index);
+ PKE_TEST_ASSERT(scale == glm::vec3(5,4,3), err_index);
+
+ pke_deserialize_scene(h);
+
+ pk_handle_item_index_T item_index;
+ PkeCamera *des_cam = &PkeCamera_GetCameras(0, item_index)[0];
+ // 57
+ PKE_TEST_ASSERT(des_cam != nullptr, err_index);
+ PKE_TEST_ASSERT(des_cam->uuid == camera_uuid, err_index);
+ PKE_TEST_ASSERT(des_cam->type == PKE_CAMERA_TYPE_PERSPECTIVE, err_index);
+ PKE_TEST_ASSERT(des_cam->view == PKE_CAMERA_VIEW_TARGET, err_index);
+ PKE_TEST_ASSERT(des_cam->phys.target_inst_uuid == target_uuid, err_index);
+ PKE_TEST_ASSERT(des_cam->isPrimary == true, err_index);
+
+ pke_deserialize_teardown(h);
+
+ } catch (const std::exception &ex) {
+ pk_bucket_destroy(bkt);
+ throw;
+ }
+ pk_bucket_destroy(bkt);
+ return 0;
+}
+
struct pke_test_group *pke_test_serialization_get_group() {
- static const uint64_t test_count = 2;
+ static const uint64_t test_count = 5;
static struct pke_test tests[test_count] = {
{
+ .title = "test 999",
+ .func = pke_test_serialization_999,
+ .expected_result = 0,
+ },
+ {
.title = "test 001",
.func = pke_test_serialization_001,
.expected_result = 0,
@@ -116,9 +368,23 @@ struct pke_test_group *pke_test_serialization_get_group() {
.func = pke_test_deserialization_101,
.expected_result = 0,
},
+ {
+ .title = "test 002",
+ .func = pke_test_serialization_002,
+ .expected_result = 0,
+ },
+ {
+ .title = "test 102",
+ .func = pke_test_deserialization_102,
+ .expected_result = 0,
+ },
};
static struct pke_test_group group = {};
group.title = "de/serialization";
+ group.group_setup = nullptr;
+ group.group_teardown = nullptr;
+ group.test_setup = pke_test_serialization_spinup;
+ group.test_teardown = pke_test_serialization_teardown;
group.n_tests = test_count;
group.tests = &tests[0];