summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-12-06 22:38:14 -0500
committerJonathan Bradley <jcb@pikum.xyz>2023-12-06 22:38:14 -0500
commite2e1d4646fa3a196b6247ba2dc04603d393df62f (patch)
tree74eb0b281f673697da5fdedf11ba49923a79747d
parenta7e6acea6f3d75ba162ac0bcedcf2900568b8ea6 (diff)
large camera refactor for saving and ui
-rw-r--r--editor/editor.cpp190
-rw-r--r--src/game.cpp135
2 files changed, 288 insertions, 37 deletions
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 4fab198..1786a18 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -24,7 +24,7 @@ const char *dbgCtrl_CameraDown = "debug-camera-down";
const char *dbgCtrl_CameraRotCC = "debug-camera-rot-counter-clockwise";
const char *dbgCtrl_CameraRotC = "debug-camera-rot-clockwise";
const char *dbgCtrl_CameraRot = "debug-camera-rot";
-const char *dbgCtrl_UnlockCamera = "debug-camera-unlock";
+const char *dbgCtrl_CameraButtonMask = "debug-camera-button-mask";
const char *dbgCtrl_SelectHovered = "debug-select-hovered";
const char *dbgCtrl_ClearSelection = "debug-clear-selection";
@@ -42,8 +42,6 @@ PkeCamera cameraDbg {
InputActionSetHandle debugControlsHandle = InputActionSetHandle_MAX;
bool shouldSetupEditor = true;
bool shouldDisableEditor = false;
-bool shouldLockCamera = false;
-bool shouldUnlockCamera = false;
struct EntityTypeInstanceCreateInfo {
EntityHandle entityTypeEntityHandle;
@@ -53,6 +51,7 @@ EntityHandle selectedEntity = EntityHandle_MAX;
EntityHandle hoveredEntity = EntityHandle_MAX;
bool shouldCreateEntityType = false;
EntityType entityTypeToCreate{};
+CameraHandle selectedCamera = CameraHandle_MAX;
char *sceneName = nullptr;
bool shouldOpenLoadSceneDialog = false;
@@ -99,17 +98,9 @@ void PkeEditor_Tick(double delta) {
Game_LoadSceneFile(sceneName);
}
- if (shouldUnlockCamera) {
- shouldUnlockCamera = false;
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
- cameraDbg.pos = ActiveCamera->pos;
- if (ActiveCamera->orientation == cameraDbg.orientation) {
- cameraDbg.rot = ActiveCamera->rot;
- } else {
- cameraDbg.rot = glm::quat(UBO.view);
- }
- cameraDbg.stale = PKE_CAMERA_STALE_ALL;
- ActiveCamera = &cameraDbg;
+ if (shouldSaveScene && sceneName) {
+ shouldSaveScene = false;
+ Game_SaveSceneFile(sceneName);
}
if (EntitiesToBeRemoved.Has(selectedEntity)) {
@@ -219,24 +210,33 @@ void PkeEditor_Tick(double delta) {
compInst.bt.rigidBody->setUserPointer(reinterpret_cast<void *>(compInst.entHandle));
}
- PkeInputEventHolder holder = PkeInput_Query(dbgCtrl_UnlockCamera);
+ PkeInputEventHolder holder = PkeInput_Query(dbgCtrl_CameraButtonMask);
if (holder.type != InputEventHash{0}) {
- PkeKeyEvent *keyEsc;
- keyEsc = static_cast<PkeKeyEvent *>(holder.ptr);
- if (keyEsc->isPressed || keyEsc->pressCount > 0) {
- pkeSettings.editorSettings.isUsingDebugCamera = false;
- shouldLockCamera = true;
+ PkeMouseButtonEvent *toggleCameraMovement;
+ toggleCameraMovement = static_cast<PkeMouseButtonEvent *>(holder.ptr);
+ if (toggleCameraMovement->thisTick) {
+ if (toggleCameraMovement->isPressed && pkeSettings.editorSettings.isUsingDebugCamera == false) {
+ pkeSettings.editorSettings.isUsingDebugCamera = true;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ selectedCamera = CameraHandle_MAX;
+ if (ActiveCamera != &cameraDbg) {
+ cameraDbg.pos = ActiveCamera->pos;
+ if (ActiveCamera->orientation == cameraDbg.orientation) {
+ cameraDbg.rot = ActiveCamera->rot;
+ } else {
+ cameraDbg.rot = glm::quat(UBO.view);
+ }
+ cameraDbg.stale = PKE_CAMERA_STALE_ALL;
+ ActiveCamera = &cameraDbg;
+ }
+ } else if (toggleCameraMovement->isPressed && pkeSettings.editorSettings.isUsingDebugCamera == true) {
+ pkeSettings.editorSettings.isUsingDebugCamera = false;
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ }
}
}
- if (shouldLockCamera) {
- shouldLockCamera = false;
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
- NullCamera.stale = PKE_CAMERA_STALE_ALL;
- ActiveCamera = &NullCamera;
- }
-
- if (pkeSettings.editorSettings.isUsingDebugCamera) {
+ if (pkeSettings.editorSettings.isUsingDebugCamera && ActiveCamera == &cameraDbg) {
holder = PkeInput_Query(dbgCtrl_CameraRot);
if (holder.type != InputEventHash{0}) {
const PkeCursorPosEvent *posEvent = static_cast<PkeCursorPosEvent *>(holder.ptr);
@@ -371,10 +371,10 @@ void RecordImGuiEditorWrapper() {
// ImGui::Checkbox("Uncap Tickrate", &pkeSettings.isTickrateUnlocked);
if (ImGui::Checkbox("Use Debug Camera", &pkeSettings.editorSettings.isUsingDebugCamera)) {
if (pkeSettings.editorSettings.isUsingDebugCamera) {
- shouldUnlockCamera = true;
+ // shouldUnlockCamera = true;
ImGui::CloseCurrentPopup();
} else {
- shouldLockCamera = true;
+ // shouldLockCamera = true;
}
}
@@ -443,6 +443,120 @@ void RecordImGuiEntityList() {
ImGui::End();
}
+void RecordImGuiCameras() {
+ if (!ImGui::Begin("Cameras")) {
+ ImGui::End();
+ return;
+ }
+ if (ImGui::Button("Create")) {
+ auto &cam = PkeCamera_Register();
+ cam.pos = ActiveCamera->pos;
+ cam.rot = ActiveCamera->rot;
+ cam.target = ActiveCamera->target;
+ cam.type = ActiveCamera->type;
+ cam.orientation = ActiveCamera->orientation;
+ }
+
+ static ImGuiTableFlags tableFlags{
+ ImGuiTableFlags_Borders |
+ ImGuiTableFlags_RowBg
+ };
+ if (ImGui::BeginTable("Entities", 8, tableFlags)) {
+ ImGui::TableSetupColumn("Interact");
+ ImGui::TableSetupColumn("CameraHandle");
+ ImGui::TableSetupColumn("Pos");
+ ImGui::TableSetupColumn("Rot");
+ ImGui::TableSetupColumn("Target");
+ ImGui::TableSetupColumn("Type");
+ ImGui::TableSetupColumn("Orientation");
+ ImGui::TableSetupColumn("Stale");
+ ImGui::TableHeadersRow();
+
+ int64_t cameraBucketCount = PkeCamera_GetBucketCount();
+ for (long b = 0; b < cameraBucketCount; ++b) {
+ int64_t count;
+ auto *cameras = PkeCamera_GetCameras(b, count);
+ ImGui::PushID(b);
+ for (long i = 0; i < count; ++i) {
+ const auto &cam = cameras[i];
+ if (cam.handle == CameraHandle_MAX)
+ continue;
+ ImGui::PushID(i);
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ ImGui::BeginDisabled(selectedCamera == cam.handle);
+ if (ImGui::Button("Select")) {
+ selectedCamera = cam.handle;
+ ActiveCamera = const_cast<PkeCamera *>(&cam);
+ ActiveCamera->stale = PKE_CAMERA_STALE_ALL;
+ }
+ ImGui::EndDisabled();
+ ImGui::TableSetColumnIndex(1);
+ ImGui::Text("0x%016lX", static_cast<CameraHandle_T>(cam.handle));
+ ImGui::TableSetColumnIndex(2);
+ ImGui::Text("%4.2f,%4.2f,%4.2f", cam.pos[0], cam.pos[1], cam.pos[2]);
+ ImGui::TableSetColumnIndex(3);
+ ImGui::Text("%4.2f,%4.2f,%4.2f,%4.2f", cam.rot[0], cam.rot[1], cam.rot[2], cam.rot[3]);
+ ImGui::TableSetColumnIndex(4);
+ ImGui::Text("%4.2f,%4.2f,%4.2f", cam.target[0], cam.target[1], cam.target[2]);
+ ImGui::TableSetColumnIndex(5);
+ ImGui::Text("%hhu", cam.type);
+ ImGui::TableSetColumnIndex(6);
+ ImGui::Text("%hhu", cam.orientation);
+ ImGui::TableSetColumnIndex(7);
+ ImGui::Text("%hhu", cam.stale);
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+ }
+ ImGui::EndTable();
+ }
+
+ if (selectedCamera != CameraHandle_MAX) {
+ int inputTextFlags = ImGuiInputTextFlags_ReadOnly;
+ auto *cam = PkeCamera_Get(selectedCamera);
+ if (cam) {
+ bool isOrientTarget{bool(static_cast<PkeCameraOrientation_T>(cam->orientation & PKE_CAMERA_ORIENTATION_TARGET))};
+ bool isOrientFree{bool(static_cast<PkeCameraOrientation_T>(cam->orientation & PKE_CAMERA_ORIENTATION_FREE))};
+ if (ImGui::InputScalarN("Pos", ImGuiDataType_Float, &cam->pos, 3, nullptr, nullptr, nullptr))
+ cam->stale = cam->stale | PKE_CAMERA_STALE_POS;
+ if (ImGui::InputScalarN("Rot", ImGuiDataType_Float, &cam->rot, 4, nullptr, nullptr, nullptr, isOrientFree ? 0 : inputTextFlags))
+ cam->stale = cam->stale | PKE_CAMERA_STALE_ROT;
+ if (ImGui::InputScalarN("Target", ImGuiDataType_Float, &cam->target, 3, nullptr, nullptr, nullptr, isOrientTarget ? 0 : inputTextFlags))
+ cam->stale = cam->stale | PKE_CAMERA_STALE_ROT;
+
+ bool isPerspective{bool(static_cast<PkeCameraType_T>(cam->type & PKE_CAMERA_TYPE_PERSPECTIVE))};
+ bool isOrthogonal{bool(static_cast<PkeCameraType_T>(cam->type & PKE_CAMERA_TYPE_ORTHOGONAL))};
+ ImGui::BeginDisabled(isPerspective);
+ if (ImGui::Button("Perspective")) {
+ cam->type = PKE_CAMERA_TYPE_PERSPECTIVE;
+ }
+ ImGui::EndDisabled();
+ ImGui::SameLine();
+ ImGui::BeginDisabled(isOrthogonal);
+ if (ImGui::Button("Orthogonal")) {
+ cam->type = PKE_CAMERA_TYPE_ORTHOGONAL;
+ }
+ ImGui::EndDisabled();
+
+ ImGui::BeginDisabled(isOrientTarget);
+ if (ImGui::Button("Target")) {
+ cam->orientation = PKE_CAMERA_ORIENTATION_TARGET;
+ }
+ ImGui::EndDisabled();
+ ImGui::SameLine();
+ ImGui::BeginDisabled(isOrientFree);
+ if (ImGui::Button("Free")) {
+ cam->orientation = PKE_CAMERA_ORIENTATION_FREE;
+ }
+ ImGui::EndDisabled();
+
+ }
+ }
+
+ ImGui::End();
+}
+
void RecordImGuiUBO() {
if (!ImGui::Begin("UBO", &pkeSettings.editorSettings.isShowingUBO)) {
ImGui::End();
@@ -623,11 +737,16 @@ void RecordImGuiSceneEditor() {
ImGui::OpenPopup("CreateEntityType");
}
if (ImGui::Button("Save")) {
- // Game_SaveSceneFile(sceneName);
+ shouldSaveScene = true;
+ }
+ if (sceneName) {
+ ImGui::SameLine();
+ ImGui::Text("%s", sceneName);
+ }
+ if (ImGui::Button("Save As...")) {
shouldOpenSaveSceneDialog = true;
}
if (ImGui::Button("Load")) {
- // Game_LoadSceneFile(sceneName);
shouldOpenLoadSceneDialog = true;
}
if (ImGui::Button("Clear Selection")) {
@@ -653,6 +772,7 @@ void PkeEditor_RecordImGui() {
RecordImGuiEntityList();
RecordImGuiSceneEditor();
RecordImGuiUBO();
+ RecordImGuiCameras();
Game_RecordImGui();
}
}
@@ -723,10 +843,10 @@ void PkeEditor_Init() {
debugControlsSet.actions[8].primaryHash = PkeInputEventMask {
.computedHash = PKE_INPUT_HASH_ALL_CURSOR_POS_EVENTS,
};
- debugControlsSet.actions[9].name = dbgCtrl_UnlockCamera;
+ debugControlsSet.actions[9].name = dbgCtrl_CameraButtonMask;
debugControlsSet.actions[9].primaryHash = PkeInputEventMask {
- .computedHash = PKE_INPUT_HASH_ALL_KEY_EVENTS,
- .button = GLFW_KEY_ESCAPE,
+ .computedHash = PKE_INPUT_HASH_ALL_MOUSE_BUTTON_EVENTS,
+ .button = GLFW_MOUSE_BUTTON_MIDDLE,
};
debugControlsSet.actions[10].name = dbgCtrl_SelectHovered;
debugControlsSet.actions[10].primaryHash = PkeInputEventMask {
diff --git a/src/game.cpp b/src/game.cpp
index 6fab5f4..6c47381 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -34,6 +34,7 @@ const char *PKE_FILE_VERSION = ":0:";
const char *PKE_FILE_OBJ_END = "";
const char *PKE_FILE_OBJ_ENTITY_TYPE = "EntityType:";
const char *PKE_FILE_OBJ_INSTANCE = "Instance:";
+const char *PKE_FILE_OBJ_CAMERA = "Camera:";
const char *PKE_FILE_ENTITY_TYPE_MODELS_DIR = "ModelsDir: ";
const char *PKE_FILE_ENTITY_TYPE_MODEL_FILE = "ModelFile: ";
@@ -57,6 +58,41 @@ const char *PKE_FILE_INSTANCE_PHYSICS_MASS = "InstPos::Mass: ";
const char *PKE_FILE_INSTANCE_PHYSICS_COLLISION_LAYER = "InstPos::CollisionLayer: ";
const char *PKE_FILE_INSTANCE_PHYSICS_COLLISION_MASK = "InstPos::CollisionMask: ";
+const char *PKE_FILE_CAMERA_POS = "Cam::Pos: ";
+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: ";
+
+void SerializeCamera(std::ofstream &stream, const PkeCamera &cam) {
+ PkeCamera c{};
+ if (cam.pos != c.pos) {
+ stream << PKE_FILE_CAMERA_POS << "["
+ << std::setw(10) << cam.pos[0] << ","
+ << std::setw(10) << cam.pos[1] << ","
+ << std::setw(10) << cam.pos[2] << "]" << std::endl;
+ }
+ if (cam.rot != c.rot) {
+ stream << PKE_FILE_CAMERA_ROT << "["
+ << std::setw(10) << cam.rot[0] << ","
+ << std::setw(10) << cam.rot[1] << ","
+ << std::setw(10) << cam.rot[2] << ","
+ << std::setw(10) << cam.rot[3] << "]" << std::endl;
+ }
+ if (cam.target != c.target) {
+ stream << PKE_FILE_CAMERA_TARGET << "["
+ << std::setw(10) << cam.target[0] << ","
+ << std::setw(10) << cam.target[1] << ","
+ << std::setw(10) << cam.target[2] << "]" << std::endl;
+ }
+ if (cam.type != c.type) {
+ stream << PKE_FILE_CAMERA_TYPE << int(static_cast<PkeCameraType_T>(cam.type)) << std::endl;
+ }
+ if (cam.orientation != c.orientation) {
+ stream << PKE_FILE_CAMERA_ORIENTATION << int(static_cast<PkeCameraOrientation_T>(cam.orientation)) << std::endl;
+ }
+}
+
void SerializeEntityType(std::ofstream &stream, const EntityType &et) {
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",static_cast<EntityHandle_T>(et.entityHandle));
@@ -143,6 +179,79 @@ void SerializeInstance(std::ofstream &stream, const CompInstance &comp) {
}
}
+void ParseCamera(std::ifstream &stream) {
+ PkeCamera cam{};
+ while (stream.getline(readLine, readLineLength)) {
+ if (strcmp(readLine, PKE_FILE_OBJ_END) == 0) {
+ auto &rCam = PkeCamera_Register();
+ rCam.pos = cam.pos;
+ rCam.rot = cam.rot;
+ rCam.target = cam.target;
+ rCam.type = cam.type;
+ rCam.orientation = cam.orientation;
+ return;
+ }
+ if (strncmp(readLine, PKE_FILE_CAMERA_POS, strlen(PKE_FILE_CAMERA_POS)) == 0) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_POS);
+ char *startingChar = strchr(readLine + prefixLen, '[') + 1;
+ assert(startingChar != nullptr);
+ char *pEnd = nullptr;
+ long index = 0;
+ do {
+ assert(index < 3);
+ STR2NUM_ERROR result = str2num(cam.pos[index], startingChar, pEnd);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ startingChar = pEnd + 1;
+ ++index;
+ } while (*pEnd != ']');
+ }
+ if (strncmp(readLine, PKE_FILE_CAMERA_ROT, strlen(PKE_FILE_CAMERA_ROT)) == 0) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_ROT);
+ char *startingChar = strchr(readLine + prefixLen, '[') + 1;
+ assert(startingChar != nullptr);
+ char *pEnd = nullptr;
+ long index = 0;
+ do {
+ assert(index < 4);
+ STR2NUM_ERROR result = str2num(cam.rot[index], startingChar, pEnd);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ startingChar = pEnd + 1;
+ ++index;
+ } while (*pEnd != ']');
+ }
+ if (strncmp(readLine, PKE_FILE_CAMERA_TARGET, strlen(PKE_FILE_CAMERA_TARGET)) == 0) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_TARGET);
+ char *startingChar = strchr(readLine + prefixLen, '[') + 1;
+ assert(startingChar != nullptr);
+ char *pEnd = nullptr;
+ long index = 0;
+ do {
+ assert(index < 3);
+ STR2NUM_ERROR result = str2num(cam.target[index], startingChar, pEnd);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ startingChar = pEnd + 1;
+ ++index;
+ } while (*pEnd != ']');
+ }
+ if (strncmp(readLine, PKE_FILE_CAMERA_TYPE, strlen(PKE_FILE_CAMERA_TYPE)) == 0) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_TYPE);
+ PkeCameraType_T handle_t;
+ STR2NUM_ERROR result = str2num(handle_t, readLine + prefixLen);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ cam.type = PkeCameraType{handle_t};
+ continue;
+ }
+ if (strncmp(readLine, PKE_FILE_CAMERA_ORIENTATION, strlen(PKE_FILE_CAMERA_ORIENTATION)) == 0) {
+ uint64_t prefixLen = strlen(PKE_FILE_CAMERA_ORIENTATION);
+ PkeCameraOrientation_T handle_t;
+ STR2NUM_ERROR result = str2num(handle_t, readLine + prefixLen);
+ assert(result == STR2NUM_ERROR::SUCCESS);
+ cam.orientation = PkeCameraOrientation{handle_t};
+ continue;
+ }
+ }
+}
+
void ParseEntityType(std::ifstream &stream) {
EntityType et{};
while (stream.getline(readLine, readLineLength)) {
@@ -384,6 +493,20 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
f << PKE_FILE_VERSION << std::endl;
f << "" << std::endl;
+ int64_t cameraBucketCount = PkeCamera_GetBucketCount();
+ for (long b = 0; b < cameraBucketCount; ++b) {
+ int64_t count;
+ auto *cameras = PkeCamera_GetCameras(b, count);
+ for (long i = 0; i < count; ++i) {
+ const auto &cam = cameras[i];
+ if (cam.handle == CameraHandle_MAX)
+ continue;
+ f << PKE_FILE_OBJ_CAMERA << std::endl;
+ SerializeCamera(f, cam);
+ f << PKE_FILE_OBJ_END << std::endl;
+ }
+ }
+
for (long i = 0; i < GlobalEntityTypes.Count(); ++i) {
f << PKE_FILE_OBJ_ENTITY_TYPE << std::endl;
const auto &et = GlobalEntityTypes[i];
@@ -418,11 +541,17 @@ void Game_SaveSceneFile(const char *sceneFilePath) {
void Game_LoadSceneFile(const char *sceneFilePath) {
std::ifstream f(sceneFilePath);
- assert(f.is_open());
+ if (!f.is_open()) {
+ fprintf(stderr, "Failed to load requested scene file: %s", sceneFilePath);
+ return;
+ }
memset(readLine, '\0', readLineLength);
while (f.getline(readLine, readLineLength)) {
- // EntityTypes
+ if (strcmp(PKE_FILE_OBJ_CAMERA, readLine) == 0) {
+ ParseCamera(f);
+ continue;
+ }
if (strcmp(PKE_FILE_OBJ_ENTITY_TYPE, readLine) == 0) {
ParseEntityType(f);
continue;
@@ -498,6 +627,7 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
fprintf(stdout, "Game_Main Entering\n");
try {
AM_Init();
+ PkeCamera_Init();
Physics_Init();
Game_Init();
ECS_Init();
@@ -604,6 +734,7 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
PkeInput_Teardown();
Physics_Teardown();
ECS_Teardown();
+ PkeCamera_Teardown();
AM_DebugPrint();
AM_Teardown();
DestroyWindow();