summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-12-19 13:32:31 -0500
committerJonathan Bradley <jcb@pikum.xyz>2023-12-23 11:41:03 -0500
commit04f5688a37030aa8598ded416f05d0cc979c37d6 (patch)
treece0bec713c49d6dda66a28f1246e1443d271b8f2
parentc7c678651a30db30e449e965e6c82ad0dcb871e6 (diff)
loading scenes and projects can now be done via args
-rw-r--r--editor/editor.cpp74
-rw-r--r--src/arg-handler.cpp16
-rw-r--r--src/camera.hpp1
-rw-r--r--src/game-settings.hpp24
-rw-r--r--src/game.cpp42
-rw-r--r--src/project.cpp2
-rw-r--r--src/project.hpp2
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);