summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2024-01-10 19:24:12 -0500
committerJonathan Bradley <jcb@pikum.xyz>2024-01-10 19:24:12 -0500
commitf07294ca65143fac8b1b426d1854212403721226 (patch)
tree2edeb8f2c9beea1cbb065f69910d53957ebda0ce
parent294c85f91ac5b2ff9e4ad3d99588ed0d1a72e6b7 (diff)
checkpoint - handle breaking ECS changes - compiles
-rw-r--r--CMakeLists.txt12
-rw-r--r--editor/editor.cpp262
-rw-r--r--src/ecs.cpp78
-rw-r--r--src/ecs.hpp6
-rw-r--r--src/entities.cpp286
-rw-r--r--src/entities.hpp26
-rw-r--r--src/game.cpp75
-rw-r--r--src/game.hpp2
-rw-r--r--src/level-types.hpp6
-rw-r--r--src/level.cpp28
-rw-r--r--src/level.hpp1
-rw-r--r--src/physics.cpp10
-rw-r--r--src/project.cpp77
13 files changed, 461 insertions, 408 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dbd9787..7582f10 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,12 +119,12 @@ if (Vulkan_FOUND)
endif (Vulkan_FOUND)
add_library(pke
- ${PKE_SOURCE_FILES}
+ ${PKE_SOURCE_FILES}
)
if (Vulkan_FOUND)
- target_link_libraries(pke PUBLIC ${Vulkan_LIBRARIES})
- target_include_directories(pke PUBLIC ${Vulkan_INCLUDE_DIR})
+ target_link_libraries(pke PUBLIC ${Vulkan_LIBRARIES})
+ target_include_directories(pke PUBLIC ${Vulkan_INCLUDE_DIR})
endif (Vulkan_FOUND)
set(SHADER_OUTPUT_DIR ${PROJECT_BINARY_DIR}/assets/shaders)
@@ -152,9 +152,9 @@ add_custom_target(shaders ALL DEPENDS ${SPV_SHADERS})
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
if (GLFW_FOUND)
- message(STATUS "GLFW found: " ${GLFW_INCLUDE_DIR})
- target_link_libraries(pke PUBLIC ${GLFW_LIBRARIES})
- target_include_directories(pke PUBLIC ${GLFW_INCLUDE_DIR})
+ message(STATUS "GLFW found: " ${GLFW_INCLUDE_DIR})
+ target_link_libraries(pke PUBLIC ${GLFW_LIBRARIES})
+ target_include_directories(pke PUBLIC ${GLFW_INCLUDE_DIR})
endif (GLFW_FOUND)
find_package(glm REQUIRED)
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 625a49f..2f7e804 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -2,6 +2,7 @@
#include "editor.hpp"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "array.hpp"
#include "camera.hpp"
#include "ecs.hpp"
#include "entities.hpp"
@@ -61,12 +62,9 @@ bool shouldDisableEditor = false;
bool shouldRebuildProjectDir = true;
bool shouldRebuildAssetList = true;
-struct EntityTypeInstanceCreateInfo {
- EntityHandle entityTypeEntityHandle;
-};
-DynArray<EntityTypeInstanceCreateInfo> entityInstancesToCreate{16};
-EntityHandle selectedEntity = EntityHandle_MAX;
-EntityHandle hoveredEntity = EntityHandle_MAX;
+DynArray<EntityType *> entityInstancesToCreate{16};
+CompInstance *selectedEntity = nullptr;
+CompInstance *hoveredEntity = nullptr;
bool shouldCreateEntityType = false;
EntityType entityTypeToCreate{};
CameraHandle selectedCamera = CameraHandle_MAX;
@@ -178,26 +176,26 @@ void PkeEditor_Tick(double delta) {
shouldRebuildProjectDir = true;
}
- if (EntitiesToBeRemoved.Has(selectedEntity)) {
- selectedEntity = EntityHandle_MAX;
+ if (selectedEntity && EntitiesToBeRemoved.Has(ECS_GetEntity(selectedEntity->entHandle))) {
+ selectedEntity = nullptr;
}
- if (EntitiesToBeRemoved.Has(hoveredEntity)) {
- hoveredEntity = EntityHandle_MAX;
+ if (hoveredEntity && EntitiesToBeRemoved.Has(ECS_GetEntity(hoveredEntity->entHandle))) {
+ hoveredEntity = nullptr;
}
bool imGuiHovered = ImGui::GetIO().WantCaptureMouse;
- if (selectedEntity != EntityHandle_MAX && !imGuiHovered) {
+ if (selectedEntity != nullptr && !imGuiHovered) {
auto holder = PkeInput_Query(dbgCtrl_ClearSelection);
if (holder.type != InputEventHash{0}) {
const PkeMouseButtonEvent *mbEvent = static_cast<PkeMouseButtonEvent *>(holder.ptr);
if (mbEvent->isPressed) {
- selectedEntity = EntityHandle_MAX;
+ selectedEntity = nullptr;
}
}
}
// raycast for hovering
- hoveredEntity = EntityHandle_MAX;
+ hoveredEntity = nullptr;
if (!imGuiHovered) {
double xMousePos, yMousePos;
if (pkeSettings.editorSettings.isUsingDebugCamera) {
@@ -220,11 +218,11 @@ void PkeEditor_Tick(double delta) {
BtDynamicsWorld->rayTest(rayOrigin, rayDestination, rayResult);
if (rayResult.hasHit()) {
- hoveredEntity.hash = reinterpret_cast<uint64_t>(rayResult.m_collisionObject->getUserPointer());
+ hoveredEntity = reinterpret_cast<CompInstance *>(rayResult.m_collisionObject->getUserPointer());;
}
}
- if (hoveredEntity != EntityHandle_MAX) {
+ if (hoveredEntity != nullptr) {
auto holder = PkeInput_Query(dbgCtrl_SelectHovered);
if (holder.type != InputEventHash{0}) {
const PkeMouseButtonEvent *mbEvent = static_cast<PkeMouseButtonEvent *>(holder.ptr);
@@ -234,17 +232,14 @@ void PkeEditor_Tick(double delta) {
}
}
- EntityHandle focusedHandle = selectedEntity != EntityHandle_MAX ? selectedEntity : hoveredEntity;
+ CompInstance *focusedInst = selectedEntity != nullptr ? selectedEntity : hoveredEntity;
bool found = false;
- if (focusedHandle != EntityHandle_MAX) {
- const auto *inst = ECS_GetInstance(focusedHandle);
- if (inst != nullptr) {
- const auto *grBinds = ECS_GetGrBinds(inst->grBindsHandle);
- if (grBinds != nullptr) {
- pkeDebugHitbox.instanceBuffer = grBinds->instanceBuffer;
- pkeDebugHitbox.instanceStartingIndex = inst->index;
- found = true;
- }
+ if (focusedInst != nullptr) {
+ const auto *grBinds = ECS_GetGrBinds(focusedInst->grBindsHandle);
+ if (grBinds != nullptr) {
+ pkeDebugHitbox.instanceBuffer = grBinds->instanceBuffer;
+ pkeDebugHitbox.instanceStartingIndex = focusedInst->index;
+ found = true;
}
}
if (!found) {
@@ -253,46 +248,40 @@ void PkeEditor_Tick(double delta) {
}
if (shouldCreateEntityType) {
- assert(entityTypeToCreate.entityHandle == EntityHandle_MAX);
- // TODO this needs to be more elegant
- int64_t existingEntityTypeIndex = EntityType_FindByTypeCode(entityTypeToCreate.entityTypeCode);
- if (existingEntityTypeIndex == -1) {
- entityTypeToCreate.entityHandle = ECS_CreateEntity();
+ EntityType *existingEntity = EntityType_FindByTypeCode(entityTypeToCreate.entityTypeCode);
+ if (existingEntity == nullptr) {
+
+ EntityType *newEntType = EntityType_Create();
+ strncpy(newEntType->modelAssetKey, entityTypeToCreate.modelAssetKey, AssetKeyLength);
+ newEntType->entityTypeCode = entityTypeToCreate.entityTypeCode;
+ if (entityTypeToCreate.createInstanceCallback.name[0] != '\0') {
+ strncpy(newEntType->createInstanceCallback.name, entityTypeToCreate.createInstanceCallback.name, CallbackSignatureLength);
+ PkePlugin_SetSignatureFunc(&newEntType->createInstanceCallback);
+ }
+ for (int64_t i = 0; i < entityTypeToCreate.detailsCount; ++i) {
+ newEntType->details[i] = entityTypeToCreate.details[i];
+ strncpy(newEntType->details[i].textureAssetKey, entityTypeToCreate.details[i].textureAssetKey, AssetKeyLength);
+ }
+
EntityType_Load(entityTypeToCreate);
- GlobalEntityTypes.Push(entityTypeToCreate);
+
+ for (int64_t i = 0; i < entityTypeToCreate.detailsCount; ++i) {
+ strncpy(newEntType->details[i].grBinds->collisionCallback.name, entityTypeToCreate.details[i].grBinds->collisionCallback.name, CallbackSignatureLength);
+ PkePlugin_SetSignatureFunc(&newEntType->details[i].grBinds->collisionCallback);
+ }
+ } else {
+ // TODO leaks entityTypeToCreate.entityTypeCode
}
entityTypeToCreate = EntityType{};
shouldCreateEntityType = false;
}
while (entityInstancesToCreate.Count() > 0) {
- auto createInfo = entityInstancesToCreate.Pop();
+ EntityType *et = entityInstancesToCreate.Pop();
// TODO needs to be more elegant
- int64_t detailIndex = 0;
- int64_t etIndex = EntityType_FindByEntityHandle(createInfo.entityTypeEntityHandle, detailIndex);
- auto &et = GlobalEntityTypes[etIndex];
- EntityHandle parentEntity = ECS_CreateEntity();
-
- for (size_t i = 0; i < et.detailsCount; ++i) {
- auto &etd = et.details[i];
- EntityHandle newEntity = ECS_CreateEntity(parentEntity);
- auto &compInst = ECS_CreateInstance(newEntity, etd.entityHandle);
- compInst.physicsLayer = etd.bt.startingCollisionLayer;
- compInst.physicsMask = etd.bt.startingCollisionMask;
- btVector3 localInertia(0, 0, 0);
- etd.bt.shape->calculateLocalInertia(etd.bt.startingMass, localInertia);
- btTransform posRot{};
- posRot.setIdentity();
- compInst.bt.motionState = Pke_New<btDefaultMotionState>(MemBkt_Bullet);
- new (compInst.bt.motionState) btDefaultMotionState(posRot);
- compInst.bt.rigidBody = Pke_New<btRigidBody>(MemBkt_Bullet);
- new (compInst.bt.rigidBody) btRigidBody(etd.bt.startingMass, compInst.bt.motionState, etd.bt.shape, localInertia);
- compInst.bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
- compInst.bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
- compInst.bt.rigidBody->getCollisionShape()->setLocalScaling(btVector3(1, 1, 1));
- BtDynamicsWorld->addRigidBody(compInst.bt.rigidBody);
- compInst.bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(etd.bt.startingCollisionLayer);
- compInst.bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(etd.bt.startingCollisionMask);
- compInst.bt.rigidBody->setUserPointer(reinterpret_cast<void *>(compInst.entHandle.hash));
+ if (et->createInstanceCallback.func) {
+ reinterpret_cast<void(*)()>(et->createInstanceCallback.func)();
+ } else {
+ EntityType_CreateGenericInstance(et, nullptr);
}
}
@@ -423,12 +412,12 @@ void PkeEditor_Tick(double delta) {
}
holder = PkeInput_Query(dbgCtrl_DeleteSelectedItem);
- if (holder.type != InputEventHash{0} && selectedEntity != EntityHandle_MAX) {
+ if (holder.type != InputEventHash{0} && selectedEntity != nullptr) {
PkeKeyEvent *delSelectedItemEvent;
delSelectedItemEvent = static_cast<PkeKeyEvent *>(holder.ptr);
if (delSelectedItemEvent->isPressed == true) {
- ECS_MarkForRemoval(selectedEntity);
- selectedEntity = EntityHandle_MAX;
+ ECS_MarkForRemoval(ECS_GetEntity(selectedEntity->entHandle));
+ selectedEntity = nullptr;
}
}
}
@@ -637,66 +626,6 @@ void RecordImGuiEditorWrapper() {
ImGui::EndMainMenuBar();
}
-void RecordImGuiEntityList() {
- if (!ImGui::Begin("EntityList", &pkeSettings.editorSettings.isShowingEntityList)) {
- ImGui::End();
- return;
- }
- static ImGuiTableFlags tableFlags{
- ImGuiTableFlags_Borders |
- ImGuiTableFlags_RowBg
- };
- if (ImGui::BeginTable("Entities", 7, tableFlags)) {
- ImGui::TableSetupColumn("Select");
- ImGui::TableSetupColumn("EntityHandle");
- ImGui::TableSetupColumn("ParentEntityHandle");
- ImGui::TableSetupColumn("GrBindsHandle");
- ImGui::TableSetupColumn("InstanceHandle");
- ImGui::TableSetupColumn("IsMarkedForRemoval");
- ImGui::TableSetupColumn("Delete");
- ImGui::TableHeadersRow();
-
- uint64_t bucketCount = ECS_GetEntities_BucketCount();
- for (long bucket = 0; bucket < bucketCount; ++bucket) {
- uint64_t itemCount = 0;
- auto *entities = ECS_GetEntities(bucket, itemCount);
- ImGui::PushID(bucket);
- for (long row = 0; row < itemCount; row++) {
- auto *entity = &entities[row];
- if (entity->handle == EntityHandle_MAX) {
- continue;
- }
- ImGui::PushID(row);
- ImGui::TableNextRow();
- ImGui::TableSetColumnIndex(0);
- ImGui::BeginDisabled(selectedEntity == entity->handle);
- if (ImGui::Button("Select"))
- selectedEntity = entity->handle;
- ImGui::EndDisabled();
- ImGui::TableSetColumnIndex(1);
- ImGui::Text("0x%016lX", entity->handle.hash);
- ImGui::TableSetColumnIndex(2);
- ImGui::Text("0x%016lX", entity->parentHandle.hash);
- ImGui::TableSetColumnIndex(3);
- ImGui::Text("0x%016lX", entity->grBindsHandle.hash);
- ImGui::TableSetColumnIndex(4);
- ImGui::Text("0x%016lX", entity->instanceHandle.hash);
- ImGui::TableSetColumnIndex(5);
- ImGui::Text("%u", entity->isMarkedForRemoval);
- ImGui::TableSetColumnIndex(6);
- ImGui::BeginDisabled(selectedEntity != entity->handle);
- if (ImGui::Button("Delete"))
- ECS_MarkForRemoval(entity->handle);
- ImGui::EndDisabled();
- ImGui::PopID();
- }
- ImGui::PopID();
- }
- ImGui::EndTable();
- }
- ImGui::End();
-}
-
void RecordImGuiCameras() {
if (!ImGui::Begin("Cameras")) {
ImGui::End();
@@ -848,7 +777,8 @@ bool RecordImGui_CallbackSelectModal(long &selectedIndex) {
void RecordImGuiModalCreateEntityType() {
if (ImGui::BeginPopupModal("CreateEntityType", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
- static char entityTypeCode[32];
+ static char entityTypeCode[32] = {'\0'};
+ static char createInstanceSig[CallbackSignatureLength + 1] = {'\0'};
static AssetPickerSearchStruct apssModel{
.source = {"cet_mdl"},
.safeKey = {""},
@@ -867,6 +797,23 @@ void RecordImGuiModalCreateEntityType() {
ImGui::Text("%s", apssModel.safeKey);
ImGui::InputText("Entity Type Code", entityTypeCode, 31);
+ static long index = -1;
+ if (ImGui::Button("Clear")) {
+ index = -1;
+ createInstanceSig[0] = '\0';
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Change")) {
+ index = -1;
+ ImGui::OpenPopup("CallbackSelect");
+ }
+ ImGui::SameLine();
+ ImGui::Text("Collision Callback: '%s'", createInstanceSig);
+ if (RecordImGui_CallbackSelectModal(index)) {
+ long x = 0;
+ memcpy(createInstanceSig, PkePlugin_GetSortedSignatures(x)[index], CallbackSignatureLength);
+ }
+
ImGui::BeginDisabled();
ImGui::InputScalar("Sub-Types", ImGuiDataType_S64, &entityTypeToCreate.detailsCount);
ImGui::SameLine();
@@ -893,9 +840,11 @@ void RecordImGuiModalCreateEntityType() {
ImGui::Separator();
+ bool shouldReset = false;
if (ImGui::Button("Create")) {
// TODO some type of validation
+ strncpy(entityTypeToCreate.createInstanceCallback.name, createInstanceSig, CallbackSignatureLength);
strncpy(entityTypeToCreate.modelAssetKey, apssModel.safeKey, AssetKeyLength);
// TODO this needs to be an array
strncpy(entityTypeToCreate.details[0].textureAssetKey, apssTexture.safeKey, AssetKeyLength);
@@ -906,19 +855,19 @@ void RecordImGuiModalCreateEntityType() {
shouldCreateEntityType = true;
- apssModel.safeKey[0] = '\0';
- apssTexture.safeKey[0] = '\0';
- entityTypeCode[0] = '\0';
- apssModel.safeKey[AssetKeyLength] = '\0';
- apssTexture.safeKey[AssetKeyLength] = '\0';
- entityTypeCode[31] = '\0';
- ImGui::CloseCurrentPopup();
+ shouldReset = true;
}
ImGui::SameLine();
if (ImGui::Button("Cancel")) {
+ shouldReset = true;
+ }
+
+ if (shouldReset) {
+ createInstanceSig[0] = '\0';
apssModel.safeKey[0] = '\0';
apssTexture.safeKey[0] = '\0';
entityTypeCode[0] = '\0';
+ createInstanceSig[CallbackSignatureLength] = '\0';
apssModel.safeKey[AssetKeyLength] = '\0';
apssTexture.safeKey[AssetKeyLength] = '\0';
entityTypeCode[31] = '\0';
@@ -938,23 +887,20 @@ void RecordImGuiLevels() {
ImGuiTableFlags_Borders |
ImGuiTableFlags_RowBg
};
- if (ImGui::BeginTable("PkeLevels", 5, tableFlags)) {
+ if (ImGui::BeginTable("PkeLevels", 3, tableFlags)) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Handle");
- ImGui::TableSetupColumn("EntityCount");
ImGui::TableSetupColumn("CameraCount");
ImGui::TableHeadersRow();
for (long i = 0; i < MAX_LEVEL_COUNT; ++i) {
- if (LEVELS[i].handle == LevelHandle_MAX)
+ if (LEVELS[i].levelHandle == LevelHandle_MAX)
continue;
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("%s", LEVELS[i].name);
ImGui::TableSetColumnIndex(1);
- ImGui::Text("0x%04hx", LEVELS[i].handle);
+ ImGui::Text("0x%04hx", LEVELS[i].levelHandle);
ImGui::TableSetColumnIndex(2);
- ImGui::Text("%u", LEVELS[i].wrappingEntities.next - 1);
- ImGui::TableSetColumnIndex(3);
ImGui::Text("%u", LEVELS[i].cameras.next - 1);
}
ImGui::EndTable();
@@ -971,12 +917,6 @@ void RecordImGui_CompGrBinds(bool readonly, CompGrBinds *component) {
ImGui::Text("CompGRBinds");
ImGui::Separator();
- if (ImGui::Button("Create Instance")) {
- entityInstancesToCreate.Push({
- .entityTypeEntityHandle = component->entHandle,
- });
- }
-
if (component->vkPipelineLayout)
ImGui::InputScalar("VkPipelineLayout", ImGuiDataType_U64, &component->vkPipelineLayout, nullptr, nullptr, "0x%016lX", ImGuiInputTextFlags_ReadOnly);
if (component->vkDescriptorSets){
@@ -1030,7 +970,7 @@ void RecordImGui_CompGrBinds(bool readonly, CompGrBinds *component) {
ImGui::Text("Collision Callback: '%s'", component->collisionCallback.name);
if (RecordImGui_CallbackSelectModal(index)) {
long x = 0;
- memcpy(component->collisionCallback.name, PkePlugin_GetSortedSignatures(x)[index], 16);
+ memcpy(component->collisionCallback.name, PkePlugin_GetSortedSignatures(x)[index], CallbackSignatureLength);
PkePlugin_SetSignatureFunc(&component->collisionCallback);
}
@@ -1096,7 +1036,7 @@ void RecordImGui_CompInstPos(bool readonly, CompInstance *component) {
auto *broadphase = component->bt.rigidBody->getBroadphaseProxy();
broadphase->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(component->physicsLayer);
broadphase->m_collisionFilterMask = static_cast<PhysicsCollision_T>(component->physicsMask);
- ECS_UpdateInstance(component->entHandle, instPos, true);
+ ECS_UpdateInstance(component, instPos, true);
}
ImGui::Spacing();
@@ -1226,14 +1166,41 @@ void RecordImGuiSceneEditor() {
ImGui::OpenPopup("CreateEntityType");
}
if (ImGui::Button("Clear Selection")) {
- selectedEntity = EntityHandle_MAX;
+ selectedEntity = nullptr;
}
ImGui::Spacing();
- if (selectedEntity != EntityHandle_MAX) {
- RecordImGui_CompGrBinds(true, ECS_GetGrBinds(selectedEntity));
- RecordImGui_CompInstPos(false, ECS_GetInstance(selectedEntity));
+ if (selectedEntity != nullptr) {
+ Entity_Base *entity = ECS_GetEntity(selectedEntity->entHandle);
+ auto *entityType = static_cast<EntityType *>(entity);
+ if (ImGui::Button("Create Instance")) {
+ entityInstancesToCreate.Push(entityType);
+ }
+ static PkeArray<CompGrBinds *> entGrBinds;
+ static PkeArray<CompInstance *> entInstances;
+ bool reset = false;
+ if (entGrBinds.next > 0) {
+ if (entGrBinds.data[0]->entHandle != selectedEntity->entHandle) {
+ reset = true;
+ }
+ } else if (entInstances.next > 0) {
+ if (entInstances.data[0]->entHandle != selectedEntity->entHandle) {
+ reset = true;
+ }
+ }
+ if (reset) {
+ PkeArray_SoftReset(&entGrBinds);
+ PkeArray_SoftReset(&entInstances);
+ }
+ ECS_GetGrBinds(ECS_GetEntity(selectedEntity->entHandle), entGrBinds);
+ ECS_GetInstances(ECS_GetEntity(selectedEntity->entHandle), entInstances);
+ for (int64_t i = 0; i < entGrBinds.next; ++i) {
+ RecordImGui_CompGrBinds(true, entGrBinds.data[i]);
+ }
+ for (int64_t i = 0; i < entInstances.next; ++i) {
+ RecordImGui_CompInstPos(false, entInstances.data[i]);
+ }
}
RecordImGuiModalCreateAsset();
@@ -1247,7 +1214,6 @@ void PkeEditor_RecordImGui() {
RecordImGuiEditorWrapper();
RecordImGuiProjectSettingsEditor();
RecordImGuiProjectBrowser();
- RecordImGuiEntityList();
RecordImGuiSceneEditor();
RecordImGuiUBO();
RecordImGuiCameras();
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 02f00d3..f499835 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -1,6 +1,7 @@
#include "ecs.hpp"
+#include "array.hpp"
#include "bucketed-array.hpp"
#include "game-settings.hpp"
#include "math-helpers.hpp"
@@ -39,7 +40,8 @@ DynArray<Entity_Base *> entitiesYetToBeRemoved{0, nullptr};
DynArray<Entity_Base *> EntitiesWithExcessInstances{16};
-BucketContainer<Entity_Base *, GrBindsHandle> Entities_BucketContainer{};
+BucketContainer<Entity_Base, PkeHandle> Entities_GenericsBC{};
+BucketContainer<Entity_Base *, EntityHandle> Entities_BucketContainer{};
BucketContainer<CompGrBinds, GrBindsHandle> Comp_GrBinds_BucketContainer{};
BucketContainer<CompInstance, InstanceHandle> Comp_Instance_BucketContainer{};
@@ -54,8 +56,14 @@ void ECS_Init() {
Buckets_Init(Comp_Instance_BucketContainer, maxBucketItemCount);
}
+Entity_Base *ECS_CreateGenericEntity() {
+ PkeHandle newHandle{Buckets_NewHandle(Entities_GenericsBC)};
+ return &Entities_GenericsBC.buckets[newHandle.bucketIndex][newHandle.itemIndex];
+}
+
EntityHandle ECS_CreateEntity(Entity_Base *entity, Entity_Base *parentEntity) {
assert(entity != nullptr);
+ assert(entity->handle == EntityHandle_MAX && "Entity already created!");
EntityHandle entityHandle{Buckets_NewHandle(Entities_BucketContainer)};
entity->handle = entityHandle;
entity->parentHandle = parentEntity->handle;
@@ -63,6 +71,11 @@ EntityHandle ECS_CreateEntity(Entity_Base *entity, Entity_Base *parentEntity) {
return entityHandle;
}
+Entity_Base *ECS_GetEntity(EntityHandle handle) {
+ ValidateHandle(handle, Entities_BucketContainer.pkeHandle, Entities_BucketContainer.limits.itemIndex);
+ return Entities_BucketContainer.buckets[handle.bucketIndex][handle.itemIndex];
+}
+
void ECS_MarkForRemoval(Entity_Base *entity) {
assert(entity->isMarkedForRemoval == false && "Entity already marked for removal");
entitiesMarkedForRemoval.Push(entity);
@@ -327,41 +340,35 @@ void ECS_Tick_Late(double delta) {
}
}
-void ECS_HandleCollision(InstanceHandle lhs, InstanceHandle rhs) {
- CompInstance *lhsInst = ECS_GetInstance(lhs);
- CompGrBinds *lhsGrBinds = nullptr;
- if (lhsInst != nullptr) {
- lhsGrBinds = ECS_GetGrBinds(lhsInst->grBindsHandle);
- }
+void ECS_HandleCollision(CompInstance *lhsInst, CompInstance *rhsInst) {
+ assert(lhsInst != nullptr);
+ assert(rhsInst != nullptr);
- CompInstance *rhsInst = ECS_GetInstance(rhs);
- CompGrBinds *rhsGrBinds = nullptr;
- if (rhsInst != nullptr) {
- rhsGrBinds = ECS_GetGrBinds(rhsInst->grBindsHandle);
- }
+ CompGrBinds *lhsGrBinds = ECS_GetGrBinds(lhsInst->grBindsHandle);
+ CompGrBinds *rhsGrBinds = ECS_GetGrBinds(rhsInst->grBindsHandle);
- void (*lhsColFunc)(InstanceHandle, InstanceHandle) = nullptr;
- void (*rhsColFunc)(InstanceHandle, InstanceHandle) = nullptr;
+ void (*lhsColFunc)(CompInstance*, CompInstance*) = nullptr;
+ void (*rhsColFunc)(CompInstance*, CompInstance*) = nullptr;
if (lhsInst && lhsInst->collisionCallback.func != nullptr) {
- lhsColFunc = reinterpret_cast<void (*)(InstanceHandle, InstanceHandle)>(lhsInst->collisionCallback.func);
+ lhsColFunc = reinterpret_cast<void (*)(CompInstance *, CompInstance *)>(lhsInst->collisionCallback.func);
}
if (lhsColFunc == nullptr && lhsGrBinds && lhsGrBinds->collisionCallback.func) {
- lhsColFunc = reinterpret_cast<void (*)(InstanceHandle, InstanceHandle)>(lhsGrBinds->collisionCallback.func);
+ lhsColFunc = reinterpret_cast<void (*)(CompInstance *, CompInstance *)>(lhsGrBinds->collisionCallback.func);
}
if (rhsInst && rhsInst->collisionCallback.func != nullptr) {
- rhsColFunc = reinterpret_cast<void (*)(InstanceHandle, InstanceHandle)>(rhsInst->collisionCallback.func);
+ rhsColFunc = reinterpret_cast<void (*)(CompInstance *, CompInstance *)>(rhsInst->collisionCallback.func);
}
if (rhsColFunc == nullptr && rhsGrBinds && rhsGrBinds->collisionCallback.func) {
- rhsColFunc = reinterpret_cast<void (*)(InstanceHandle, InstanceHandle)>(rhsGrBinds->collisionCallback.func);
+ rhsColFunc = reinterpret_cast<void (*)(CompInstance *, CompInstance *)>(rhsGrBinds->collisionCallback.func);
}
if (lhsColFunc) {
- lhsColFunc(lhs, rhs);
+ lhsColFunc(lhsInst, rhsInst);
}
if (rhsColFunc) {
- rhsColFunc(lhs, rhs);
+ rhsColFunc(lhsInst, rhsInst);
}
}
@@ -383,6 +390,19 @@ CompGrBinds *ECS_GetGrBinds(GrBindsHandle grBindsHandle) {
return &Comp_GrBinds_BucketContainer.buckets[grBindsHandle.bucketIndex][grBindsHandle.itemIndex];
}
+void ECS_GetGrBinds(Entity_Base *entity, PkeArray<CompGrBinds *> &arr) {
+ for (PkeHandleBucketIndex_T b = 0; b <= Comp_GrBinds_BucketContainer.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = Comp_GrBinds_BucketContainer.buckets[b];
+ long itemCount = Comp_GrBinds_BucketContainer.pkeHandle.bucketIndex == b ? Comp_GrBinds_BucketContainer.pkeHandle.itemIndex : Comp_GrBinds_BucketContainer.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &grBinds = bkt[i];
+ if (grBinds.entHandle == entity->handle) {
+ PkeArray_Add(&arr, &grBinds);
+ }
+ }
+ }
+}
+
uint64_t ECS_GetGrBinds_BucketCount() {
return Comp_GrBinds_BucketContainer.pkeHandle.bucketIndex + 1;
}
@@ -427,6 +447,19 @@ CompInstance *ECS_GetInstance(InstanceHandle instanceHandle ) {
return inst;
}
+void ECS_GetInstances(Entity_Base *entity, PkeArray<CompInstance *> &arr) {
+ for (PkeHandleBucketIndex_T b = 0; b <= Comp_Instance_BucketContainer.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = Comp_Instance_BucketContainer.buckets[b];
+ long itemCount = Comp_Instance_BucketContainer.pkeHandle.bucketIndex == b ? Comp_Instance_BucketContainer.pkeHandle.itemIndex : Comp_Instance_BucketContainer.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &inst = bkt[i];
+ if (inst.entHandle == entity->handle) {
+ PkeArray_Add(&arr, &inst);
+ }
+ }
+ }
+}
+
void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics) {
if (BtDynamicsWorld && overridePhysics) {
btVector3 localInertia(0, 0, 0);
@@ -460,7 +493,8 @@ void ECS_Teardown() {
entitiesYetToBeRemoved.~DynArray();
EntitiesToBeRemoved.~DynArray();
entitiesMarkedForRemoval.~DynArray();
- Buckets_Destroy(Entities_BucketContainer);
- Buckets_Destroy(Comp_GrBinds_BucketContainer);
Buckets_Destroy(Comp_Instance_BucketContainer);
+ Buckets_Destroy(Comp_GrBinds_BucketContainer);
+ Buckets_Destroy(Entities_BucketContainer);
+ Buckets_Destroy(Entities_GenericsBC);
}
diff --git a/src/ecs.hpp b/src/ecs.hpp
index 567f6df..4ddf232 100644
--- a/src/ecs.hpp
+++ b/src/ecs.hpp
@@ -1,6 +1,7 @@
#ifndef PKE_ECS_HPP
#define PKE_ECS_HPP
+#include "array.hpp"
#include "dynamic-array.hpp"
#include "macros.hpp"
#include "memory.hpp"
@@ -23,19 +24,22 @@ void ECS_Tick_Early(double delta);
void ECS_Tick(double delta);
void ECS_Tick_Late(double delta);
+Entity_Base *ECS_CreateGenericEntity();
EntityHandle ECS_CreateEntity(Entity_Base *entity, Entity_Base *parentEnt = nullptr);
Entity_Base *ECS_GetEntity(EntityHandle handle);
void ECS_MarkForRemoval(Entity_Base *entity);
-void ECS_HandleCollision(Entity_Base *lhs, Entity_Base *rhs);
+void ECS_HandleCollision(CompInstance *lhs, CompInstance *rhs);
CompGrBinds *ECS_CreateGrBinds(Entity_Base *);
CompGrBinds *ECS_GetGrBinds(GrBindsHandle grBindsHandle);
+void ECS_GetGrBinds(Entity_Base *entity, PkeArray<CompGrBinds *> &arr);
uint64_t ECS_GetGrBinds_BucketCount();
CompGrBinds *ECS_GetGrBinds(uint64_t bucketIndex, uint64_t &itemCount);
CompInstance *ECS_CreateInstance(Entity_Base *entity, CompGrBinds *entityTypeGrBinds);
CompInstance *ECS_GetInstance(InstanceHandle instanceHandle);
+void ECS_GetInstances(Entity_Base *entity, PkeArray<CompInstance *> &arr);
void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics = false);
uint64_t ECS_GetInstances_BucketCount();
CompInstance *ECS_GetInstances(uint64_t bucketIndex, uint64_t &itemCount);
diff --git a/src/entities.cpp b/src/entities.cpp
index 91c94d8..bd24830 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -1,7 +1,10 @@
#include "entities.hpp"
+#include "bucketed-array.hpp"
#include "ecs.hpp"
+#include "game-settings.hpp"
+#include "level.hpp"
#include "math-helpers.hpp"
#include "memory.hpp"
#include "physics.hpp"
@@ -14,7 +17,8 @@
#include <type_traits>
#include <vulkan/vulkan_core.h>
-DynArray<EntityType> GlobalEntityTypes{16};
+BucketContainer<EntityType> EntityType_BC{};
+
struct EntToTeardown {
EntityHandle handle = EntityHandle_MAX;
CompGrBinds *grBinds[1] = {nullptr};
@@ -23,37 +27,85 @@ struct EntToTeardown {
DynArray<EntToTeardown> EntityTypesToTeardown{16};
void EntityType_Init() {
- long entityTypeCount = GlobalEntityTypes.Count();
- for (long i = 0; i < entityTypeCount; ++i) {
- EntityType_Load(GlobalEntityTypes[i]);
- }
+ Buckets_Init(EntityType_BC);
}
-int64_t EntityType_FindByTypeCode(const char *typeCode) {
- for (int64_t i = 0; i < GlobalEntityTypes.Count(); ++i) {
- if (strcmp(typeCode, GlobalEntityTypes[i].entityTypeCode) == 0) {
- return i;
+EntityType *EntityType_Create() {
+ EntityTypeHandle entTypeHandle{Buckets_NewHandle(EntityType_BC)};
+ EntityType &entityType = EntityType_BC.buckets[entTypeHandle.bucketIndex][entTypeHandle.itemIndex];
+ new (&entityType) EntityType{};
+ ECS_CreateEntity(&entityType);
+ return &entityType;
+}
+
+Entity_Base *EntityType_CreateGenericInstance(EntityType *et, CompInstance *srcInstance) {
+ assert(et != nullptr);
+ Entity_Base *genericEntity = ECS_CreateGenericEntity();
+ auto *level = PkeLevel_Get(pkeSettings.rt.activeLevel);
+ ECS_CreateEntity(genericEntity, level);
+
+ for (size_t i = 0; i < et->detailsCount; ++i) {
+ auto &etd = et->details[i];
+ auto *compInst = ECS_CreateInstance(genericEntity, etd.grBinds);
+
+ if (srcInstance != nullptr) {
+ if (srcInstance->collisionCallback.name[0] != '\0') {
+ strncpy(compInst->collisionCallback.name, srcInstance->collisionCallback.name, CallbackSignatureLength);
+ PkePlugin_SetSignatureFunc(&compInst->collisionCallback);
+ }
+ compInst->physicsLayer = srcInstance->physicsLayer;
+ compInst->physicsMask = srcInstance->physicsMask;
+ } else {
+ compInst->physicsLayer = etd.bt.startingCollisionLayer;
+ compInst->physicsMask = etd.bt.startingCollisionMask;
}
+ btVector3 localInertia(0, 0, 0);
+ etd.bt.shape->calculateLocalInertia(etd.bt.startingMass, localInertia);
+ btTransform posRot{};
+ posRot.setIdentity();
+ compInst->bt.motionState = Pke_New<btDefaultMotionState>(MemBkt_Bullet);
+ new (compInst->bt.motionState) btDefaultMotionState(posRot);
+ compInst->bt.rigidBody = Pke_New<btRigidBody>(MemBkt_Bullet);
+ new (compInst->bt.rigidBody) btRigidBody(etd.bt.startingMass, compInst->bt.motionState, etd.bt.shape, localInertia);
+ compInst->bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
+ compInst->bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
+ compInst->bt.rigidBody->getCollisionShape()->setLocalScaling(btVector3(1, 1, 1));
+ BtDynamicsWorld->addRigidBody(compInst->bt.rigidBody);
+ compInst->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(compInst->physicsLayer);
+ compInst->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(compInst->physicsMask);
+ compInst->bt.rigidBody->setUserPointer(reinterpret_cast<void *>(compInst->entHandle.hash));
}
- return -1;
+ return genericEntity;
}
-int64_t EntityType_FindByEntity(Entity_Base *entity, int64_t &detailIndex) {
- assert(entity != nullptr);
- for (int64_t i = 0; i < GlobalEntityTypes.Count(); ++i) {
- for (int64_t k = 0; k < GlobalEntityTypes[i].detailsCount; ++k) {
- if (GlobalEntityTypes[i].details[k].entityHandle == entity->handle) {
- detailIndex = k;
- return i;
+EntityType *EntityType_FindByTypeCode(const char *typeCode) {
+ for (PkeHandleBucketIndex_T b = 0; b <= EntityType_BC.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = EntityType_BC.buckets[b];
+ long itemCount = EntityType_BC.pkeHandle.bucketIndex == b ? EntityType_BC.pkeHandle.itemIndex : EntityType_BC.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &entityType = bkt[i];
+ if (entityType.handle == EntityHandle_MAX) continue;
+ if (strcmp(typeCode, entityType.entityTypeCode) == 0) {
+ return &entityType;
}
}
- if (GlobalEntityTypes[i].entityHandle == entity->handle) {
- detailIndex = -1;
- return i;
+ }
+ return nullptr;
+}
+
+EntityType *EntityType_FindByEntityHandle(EntityHandle handle) {
+ if (handle == EntityHandle_MAX) return nullptr;
+ for (PkeHandleBucketIndex_T b = 0; b <= EntityType_BC.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = EntityType_BC.buckets[b];
+ long itemCount = EntityType_BC.pkeHandle.bucketIndex == b ? EntityType_BC.pkeHandle.itemIndex : EntityType_BC.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &entityType = bkt[i];
+ if (entityType.handle == handle) {
+ return &entityType;
+ }
}
}
- detailIndex = -1;
- return -1;
+ return nullptr;
}
void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memReqs, VkMemoryRequirements &combinedMemReqs) {
@@ -94,7 +146,6 @@ struct EntityTypeDetails_LoadHelperStruct {
EntityTypeDetails *etd = nullptr;
AssetHandle textureAssetHandle = AssetHandle_MAX;
const Asset *textureAsset = nullptr;
- CompGrBinds *grBinds = nullptr;
struct {
DynArray<glm::vec3> *vertexes = nullptr;
DynArray<glm::vec3> *normals = nullptr;
@@ -155,10 +206,7 @@ void EntityType_PreLoad(EntityType_LoadHelperStruct &helper) {
EntityTypeDetails &etd = helper.et.details[i];
EntityTypeDetails_LoadHelperStruct &etdHelper = helper.etdHelpers->Push();
etdHelper.etd = &etd;
- etd.entityHandle = ECS_CreateEntity(helper.et.entityHandle);
- auto &grBinds = ECS_CreateGrBinds(etd.entityHandle);
- etdHelper.grBinds = &grBinds;
- etd.grBindsHandle = grBinds.grBindsHandle;
+ etd.grBinds = ECS_CreateGrBinds(&helper.et);;
etdHelper.physDbg.vertexes = reinterpret_cast<DynArray<glm::vec3> *>(Pke_New(sizeof(DynArray<glm::vec3>), 64, helper.bkt));
etdHelper.physDbg.normals = reinterpret_cast<DynArray<glm::vec3> *>(Pke_New(sizeof(DynArray<glm::vec3>), 64, helper.bkt));
etdHelper.physDbg.uv = reinterpret_cast<DynArray<glm::vec2> *>(Pke_New(sizeof(DynArray<glm::vec2>), 64, helper.bkt));
@@ -580,11 +628,11 @@ void EntityType_LoadTexture(EntityType_LoadHelperStruct &helper, const int64_t i
vkDescriptorSetAllocateInfo.descriptorSetCount = MAX_FRAMES_IN_FLIGHT;
vkDescriptorSetAllocateInfo.pSetLayouts = descriptorSets;
- etdHelper.grBinds->vkDescriptorSets = Pke_New<VkDescriptorSet>(MAX_FRAMES_IN_FLIGHT);
+ etdHelper.etd->grBinds->vkDescriptorSets = Pke_New<VkDescriptorSet>(MAX_FRAMES_IN_FLIGHT);
for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
- etdHelper.grBinds->vkDescriptorSets[i] = VkDescriptorSet{};
+ etdHelper.etd->grBinds->vkDescriptorSets[i] = VkDescriptorSet{};
}
- vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, etdHelper.grBinds->vkDescriptorSets);
+ vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, etdHelper.etd->grBinds->vkDescriptorSets);
assert(vkResult == VK_SUCCESS);
VkWriteDescriptorSet writeDescriptorSets[2 * MAX_FRAMES_IN_FLIGHT];
@@ -618,10 +666,10 @@ void EntityType_LoadTexture(EntityType_LoadHelperStruct &helper, const int64_t i
long samplerIndex = uboIndex + 1;
writeDescriptorSets[uboIndex].pBufferInfo = &vkDescriptorBufferInfo[i];
- writeDescriptorSets[uboIndex].dstSet = etdHelper.grBinds->vkDescriptorSets[i];
+ writeDescriptorSets[uboIndex].dstSet = etdHelper.etd->grBinds->vkDescriptorSets[i];
writeDescriptorSets[samplerIndex].pImageInfo = &textureDescriptorInfo;
- writeDescriptorSets[samplerIndex].dstSet = etdHelper.grBinds->vkDescriptorSets[i];
+ writeDescriptorSets[samplerIndex].dstSet = etdHelper.etd->grBinds->vkDescriptorSets[i];
}
vkUpdateDescriptorSets(vkDevice, 2 * MAX_FRAMES_IN_FLIGHT, writeDescriptorSets, 0, nullptr);
@@ -656,15 +704,15 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
const auto &accVert = helper.gltfData->accessors[accessorIndexVertex];
uint32_t offsetVert = runningOffset;
uint32_t sizeVert = accVert.buffer_view->size;
- etdHelper.grBinds->vertexFirstBinding = index;
- etdHelper.grBinds->vertexBindingCount = 1;
+ etdHelper.etd->grBinds->vertexFirstBinding = index;
+ etdHelper.etd->grBinds->vertexBindingCount = 1;
alignmentPadding = sizeVert % helper.vertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.vertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeVert += alignmentPadding;
bufferCI.size = sizeVert;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->vertexBuffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->vertexBuffer, helper.et.deviceMemoryVert, offsetVert);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->vertexBuffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->vertexBuffer, helper.et.deviceMemoryVert, offsetVert);
runningOffset += sizeVert;
index += 1;
@@ -672,14 +720,14 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
const auto &accNorm = helper.gltfData->accessors[accessorIndexNormal];
uint32_t offsetNorm = runningOffset;
uint32_t sizeNorm = accNorm.buffer_view->size;
- etdHelper.grBinds->normalsFirstBinding = index;
- etdHelper.grBinds->normalsBindingCount = 1;
+ etdHelper.etd->grBinds->normalsFirstBinding = index;
+ etdHelper.etd->grBinds->normalsBindingCount = 1;
alignmentPadding = sizeNorm % helper.vertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.vertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeNorm += alignmentPadding;
bufferCI.size = sizeNorm;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->normalsBuffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->normalsBuffer, helper.et.deviceMemoryVert, offsetNorm);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->normalsBuffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->normalsBuffer, helper.et.deviceMemoryVert, offsetNorm);
runningOffset += sizeNorm;
index += 1;
@@ -687,21 +735,21 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
const auto &accUV = helper.gltfData->accessors[accessorIndexUV];
uint32_t offsetUV = runningOffset;
uint32_t sizeUV = accUV.buffer_view->size;
- etdHelper.grBinds->uvFirstBinding = index;
- etdHelper.grBinds->uvBindingCount = 1;
+ etdHelper.etd->grBinds->uvFirstBinding = index;
+ etdHelper.etd->grBinds->uvBindingCount = 1;
alignmentPadding = sizeUV % helper.vertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.vertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeUV += alignmentPadding;
bufferCI.size = sizeUV;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->uvBuffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->uvBuffer , helper.et.deviceMemoryVert, offsetUV);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->uvBuffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->uvBuffer , helper.et.deviceMemoryVert, offsetUV);
runningOffset += sizeUV;
index += 1;
// 2023-09-27 - JCB
// I don't know where else to put this
- etdHelper.grBinds->instanceFirstBinding = index;
- etdHelper.grBinds->instanceBindingCount = 1;
+ etdHelper.etd->grBinds->instanceFirstBinding = index;
+ etdHelper.etd->grBinds->instanceBindingCount = 1;
// no index += 1 because index just happens to be the right value here for
// the binding index, whereas binding the IndexBuffer doesn't need a binding index.
@@ -709,15 +757,15 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
const auto &accIndex = helper.gltfData->accessors[accessorIndexIndex];
uint32_t offsetIndex = runningOffset;
uint32_t sizeIndex = accIndex.buffer_view->size;
- etdHelper.grBinds->indexBindingCount = 1;
- etdHelper.grBinds->indexCount = accIndex.count;
+ etdHelper.etd->grBinds->indexBindingCount = 1;
+ etdHelper.etd->grBinds->indexCount = accIndex.count;
alignmentPadding = sizeIndex % helper.vertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.vertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeIndex += alignmentPadding;
bufferCI.size = sizeIndex;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->indexBuffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->indexBuffer, helper.et.deviceMemoryVert, offsetIndex);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->indexBuffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->indexBuffer, helper.et.deviceMemoryVert, offsetIndex);
runningOffset += sizeIndex;
// index += 1;
@@ -764,22 +812,22 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
index = 0;
bufferCopys[index].srcOffset = offsetVert;
bufferCopys[index].size = sizeVert;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->vertexBuffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->vertexBuffer, 1, &bufferCopys[index]);
index+=1;
bufferCopys[index].srcOffset = offsetNorm;
bufferCopys[index].size = sizeNorm;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->normalsBuffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->normalsBuffer, 1, &bufferCopys[index]);
index+=1;
bufferCopys[index].srcOffset = offsetUV;
bufferCopys[index].size = sizeUV;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->uvBuffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->uvBuffer, 1, &bufferCopys[index]);
index+=1;
bufferCopys[index].srcOffset = offsetIndex;
bufferCopys[index].size = sizeIndex;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->indexBuffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->indexBuffer, 1, &bufferCopys[index]);
// index+=1;
vkEndCommandBuffer(transferCommandBuffer);
@@ -801,12 +849,12 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
}
// set up instance buffer
- etdHelper.grBinds->instanceBufferMaxCount = etdHelper.etd->startingInstanceCount;
- etdHelper.grBinds->instanceBufferMaxCount = etdHelper.grBinds->instanceBufferMaxCount < 1 ? 1 : etdHelper.grBinds->instanceBufferMaxCount;
- bufferCI.size = sizeof(glm::mat4) * etdHelper.grBinds->instanceBufferMaxCount;
+ etdHelper.etd->grBinds->instanceBufferMaxCount = etdHelper.etd->startingInstanceCount;
+ etdHelper.etd->grBinds->instanceBufferMaxCount = etdHelper.etd->grBinds->instanceBufferMaxCount < 1 ? 1 : etdHelper.etd->grBinds->instanceBufferMaxCount;
+ bufferCI.size = sizeof(glm::mat4) * etdHelper.etd->grBinds->instanceBufferMaxCount;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->instanceBuffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->instanceBuffer, helper.et.deviceMemoryInst, 0);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->instanceBuffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->instanceBuffer, helper.et.deviceMemoryInst, 0);
// bullet
@@ -818,60 +866,60 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
// vertex
offsetVert = runningOffset;
sizeVert = sizeof(glm::vec3) * etdHelper.physDbg.vertexes->Count();
- etdHelper.grBinds->physVertBD.firstBinding = index;
- etdHelper.grBinds->physVertBD.bindingCount = 1;
+ etdHelper.etd->grBinds->physVertBD.firstBinding = index;
+ etdHelper.etd->grBinds->physVertBD.bindingCount = 1;
alignmentPadding = sizeVert % helper.physVertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.physVertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeVert += alignmentPadding;
bufferCI.size = sizeVert;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->physVertBD.buffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->physVertBD.buffer, helper.et.deviceMemoryPhysVert, offsetVert);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->physVertBD.buffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->physVertBD.buffer, helper.et.deviceMemoryPhysVert, offsetVert);
runningOffset += sizeVert;
// norm
index = 1;
offsetNorm = runningOffset;
sizeNorm = sizeof(glm::vec3) * etdHelper.physDbg.normals->Count();
- etdHelper.grBinds->physNormBD.firstBinding = index;
- etdHelper.grBinds->physNormBD.bindingCount = 1;
+ etdHelper.etd->grBinds->physNormBD.firstBinding = index;
+ etdHelper.etd->grBinds->physNormBD.bindingCount = 1;
alignmentPadding = sizeNorm % helper.physVertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.physVertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeNorm += alignmentPadding;
bufferCI.size = sizeNorm;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->physNormBD.buffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->physNormBD.buffer, helper.et.deviceMemoryPhysVert, offsetNorm);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->physNormBD.buffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->physNormBD.buffer, helper.et.deviceMemoryPhysVert, offsetNorm);
runningOffset += sizeNorm;
// uv
index = 2;
offsetUV = runningOffset;
sizeUV = sizeof(glm::vec2) * etdHelper.physDbg.uv->Count();
- etdHelper.grBinds->physUvBD.firstBinding = index;
- etdHelper.grBinds->physUvBD.bindingCount = 1;
+ etdHelper.etd->grBinds->physUvBD.firstBinding = index;
+ etdHelper.etd->grBinds->physUvBD.bindingCount = 1;
alignmentPadding = sizeUV % helper.physVertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.physVertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeUV += alignmentPadding;
bufferCI.size = sizeUV;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->physUvBD.buffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->physUvBD.buffer, helper.et.deviceMemoryPhysVert, offsetUV);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->physUvBD.buffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->physUvBD.buffer, helper.et.deviceMemoryPhysVert, offsetUV);
runningOffset += sizeUV;
// index
index = 3;
offsetIndex = runningOffset;
sizeIndex = sizeof(uint16_t) * etdHelper.physDbg.indexes->Count();
- etdHelper.grBinds->physIndxBD.firstBinding = index;
- etdHelper.grBinds->physIndxBD.bindingCount = 1;
+ etdHelper.etd->grBinds->physIndxBD.firstBinding = index;
+ etdHelper.etd->grBinds->physIndxBD.bindingCount = 1;
alignmentPadding = sizeIndex % helper.physVertMemoryRequirementsCombined.alignment;
alignmentPadding = alignmentPadding == 0 ? 0 : helper.physVertMemoryRequirementsCombined.alignment - alignmentPadding;
sizeIndex += alignmentPadding;
bufferCI.size = sizeIndex;
bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.grBinds->physIndxBD.buffer);
- vkBindBufferMemory(vkDevice, etdHelper.grBinds->physIndxBD.buffer, helper.et.deviceMemoryPhysVert, offsetIndex);
+ vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &etdHelper.etd->grBinds->physIndxBD.buffer);
+ vkBindBufferMemory(vkDevice, etdHelper.etd->grBinds->physIndxBD.buffer, helper.et.deviceMemoryPhysVert, offsetIndex);
runningOffset += sizeIndex;
assert(runningOffset == helper.physVertMemoryRequirementsCombined.size);
@@ -922,25 +970,25 @@ void EntityType_LoadMesh(EntityType_LoadHelperStruct &helper, const int64_t mesh
runningOffset = 0;
bufferCopys[index].srcOffset = runningOffset;
bufferCopys[index].size = sizeVert;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->physVertBD.buffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->physVertBD.buffer, 1, &bufferCopys[index]);
runningOffset += sizeVert;
index+=1;
bufferCopys[index].srcOffset = runningOffset;
bufferCopys[index].size = sizeNorm;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->physNormBD.buffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->physNormBD.buffer, 1, &bufferCopys[index]);
runningOffset += sizeNorm;
index+=1;
bufferCopys[index].srcOffset = runningOffset;
bufferCopys[index].size = sizeUV;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->physUvBD.buffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->physUvBD.buffer, 1, &bufferCopys[index]);
runningOffset += sizeUV;
index+=1;
bufferCopys[index].srcOffset = runningOffset;
bufferCopys[index].size = sizeIndex;
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.grBinds->physIndxBD.buffer, 1, &bufferCopys[index]);
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, etdHelper.etd->grBinds->physIndxBD.buffer, 1, &bufferCopys[index]);
// runningOffset += sizeIndex;
// index+=1;
@@ -1012,14 +1060,14 @@ void EntityType_Load(EntityType &et) {
EntityType_PreLoad(helper);
for (int64_t i = 0; i < et.detailsCount; ++i) {
- EntityTypeDetails_LoadHelperStruct &etd = (*helper.etdHelpers)[i];
+ EntityTypeDetails_LoadHelperStruct &etdHelper = (*helper.etdHelpers)[i];
/*
* 2023-09-13 - JCB
* I don't like that we're just copying this.
* This should be moved to window.cpp.
*/
- etd.grBinds->vkPipelineLayout = pkePipelines.vkPipelineLayout_Texture;
- etd.grBinds->graphicsPipeline = pkePipelines.pipelines.Texture;
+ etdHelper.etd->grBinds->vkPipelineLayout = pkePipelines.vkPipelineLayout_Texture;
+ etdHelper.etd->grBinds->graphicsPipeline = pkePipelines.pipelines.Texture;
// handle texture
EntityType_LoadTexture(helper, i);
@@ -1151,17 +1199,15 @@ void EntityType_Unload(EntityType &et, CompGrBinds *grBindsArr[1]) {
void EntityType_Tick(double delta) {
const auto count = EntitiesToBeRemoved.Count();
- int64_t detailIndex = -1;
for (long i = 0; i < count; ++i) {
- if (auto index = EntityType_FindByEntity(EntitiesToBeRemoved[i], detailIndex); index > -1) {
- auto &entType = GlobalEntityTypes[index];
- if (auto *grBinds = ECS_GetGrBinds(entType.details[detailIndex].grBindsHandle); grBinds != nullptr) {
- auto &td = EntityTypesToTeardown.Push();
- td.handle = EntitiesToBeRemoved[i]->handle;
- td.ticksToWait = 1;
- for (long k = 0; k < GlobalEntityTypes[index].detailsCount; ++k) {
- td.grBinds[k] = grBinds;
- }
+ auto *entTypePtr = EntityType_FindByEntityHandle(EntitiesToBeRemoved[i]->handle);
+ if (entTypePtr != nullptr) {
+ auto &entType = *entTypePtr;
+ auto &td = EntityTypesToTeardown.Push();
+ td.handle = EntitiesToBeRemoved[i]->handle;
+ td.ticksToWait = 1;
+ for (long k = 0; k < entType.detailsCount; ++k) {
+ td.grBinds[k] = entType.details[k].grBinds;
}
}
}
@@ -1170,21 +1216,22 @@ void EntityType_Tick(double delta) {
void EntityType_Tick_Late(double delta) {
while (EntitiesWithExcessInstances.Count() != 0) {
auto *entity = EntitiesWithExcessInstances.Pop();
- int64_t detailIndex = 0;
- auto index = EntityType_FindByEntity(entity, detailIndex);
- auto &et = GlobalEntityTypes[index];
- auto &etd = GlobalEntityTypes[index].details[detailIndex];
- auto *grBinds = ECS_GetGrBinds(etd.grBindsHandle);
- EntityType_RolloverInstances(et, *grBinds);
+ auto *etPtr = EntityType_FindByEntityHandle(entity->handle);
+ assert(etPtr != nullptr);
+ auto &et = *etPtr;
+ for (int64_t i = 0; i < et.detailsCount; ++i) {
+ auto &etd = et.details[i];
+ assert(etd.grBinds != nullptr);
+ EntityType_RolloverInstances(et, *etd.grBinds);
+ }
}
for (int64_t i = EntityTypesToTeardown.Count() - 1; i >= 0; --i) {
auto &td = EntityTypesToTeardown[i];
td.ticksToWait -= 1;
if (td.ticksToWait == 0) {
- int64_t detailIndex = -1;
- auto index = EntityType_FindByEntityHandle(td.handle, detailIndex);
- EntityType_Unload(GlobalEntityTypes[index], td.grBinds);
- GlobalEntityTypes.Remove(index);
+ auto *entityType = EntityType_FindByEntityHandle(td.handle);
+ assert(entityType != nullptr);
+ EntityType_Unload(*entityType, td.grBinds);
EntityTypesToTeardown.Remove(i);
}
}
@@ -1286,18 +1333,33 @@ void EntityType_RolloverInstances(EntityType &et, CompGrBinds &grBinds) {
vkFreeMemory(vkDevice, oldMemory, vkAllocator);
}
+PkeHandleBucketIndex_T EntityType_GetBucketCount() {
+ return EntityType_BC.pkeHandle.bucketIndex + 1;
+}
+
+EntityType *EntityType_GetEntityTypes(PkeHandleBucketIndex_T bucketIndex, PkeHandleItemIndex_T &itemCount) {
+ assert(bucketIndex <= EntityType_BC.pkeHandle.bucketIndex);
+ if (bucketIndex == EntityType_BC.pkeHandle.bucketIndex) itemCount = EntityType_BC.pkeHandle.itemIndex;
+ itemCount = EntityType_BC.limits.itemIndex;
+ return EntityType_BC.buckets[bucketIndex];
+}
+
void EntityType_Teardown() {
- for (int64_t i = GlobalEntityTypes.Count() - 1; i >= 0; --i) {
- if (GlobalEntityTypes[i].modelAssetKey[0] == '\0') continue;
- EntityType &et = GlobalEntityTypes[i];
- CompGrBinds *grBindsArr[1] = {nullptr};
-
- for (long k = 0; k < et.detailsCount; ++k) {
- const EntityTypeDetails &etd = et.details[k];
- grBindsArr[k] = ECS_GetGrBinds(etd.entityHandle);
+
+ for (PkeHandleBucketIndex_T b = 0; b <= EntityType_BC.pkeHandle.bucketIndex; ++b) {
+ auto &bkt = EntityType_BC.buckets[b];
+ long itemCount = EntityType_BC.pkeHandle.bucketIndex == b ? EntityType_BC.pkeHandle.itemIndex : EntityType_BC.limits.itemIndex;
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ auto &et = bkt[i];
+ if (et.modelAssetKey[0] == '\0') continue;
+ CompGrBinds *grBindsArr[EntityTypeDetails_MAX] = {nullptr};
+ for (long k = 0; k < et.detailsCount; ++k) {
+ const EntityTypeDetails &etd = et.details[k];
+ grBindsArr[k] = etd.grBinds;
+ }
+ EntityType_Unload(et, grBindsArr);
}
- EntityType_Unload(et, grBindsArr);
}
- GlobalEntityTypes.~DynArray();
+ Buckets_Destroy(EntityType_BC);
EntityTypesToTeardown.~DynArray();
}
diff --git a/src/entities.hpp b/src/entities.hpp
index cbb8e15..ce680e0 100644
--- a/src/entities.hpp
+++ b/src/entities.hpp
@@ -1,6 +1,7 @@
#ifndef PKE_ENTITIES_HPP
#define PKE_ENTITIES_HPP
+#include "memory-type-defs.hpp"
#include "vendor/cgltf-include.hpp"
#include "vendor/stb_image_include.hpp"
#include "ecs.hpp"
@@ -12,10 +13,10 @@
#include <BulletCollision/CollisionShapes/btCollisionShape.h>
#include <vulkan/vulkan_core.h>
+const size_t EntityTypeDetails_MAX = 1;
struct EntityTypeDetails {
AssetKey textureAssetKey;
- EntityHandle entityHandle = EntityHandle_MAX;
- GrBindsHandle grBindsHandle = GrBindsHandle_MAX;
+ CompGrBinds *grBinds = nullptr;
VkImage textureImage = VK_NULL_HANDLE;
VkImageView textureImageView = VK_NULL_HANDLE;
VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE;
@@ -27,26 +28,33 @@ struct EntityTypeDetails {
} bt;
uint32_t startingInstanceCount = 1024;
};
-struct EntityType {
+struct EntityType : public Entity_Base {
AssetKey modelAssetKey;
const char *entityTypeCode = nullptr;
- EntityHandle entityHandle = EntityHandle_MAX;
VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE;
VkDeviceMemory deviceMemoryInst = VK_NULL_HANDLE;
VkDeviceMemory deviceMemoryPhysVert = VK_NULL_HANDLE;
VkDeviceMemory deviceMemoryTexture = VK_NULL_HANDLE;
- int64_t detailsCount = 1;
- EntityTypeDetails details[1];
+ int64_t detailsCount = 0;
+ EntityTypeDetails details[EntityTypeDetails_MAX];
+ PkeCallback createInstanceCallback;
+ // PkeCallback serializeInstanceCallback; // TODO
+ // PkeCallback parseInstanceCallback; // TODO
};
-extern DynArray<EntityType> GlobalEntityTypes;
+struct EntityTypeHandle : PkeHandle {};
+constexpr EntityTypeHandle EntityTypeHandle_MAX = EntityTypeHandle{};
void EntityType_Init();
-int64_t EntityType_FindByTypeCode(const char *typeCode);
-int64_t EntityType_FindByEntityHandle(EntityHandle handle, int64_t &detailIndex);
+EntityType *EntityType_FindByTypeCode(const char *typeCode);
+EntityType *EntityType_FindByEntityHandle(EntityHandle handle);
+EntityType *EntityType_Create();
+Entity_Base *EntityType_CreateGenericInstance(EntityType *et, CompInstance *srcInstance = nullptr);
void EntityType_Load(EntityType &et);
void EntityType_Tick(double delta);
void EntityType_Tick_Late(double delta);
void EntityType_RolloverInstances(EntityType &et, CompGrBinds &grBinds);
+PkeHandleBucketIndex_T EntityType_GetBucketCount();
+EntityType *EntityType_GetEntityTypes(PkeHandleBucketIndex_T bucketIndex, PkeHandleItemIndex_T &itemCount);
void EntityType_Teardown();
#endif /* PKE_ENTITIES_HPP */
diff --git a/src/game.cpp b/src/game.cpp
index dc32b2a..97bc247 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -91,17 +91,7 @@ void SerializeCamera(std::ofstream &stream, const PkeCamera &cam) {
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", comp.entHandle.hash);
- EntityType *et = nullptr;
- // EntityTypeDetails *etd = nullptr;
- for (long i = 0; i < GlobalEntityTypes.Count(); ++i) {
- for (int64_t k = 0; k < GlobalEntityTypes[i].detailsCount; ++k) {
- if (GlobalEntityTypes[i].details[k].grBindsHandle == comp.grBindsHandle) {
- et = &GlobalEntityTypes[i];
- // etd = &GlobalEntityTypes[i].details[k];
- break;
- }
- }
- }
+ EntityType *et = EntityType_FindByEntityHandle(comp.entHandle);
assert(et != nullptr);
CompInstance c{};
InstPos baseInst{};
@@ -151,7 +141,7 @@ void SerializeInstance(std::ofstream &stream, const CompInstance &comp) {
}
}
-void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) {
+void ParseCamera(PkeLevel *level, std::ifstream &stream) {
PkeCamera cam{};
while (stream.getline(readLine, readLineLength)) {
if (strcmp(readLine, PKE_FILE_OBJ_END) == 0) {
@@ -162,9 +152,7 @@ void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) {
rCam.type = cam.type;
rCam.orientation = cam.orientation;
rCam.isPrimary = cam.isPrimary;
- if (levelHandle != LevelHandle_MAX) {
- PkeLevel_RegisterCamera(levelHandle, rCam.handle);
- }
+ PkeLevel_RegisterCamera(level->levelHandle, rCam.handle);
if (rCam.isPrimary == true) {
ActiveCamera = &rCam;
}
@@ -239,7 +227,7 @@ void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) {
}
}
-void ParseInstance(EntityHandle parentEntHandle, std::ifstream &stream) {
+void ParseInstance(Entity_Base *parentEntity, std::ifstream &stream) {
CompInstance comp{};
InstPos instPos{};
instPos.posRot = btTransform{};
@@ -252,39 +240,20 @@ void ParseInstance(EntityHandle parentEntHandle, std::ifstream &stream) {
while (stream.getline(readLine, readLineLength)) {
if (strstr(PKE_FILE_OBJ_END, readLine)) {
if (entTypeCode[0] == '\0') {
- printf("[Game::ParseInstance] Failed to create instance from save file. No EntTypeCode present.\n");
+ fprintf(stdout, "[Game::ParseInstance] Failed to create instance from save file. No EntTypeCode present.\n");
break;
}
- int64_t existingEntityTypeIndex = EntityType_FindByTypeCode(entTypeCode);
- if (existingEntityTypeIndex == -1) {
- printf("[Game::ParseInstance] Failed to create instance from save file. Unknown EntityTypeCode: \"%s\"\n", entTypeCode);
+ auto *etPtr = EntityType_FindByTypeCode(entTypeCode);
+ if (etPtr == nullptr) {
+ fprintf(stdout, "[Game::ParseInstance] Failed to create instance from save file. Unknown EntityTypeCode: \"%s\"\n", entTypeCode);
break;
}
- const auto &et = GlobalEntityTypes[existingEntityTypeIndex];
- for (int64_t i = 0; i < et.detailsCount; ++i) {
- auto &etd = et.details[i];
- auto entHandle = ECS_CreateEntity(parentEntHandle);
- auto &compInst = ECS_CreateInstance(entHandle, etd.entityHandle);
-
- strncpy(compInst.collisionCallback.name, comp.collisionCallback.name, 16);
- PkePlugin_SetSignatureFunc(&compInst.collisionCallback);
-
- compInst.physicsLayer = comp.physicsLayer;
- compInst.physicsMask = comp.physicsMask;
- btVector3 localInertia(0, 0, 0);
- etd.bt.shape->calculateLocalInertia(instPos.mass, localInertia);
- compInst.bt.motionState = Pke_New<btDefaultMotionState>(MemBkt_Bullet);
- new (compInst.bt.motionState) btDefaultMotionState(instPos.posRot);
- compInst.bt.rigidBody = Pke_New<btRigidBody>(MemBkt_Bullet);
- new (compInst.bt.rigidBody) btRigidBody(instPos.mass, compInst.bt.motionState, etd.bt.shape, localInertia);
- compInst.bt.rigidBody->setLinearVelocity(btVector3(0,0,0));
- compInst.bt.rigidBody->setAngularVelocity(btVector3(0,0,0));
- compInst.bt.rigidBody->getCollisionShape()->setLocalScaling(instPos.scale);
- BtDynamicsWorld->addRigidBody(compInst.bt.rigidBody);
- auto *broadphaseProxy = compInst.bt.rigidBody->getBroadphaseProxy();
- broadphaseProxy->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(comp.physicsLayer);
- broadphaseProxy->m_collisionFilterMask = static_cast<PhysicsCollision_T>(comp.physicsMask);
- compInst.bt.rigidBody->setUserPointer(reinterpret_cast<void *>(compInst.entHandle.hash));
+
+ if (etPtr->createInstanceCallback.func != nullptr) {
+ reinterpret_cast<void(*)()>(etPtr->createInstanceCallback.func)();
+ } else {
+ EntityType_CreateGenericInstance(etPtr, &comp);
+ fprintf(stdout ,"[Game::ParseInstance] No callback func to create instance.");
}
break;
}
@@ -421,26 +390,22 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
f.close();
}
-void Game_LoadSceneFile(LevelHandle levelHandle, const char *sceneFilePath) {
+void Game_LoadSceneFile(PkeLevel *level, const char *sceneFilePath) {
std::ifstream f(sceneFilePath);
if (!f.is_open()) {
fprintf(stderr, "Failed to load requested scene file: %s\n", sceneFilePath);
return;
}
memset(readLine, '\0', readLineLength);
- EntityHandle parentEntHandle = EntityHandle_MAX;
- if (levelHandle != LevelHandle_MAX) {
- parentEntHandle = ECS_CreateEntity();
- PkeLevel_RegisterWrappingEntity(levelHandle, parentEntHandle);
- }
+ ECS_CreateEntity(level);
while (f.getline(readLine, readLineLength)) {
if (strcmp(PKE_FILE_OBJ_CAMERA, readLine) == 0) {
- ParseCamera(levelHandle, f);
+ ParseCamera(level, f);
continue;
}
if (strcmp(PKE_FILE_OBJ_INSTANCE, readLine) == 0) {
- ParseInstance(parentEntHandle, f);
+ ParseInstance(level, f);
continue;
}
}
@@ -498,7 +463,7 @@ void Game_Tick(double delta) {
}
if (pkeSettings.rt.nextLevel != LevelHandle_MAX) {
// TODO async this
- Game_LoadSceneFile(pkeSettings.rt.nextLevel, pkeSettings.rt.sceneName);
+ Game_LoadSceneFile(PkeLevel_Get(pkeSettings.rt.nextLevel), pkeSettings.rt.sceneName);
pkeSettings.rt.activeLevel = pkeSettings.rt.nextLevel;
pkeSettings.rt.nextLevel = LevelHandle_MAX;
}
@@ -537,10 +502,10 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
Physics_Init();
Game_Init();
ECS_Init();
+ EntityType_Init();
PkeProject_Load(pkeSettings.args.projectPath);
CreateWindow(windowProps);
PkeInput_Init();
- EntityType_Init();
if (pkeSettings.args.pluginPath != nullptr) {
PkePlugin_Load(pkeSettings.args.pluginPath);
}
diff --git a/src/game.hpp b/src/game.hpp
index 3912f0a..b575376 100644
--- a/src/game.hpp
+++ b/src/game.hpp
@@ -11,6 +11,6 @@ void Game_Tick(double delta);
void Game_Teardown();
void Game_RecordImGui();
void Game_SaveSceneFile(const char *);
-void Game_LoadSceneFile(LevelHandle levelHandle, const char *);
+void Game_LoadSceneFile(PkeLevel *level, const char *);
#endif /* PKE_GAME_HPP */
diff --git a/src/level-types.hpp b/src/level-types.hpp
index 64eef32..0809572 100644
--- a/src/level-types.hpp
+++ b/src/level-types.hpp
@@ -9,14 +9,12 @@
TypeSafeInt_Const_Expr(LevelHandle, uint16_t, 0xFFFF);
-struct LvlEntHandleArr : public PkeArray<EntityHandle> { };
struct LvlCamArr : public PkeArray<CameraHandle> { };
-struct PkeLevel {
+struct PkeLevel : public Entity_Base {
MemBucket *bkt = nullptr;
char name[16] = {};
- LevelHandle handle = LevelHandle_MAX;
- LvlEntHandleArr wrappingEntities;
+ LevelHandle levelHandle = LevelHandle_MAX;
LvlCamArr cameras;
};
diff --git a/src/level.cpp b/src/level.cpp
index 123d5e2..d4e4075 100644
--- a/src/level.cpp
+++ b/src/level.cpp
@@ -11,7 +11,7 @@ PkeLevel LEVELS[MAX_LEVEL_COUNT];
PkeLevel *PkeLevel_Get_Inner(LevelHandle handle) {
for (long i = 0; i < MAX_LEVEL_COUNT; ++i) {
- if (LEVELS[i].handle == handle) {
+ if (LEVELS[i].levelHandle == handle) {
return &LEVELS[i];
}
}
@@ -28,13 +28,13 @@ LevelHandle PkeLevel_Create(const char *levelName) {
if (lvl->bkt == nullptr) {
lvl->bkt = Pke_BeginTransientBucket();
}
- lvl->handle = nextHandle;
+ lvl->levelHandle = nextHandle;
++nextHandle;
auto len = strlen(levelName);
auto start = len <= (LEVEL_NAME_LENGTH - 1) ? 0 : len - (LEVEL_NAME_LENGTH - 1);
strncpy(lvl->name, levelName + start, LEVEL_NAME_LENGTH);
- return lvl->handle;
+ return lvl->levelHandle;
}
PkeLevel *PkeLevel_Get(LevelHandle handle) {
@@ -47,23 +47,15 @@ LevelHandle PkeLevel_GetHandle(const char *levelName) {
auto start = len <= (LEVEL_NAME_LENGTH - 1) ? 0 : len - (LEVEL_NAME_LENGTH - 1);
strncpy(safeName, levelName + start, LEVEL_NAME_LENGTH);
for (long i = 0; i < MAX_LEVEL_COUNT; ++i) {
- if (LEVELS[i].handle != LevelHandle_MAX) {
+ if (LEVELS[i].levelHandle != LevelHandle_MAX) {
if (strcmp(safeName, LEVELS[i].name)) {
- return LEVELS[i].handle;
+ return LEVELS[i].levelHandle;
}
}
}
return LevelHandle_MAX;
}
-void PkeLevel_RegisterWrappingEntity(LevelHandle levelHandle, EntityHandle entityHandle) {
- assert(levelHandle != LevelHandle_MAX);
- assert(entityHandle != EntityHandle_MAX);
- PkeLevel *lvl = PkeLevel_Get_Inner(levelHandle);
- assert(lvl != nullptr && "Failed to find level by requested LevelHandle");
- PkeArray_Add(&lvl->wrappingEntities, entityHandle, lvl->bkt);
-}
-
void PkeLevel_RegisterCamera(LevelHandle levelHandle, CameraHandle cameraHandle) {
assert(levelHandle != LevelHandle_MAX);
assert(cameraHandle != CameraHandle_MAX);
@@ -76,17 +68,11 @@ void PkeLevel_Remove(LevelHandle handle) {
PkeLevel *lvl = PkeLevel_Get_Inner(handle);
assert(lvl != nullptr && "Failed to find level to remove by requested LevelHandle");
levelCount -= 1;
- for (long i = 0; i < lvl->wrappingEntities.next; ++i) {
- ECS_MarkForRemoval(lvl->wrappingEntities.data[i]);
- }
+ ECS_MarkForRemoval(lvl);
for (long i = 0; i < lvl->cameras.next; ++i) {
PkeCamera_Destroy(lvl->cameras.data[i]);
}
- PkeArray_HardReset<EntityHandle>(&lvl->wrappingEntities);
PkeArray_HardReset<CameraHandle>(&lvl->cameras);
Pke_ResetBucket(lvl->bkt);
- lvl->handle = LevelHandle_MAX;
- lvl->wrappingEntities.next = 0;
- lvl->wrappingEntities.reserved = 0;
- lvl->wrappingEntities.data = CAFE_BABE(EntityHandle);
+ lvl->levelHandle = LevelHandle_MAX;
}
diff --git a/src/level.hpp b/src/level.hpp
index 793d2b9..ae454a5 100644
--- a/src/level.hpp
+++ b/src/level.hpp
@@ -9,7 +9,6 @@ extern PkeLevel LEVELS[];
LevelHandle PkeLevel_Create(const char *levelName);
PkeLevel *PkeLevel_Get(LevelHandle handle);
LevelHandle PkeLevel_GetHandle(const char *levelName);
-void PkeLevel_RegisterWrappingEntity(LevelHandle levelHandle, EntityHandle entHandle);
void PkeLevel_RegisterCamera(LevelHandle levelHandle, CameraHandle cameraHandle);
void PkeLevel_Remove(LevelHandle handle);
diff --git a/src/physics.cpp b/src/physics.cpp
index 4825955..88c8139 100644
--- a/src/physics.cpp
+++ b/src/physics.cpp
@@ -28,7 +28,7 @@ btBroadphaseInterface *btBroadphase = nullptr;
btConstraintSolver *btSolver = nullptr;
struct EntityCollision {
- EntityHandle a, b;
+ CompInstance *a, *b;
};
PkeArray<EntityCollision> collisionsThisTick{};
@@ -80,11 +80,9 @@ struct CollisionHandlerStruct : public btOverlapFilterCallback {
const auto *col0 = static_cast<btCollisionObject *>(proxy0->m_clientObject);
const auto *col1 = static_cast<btCollisionObject *>(proxy1->m_clientObject);
if (col0 && col1) {
- EntityHandle ent0{};
- ent0.hash = reinterpret_cast<uint64_t>(col0->getUserPointer());
- EntityHandle ent1{};
- ent1.hash = reinterpret_cast<uint64_t>(col1->getUserPointer());
- if (ent0 != EntityHandle_MAX && ent1 != EntityHandle_MAX) {
+ CompInstance *ent0 = reinterpret_cast<CompInstance *>(col0->getUserPointer());
+ CompInstance *ent1 = reinterpret_cast<CompInstance *>(col1->getUserPointer());
+ if (ent0 != nullptr && ent1 != nullptr) {
PkeArray_Add<EntityCollision>(&collisionsThisTick, {
.a = ent0,
.b = ent1,
diff --git a/src/project.cpp b/src/project.cpp
index 4abe7ab..0f08859 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -27,6 +27,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_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: {";
const char* const PKE_PROJ_FILE_ENTITY_TYPE_DETAILS_END = "EntityHandleDetails: }";
@@ -65,19 +66,21 @@ void Proj_SerializeEntityType(std::ofstream &stream, const EntityType &et) {
NULL_CHAR_ARR(handleStr, 19);
NULL_CHAR_ARR(modelAssetKey, AssetKeyLength + 1);
NULL_CHAR_ARR(textureAssetKey, AssetKeyLength + 1);
- snprintf(handleStr, 19, "0x%016lX", et.entityHandle.hash);
+ snprintf(handleStr, 19, "0x%016lX", et.handle.hash);
snprintf(modelAssetKey, AssetKeyLength + 1, "%s", et.modelAssetKey);
EntityType e{};
if (modelAssetKey[0] != '\0')
stream << PKE_PROJ_FILE_ENTITY_TYPE_MODEL_ASSET_KEY << modelAssetKey << 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)
+ if (et.handle != e.handle)
stream << PKE_PROJ_FILE_ENTITY_TYPE_ENTITY_HANDLE << handleStr << std::endl;
+ if (et.createInstanceCallback.name[0] != '\0') {
+ stream << PKE_PROJ_FILE_ENTITY_TYPE_CREATE_INSTANCE_CALLBACK_SIGNATURE << et.createInstanceCallback.name << std::endl;
+ }
for (size_t i = 0; i < et.detailsCount; ++i) {
const EntityTypeDetails &etd = et.details[i];
snprintf(textureAssetKey, AssetKeyLength + 1, "%s", etd.textureAssetKey);
- CompGrBinds *grBinds = ECS_GetGrBinds(etd.entityHandle);
stream << PKE_PROJ_FILE_ENTITY_TYPE_DETAILS_BEGIN << std::endl;
if (textureAssetKey[0] != '\0')
@@ -90,9 +93,9 @@ void Proj_SerializeEntityType(std::ofstream &stream, const EntityType &et) {
stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_LAYER << static_cast<PhysicsCollision_T>(etd.bt.startingCollisionLayer) << std::endl;
if (etd.bt.startingCollisionMask != e.details[0].bt.startingCollisionMask)
stream << PKE_PROJ_FILE_ENTITY_TYPE_PHYSICS_STARTING_COLLISION_MASK << static_cast<PhysicsCollision_T>(etd.bt.startingCollisionMask) << 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 (etd.grBinds) {
+ if (etd.grBinds->collisionCallback.name[0] != '\0') {
+ stream << PKE_PROJ_FILE_ENTITY_TYPE_COLLISION_CALLBACK_SIGNATURE << etd.grBinds->collisionCallback.name << std::endl;
}
}
stream << PKE_PROJ_FILE_ENTITY_TYPE_DETAILS_END << std::endl;
@@ -155,21 +158,40 @@ void Proj_ParseProjectSettings(std::ifstream &stream) {
void Proj_ParseEntityType(std::ifstream &stream) {
char collisionSig[CallbackSignatureLength + 1];
collisionSig[0] = '\0';
+ char createInstanceSig[CallbackSignatureLength + 1];
+ createInstanceSig[0] = '\0';
EntityType et{};
- uint8_t detailCount = 0;
+ int64_t detailCount = 0;
while (stream.getline(projReadLine, projReadLineLength)) {
if (strcmp(PKE_PROJ_FILE_OBJ_END, projReadLine) == 0) {
- int64_t existingEntityTypeIndex = EntityType_FindByTypeCode(et.entityTypeCode);
- if (existingEntityTypeIndex != -1) {
+ EntityType *existingPtr = EntityType_FindByTypeCode(et.entityTypeCode);
+ if (existingPtr != nullptr) {
+ // TODO leaks et.EntityTypeCode
continue;
}
- et.entityHandle = ECS_CreateEntity();
- GlobalEntityTypes.Push(et);
- CompGrBinds *grBinds = ECS_GetGrBinds(et.entityHandle);
- if (grBinds) {
- strncpy(grBinds->collisionCallback.name, collisionSig, CallbackSignatureLength);
- PkePlugin_SetSignatureFunc(&grBinds->collisionCallback);
+ EntityType *etPtr = EntityType_Create();
+ strncpy(etPtr->modelAssetKey, et.modelAssetKey, AssetKeyLength);
+ etPtr->entityTypeCode = et.entityTypeCode;
+ if (createInstanceSig[0] == '\0') {
+ strncpy(etPtr->createInstanceCallback.name, createInstanceSig, CallbackSignatureLength);
+ PkePlugin_SetSignatureFunc(&etPtr->createInstanceCallback);
+ } else {
+ etPtr->createInstanceCallback.name[0] = 'd';
+ etPtr->createInstanceCallback.func = reinterpret_cast<void *>(EntityType_CreateGenericInstance);
+ }
+
+ for (int64_t i = 0; i < detailCount; ++i) {
+ etPtr->details[i] = et.details[i];
+ strncpy(etPtr->details[i].textureAssetKey, et.details[i].textureAssetKey, AssetKeyLength);
}
+
+ EntityType_Load(*etPtr);
+
+ for (int64_t i = 0; i < detailCount; ++i) {
+ strncpy(etPtr->details[i].grBinds->collisionCallback.name, collisionSig, CallbackSignatureLength);
+ PkePlugin_SetSignatureFunc(&etPtr->details[i].grBinds->collisionCallback);
+ }
+
return;
}
if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_MODEL_ASSET_KEY)) {
@@ -188,10 +210,15 @@ void Proj_ParseEntityType(std::ifstream &stream) {
}
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);
+ STR2NUM_ERROR result = str2num(et.handle.hash, projReadLine + prefixLen);
assert(result == STR2NUM_ERROR::SUCCESS);
continue;
}
+ if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_CREATE_INSTANCE_CALLBACK_SIGNATURE)) {
+ uint64_t prefixLen = strlen(PKE_PROJ_FILE_ENTITY_TYPE_CREATE_INSTANCE_CALLBACK_SIGNATURE);
+ strncpy(createInstanceSig, projReadLine + prefixLen, CallbackSignatureLength + 1);
+ continue;
+ }
if (strstr(projReadLine, PKE_PROJ_FILE_ENTITY_TYPE_DETAILS_BEGIN)) {
EntityTypeDetails &etd = et.details[detailCount];
while (stream.getline(projReadLine, projReadLineLength)) {
@@ -343,12 +370,18 @@ void PkeProject_Save(const char *filePath) {
}
}
- 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);
- Proj_SerializeEntityType(f, et);
- f << PKE_PROJ_FILE_OBJ_END << std::endl;
+ const auto entBucketCount = EntityType_GetBucketCount();
+ for (PkeHandleBucketIndex_T b = 0; b < entBucketCount; ++b) {
+ PkeHandleItemIndex_T itemCount = 0;
+ auto *entities = EntityType_GetEntityTypes(b, itemCount);
+ for (PkeHandleItemIndex_T i = 0; i < itemCount; ++i) {
+ if (entities[i].modelAssetKey[0] == '\0') {
+ continue;
+ }
+ f << PKE_PROJ_FILE_OBJ_ENTITY_TYPE << std::endl;
+ Proj_SerializeEntityType(f, entities[i]);
+ f << PKE_PROJ_FILE_OBJ_END << std::endl;
+ }
}
f << PKE_PROJ_FILE_END << std::endl;