diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 46b74848af..7b17252f06 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -134,6 +134,7 @@ struct UserSettings { ConfigVar invertCameraYAxis; ConfigVar freeCameraSensitivity; ConfigVar debugFlyCam; + ConfigVar debugFlyCamLockEvents; // Cheats ConfigVar infiniteHearts; diff --git a/src/d/d_camera.cpp b/src/d/d_camera.cpp index e559a56d95..8e13c6271f 100644 --- a/src/d/d_camera.cpp +++ b/src/d/d_camera.cpp @@ -31,6 +31,7 @@ #if TARGET_PC #include "dusk/frame_interpolation.h" #include "dusk/logging.h" +#include "imgui.h" #endif namespace { @@ -7483,6 +7484,8 @@ static constexpr f32 FLYCAM_SPEED = 0.5f; static constexpr f32 FLYCAM_FAST_SPEED = 4.0f; static constexpr f32 FLYCAM_ROTATION_SPEED = 0.002f; static constexpr f32 FLYCAM_TRIGGER_DEADZONE = 20.0f; +static constexpr s16 FLYCAM_ROLL_SPEED = 256; +static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f}; #if TARGET_PC bool dCamera_c::executeDebugFlyCam() { @@ -7490,6 +7493,7 @@ bool dCamera_c::executeDebugFlyCam() { if (mDebugFlyCam.initialized) { deactivateDebugFlyCam(); } + sFlyCamLastMousePos = {-1.f, -1.f}; return false; } @@ -7519,16 +7523,63 @@ bool dCamera_c::executeDebugFlyCam() { mDebugFlyCam.initialized = true; } - event->mEventStatus = 1; - dComIfGp_getEventManager().setCameraPlay(1); + if (dusk::getSettings().game.debugFlyCamLockEvents) { + event->mEventStatus = 1; + dComIfGp_getEventManager().setCameraPlay(1); + } else { + if (event->mEventStatus != 0) { + event->mEventStatus = 0; + } + dComIfGp_getEventManager().setCameraPlay(0); + } - interface_of_controller_pad& pad = mDoCPd_c::getCpadInfo(0); - f32 stickY = pad.mMainStickPosY * 72.0f; - f32 stickX = pad.mMainStickPosX * 72.0f; - f32 cStickY = pad.mCStickPosY * 59.0f; - f32 cStickX = pad.mCStickPosX * 59.0f; - f32 trigL = pad.mTriggerLeft * 150.0f; - f32 trigR = pad.mTriggerRight * 150.0f; + f32 stickY = 0.f; + f32 stickX = 0.f; + f32 cStickY = 0.f; + f32 cStickX = 0.f; + f32 trigL = 0.f; + f32 trigR = 0.f; + f32 rollInput = 0.f; + bool fast = false; + + if (dusk::getSettings().game.debugFlyCamLockEvents) { + interface_of_controller_pad& pad = mDoCPd_c::getCpadInfo(0); + stickY = pad.mMainStickPosY * 72.0f; + stickX = pad.mMainStickPosX * 72.0f; + cStickY = pad.mCStickPosY * 59.0f; + cStickX = pad.mCStickPosX * 59.0f; + trigL = pad.mTriggerLeft * 150.0f; + trigR = pad.mTriggerRight * 150.0f; + fast = mDoCPd_c::getHoldZ(PAD_1); + if (mDoCPd_c::getHoldY(PAD_1)) rollInput -= 1.f; + if (mDoCPd_c::getHoldX(PAD_1)) rollInput += 1.f; + } + + { + ImGuiIO& io = ImGui::GetIO(); + if (!io.WantCaptureKeyboard) { + f32 kbX = 0.0f, kbY = 0.0f; + if (ImGui::IsKeyDown(ImGuiKey_W) || ImGui::IsKeyDown(ImGuiKey_UpArrow)) kbY += 1.f; + if (ImGui::IsKeyDown(ImGuiKey_S) || ImGui::IsKeyDown(ImGuiKey_DownArrow)) kbY -= 1.f; + if (ImGui::IsKeyDown(ImGuiKey_D) || ImGui::IsKeyDown(ImGuiKey_RightArrow)) kbX += 1.f; + if (ImGui::IsKeyDown(ImGuiKey_A) || ImGui::IsKeyDown(ImGuiKey_LeftArrow)) kbX -= 1.f; + f32 len = sqrtf(kbX * kbX + kbY * kbY); + if (len > 1.f) { kbX /= len; kbY /= len; } + stickX += kbX * 72.0f; + stickY += kbY * 72.0f; + if (ImGui::IsKeyDown(ImGuiKey_Space)) trigR += 150.0f; + if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) trigL += 150.0f; + if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) fast = true; + if (ImGui::IsKeyDown(ImGuiKey_Q)) rollInput -= 1.0f; + if (ImGui::IsKeyDown(ImGuiKey_E)) rollInput += 1.0f; + } + bool mouseValid = !io.WantCaptureMouse && io.MousePos.x >= 0.0f && io.MousePos.y >= 0.0f; + if (mouseValid && sFlyCamLastMousePos.x >= 0.0f) { + cStickX -= (io.MousePos.x - sFlyCamLastMousePos.x) * 2.0f; + cStickY -= (io.MousePos.y - sFlyCamLastMousePos.y) * 2.0f; + } + sFlyCamLastMousePos = mouseValid ? io.MousePos : ImVec2{-1.0f, -1.0f}; + } f32 verticalDisp = 0.0f; if (trigR >= FLYCAM_TRIGGER_DEADZONE) { @@ -7542,7 +7593,7 @@ bool dCamera_c::executeDebugFlyCam() { f32 moveDx = stickY * cosf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) - stickX * sinf(mDebugFlyCam.yaw); f32 moveDz = stickY * sinf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) + stickX * cosf(mDebugFlyCam.yaw); - f32 speed = mDoCPd_c::getHoldZ(PAD_1) ? FLYCAM_FAST_SPEED : FLYCAM_SPEED; + f32 speed = fast ? FLYCAM_FAST_SPEED : FLYCAM_SPEED; mEye.x += speed * moveDx; mEye.y += speed * moveDy; @@ -7553,6 +7604,7 @@ bool dCamera_c::executeDebugFlyCam() { mCenter.z = mEye.z + sinf(mDebugFlyCam.yaw) * cosf(mDebugFlyCam.pitch) * FLYCAM_TARGET_DIST; mCenter.y = mEye.y + sinf(mDebugFlyCam.pitch) * FLYCAM_TARGET_DIST; + mBank = mBank + static_cast(rollInput * FLYCAM_ROLL_SPEED * (fast ? FLYCAM_FAST_SPEED / FLYCAM_SPEED : 1.f)); Reset(mCenter, mEye); f32 yawInput = dusk::getSettings().game.invertCameraXAxis ? cStickX : -cStickX; @@ -7570,7 +7622,7 @@ void dCamera_c::deactivateDebugFlyCam() { Reset(mDebugFlyCam.savedCenter, mDebugFlyCam.savedEye, mDebugFlyCam.savedFovy, mDebugFlyCam.savedBank.Val()); dEvt_control_c* event = dComIfGp_getEvent(); - if (event != nullptr) { + if (event != nullptr && event->mEventStatus != 0) { event->mEventStatus = 0; } dComIfGp_getEventManager().setCameraPlay(0); diff --git a/src/d/d_meter2.cpp b/src/d/d_meter2.cpp index fa6774d0a5..21f2c31326 100644 --- a/src/d/d_meter2.cpp +++ b/src/d/d_meter2.cpp @@ -317,7 +317,7 @@ int dMeter2_c::_execute() { int dMeter2_c::_draw() { #if TARGET_PC - if (dusk::getSettings().game.disableMainHUD) { + if (dusk::getSettings().game.disableMainHUD || dusk::getSettings().game.debugFlyCam) { return 1; } #endif diff --git a/src/dusk/imgui/ImGuiCameraOverlay.cpp b/src/dusk/imgui/ImGuiCameraOverlay.cpp index abdb988af0..0d2168924c 100644 --- a/src/dusk/imgui/ImGuiCameraOverlay.cpp +++ b/src/dusk/imgui/ImGuiCameraOverlay.cpp @@ -63,16 +63,32 @@ namespace dusk { ImGui::SetTooltip("Cannot enable while paused or during an active event."); } else { ImGui::SetTooltip("Detach camera and fly freely.\n" - "Left stick: move, C-stick: look\n" - "L/R triggers: up/down, Z: fast"); + "WASD/Arrows/Left stick: move, Mouse/C-stick: look\n" + "Ctrl/L: down, Space/R: up, Shift/Z: fast\n" + "Q Key/Y: roll left, R Key/X: roll right"); } } if (eventRunning) { ImGui::EndDisabled(); } + if (!getSettings().game.debugFlyCam) { + ImGui::BeginDisabled(); + } + config::ImGuiCheckbox("Lock Events", getSettings().game.debugFlyCamLockEvents); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { + if (!getSettings().game.debugFlyCam) { + ImGui::SetTooltip("Enable Fly Mode first."); + } else { + ImGui::SetTooltip("Freeze game events while flying."); + } + } + if (!getSettings().game.debugFlyCam) { + ImGui::EndDisabled(); + } + ShowCornerContextMenu(m_cameraOverlayCorner, 0); ImGui::End(); } -} \ No newline at end of file +} diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index 64ef59ddb2..2ba1d41398 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -81,6 +81,7 @@ UserSettings g_userSettings = { .invertCameraYAxis {"game.invertCameraYAxis", false}, .freeCameraSensitivity {"game.freeCameraSensitivity", 1.0f}, .debugFlyCam {"game.debugFlyCam", false}, + .debugFlyCamLockEvents {"game.debugFlyCamLockEvents", true}, // Cheats .infiniteHearts {"game.infiniteHearts", false}, @@ -210,6 +211,7 @@ void registerSettings() { Register(g_userSettings.game.gyroInvertYaw); Register(g_userSettings.game.freeCamera); Register(g_userSettings.game.debugFlyCam); + Register(g_userSettings.game.debugFlyCamLockEvents); Register(g_userSettings.backend.isoPath); Register(g_userSettings.backend.isoVerification);