diff options
| -rw-r--r-- | CMakeLists.txt | 4 | ||||
| -rw-r--r-- | editor/editor.cpp | 57 | ||||
| -rw-r--r-- | src/game.cpp | 22 | ||||
| -rw-r--r-- | src/game.hpp | 3 | ||||
| -rw-r--r-- | src/level-types.cpp | 3 | ||||
| -rw-r--r-- | src/level-types.hpp | 23 | ||||
| -rw-r--r-- | src/level.cpp | 91 | ||||
| -rw-r--r-- | src/level.hpp | 16 |
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 */ |
