summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-12-13 15:53:52 -0500
committerJonathan Bradley <jcb@pikum.xyz>2023-12-23 11:41:03 -0500
commit064e9ba16e390b13566d0007ef367dcb1adacc8d (patch)
tree359be3c8de88da8544646bfc9a84a8c8b3f383cd
parenta527dd1b773f14df140d3ac6a167339d7dc39e33 (diff)
checkpoint - add PkeLevel - editor removes on scene load
-rw-r--r--CMakeLists.txt4
-rw-r--r--editor/editor.cpp57
-rw-r--r--src/game.cpp22
-rw-r--r--src/game.hpp3
-rw-r--r--src/level-types.cpp3
-rw-r--r--src/level-types.hpp23
-rw-r--r--src/level.cpp91
-rw-r--r--src/level.hpp16
8 files changed, 204 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4317ba..bd5b237 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,10 @@ set(PKE_SOURCE_FILES
src/game-type-defs.hpp
src/helpers.hpp
src/helpers.cpp
+ src/level-types.hpp
+ src/level-types.cpp
+ src/level.hpp
+ src/level.cpp
src/math-helpers.hpp
src/math-helpers.cpp
src/memory-type-defs.hpp
diff --git a/editor/editor.cpp b/editor/editor.cpp
index c4a2a20..2f3a7d4 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -1,20 +1,21 @@
#include "editor.hpp"
-#include "ecs.hpp"
-#include "project.hpp"
-#include "thread_pool.hpp"
-#include "game.hpp"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-#include "math-helpers.hpp"
#include "camera.hpp"
+#include "ecs.hpp"
#include "entities.hpp"
#include "game-settings.hpp"
+#include "game.hpp"
+#include "imgui.h"
+#include "level.hpp"
+#include "math-helpers.hpp"
#include "player-input.hpp"
-#include "window.hpp"
+#include "project.hpp"
+#include "thread_pool.hpp"
#include "vendor/glm_include.hpp"
#include "vendor/tinyfiledialogs//tinyfiledialogs.h"
-#include "imgui.h"
+#include "window.hpp"
#include <GLFW/glfw3.h>
#include <compare>
@@ -77,6 +78,7 @@ bool shouldSaveScene = false;
bool shouldSaveProjectFile = false;
bool shouldRunCurrentScene = false;
bool subProgramRunning = false;
+LevelHandle levelHandle = LevelHandle_MAX;
glm::vec3 unproject(glm::vec3 windowCoords) {
double xDevNorm = (2.0f * windowCoords.x) / Extent.width - 1.0f;
@@ -138,7 +140,12 @@ void PkeEditor_Tick(double delta) {
}
if (shouldLoadScene && sceneName) {
shouldLoadScene = false;
- Game_LoadSceneFile(sceneName);
+ if (levelHandle != LevelHandle_MAX) {
+ PkeLevel_Remove(levelHandle);
+ ActiveCamera = &NullCamera;
+ }
+ levelHandle = PkeLevel_Create("editorLevel");
+ Game_LoadSceneFile(levelHandle, sceneName);
}
if (shouldOpenSaveSceneDialog) {
@@ -713,6 +720,39 @@ void RecordImGuiModalCreateEntityType() {
}
}
+void RecordImGuiLevels() {
+ if (!ImGui::Begin("Levels")) {
+ ImGui::End();
+ return;
+ }
+ static ImGuiTableFlags tableFlags{
+ ImGuiTableFlags_Borders |
+ ImGuiTableFlags_RowBg
+ };
+ if (ImGui::BeginTable("PkeLevels", 5, 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)
+ continue;
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ ImGui::Text("%s", LEVELS[i].name);
+ ImGui::TableSetColumnIndex(1);
+ ImGui::Text("0x%04hx", LEVELS[i].handle);
+ ImGui::TableSetColumnIndex(2);
+ ImGui::Text("%u", LEVELS[i].wrappingEntities.next - 1);
+ ImGui::TableSetColumnIndex(3);
+ ImGui::Text("%u", LEVELS[i].cameras.next - 1);
+ }
+ ImGui::EndTable();
+ }
+ ImGui::End();
+}
+
void RecordImGui_CompGrBinds(bool readonly, CompGrBinds *component) {
if (component == nullptr) return;
int inputTextFlags = 0;
@@ -961,6 +1001,7 @@ void PkeEditor_RecordImGui() {
RecordImGuiSceneEditor();
RecordImGuiUBO();
RecordImGuiCameras();
+ RecordImGuiLevels();
Game_RecordImGui();
}
}
diff --git a/src/game.cpp b/src/game.cpp
index bf30cfe..4dde008 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -8,6 +8,8 @@
#include "game-settings.hpp"
#include "helpers.hpp"
#include "imgui.h"
+#include "level-types.hpp"
+#include "level.hpp"
#include "math-helpers.hpp"
#include "physics.hpp"
#include "player-input.hpp"
@@ -137,7 +139,7 @@ void SerializeInstance(std::ofstream &stream, const CompInstance &comp) {
}
}
-void ParseCamera(std::ifstream &stream) {
+void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) {
PkeCamera cam{};
while (stream.getline(readLine, readLineLength)) {
if (strcmp(readLine, PKE_FILE_OBJ_END) == 0) {
@@ -147,6 +149,9 @@ void ParseCamera(std::ifstream &stream) {
rCam.target = cam.target;
rCam.type = cam.type;
rCam.orientation = cam.orientation;
+ if (levelHandle != LevelHandle_MAX) {
+ PkeLevel_RegisterCamera(levelHandle, rCam.handle);
+ }
return;
}
if (strncmp(readLine, PKE_FILE_CAMERA_POS, strlen(PKE_FILE_CAMERA_POS)) == 0) {
@@ -210,7 +215,7 @@ void ParseCamera(std::ifstream &stream) {
}
}
-void ParseInstance(std::ifstream &stream) {
+void ParseInstance(EntityHandle parentEntHandle, std::ifstream &stream) {
CompInstance comp{};
InstPos instPos{};
instPos.posRot = btTransform{};
@@ -231,7 +236,7 @@ void ParseInstance(std::ifstream &stream) {
break;
}
const auto &et = GlobalEntityTypes[existingEntityTypeIndex];
- auto entityHandle = ECS_CreateEntity();
+ auto entityHandle = ECS_CreateEntity(parentEntHandle);
auto &compInst = ECS_CreateInstance(entityHandle, et.entityHandle);
compInst.physicsLayer = comp.physicsLayer;
@@ -380,21 +385,26 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
f.close();
}
-void Game_LoadSceneFile(const char *sceneFilePath) {
+void Game_LoadSceneFile(LevelHandle levelHandle, 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);
+ }
while (f.getline(readLine, readLineLength)) {
if (strcmp(PKE_FILE_OBJ_CAMERA, readLine) == 0) {
- ParseCamera(f);
+ ParseCamera(levelHandle, f);
continue;
}
if (strcmp(PKE_FILE_OBJ_INSTANCE, readLine) == 0) {
- ParseInstance(f);
+ ParseInstance(parentEntHandle, f);
continue;
}
}
diff --git a/src/game.hpp b/src/game.hpp
index e85e8ce..3912f0a 100644
--- a/src/game.hpp
+++ b/src/game.hpp
@@ -2,6 +2,7 @@
#define PKE_GAME_HPP
#include "game-settings.hpp"
+#include "level-types.hpp"
#include "window-types.hpp"
void Game_Main(PKEWindowProperties windowProps, const char *executablePath);
@@ -10,6 +11,6 @@ void Game_Tick(double delta);
void Game_Teardown();
void Game_RecordImGui();
void Game_SaveSceneFile(const char *);
-void Game_LoadSceneFile(const char *);
+void Game_LoadSceneFile(LevelHandle levelHandle, const char *);
#endif /* PKE_GAME_HPP */
diff --git a/src/level-types.cpp b/src/level-types.cpp
new file mode 100644
index 0000000..9a77553
--- /dev/null
+++ b/src/level-types.cpp
@@ -0,0 +1,3 @@
+
+#include "level-types.hpp"
+
diff --git a/src/level-types.hpp b/src/level-types.hpp
new file mode 100644
index 0000000..64eef32
--- /dev/null
+++ b/src/level-types.hpp
@@ -0,0 +1,23 @@
+#ifndef PKE_LEVEL_TYPES_HPP
+#define PKE_LEVEL_TYPES_HPP
+
+#include "array.hpp"
+#include "macros.hpp"
+#include "memory-type-defs.hpp"
+#include "camera.hpp"
+#include "components.hpp"
+
+TypeSafeInt_Const_Expr(LevelHandle, uint16_t, 0xFFFF);
+
+struct LvlEntHandleArr : public PkeArray<EntityHandle> { };
+struct LvlCamArr : public PkeArray<CameraHandle> { };
+
+struct PkeLevel {
+ MemBucket *bkt = nullptr;
+ char name[16] = {};
+ LevelHandle handle = LevelHandle_MAX;
+ LvlEntHandleArr wrappingEntities;
+ LvlCamArr cameras;
+};
+
+#endif /* PKE_LEVEL_TYPES_HPP */
diff --git a/src/level.cpp b/src/level.cpp
new file mode 100644
index 0000000..fcca5bd
--- /dev/null
+++ b/src/level.cpp
@@ -0,0 +1,91 @@
+
+#include "level.hpp"
+
+#include "camera.hpp"
+#include "ecs.hpp"
+
+LevelHandle nextHandle = LevelHandle{0};
+long levelCount = 0;
+constexpr long LEVEL_NAME_LENGTH = 16;
+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) {
+ return &LEVELS[i];
+ }
+ }
+ return nullptr;
+}
+
+LevelHandle PkeLevel_Create(const char *levelName) {
+ assert(levelCount < MAX_LEVEL_COUNT && "only MAX_LEVEL_COUNT levels can be loaded at once");
+ levelCount += 1;
+
+ PkeLevel *lvl = PkeLevel_Get_Inner(LevelHandle_MAX);
+ assert(lvl != nullptr && "max level count not reached, but failed to find a valid level slot");
+
+ lvl->bkt = Pke_BeginTransientBucket();
+ lvl->handle = 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;
+}
+
+PkeLevel *PkeLevel_Get(LevelHandle handle) {
+ return PkeLevel_Get_Inner(handle);
+}
+
+LevelHandle PkeLevel_GetHandle(const char *levelName) {
+ char safeName[LEVEL_NAME_LENGTH];
+ auto len = strlen(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 (strcmp(safeName, LEVELS[i].name)) {
+ return LEVELS[i].handle;
+ }
+ }
+ }
+ 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);
+ PkeLevel *lvl = PkeLevel_Get_Inner(levelHandle);
+ assert(lvl != nullptr && "Failed to find level by requested LevelHandle");
+ PkeArray_Add(&lvl->cameras, cameraHandle, lvl->bkt);
+}
+
+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]);
+ }
+ 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_EndTransientBucket(lvl->bkt);
+ lvl->bkt = CAFE_BABE(MemBucket);
+ lvl->handle = LevelHandle_MAX;
+ lvl->wrappingEntities.next = 0;
+ lvl->wrappingEntities.reserved = 0;
+ lvl->wrappingEntities.data = CAFE_BABE(EntityHandle);
+}
diff --git a/src/level.hpp b/src/level.hpp
new file mode 100644
index 0000000..793d2b9
--- /dev/null
+++ b/src/level.hpp
@@ -0,0 +1,16 @@
+#ifndef PKE_LEVEL_HPP
+#define PKE_LEVEL_HPP
+
+#include "level-types.hpp"
+
+constexpr long MAX_LEVEL_COUNT = 16;
+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);
+
+#endif /* PKE_LEVEL_HPP */