diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2023-12-19 13:32:31 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2023-12-23 11:41:03 -0500 |
| commit | 04f5688a37030aa8598ded416f05d0cc979c37d6 (patch) | |
| tree | ce0bec713c49d6dda66a28f1246e1443d271b8f2 | |
| parent | c7c678651a30db30e449e965e6c82ad0dcb871e6 (diff) | |
loading scenes and projects can now be done via args
| -rw-r--r-- | editor/editor.cpp | 74 | ||||
| -rw-r--r-- | src/arg-handler.cpp | 16 | ||||
| -rw-r--r-- | src/camera.hpp | 1 | ||||
| -rw-r--r-- | src/game-settings.hpp | 24 | ||||
| -rw-r--r-- | src/game.cpp | 42 | ||||
| -rw-r--r-- | src/project.cpp | 2 | ||||
| -rw-r--r-- | src/project.hpp | 2 |
7 files changed, 109 insertions, 52 deletions
diff --git a/editor/editor.cpp b/editor/editor.cpp index 4170ac9..7bb972c 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -71,16 +71,12 @@ EntityType entityTypeToCreate{}; CameraHandle selectedCamera = CameraHandle_MAX; const char* const newSceneName = "newScene.pstf"; -const char *sceneName = nullptr; bool shouldOpenLoadSceneDialog = false; bool shouldOpenSaveSceneDialog = false; bool shouldOpenNewScene = false; -bool shouldLoadScene = false; -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; @@ -105,12 +101,11 @@ void PkeEditor_Tick(double delta) { PkeThreads_Enqueue(threadPoolHandle, std::packaged_task<void()>( [] { auto pid = fork(); if (pid == 0) { - char pluginOpt[128]; - pluginOpt[127] = '\n'; - sprintf(pluginOpt, "--plugin %s", pkeSettings.pluginPath == nullptr ? "example.o" : pkeSettings.pluginPath); int status = -1; const char *argv[] = { - pluginOpt, + "--plugin", pkeSettings.args.pluginPath == nullptr ? "example.o" : pkeSettings.args.pluginPath, + "--project", pkeSettings.args.projectPath == nullptr ? PKE_PROJ_DEFAULT_FILENAME : pkeSettings.args.projectPath, + "--scene", pkeSettings.rt.sceneName == nullptr ? PKE_PROJ_DEFAULT_FILENAME : pkeSettings.rt.sceneName, NULL, }; status = execvp("pke_runtime", const_cast<char **>(argv)); @@ -135,12 +130,12 @@ void PkeEditor_Tick(double delta) { } if (shouldOpenNewScene) { shouldOpenNewScene = false; - if (levelHandle != LevelHandle_MAX) { - PkeLevel_Remove(levelHandle); - ActiveCamera = &NullCamera; - } - levelHandle = PkeLevel_Create("editorLevel"); - sceneName = newSceneName; + // queues unloading + pkeSettings.rt.previousLevel = pkeSettings.rt.activeLevel; + // bypasses loading a level by setting a new active one + pkeSettings.rt.activeLevel = PkeLevel_Create("editorLevel"); + pkeSettings.rt.sceneName = newSceneName; + ActiveCamera = &NullCamera; } if (shouldSaveProjectFile) { shouldSaveProjectFile = false; @@ -152,35 +147,27 @@ void PkeEditor_Tick(double delta) { const char * patterns[1] = {"*.pstf"}; char *selectedScene = tinyfd_openFileDialog(nullptr, "cafebabe.pstf", 1, patterns, "Pke Scene Text File", 0); if (selectedScene != nullptr) { - sceneName = selectedScene; - shouldLoadScene = true; + pkeSettings.rt.sceneName = selectedScene; + pkeSettings.rt.shouldLoadScene = true; + ActiveCamera = &NullCamera; } })); } - if (shouldLoadScene && sceneName) { - shouldLoadScene = false; - if (levelHandle != LevelHandle_MAX) { - PkeLevel_Remove(levelHandle); - ActiveCamera = &NullCamera; - } - levelHandle = PkeLevel_Create("editorLevel"); - Game_LoadSceneFile(levelHandle, sceneName); - } if (shouldOpenSaveSceneDialog) { shouldOpenSaveSceneDialog = false; PkeThreads_Enqueue(threadPoolHandle, std::packaged_task<void()>( [] { const char * patterns[1] = {"*.pstf"}; - char *selectedScene = tinyfd_saveFileDialog(nullptr, sceneName, 1, patterns, "Pke Scene Text File"); + char *selectedScene = tinyfd_saveFileDialog(nullptr, pkeSettings.rt.sceneName, 1, patterns, "Pke Scene Text File"); if (selectedScene != nullptr) { - sceneName = selectedScene; - shouldSaveScene = true; + pkeSettings.rt.sceneName = selectedScene; + pkeSettings.rt.shouldSaveScene = true; } })); } - if (shouldSaveScene && sceneName) { - shouldSaveScene = false; - Game_SaveSceneFile(sceneName); + if (pkeSettings.rt.shouldSaveScene && pkeSettings.rt.sceneName) { + pkeSettings.rt.shouldSaveScene = false; + Game_SaveSceneFile(pkeSettings.rt.sceneName); shouldRebuildProjectDir = true; } @@ -449,20 +436,20 @@ void RecordImGuiEditorWrapper() { * - the goal is not to prevent a specific scene name, * I just want to know if they clicked the "New Scene" button */ - ImGui::BeginDisabled(sceneName == newSceneName); + ImGui::BeginDisabled(pkeSettings.rt.sceneName == newSceneName); if (ImGui::MenuItem("Save")) { shouldSaveProjectFile = true; - shouldSaveScene = true; + pkeSettings.rt.shouldSaveScene = true; } - if (sceneName) { + if (pkeSettings.rt.sceneName) { ImGui::SameLine(); int offset = 0; - const auto *slash = strrchr(sceneName, '\\'); - slash = slash != nullptr ? slash : strrchr(sceneName, '/'); + const auto *slash = strrchr(pkeSettings.rt.sceneName, '\\'); + slash = slash != nullptr ? slash : strrchr(pkeSettings.rt.sceneName, '/'); if (slash != nullptr) { - offset = slash - sceneName; + offset = slash - pkeSettings.rt.sceneName; } - ImGui::Text("%s", sceneName + offset); + ImGui::Text("%s", pkeSettings.rt.sceneName + offset); } ImGui::EndDisabled(); if (ImGui::MenuItem("Save As...")) { @@ -581,13 +568,14 @@ void RecordImGuiCameras() { cam.target = ActiveCamera->target; cam.type = ActiveCamera->type; cam.orientation = ActiveCamera->orientation; + cam.isPrimary = false; } static ImGuiTableFlags tableFlags{ ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg }; - if (ImGui::BeginTable("Entities", 8, tableFlags)) { + if (ImGui::BeginTable("Entities", 9, tableFlags)) { ImGui::TableSetupColumn("Interact"); ImGui::TableSetupColumn("CameraHandle"); ImGui::TableSetupColumn("Pos"); @@ -596,6 +584,7 @@ void RecordImGuiCameras() { ImGui::TableSetupColumn("Type"); ImGui::TableSetupColumn("Orientation"); ImGui::TableSetupColumn("Stale"); + ImGui::TableSetupColumn("IsPrimary"); ImGui::TableHeadersRow(); int64_t cameraBucketCount = PkeCamera_GetBucketCount(); @@ -631,6 +620,8 @@ void RecordImGuiCameras() { ImGui::Text("%hhu", cam.orientation); ImGui::TableSetColumnIndex(7); ImGui::Text("%hhu", cam.stale); + ImGui::TableSetColumnIndex(8); + ImGui::Text("%i", cam.isPrimary); ImGui::PopID(); } ImGui::PopID(); @@ -961,8 +952,9 @@ void BuildDirRecursive(const std::filesystem::directory_entry &de, fsEntry *dirF void BuildProjectMenuRecursive(fsEntry &entry) { if (entry.type == 1) { if (ImGui::Selectable(entry.name, false, ImGuiSelectableFlags_AllowDoubleClick) && ImGui::IsMouseDoubleClicked(0)) { - sceneName = entry.name; - shouldLoadScene = true; + pkeSettings.rt.sceneName = entry.name; + pkeSettings.rt.shouldLoadScene = true; + ActiveCamera = &NullCamera; } } else if (entry.type == 0) { if (ImGui::TreeNode(entry.name)) { diff --git a/src/arg-handler.cpp b/src/arg-handler.cpp index 1b40039..2183347 100644 --- a/src/arg-handler.cpp +++ b/src/arg-handler.cpp @@ -1,6 +1,7 @@ #include "arg-handler.hpp" #include "game-settings.hpp" +#include "level.hpp" #include <cstdio> #include <getopt.h> @@ -10,11 +11,13 @@ void PkeArgs_Parse(int argc, char *argv[]) { static struct option long_options[] = { {"plugin", required_argument, 0, 'p'}, + {"project", required_argument, 0, 'r'}, + {"scene", required_argument, 0, 's'}, {0, 0, 0, 0}, }; int optionIndex = 0; - int c = getopt_long(argc, argv, "p:", long_options, &optionIndex); + int c = getopt_long(argc, argv, "", long_options, &optionIndex); if (c == -1) { break; } @@ -23,7 +26,16 @@ void PkeArgs_Parse(int argc, char *argv[]) { case 0: break; case 'p': - pkeSettings.pluginPath = optarg; + pkeSettings.args.pluginPath = optarg; + break; + case 'r': + pkeSettings.args.projectPath = optarg; + break; + case 's': + pkeSettings.args.sceneName = optarg; + pkeSettings.rt.shouldLoadScene = true; + pkeSettings.rt.sceneName = pkeSettings.args.sceneName; + pkeSettings.rt.nextLevel = PkeLevel_Create("transient"); break; default: fprintf(stderr, "Unused parameter: %c\n", c); diff --git a/src/camera.hpp b/src/camera.hpp index 844cb26..ab10a5a 100644 --- a/src/camera.hpp +++ b/src/camera.hpp @@ -34,6 +34,7 @@ struct PkeCamera { PkeCameraType type = PkeCameraType_MAX; PkeCameraOrientation orientation = PkeCameraOrientation_MAX; PkeCameraStaleFlags stale = PkeCameraStaleFlags_MAX; + bool isPrimary = false; }; extern PkeCamera NullCamera; extern PkeCamera *ActiveCamera; diff --git a/src/game-settings.hpp b/src/game-settings.hpp index 7bc6765..10be624 100644 --- a/src/game-settings.hpp +++ b/src/game-settings.hpp @@ -1,6 +1,7 @@ #ifndef PKE_GAME_SETTINGS_HPP #define PKE_GAME_SETTINGS_HPP +#include "level-types.hpp" #include "memory-type-defs.hpp" #include <chrono> @@ -8,7 +9,6 @@ struct GameSettings { const char *executablePath; - const char *pluginPath = nullptr; bool isGameRunning = true; bool isGamePaused = false; bool isShowingEditor = true; @@ -19,20 +19,36 @@ struct GameSettings { int64_t minFPS = 20; double deltaPerFrame = 1.0 / double(targetFPS); double minimumDeltaPerFrame = 1.0 / double(minFPS); - struct { + struct editor { bool isUsingDebugCamera = false; bool isShowingConsole = true; bool isShowingEntityList = true; bool isShowingSceneEditor = true; bool isShowingUBO = true; } editorSettings; - struct { + struct graphics { bool isFramerateUnlocked = false; bool isWaitingForVsync = true; } graphicsSettings; - struct { + struct memory { MemBucket *bkt = nullptr; } mem; + struct engineArgs { + const char *pluginPath = nullptr; + const char *projectPath = nullptr; + const char *sceneName = nullptr; + } args; + struct runtime { + // current level + LevelHandle activeLevel = LevelHandle_MAX; + // level to start loading + LevelHandle nextLevel = LevelHandle_MAX; + // level to unload + LevelHandle previousLevel = LevelHandle_MAX; + const char *sceneName = nullptr; + bool shouldLoadScene = false; + bool shouldSaveScene = false; + } rt; }; extern GameSettings pkeSettings; diff --git a/src/game.cpp b/src/game.cpp index 7dfca42..20e67a0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -53,6 +53,7 @@ const char *PKE_FILE_CAMERA_ROT = "Cam::Rot: "; const char *PKE_FILE_CAMERA_TARGET = "Cam::Target: "; const char *PKE_FILE_CAMERA_TYPE = "Cam::Type: "; const char *PKE_FILE_CAMERA_ORIENTATION = "Cam::Orientation: "; +const char *PKE_FILE_CAMERA_IS_PRIMARY = "Cam::IsPrimary: "; void SerializeCamera(std::ofstream &stream, const PkeCamera &cam) { PkeCamera c{}; @@ -81,6 +82,9 @@ void SerializeCamera(std::ofstream &stream, const PkeCamera &cam) { if (cam.orientation != c.orientation) { stream << PKE_FILE_CAMERA_ORIENTATION << int(static_cast<PkeCameraOrientation_T>(cam.orientation)) << std::endl; } + if (cam.isPrimary != c.isPrimary) { + stream << PKE_FILE_CAMERA_IS_PRIMARY << cam.isPrimary << std::endl; + } } void SerializeInstance(std::ofstream &stream, const CompInstance &comp) { @@ -149,9 +153,13 @@ void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) { rCam.target = cam.target; rCam.type = cam.type; rCam.orientation = cam.orientation; + rCam.isPrimary = cam.isPrimary; if (levelHandle != LevelHandle_MAX) { PkeLevel_RegisterCamera(levelHandle, rCam.handle); } + if (rCam.isPrimary == true) { + ActiveCamera = &rCam; + } return; } if (strncmp(readLine, PKE_FILE_CAMERA_POS, strlen(PKE_FILE_CAMERA_POS)) == 0) { @@ -212,6 +220,14 @@ void ParseCamera(LevelHandle levelHandle, std::ifstream &stream) { cam.orientation = PkeCameraOrientation{handle_t}; continue; } + if (strncmp(readLine, PKE_FILE_CAMERA_IS_PRIMARY, strlen(PKE_FILE_CAMERA_IS_PRIMARY)) == 0) { + uint64_t prefixLen = strlen(PKE_FILE_CAMERA_IS_PRIMARY); + uint8_t isPrimary; + STR2NUM_ERROR result = str2num(isPrimary, readLine + prefixLen); + assert(result == STR2NUM_ERROR::SUCCESS); + cam.isPrimary = bool(isPrimary); + continue; + } } } @@ -451,6 +467,26 @@ void Game_RecordImGui() { void Game_Tick(double delta) { Pke_ResetBucket(pkeSettings.mem.bkt); + + // TODO this should be removed in favor of storing the scene details inside a level definition + if (pkeSettings.rt.shouldLoadScene && pkeSettings.rt.sceneName) { + pkeSettings.rt.shouldLoadScene = false; + if (pkeSettings.rt.activeLevel != LevelHandle_MAX) { + pkeSettings.rt.previousLevel = pkeSettings.rt.activeLevel; + } + pkeSettings.rt.nextLevel = PkeLevel_Create(pkeSettings.rt.sceneName); + } + if (pkeSettings.rt.nextLevel != LevelHandle_MAX) { + // TODO async this + Game_LoadSceneFile(pkeSettings.rt.nextLevel, pkeSettings.rt.sceneName); + pkeSettings.rt.activeLevel = pkeSettings.rt.nextLevel; + pkeSettings.rt.nextLevel = LevelHandle_MAX; + } + if (pkeSettings.rt.previousLevel != LevelHandle_MAX) { + PkeLevel_Remove(pkeSettings.rt.previousLevel); + pkeSettings.rt.previousLevel = LevelHandle_MAX; + } + /* * ECS_Tick() gets called first because it updates the public * `EntitiesToBeRemoved` for all other ticks to use. @@ -481,13 +517,13 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { CreateWindow(windowProps); PkeInput_Init(); EntityType_Init(); - if (pkeSettings.pluginPath) { - Pke_LoadPlugin(pkeSettings.pluginPath); + if (pkeSettings.args.pluginPath) { + Pke_LoadPlugin(pkeSettings.args.pluginPath); } if (pkePlugin.OnInit) { pkePlugin.OnInit(); } - PkeProject_Load(); + PkeProject_Load(pkeSettings.args.projectPath); GameTimePoint lastTimePoint = pkeSettings.steadyClock.now(); double deltaTillNextRender = pkeSettings.deltaPerFrame; diff --git a/src/project.cpp b/src/project.cpp index f7200dd..e5b5583 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -11,8 +11,6 @@ const long projReadLineLength = 128; char projReadLine[projReadLineLength]; -const char* const PKE_PROJ_DEFAULT_FILENAME = "project.pptf"; - const char* const PKE_PROJ_FILE_BEGIN = ":PKPB:"; const char* const PKE_PROJ_FILE_END = ":PKPE:"; const char* const PKE_PROJ_FILE_VERSION = ":0:"; diff --git a/src/project.hpp b/src/project.hpp index 9a5ed4b..54dff33 100644 --- a/src/project.hpp +++ b/src/project.hpp @@ -3,6 +3,8 @@ #include "project-settings.hpp" +const char* const PKE_PROJ_DEFAULT_FILENAME = "project.pptf"; + void PkeProject_Load(const char *filePath = nullptr); void PkeProject_Save(const char *filePath = nullptr); |
