From 39d43a8d8fb5263ad550923773fb120bcd983c9a Mon Sep 17 00:00:00 2001 From: qwertyquerty Date: Wed, 6 May 2026 21:07:28 -0700 Subject: [PATCH] Keyboard mouse binding controls (#682) * kbm controls * submodule * files.cmake * a * Fixes * include in J3DStruct.h --------- Co-authored-by: Luke Street --- files.cmake | 1 - .../include/JSystem/J3DGraphBase/J3DStruct.h | 26 +- src/d/d_menu_fmap2D.cpp | 2 +- src/dusk/imgui/ImGuiConsole.cpp | 1 - src/dusk/imgui/ImGuiConsole.hpp | 2 - src/dusk/imgui/ImGuiDebugPad.cpp | 61 ---- src/dusk/imgui/ImGuiEventFlags.hpp | 4 +- src/dusk/ui/controller_config.cpp | 331 +++++++++++++++++- src/dusk/ui/controller_config.hpp | 4 + src/dusk/ui/overlay.cpp | 5 +- src/m_Do/m_Do_main.cpp | 1 - 11 files changed, 340 insertions(+), 98 deletions(-) delete mode 100644 src/dusk/imgui/ImGuiDebugPad.cpp diff --git a/files.cmake b/files.cmake index e5406ceb02..0b372349eb 100644 --- a/files.cmake +++ b/files.cmake @@ -1450,7 +1450,6 @@ set(DUSK_FILES src/dusk/imgui/ImGuiProcessOverlay.cpp src/dusk/imgui/ImGuiCameraOverlay.cpp src/dusk/imgui/ImGuiHeapOverlay.cpp - src/dusk/imgui/ImGuiDebugPad.cpp src/dusk/imgui/ImGuiControllerOverlay.cpp src/dusk/imgui/ImGuiStubLog.cpp src/dusk/imgui/ImGuiMapLoader.cpp diff --git a/libs/JSystem/include/JSystem/J3DGraphBase/J3DStruct.h b/libs/JSystem/include/JSystem/J3DGraphBase/J3DStruct.h index b565ad78f8..05663fd84e 100644 --- a/libs/JSystem/include/JSystem/J3DGraphBase/J3DStruct.h +++ b/libs/JSystem/include/JSystem/J3DGraphBase/J3DStruct.h @@ -1,9 +1,9 @@ #ifndef J3DSTRUCT_H #define J3DSTRUCT_H +#include #include #include -#include #include "global.h" #include "JSystem/JMath/JMath.h" @@ -11,7 +11,7 @@ /** * @ingroup jsystem-j3d - * + * */ struct J3DLightInfo { bool operator==(J3DLightInfo& other) const; @@ -28,7 +28,7 @@ struct J3DLightInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTextureSRTInfo { // NOTE: Big endian when loaded from file! @@ -79,7 +79,7 @@ enum J3DTexMtxMode { /** * @ingroup jsystem-j3d - * + * */ struct J3DTexMtxInfo { bool operator==(J3DTexMtxInfo& other) const; @@ -97,7 +97,7 @@ struct J3DTexMtxInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DIndTexMtxInfo { J3DIndTexMtxInfo& operator=(J3DIndTexMtxInfo const&); @@ -107,7 +107,7 @@ struct J3DIndTexMtxInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DFogInfo { bool operator==(J3DFogInfo&) const; @@ -126,7 +126,7 @@ struct J3DFogInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DNBTScaleInfo { bool operator==(const J3DNBTScaleInfo& other) const; @@ -153,7 +153,7 @@ struct J3DIndTexOrderInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTevSwapModeInfo { /* 0x0 */ u8 mRasSel; @@ -164,7 +164,7 @@ struct J3DTevSwapModeInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTevSwapModeTableInfo { /* 0x0 */ u8 field_0x0; @@ -175,7 +175,7 @@ struct J3DTevSwapModeTableInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTevStageInfo { /* 0x0 */ u8 field_0x0; @@ -202,7 +202,7 @@ struct J3DTevStageInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DIndTevStageInfo { /* 0x0 */ u8 mIndStage; @@ -219,7 +219,7 @@ struct J3DIndTevStageInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTexCoordInfo { /* 0x0 */ u8 mTexGenType; @@ -265,7 +265,7 @@ struct J3DBlendInfo { /** * @ingroup jsystem-j3d - * + * */ struct J3DTevOrderInfo { void operator=(const J3DTevOrderInfo& other) { diff --git a/src/d/d_menu_fmap2D.cpp b/src/d/d_menu_fmap2D.cpp index ffec184d4e..d62f7d1037 100644 --- a/src/d/d_menu_fmap2D.cpp +++ b/src/d/d_menu_fmap2D.cpp @@ -1403,7 +1403,7 @@ void dMenu_Fmap2DBack_c::regionTextureDraw() { if (uVar10 != uVar9) { bool b = 0; f32 v = mTransX + (dVar14 + (mRegionMinMapX[uVar10] + field_0xf0c[uVar10])); - + #if TARGET_PC if (dusk::getSettings().game.enableMirrorMode) { b = true; diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index 86e4312b00..09d1ca6e81 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -385,7 +385,6 @@ namespace dusk { m_menuTools.ShowSaveEditor(); m_menuTools.ShowStateShare(); } - DuskDebugPad(); // temporary, remove later // Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds. ImGuiIO& io = ImGui::GetIO(); diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index 1b6964c2cc..6715846e7b 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -73,8 +73,6 @@ bool ImGuiButtonCenter(std::string_view text); float ImGuiScale(); } // namespace dusk -void DuskDebugPad(); - #if defined(_WIN32) || \ (defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_MACCATALYST) || \ (defined(__linux__) && !defined(__ANDROID__)) diff --git a/src/dusk/imgui/ImGuiDebugPad.cpp b/src/dusk/imgui/ImGuiDebugPad.cpp deleted file mode 100644 index b1591f1968..0000000000 --- a/src/dusk/imgui/ImGuiDebugPad.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "m_Do/m_Do_controller_pad.h" - -#include "imgui.h" -#include "ImGuiConsole.hpp" - -void DuskDebugPad() { - auto& pad = mDoCPd_c::getCpadInfo(PAD_1); - auto KeyFlag = [&](ImGuiKey key, u32 padFlag) { - if (ImGui::IsKeyDown(key)) - pad.mButtonFlags |= padFlag; - if (ImGui::IsKeyPressed(key)) - pad.mPressedButtonFlags |= padFlag; - - }; - - KeyFlag(ImGuiKey_K, PAD_BUTTON_A); - KeyFlag(ImGuiKey_J, PAD_BUTTON_B); - KeyFlag(ImGuiKey_L, PAD_BUTTON_X); - KeyFlag(ImGuiKey_I, PAD_BUTTON_Y); - KeyFlag(ImGuiKey_H, PAD_BUTTON_START); - KeyFlag(ImGuiKey_O, PAD_TRIGGER_Z); - KeyFlag(ImGuiKey_Keypad8, PAD_BUTTON_UP); - KeyFlag(ImGuiKey_Keypad2, PAD_BUTTON_DOWN); - KeyFlag(ImGuiKey_Keypad6, PAD_BUTTON_RIGHT); - KeyFlag(ImGuiKey_Keypad4, PAD_BUTTON_LEFT); - - if (ImGui::IsKeyDown(ImGuiKey_W)) { - pad.mMainStickPosY = 1.0f; - pad.mMainStickValue = 1.0f; - pad.mMainStickAngle = 0x8000; - } - - if (ImGui::IsKeyDown(ImGuiKey_S)) { - pad.mMainStickPosY = -1.0f; - pad.mMainStickValue = 1.0f; - pad.mMainStickAngle = 0; - } - - if (ImGui::IsKeyDown(ImGuiKey_D)) { - pad.mMainStickPosX = 1.0f; - pad.mMainStickValue = 1.0f; - pad.mMainStickAngle = 0x4000; - } - - if (ImGui::IsKeyDown(ImGuiKey_A)) { - pad.mMainStickPosX = -1.0f; - pad.mMainStickValue = 1.0f; - pad.mMainStickAngle = -0x4000; - } - - if (ImGui::IsKeyDown(ImGuiKey_Q)) { - pad.mTriggerLeft = 1.0; - pad.mTrigLockL = 1; - pad.mHoldLockL = 1; - } - if (ImGui::IsKeyDown(ImGuiKey_E)) { - pad.mTriggerRight = 1.0; - pad.mTrigLockR = 1; - pad.mHoldLockR = 1; - } -} diff --git a/src/dusk/imgui/ImGuiEventFlags.hpp b/src/dusk/imgui/ImGuiEventFlags.hpp index 8c6dddb5a3..5c110821f6 100644 --- a/src/dusk/imgui/ImGuiEventFlags.hpp +++ b/src/dusk/imgui/ImGuiEventFlags.hpp @@ -899,7 +899,7 @@ constexpr auto eventFlagToAreaFlagFormat(uint16_t eventFlag) -> AreaFlagInd { // so we skip 24 bytes for the first byte, 16 for the second, etc // essentially (3 - (x % 4)), reversing the modulus, 0=3, 1=2 const auto bitsToSkip = 8 * ((sizeof(u32) - 1) - (relativeByteInd % sizeof(u32))); - const int areaFlag = ((eventU32Ind) << areaIndexSize) | + const int areaFlag = ((eventU32Ind) << areaIndexSize) | ((std::countr_zero(eventFlag) + bitsToSkip) & makeMask(areaIndexSize)); return AreaFlagInd{byteIndexToAreaFlagType(byteInd), areaFlag}; @@ -3520,4 +3520,4 @@ inline std::map imguiAreaFlagLookup = { 0x1B, AreaFlagIter{ eventAreaFlagsGrotto, {} } }, }; -#endif // !DUSK_IMGUI_EVENTFLAGS_HPP \ No newline at end of file +#endif // !DUSK_IMGUI_EVENTFLAGS_HPP diff --git a/src/dusk/ui/controller_config.cpp b/src/dusk/ui/controller_config.cpp index 038248d7d0..a5fe9ea7d2 100644 --- a/src/dusk/ui/controller_config.cpp +++ b/src/dusk/ui/controller_config.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -17,9 +18,17 @@ namespace dusk::ui { namespace { +bool keyboard_active(int port) { + u32 count = 0; + return PADGetKeyButtonBindings(static_cast(port), &count) != nullptr; +} + Rml::String current_controller_name(int port) { const char* name = PADGetName(port); - return name == nullptr ? "None" : name; + if (name != nullptr) { + return name; + } + return keyboard_active(port) ? "Keyboard" : "None"; } Rml::String controller_index_name(u32 index) { @@ -202,6 +211,74 @@ bool keyboard_escape_pressed() { return keys != nullptr && SDL_SCANCODE_ESCAPE < keyCount && keys[SDL_SCANCODE_ESCAPE]; } +Rml::String keyboard_key_name(s32 scancode) { + if (scancode == PAD_KEY_INVALID) { + return "Not bound"; + } + switch (scancode) { + case PAD_KEY_MOUSE_LEFT: + return "Mouse Left"; + case PAD_KEY_MOUSE_MIDDLE: + return "Mouse Middle"; + case PAD_KEY_MOUSE_RIGHT: + return "Mouse Right"; + case PAD_KEY_MOUSE_X1: + return "Mouse X1"; + case PAD_KEY_MOUSE_X2: + return "Mouse X2"; + default: + break; + } + if (scancode < 0) { + return "Unknown"; + } + const char* name = SDL_GetScancodeName(static_cast(scancode)); + if (name == nullptr || name[0] == '\0') { + return "Unknown"; + } + return name; +} + +bool keyboard_neutral() { + int keyCount = 0; + const bool* keys = SDL_GetKeyboardState(&keyCount); + if (keys != nullptr) { + for (int i = 0; i < keyCount; ++i) { + if (keys[i]) { + return false; + } + } + } + float x, y; + if (SDL_GetMouseState(&x, &y) != 0) { + return false; + } + return true; +} + +s32 keyboard_key_pressed() { + int keyCount = 0; + const bool* keys = SDL_GetKeyboardState(&keyCount); + if (keys != nullptr) { + for (int i = 1; i < keyCount; ++i) { + if (i == SDL_SCANCODE_ESCAPE) { + continue; + } + if (keys[i]) { + return static_cast(i); + } + } + } + float x, y; + const auto mouseButtons = SDL_GetMouseState(&x, &y); + for (int btn = 1; btn <= 5; ++btn) { + if (mouseButtons & (1u << (btn - 1))) { + return -(btn + 1); // maps to PAD_KEY_MOUSE_LEFT (-2), etc. + } + } + return PAD_KEY_INVALID; +} + } // namespace ControllerConfigWindow::ControllerConfigWindow() { @@ -311,23 +388,38 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { switch (page) { case Page::Controller: { - const u32 controllerCount = PADCount(); - if (controllerCount == 0) { - pane.add_text("No controllers detected"); - break; - } + pane.add_button( + { + .text = "None", + .isSelected = + [port] { return PADGetIndexForPort(port) < 0 && !keyboard_active(port); }, + }) + .on_pressed([this, port] { + mDoAud_seStartMenu(kSoundItemChange); + cancel_pending_binding(); + PADClearPort(port); + PADSetKeyboardActive(static_cast(port), FALSE); + PADSerializeMappings(); + }); pane.add_button({ - .text = "None", - .isSelected = [port] { return PADGetIndexForPort(port) < 0; }, + .text = "Keyboard", + .isSelected = [port] { return keyboard_active(port); }, }) .on_pressed([this, port] { mDoAud_seStartMenu(kSoundItemChange); cancel_pending_binding(); PADClearPort(port); + PADSetKeyboardActive(static_cast(port), TRUE); PADSerializeMappings(); }); + const u32 controllerCount = PADCount(); + if (controllerCount == 0) { + pane.add_text("No controllers detected"); + break; + } + for (u32 i = 0; i < controllerCount; ++i) { pane.add_button( { @@ -338,6 +430,7 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { .on_pressed([this, port, i] { mDoAud_seStartMenu(kSoundItemChange); cancel_pending_binding(); + PADSetKeyboardActive(static_cast(port), FALSE); PADSetPortForIndex(i, port); PADSerializeMappings(); }); @@ -345,6 +438,54 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { break; } case Page::Buttons: { + if (keyboard_active(port)) { + auto addKeyButton = [&](PADButton button) { + pane.add_select_button( + { + .key = PADGetButtonName(button), + .getValue = + [this, port, button] { + if (mPendingKeyButton == static_cast(button)) { + return pending_key_label(); + } + u32 count = 0; + PADKeyButtonBinding* bindings = + PADGetKeyButtonBindings(static_cast(port), &count); + if (bindings == nullptr) { + return Rml::String("Not bound"); + } + for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) { + if (bindings[i].padButton == button) { + return keyboard_key_name(bindings[i].scancode); + } + } + return Rml::String("Not bound"); + }, + }) + .on_pressed([this, port, button] { + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; + mPendingKeyButton = static_cast(button); + }); + }; + + pane.add_section("Buttons"); + addKeyButton(PAD_BUTTON_A); + addKeyButton(PAD_BUTTON_B); + addKeyButton(PAD_BUTTON_X); + addKeyButton(PAD_BUTTON_Y); + addKeyButton(PAD_BUTTON_START); + addKeyButton(PAD_TRIGGER_Z); + + pane.add_section("D-Pad"); + addKeyButton(PAD_BUTTON_UP); + addKeyButton(PAD_BUTTON_DOWN); + addKeyButton(PAD_BUTTON_LEFT); + addKeyButton(PAD_BUTTON_RIGHT); + break; + } + u32 buttonCount = 0; PADButtonMapping* mappings = PADGetButtonMappings(port, &buttonCount); if (mappings == nullptr) { @@ -407,6 +548,79 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { break; } case Page::Triggers: { + if (keyboard_active(port)) { + auto addKeyButton = [&](PADButton button) { + pane.add_select_button( + { + .key = PADGetButtonName(button), + .getValue = + [this, port, button] { + if (mPendingKeyButton == static_cast(button)) { + return pending_key_label(); + } + u32 count = 0; + PADKeyButtonBinding* bindings = + PADGetKeyButtonBindings(static_cast(port), &count); + if (bindings == nullptr) { + return Rml::String("Not bound"); + } + for (u32 i = 0; i < PAD_BUTTON_COUNT; ++i) { + if (bindings[i].padButton == button) { + return keyboard_key_name(bindings[i].scancode); + } + } + return Rml::String("Not bound"); + }, + }) + .on_pressed([this, port, button] { + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; + mPendingKeyButton = static_cast(button); + }); + }; + + auto addKeyAxis = [&](PADAxis axis) { + pane.add_select_button( + { + .key = PADGetAxisName(axis), + .getValue = + [this, port, axis] { + if (mPendingKeyAxis == static_cast(axis)) { + return pending_key_label(); + } + u32 count = 0; + PADKeyAxisBinding* bindings = + PADGetKeyAxisBindings(static_cast(port), &count); + if (bindings == nullptr) { + return Rml::String("Not bound"); + } + for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) { + if (bindings[i].padAxis == axis) { + return keyboard_key_name(bindings[i].scancode); + } + } + return Rml::String("Not bound"); + }, + }) + .on_pressed([this, port, axis] { + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; + mPendingKeyAxis = static_cast(axis); + }); + }; + + pane.add_section("Analog"); + addKeyAxis(PAD_AXIS_TRIGGER_L); + addKeyAxis(PAD_AXIS_TRIGGER_R); + + pane.add_section("Digital"); + addKeyButton(PAD_TRIGGER_L); + addKeyButton(PAD_TRIGGER_R); + break; + } + u32 axisCount = 0; PADAxisMapping* axes = PADGetAxisMappings(port, &axisCount); u32 buttonCount = 0; @@ -473,6 +687,52 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) { break; } case Page::Sticks: { + if (keyboard_active(port)) { + auto addKeyAxis = [&](PADAxis axis) { + pane.add_select_button( + { + .key = PADGetAxisDirectionLabel(axis), + .getValue = + [this, port, axis] { + if (mPendingKeyAxis == static_cast(axis)) { + return pending_key_label(); + } + u32 count = 0; + PADKeyAxisBinding* bindings = + PADGetKeyAxisBindings(static_cast(port), &count); + if (bindings == nullptr) { + return Rml::String("Not bound"); + } + for (u32 i = 0; i < PAD_AXIS_COUNT; ++i) { + if (bindings[i].padAxis == axis) { + return keyboard_key_name(bindings[i].scancode); + } + } + return Rml::String("Not bound"); + }, + }) + .on_pressed([this, port, axis] { + cancel_pending_binding(); + mPendingPort = port; + mPendingBindingArmed = false; + mPendingKeyAxis = static_cast(axis); + }); + }; + + pane.add_section("Control Stick"); + addKeyAxis(PAD_AXIS_LEFT_Y_POS); + addKeyAxis(PAD_AXIS_LEFT_Y_NEG); + addKeyAxis(PAD_AXIS_LEFT_X_NEG); + addKeyAxis(PAD_AXIS_LEFT_X_POS); + + pane.add_section("C Stick"); + addKeyAxis(PAD_AXIS_RIGHT_Y_POS); + addKeyAxis(PAD_AXIS_RIGHT_Y_NEG); + addKeyAxis(PAD_AXIS_RIGHT_X_NEG); + addKeyAxis(PAD_AXIS_RIGHT_X_POS); + break; + } + u32 axisCount = 0; PADAxisMapping* axes = PADGetAxisMappings(port, &axisCount); if (axes == nullptr) { @@ -549,6 +809,21 @@ void ControllerConfigWindow::poll_pending_binding() { return; } + if (mPendingKeyButton >= 0 || mPendingKeyAxis >= 0) { + const s32 scancode = keyboard_key_pressed(); + if (scancode != PAD_KEY_INVALID) { + if (mPendingKeyButton >= 0) { + PADSetKeyButtonBinding(static_cast(mPendingPort), + {scancode, static_cast(mPendingKeyButton)}); + } else { + PADSetKeyAxisBinding(static_cast(mPendingPort), + {scancode, static_cast(mPendingKeyAxis), 0}); + } + finish_pending_key_binding(); + } + return; + } + if (mPendingButtonMapping != nullptr) { const s32 nativeButton = PADGetNativeButtonPressed(mPendingPort); if (nativeButton != -1) { @@ -590,26 +865,40 @@ void ControllerConfigWindow::finish_pending_binding(int completedPort) { } void ControllerConfigWindow::unmap_pending_binding() { - if (mPendingButtonMapping == nullptr && mPendingAxisMapping == nullptr) { + if (mPendingButtonMapping == nullptr && mPendingAxisMapping == nullptr && + mPendingKeyButton < 0 && mPendingKeyAxis < 0) + { return; } const int completedPort = mPendingPort; if (mPendingButtonMapping != nullptr) { mPendingButtonMapping->nativeButton = PAD_NATIVE_BUTTON_INVALID; - } - if (mPendingAxisMapping != nullptr) { + finish_pending_binding(completedPort); + } else if (mPendingAxisMapping != nullptr) { mPendingAxisMapping->nativeAxis = {-1, AXIS_SIGN_POSITIVE}; mPendingAxisMapping->nativeButton = -1; + finish_pending_binding(completedPort); + } else if (mPendingKeyButton >= 0) { + PADSetKeyButtonBinding(static_cast(completedPort), + {PAD_KEY_INVALID, static_cast(mPendingKeyButton)}); + finish_pending_key_binding(); + } else if (mPendingKeyAxis >= 0) { + PADSetKeyAxisBinding(static_cast(completedPort), + {PAD_KEY_INVALID, static_cast(mPendingKeyAxis), 0}); + finish_pending_key_binding(); } - finish_pending_binding(completedPort); } bool ControllerConfigWindow::capture_active() const { - return mPendingButtonMapping != nullptr || mPendingAxisMapping != nullptr; + return mPendingButtonMapping != nullptr || mPendingAxisMapping != nullptr || + mPendingKeyButton >= 0 || mPendingKeyAxis >= 0; } bool ControllerConfigWindow::pending_input_neutral() const { + if (mPendingKeyButton >= 0 || mPendingKeyAxis >= 0) { + return keyboard_neutral(); + } return input_neutral(mPendingPort); } @@ -623,16 +912,30 @@ Rml::String ControllerConfigWindow::pending_axis_label() const { void ControllerConfigWindow::cancel_pending_binding() { if (mPendingButtonMapping == nullptr && mPendingAxisMapping == nullptr && - !mSuppressNavigationUntilNeutral) + !mSuppressNavigationUntilNeutral && mPendingKeyButton < 0 && mPendingKeyAxis < 0) { return; } mPendingButtonMapping = nullptr; mPendingAxisMapping = nullptr; + mPendingKeyButton = -1; + mPendingKeyAxis = -1; mPendingPort = -1; mPendingBindingArmed = false; mSuppressNavigationUntilNeutral = false; mSuppressNavigationPort = -1; } +void ControllerConfigWindow::finish_pending_key_binding() { + mPendingKeyButton = -1; + mPendingKeyAxis = -1; + mPendingPort = -1; + mPendingBindingArmed = false; + PADSerializeMappings(); +} + +Rml::String ControllerConfigWindow::pending_key_label() const { + return mPendingBindingArmed ? "Press a key or mouse button..." : "Waiting..."; +} + } // namespace dusk::ui diff --git a/src/dusk/ui/controller_config.hpp b/src/dusk/ui/controller_config.hpp index 4bcf41ae8d..c2a037309e 100644 --- a/src/dusk/ui/controller_config.hpp +++ b/src/dusk/ui/controller_config.hpp @@ -32,6 +32,8 @@ private: Rml::String pending_button_label() const; Rml::String pending_axis_label() const; void cancel_pending_binding(); + void finish_pending_key_binding(); + Rml::String pending_key_label() const; Page mPage = Page::Controller; Pane* mRightPane = nullptr; @@ -42,6 +44,8 @@ private: int mSuppressNavigationPort = -1; PADButtonMapping* mPendingButtonMapping = nullptr; PADAxisMapping* mPendingAxisMapping = nullptr; + int mPendingKeyButton = -1; + int mPendingKeyAxis = -1; }; } // namespace dusk::ui diff --git a/src/dusk/ui/overlay.cpp b/src/dusk/ui/overlay.cpp index c11ad51b78..a5c0e036d2 100644 --- a/src/dusk/ui/overlay.cpp +++ b/src/dusk/ui/overlay.cpp @@ -187,8 +187,9 @@ void Overlay::update() { return; } - const bool showControllerWarning = - PADGetIndexForPort(PAD_CHAN0) < 0 && dynamic_cast(top_document()) == nullptr; + const bool showControllerWarning = PADGetIndexForPort(PAD_CHAN0) < 0 && + PADGetKeyButtonBindings(PAD_CHAN0, nullptr) == nullptr && + dynamic_cast(top_document()) == nullptr; if (showControllerWarning && mControllerWarning == nullptr) { mControllerWarning = create_controller_warning(mDocument); } else if (showControllerWarning && mControllerWarning != nullptr) { diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index f7b6cd8865..25d367cab9 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -280,7 +280,6 @@ void main01(void) { for (int sim_tick = 0; sim_tick < pacing.sim_ticks_to_run; ++sim_tick) { dusk::frame_interp::begin_sim_tick(); mDoCPd_c::read(); - DuskDebugPad(); dusk::gyro::read(pacing.sim_pace); fapGm_Execute(); mDoAud_Execute();