From 9ad0e0bd88f07450b73ab82fafa4b308cba1bfa8 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 23 Sep 2024 20:47:12 -0400 Subject: [PATCH 01/28] add: WIP first working attempt --- Code/client/Services/Debug/DebugService.cpp | 4 + .../Services/Debug/Views/RebindView.cpp | 77 ++++ Code/client/Services/DebugService.h | 1 + Code/client/Services/Generic/InputService.cpp | 46 ++- Code/client/Services/InputService.h | 354 ++++++++++++++++++ Code/client/World.h | 4 + 6 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 Code/client/Services/Debug/Views/RebindView.cpp diff --git a/Code/client/Services/Debug/DebugService.cpp b/Code/client/Services/Debug/DebugService.cpp index 00c6ef9cb..e1479825d 100644 --- a/Code/client/Services/Debug/DebugService.cpp +++ b/Code/client/Services/Debug/DebugService.cpp @@ -236,6 +236,7 @@ static bool g_enableWeatherWindow{false}; static bool g_enableCombatWindow{false}; static bool g_enableCalendarWindow{false}; static bool g_enableDragonSpawnerWindow{false}; +static bool g_enableRebindWindow{false}; void DebugService::DrawServerView() noexcept { @@ -336,6 +337,7 @@ void DebugService::OnDraw() noexcept ImGui::MenuItem("Server", nullptr, &g_enableServerWindow); ImGui::MenuItem("Party", nullptr, &g_enablePartyWindow); ImGui::MenuItem("Dragon spawner", nullptr, &g_enableDragonSpawnerWindow); + ImGui::MenuItem("Rebind", nullptr, &g_enableRebindWindow); #if (!IS_MASTER) ImGui::MenuItem("Network", nullptr, &g_enableNetworkWindow); @@ -382,6 +384,8 @@ void DebugService::OnDraw() noexcept DrawPartyView(); if (g_enableDragonSpawnerWindow) DrawDragonSpawnerView(); + if (g_enableRebindWindow) + DrawRebindView(); #if (!IS_MASTER) if (g_enableNetworkWindow) diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/RebindView.cpp new file mode 100644 index 000000000..91a2a1e2b --- /dev/null +++ b/Code/client/Services/Debug/Views/RebindView.cpp @@ -0,0 +1,77 @@ +#include "DInputHook.hpp" + +#include + +#include "World.h" + +#include + +void DebugService::DrawRebindView() +{ +#if TP_SKYRIM64 + auto& inputService = World::Get().GetInputService(); + std::pair uiKey = inputService.GetUIKey(); + static bool s_bindingActive = false; + + ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); + ImGui::Begin("Rebind"); + + if (ImGui::CollapsingHeader("UI")) + { + if (ImGui::Button("Open/Close", ImVec2(150, 30)) || s_bindingActive) + { + ImGui::SameLine(0); + s_bindingActive = true; + + if (s_bindingActive) + ImGui::Text("Press a key..."); + else + ImGui::Text(uiKey.first.c_str()); + + // Loop through all virtual keys to find which key is pressed + for (int key = 1; key < 256; key++) + { + if (GetAsyncKeyState(key) & 0x8000) + { + if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) + break; + + auto& newKey = inputService.GetKey(key); + + if (!newKey.first.empty()) + { + s_bindingActive = false; + uiKey = newKey; + + if(inputService.SetUIKey(uiKey.first)) + { + uint32_t directInputKey = inputService.GetDirectInputKeyCode(uiKey.second); + + if (directInputKey) + { + TiltedPhoques::DInputHook::Get().SetToggleKeys({DIK_RCONTROL, directInputKey}); + } + + break; + } + + spdlog::warn("{} key was not found", uiKey.first); + } + } + } + } + else + { + ImGui::SameLine(0); + ImGui::Text("%s", uiKey.first.c_str()); + } + } + + if (ImGui::CollapsingHeader("Debug")) + { + + } + + ImGui::End(); +#endif +} diff --git a/Code/client/Services/DebugService.h b/Code/client/Services/DebugService.h index 32a967855..020540894 100644 --- a/Code/client/Services/DebugService.h +++ b/Code/client/Services/DebugService.h @@ -60,6 +60,7 @@ struct DebugService void DrawCombatView(); void DrawCalendarView(); void DrawDragonSpawnerView(); + void DrawRebindView(); public: bool m_showDebugStuff = false; diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index d6d8c2324..29d950c4e 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -95,7 +95,7 @@ uint32_t GetCefModifiers(uint16_t aVirtualKey) // remember to update this when updating toggle keys bool IsToggleKey(int aKey) noexcept { - return aKey == VK_RCONTROL || aKey == VK_F2; + return aKey == World::Get().GetInputService().GetUIKey().second; } bool IsDisableKey(int aKey) noexcept @@ -458,6 +458,50 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } +const std::pair& InputService::GetKey(int32_t aKeyCode) const noexcept +{ + for (const auto& key : m_virtualKeys) + { + if (key.second == aKeyCode) + return key; + } + + return std::pair("", -1); +} + +const std::pair& InputService::GetKey(const TiltedPhoques::String& acKeyName) const noexcept +{ + for (const auto& key : m_virtualKeys) + { + if (key.first == acKeyName) + return key; + } + + return std::pair("", -1); +} + +bool InputService::SetUIKey(const TiltedPhoques::String& acKeyName) noexcept +{ + if (const auto& key = GetKey(acKeyName); !key.first.empty()) + { + World::Get().GetInputService().m_uiKey = key; + return true; + } + + return false; +} + +bool InputService::SetUIKey(int32_t aKeyCode) noexcept +{ + if (const auto& key = GetKey(aKeyCode); key.second != -1) + { + World::Get().GetInputService().m_uiKey = key; + return true; + } + + return false; +} + InputService::InputService(OverlayService& aOverlay) noexcept { s_pOverlay = &aOverlay; diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index bf86ce052..8e64fa2d3 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -1,4 +1,5 @@ #pragma once +#include struct OverlayService; @@ -12,5 +13,358 @@ struct InputService static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + std::pair GetUIKey() const noexcept { return m_uiKey; } + bool SetUIKey(const TiltedPhoques::String& aKeyName) noexcept; + bool SetUIKey(int32_t aKeyCode) noexcept; + const std::pair& GetKey(int32_t aKeyCode) const noexcept; + const std::pair& GetKey(const TiltedPhoques::String& acKeyName) const noexcept; + const TiltedPhoques::Map& GetVirtualKeys() const noexcept { return m_virtualKeys; } + const int32_t GetDirectInputKeyCode(int32_t aVirtualKeyCode) const noexcept { return m_directInputKeys.find(aVirtualKeyCode).value(); } + + + // assumes US standard keyboard layout because that was the most documented list + // https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + const TiltedPhoques::Map m_virtualKeys + { + {"A", 0x41}, + {"B", 0x42}, + {"C", 0x43}, + {"D", 0x44}, + {"E", 0x45}, + {"F", 0x46}, + {"G", 0x47}, + {"H", 0x48}, + {"I", 0x49}, + {"J", 0x4A}, + {"K", 0x4B}, + {"L", 0x4C}, + {"M", 0x4D}, + {"N", 0x4E}, + {"O", 0x4F}, + {"P", 0x50}, + {"Q", 0x51}, + {"R", 0x52}, + {"S", 0x53}, + {"T", 0x54}, + {"U", 0x55}, + {"V", 0x56}, + {"W", 0x57}, + {"X", 0x58}, + {"Y", 0x59}, + {"Z", 0x5A}, + {"0", 0x30}, + {"1", 0x31}, + {"2", 0x32}, + {"3", 0x33}, + {"4", 0x34}, + {"5", 0x35}, + {"6", 0x36}, + {"7", 0x37}, + {"8", 0x38}, + {"9", 0x39}, + {"MOUSE1", VK_LBUTTON}, + {"MOUSE2", VK_RBUTTON}, + {"MOUSE3", VK_MBUTTON}, + {"MOUSE4", VK_XBUTTON1}, + {"MOUSE5", VK_XBUTTON2}, + {"Backspace", VK_BACK}, + {"Tab", VK_TAB}, + {"Clear", VK_CLEAR}, + {"Enter", VK_RETURN}, + {"LSHIFT", VK_LSHIFT}, + {"RSHIFT", VK_RSHIFT}, + {"LCTRL", VK_LCONTROL}, + {"RCTRL", VK_RCONTROL}, + {"LALT", VK_LMENU}, + {"RALT", VK_RMENU}, + {"Pause", VK_PAUSE}, + {"Caps Lock", VK_CAPITAL}, + {"IME Kana mode", VK_KANA}, + {"IME Hangul mode", VK_HANGUL}, + {"IME On", VK_IME_ON}, + {"IME Junja mode", VK_JUNJA}, + {"IME final mode", VK_FINAL}, + {"IME Hanja mode", VK_HANJA}, + {"IME Kanji mode", VK_KANJI}, + {"IME Off", VK_IME_OFF}, + {"Esc", VK_ESCAPE}, + {"IME convert", VK_CONVERT}, + {"IME nonconvert", VK_NONCONVERT}, + {"IME accept", VK_ACCEPT}, + {"IME mode change request", VK_MODECHANGE}, + {"Space", VK_SPACE}, + {"Page Up", VK_PRIOR}, + {"Page Down", VK_NEXT}, + {"End", VK_END}, + {"Home", VK_HOME}, + {"Left Arrow", VK_LEFT}, + {"Up Arrow", VK_UP}, + {"Right Arrow", VK_RIGHT}, + {"Down Arrow", VK_DOWN}, + {"Select", VK_SELECT}, + {"Print", VK_PRINT}, + {"Execute", VK_EXECUTE}, + {"PrtSc", VK_SNAPSHOT}, + {"Insert", VK_INSERT}, + {"Delete", VK_DELETE}, + {"Help", VK_HELP}, + {"LWIN", VK_LWIN}, + {"RWIN", VK_RWIN}, + {"Applications", VK_APPS}, + {"Sleep", VK_SLEEP}, + {"NUMPAD0", VK_NUMPAD0}, + {"NUMPAD1", VK_NUMPAD1}, + {"NUMPAD2", VK_NUMPAD2}, + {"NUMPAD3", VK_NUMPAD3}, + {"NUMPAD4", VK_NUMPAD4}, + {"NUMPAD5", VK_NUMPAD5}, + {"NUMPAD6", VK_NUMPAD6}, + {"NUMPAD7", VK_NUMPAD7}, + {"NUMPAD8", VK_NUMPAD8}, + {"NUMPAD9", VK_NUMPAD9}, + {"*", VK_MULTIPLY}, + {"Add", VK_ADD}, + {"Separator", VK_SEPARATOR}, + {"Subtract", VK_SUBTRACT}, + {"Decimal", VK_DECIMAL}, + {"Divide", VK_DIVIDE}, + {"F1", VK_F1}, + {"F2", VK_F2}, + {"F3", VK_F3}, + {"F4", VK_F4}, + {"F5", VK_F5}, + {"F6", VK_F6}, + {"F7", VK_F7}, + {"F8", VK_F8}, + {"F9", VK_F9}, + {"F10", VK_F10}, + {"F11", VK_F11}, + {"F12", VK_F12}, + {"F13", VK_F13}, + {"F14", VK_F14}, + {"F15", VK_F15}, + {"F16", VK_F16}, + {"F17", VK_F17}, + {"F18", VK_F18}, + {"F19", VK_F19}, + {"F20", VK_F20}, + {"F21", VK_F21}, + {"F22", VK_F22}, + {"F23", VK_F23}, + {"F24", VK_F24}, + {"Num Lock", VK_NUMLOCK}, + {"Scroll Lock", VK_SCROLL}, + {"Browser Back", VK_BROWSER_BACK}, + {"Browser Forward", VK_BROWSER_FORWARD}, + {"Browser Refresh", VK_BROWSER_REFRESH}, + {"Browser Stop", VK_BROWSER_STOP}, + {"Browser Search", VK_BROWSER_SEARCH}, + {"Browser Favorites", VK_BROWSER_FAVORITES}, + {"Browser Stard and Home", VK_BROWSER_HOME}, + {"Volume Mute", VK_VOLUME_MUTE}, + {"Volume Down", VK_VOLUME_DOWN}, + {"Volume Up", VK_VOLUME_UP}, + {"Next Track", VK_MEDIA_NEXT_TRACK}, + {"Previous Track", VK_MEDIA_PREV_TRACK}, + {"Stop Media", VK_MEDIA_STOP}, + {"Play/Pause Media", VK_MEDIA_PLAY_PAUSE}, + {"Start Mail", VK_LAUNCH_MAIL}, + {"Select Media", VK_LAUNCH_MEDIA_SELECT}, + {"Start Application 1", VK_LAUNCH_APP1}, + {"Start Application 2", VK_LAUNCH_APP2}, + {"=", VK_OEM_PLUS}, // <-- EQUALS???? + {",", VK_OEM_COMMA}, + {"-", VK_OEM_MINUS}, + {".", VK_OEM_PERIOD}, + {";", VK_OEM_1}, + {"/", VK_OEM_2}, + {"`", VK_OEM_3}, + {"[", VK_OEM_4}, + {"\\", VK_OEM_5}, + {"]", VK_OEM_6}, + {"'", VK_OEM_7}, + {"IME PROCESS", VK_PROCESSKEY}, + {"Attn", VK_ATTN}, + {"CrSel", VK_CRSEL}, + {"ExSel", VK_EXSEL}, + {"Erase EOF", VK_EREOF}, + {"Play", VK_PLAY}, + {"Zoom", VK_ZOOM}, + {"PA1", VK_PA1}, + {"Clear", VK_OEM_CLEAR} + }; + + const TiltedPhoques::Map m_directInputKeys + { + {0x41, DIK_A}, + {0x42, DIK_B}, + {0x43, DIK_C}, + {0x44, DIK_D}, + {0x45, DIK_E}, + {0x46, DIK_F}, + {0x47, DIK_G}, + {0x48, DIK_H}, + {0x49, DIK_I}, + {0x4A, DIK_J}, + {0x4B, DIK_K}, + {0x4C, DIK_L}, + {0x4D, DIK_M}, + {0x4E, DIK_N}, + {0x4F, DIK_O}, + {0x50, DIK_P}, + {0x51, DIK_Q}, + {0x52, DIK_R}, + {0x53, DIK_S}, + {0x54, DIK_T}, + {0x55, DIK_U}, + {0x56, DIK_V}, + {0x57, DIK_W}, + {0x58, DIK_X}, + {0x59, DIK_Y}, + {0x5A, DIK_Z}, + {0x30, DIK_0}, + {0x31, DIK_1}, + {0x32, DIK_2}, + {0x33, DIK_3}, + {0x34, DIK_4}, + {0x35, DIK_5}, + {0x36, DIK_6}, + {0x37, DIK_7}, + {0x38, DIK_8}, + {0x39, DIK_9}, + {VK_LBUTTON, DIMOUSE_BUTTON0}, + {VK_RBUTTON, DIMOUSE_BUTTON1}, + {VK_MBUTTON, DIMOUSE_BUTTON2}, + {VK_XBUTTON1, DIMOUSE_BUTTON3}, + {VK_XBUTTON2, DIMOUSE_BUTTON4}, + {VK_BACK, DIK_BACK}, + {VK_TAB, DIK_TAB}, + {VK_CLEAR, VK_CLEAR}, + {VK_RETURN, DIK_RETURN}, + {VK_LSHIFT, DIK_LSHIFT}, + {VK_RSHIFT, DIK_RSHIFT}, + {VK_LCONTROL, DIK_LCONTROL}, + {VK_RCONTROL, DIK_RCONTROL}, + {VK_LMENU, DIK_LMENU}, + {VK_RMENU, DIK_RMENU}, + {VK_PAUSE, DIK_PAUSE}, + {VK_CAPITAL, DIK_CAPITAL}, + {VK_KANA, DIK_KANA}, + {VK_HANGUL, VK_HANGUL}, + {VK_IME_ON, VK_IME_ON}, + {VK_JUNJA, VK_JUNJA}, + {VK_FINAL, VK_FINAL}, + {VK_HANJA, VK_HANJA}, + {VK_KANJI, DIK_KANJI}, + {VK_IME_OFF, VK_IME_OFF}, + {VK_ESCAPE, DIK_ESCAPE}, + {VK_CONVERT, DIK_CONVERT}, + {VK_NONCONVERT, DIK_NOCONVERT}, + {VK_ACCEPT, VK_ACCEPT}, + {VK_MODECHANGE, VK_MODECHANGE}, + {VK_SPACE, DIK_SPACE}, + {VK_PRIOR, DIK_PRIOR}, + {VK_NEXT, DIK_NEXT}, + {VK_END, DIK_END}, + {VK_HOME, DIK_HOME}, + {VK_LEFT, DIK_LEFT}, + {VK_UP, DIK_UP}, + {VK_RIGHT, DIK_RIGHT}, + {VK_DOWN, DIK_DOWN}, + {VK_SELECT, VK_SELECT}, + {VK_PRINT, VK_PRINT}, + {VK_EXECUTE, VK_EXECUTE}, + {VK_SNAPSHOT, VK_SNAPSHOT}, + {VK_INSERT, DIK_INSERT}, + {VK_DELETE, DIK_DELETE}, + {VK_HELP, VK_HELP}, + {VK_LWIN, DIK_LWIN}, + {VK_RWIN, DIK_RWIN}, + {VK_APPS, DIK_APPS}, + {VK_SLEEP, DIK_SLEEP}, + {VK_NUMPAD0, DIK_NUMPAD0}, + {VK_NUMPAD1, DIK_NUMPAD1}, + {VK_NUMPAD2, DIK_NUMPAD2}, + {VK_NUMPAD3, DIK_NUMPAD3}, + {VK_NUMPAD4, DIK_NUMPAD4}, + {VK_NUMPAD5, DIK_NUMPAD5}, + {VK_NUMPAD6, DIK_NUMPAD6}, + {VK_NUMPAD7, DIK_NUMPAD7}, + {VK_NUMPAD8, DIK_NUMPAD8}, + {VK_NUMPAD9, DIK_NUMPAD9}, + {VK_MULTIPLY, DIK_MULTIPLY}, + {VK_ADD, DIK_NUMPADPLUS}, + {VK_SEPARATOR, DIK_PERIOD}, + {VK_SUBTRACT, DIK_SUBTRACT}, + {VK_DECIMAL, DIK_DECIMAL}, + {VK_DIVIDE, DIK_DIVIDE}, + {VK_F1, DIK_F1}, + {VK_F2, DIK_F2}, + {VK_F3, DIK_F3}, + {VK_F4, DIK_F4}, + {VK_F5, DIK_F5}, + {VK_F6, DIK_F6}, + {VK_F7, DIK_F7}, + {VK_F8, DIK_F8}, + {VK_F9, DIK_F9}, + {VK_F10, DIK_F10}, + {VK_F11, DIK_F11}, + {VK_F12, DIK_F12}, + {VK_F13, DIK_F13}, + {VK_F14, DIK_F14}, + {VK_F15, DIK_F15}, + {VK_F16, VK_F16}, + {VK_F17, VK_F17}, + {VK_F18, VK_F18}, + {VK_F19, VK_F19}, + {VK_F20, VK_F20}, + {VK_F21, VK_F21}, + {VK_F22, VK_F22}, + {VK_F23, VK_F23}, + {VK_F24, VK_F24}, + {VK_NUMLOCK, DIK_NUMLOCK}, + {VK_SCROLL, DIK_SCROLL}, + {VK_BROWSER_BACK, DIK_WEBBACK}, + {VK_BROWSER_FORWARD, DIK_WEBFORWARD}, + {VK_BROWSER_REFRESH, DIK_WEBREFRESH}, + {VK_BROWSER_STOP, DIK_WEBSTOP}, + {VK_BROWSER_SEARCH, DIK_WEBSEARCH}, + {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}, + {VK_BROWSER_HOME, DIK_WEBHOME}, + {VK_VOLUME_MUTE, DIK_MUTE}, + {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}, + {VK_VOLUME_UP, DIK_VOLUMEUP}, + {VK_MEDIA_NEXT_TRACK, DIK_NEXTTRACK}, + {VK_MEDIA_PREV_TRACK, DIK_PREVTRACK}, + {VK_MEDIA_STOP, DIK_MEDIASTOP}, + {VK_MEDIA_PLAY_PAUSE, DIK_PLAYPAUSE}, + {VK_LAUNCH_MAIL, DIK_MAIL}, + {VK_LAUNCH_MEDIA_SELECT, DIK_MEDIASELECT}, + {VK_LAUNCH_APP1, VK_LAUNCH_APP1}, + {VK_LAUNCH_APP2, VK_LAUNCH_APP2}, + {VK_OEM_PLUS, DIK_EQUALS}, + {VK_OEM_COMMA, DIK_COMMA}, + {VK_OEM_MINUS, DIK_MINUS}, + {VK_OEM_PERIOD, DIK_PERIOD}, + {VK_OEM_1, DIK_SEMICOLON}, + {VK_OEM_2, DIK_SLASH}, + {VK_OEM_3, DIK_GRAVE}, + {VK_OEM_4, DIK_LBRACKET}, + {VK_OEM_5, DIK_BACKSLASH}, + {VK_OEM_6, DIK_RBRACKET}, + {VK_OEM_7, DIK_APOSTROPHE}, + {VK_PROCESSKEY, VK_PROCESSKEY}, + {VK_ATTN, VK_ATTN}, + {VK_CRSEL, VK_CRSEL}, + {VK_EXSEL, VK_EXSEL}, + {VK_EREOF, VK_EREOF}, + {VK_PLAY, VK_PLAY}, + {VK_ZOOM, VK_ZOOM}, + {VK_PA1, VK_PA1}, + {VK_OEM_CLEAR, VK_OEM_CLEAR} + }; + + std::pair m_uiKey{"F2", VK_F2}; + TP_NOCOPYMOVE(InputService); }; diff --git a/Code/client/World.h b/Code/client/World.h index 862f49b5f..96dc4d4db 100644 --- a/Code/client/World.h +++ b/Code/client/World.h @@ -1,5 +1,6 @@ #pragma once + #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include "Services/InputService.h" #include @@ -31,6 +33,8 @@ struct World : entt::registry const OverlayService& GetOverlayService() const noexcept { return ctx().at(); } DebugService& GetDebugService() noexcept { return ctx().at(); } const DebugService& GetDebugService() const noexcept { return ctx().at(); } + InputService& GetInputService() noexcept { return ctx().at(); } + const InputService& GetInputService() const noexcept { return ctx().at(); } auto& GetDispatcher() noexcept { return m_dispatcher; } From 8bcfd787ed51253ed5f2fa8880bca6bc04df3c34 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 25 Sep 2024 15:27:55 -0400 Subject: [PATCH 02/28] add: RebindService --- .../Services/Debug/Views/RebindView.cpp | 18 +- Code/client/Services/Generic/InputService.cpp | 49 +-- .../client/Services/Generic/RebindService.cpp | 130 +++++++ Code/client/Services/InputService.h | 362 +----------------- Code/client/Services/RebindService.h | 235 ++++++++++++ Code/client/World.cpp | 1 + Code/client/World.h | 4 + 7 files changed, 394 insertions(+), 405 deletions(-) create mode 100644 Code/client/Services/Generic/RebindService.cpp create mode 100644 Code/client/Services/RebindService.h diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/RebindView.cpp index 91a2a1e2b..3bb5771f9 100644 --- a/Code/client/Services/Debug/Views/RebindView.cpp +++ b/Code/client/Services/Debug/Views/RebindView.cpp @@ -1,6 +1,7 @@ #include "DInputHook.hpp" #include +#include #include "World.h" @@ -10,7 +11,8 @@ void DebugService::DrawRebindView() { #if TP_SKYRIM64 auto& inputService = World::Get().GetInputService(); - std::pair uiKey = inputService.GetUIKey(); + auto& rebindService = World::Get().GetRebindService(); + auto uiKey = inputService.GetUIKey(); static bool s_bindingActive = false; ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); @@ -18,7 +20,7 @@ void DebugService::DrawRebindView() if (ImGui::CollapsingHeader("UI")) { - if (ImGui::Button("Open/Close", ImVec2(150, 30)) || s_bindingActive) + if (ImGui::Button("Open/Close", ImVec2(100, 30)) || s_bindingActive) { ImGui::SameLine(0); s_bindingActive = true; @@ -36,22 +38,16 @@ void DebugService::DrawRebindView() if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) break; - auto& newKey = inputService.GetKey(key); + auto& newKey = rebindService.GetKeyFromVKKeyCode(key); if (!newKey.first.empty()) { s_bindingActive = false; uiKey = newKey; - if(inputService.SetUIKey(uiKey.first)) + if(rebindService.SetUIKey(uiKey)) { - uint32_t directInputKey = inputService.GetDirectInputKeyCode(uiKey.second); - - if (directInputKey) - { - TiltedPhoques::DInputHook::Get().SetToggleKeys({DIK_RCONTROL, directInputKey}); - } - + TiltedPhoques::DInputHook::Get().SetToggleKeys({DIK_RCONTROL, static_cast(uiKey.second.diKeyCode)}); break; } diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 29d950c4e..a9d48592d 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -95,7 +95,7 @@ uint32_t GetCefModifiers(uint16_t aVirtualKey) // remember to update this when updating toggle keys bool IsToggleKey(int aKey) noexcept { - return aKey == World::Get().GetInputService().GetUIKey().second; + return aKey == World::Get().GetInputService().GetUIKey().second.vkKeyCode; } bool IsDisableKey(int aKey) noexcept @@ -458,54 +458,21 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } -const std::pair& InputService::GetKey(int32_t aKeyCode) const noexcept +bool InputService::SetUIKey(const RebindService::Key& acKey) noexcept { - for (const auto& key : m_virtualKeys) - { - if (key.second == aKeyCode) - return key; - } - - return std::pair("", -1); -} - -const std::pair& InputService::GetKey(const TiltedPhoques::String& acKeyName) const noexcept -{ - for (const auto& key : m_virtualKeys) - { - if (key.first == acKeyName) - return key; - } - - return std::pair("", -1); -} - -bool InputService::SetUIKey(const TiltedPhoques::String& acKeyName) noexcept -{ - if (const auto& key = GetKey(acKeyName); !key.first.empty()) - { - World::Get().GetInputService().m_uiKey = key; - return true; - } - - return false; + if (acKey.first.empty() || acKey.second.diKeyCode == -1 || acKey.second.vkKeyCode == -1) + return false; + + m_pUiKey = acKey; + return true; } -bool InputService::SetUIKey(int32_t aKeyCode) noexcept -{ - if (const auto& key = GetKey(aKeyCode); key.second != -1) - { - World::Get().GetInputService().m_uiKey = key; - return true; - } - - return false; -} InputService::InputService(OverlayService& aOverlay) noexcept { s_pOverlay = &aOverlay; s_currentACP = GetRealACP(); + m_pUiKey = {"F2", {VK_F2, DIK_F2}}; } InputService::~InputService() noexcept diff --git a/Code/client/Services/Generic/RebindService.cpp b/Code/client/Services/Generic/RebindService.cpp new file mode 100644 index 000000000..1736575fa --- /dev/null +++ b/Code/client/Services/Generic/RebindService.cpp @@ -0,0 +1,130 @@ +#include "Services/RebindService.h" + +RebindService::RebindService(InputService& aInputService) : + m_inputService(aInputService) +{ +} + +const RebindService::Key& RebindService::GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept +{ + const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [acKeyName](const Key& aKey) { return aKey.first == acKeyName; }); + + Key pKey; + + if (key != m_keys.end()) + { + pKey = *key; + } + + return pKey; +} + + +const RebindService::Key& RebindService::GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept +{ + const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.vkKeyCode == aKeyCode; }); + + Key pKey; + + if (key != m_keys.end()) + { + pKey = *key; + } + + return pKey; +} + +const RebindService::Key& RebindService::GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept +{ + const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.diKeyCode == aKeyCode; }); + + Key pKey; + + if (key != m_keys.end()) + { + pKey = *key; + } + + return pKey; +} + +int32_t RebindService::GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept +{ + for (const auto& key : m_keys) + { + if (key.first == aKeyName) + return key.second.diKeyCode; + } + + /*if (const auto& key = m_keys.find(aKeyName); key != m_keys.end()) + { + return m_keys.find(aKeyName)->second.diKeyCode; + }*/ + + return KeyCodes::Error; +} + +int32_t RebindService::GetVKKeyCode(const TiltedPhoques::String& aKeyName) const noexcept +{ + for (const auto& key : m_keys) + { + if (key.first == aKeyName) + return key.second.vkKeyCode; + } + + /*if (const auto& key = m_keys.find(aKeyName); key != m_keys.end()) + { + return m_keys.find(aKeyName)->second.vkKeyCode; + }*/ + + return KeyCodes::Error; +} + +bool RebindService::SetUIKey(const Key& apKey) noexcept +{ + m_inputService.SetUIKey(apKey); + m_pUiKey = apKey; + return true; +} + +bool RebindService::SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept +{ + const auto& key = GetKeyFromVKKeyCode(aKeyCode); + + if (key != m_errorKey) + { + m_inputService.SetUIKey(key); + m_pUiKey = key; + return true; + } + + return false; +} + +bool RebindService::SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept +{ + const auto& key = GetKeyFromDIKeyCode(aKeyCode); + + if (key != m_errorKey) + { + m_inputService.SetUIKey(key); + m_pUiKey = key; + return true; + } + + return false; +} + +bool RebindService::SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept +{ + if (const auto& key = GetKeyFromName(acKeyName); key != m_errorKey) + { + //World::Get().GetInputService().SetUIKey(key); + m_inputService.SetUIKey(key); + m_pUiKey = key; + return true; + } + + return false; +} + diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index 8e64fa2d3..98a4d650f 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -1,5 +1,6 @@ #pragma once -#include + +#include struct OverlayService; @@ -11,360 +12,15 @@ struct InputService InputService(OverlayService& aOverlay) noexcept; ~InputService() noexcept; - static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - std::pair GetUIKey() const noexcept { return m_uiKey; } - bool SetUIKey(const TiltedPhoques::String& aKeyName) noexcept; - bool SetUIKey(int32_t aKeyCode) noexcept; - const std::pair& GetKey(int32_t aKeyCode) const noexcept; - const std::pair& GetKey(const TiltedPhoques::String& acKeyName) const noexcept; - const TiltedPhoques::Map& GetVirtualKeys() const noexcept { return m_virtualKeys; } - const int32_t GetDirectInputKeyCode(int32_t aVirtualKeyCode) const noexcept { return m_directInputKeys.find(aVirtualKeyCode).value(); } + // Use this function to get the player's current UI key + RebindService::Key GetUIKey() const noexcept { return m_pUiKey; } + bool SetUIKey(const RebindService::Key& apKey) noexcept; + static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - // assumes US standard keyboard layout because that was the most documented list - // https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - const TiltedPhoques::Map m_virtualKeys - { - {"A", 0x41}, - {"B", 0x42}, - {"C", 0x43}, - {"D", 0x44}, - {"E", 0x45}, - {"F", 0x46}, - {"G", 0x47}, - {"H", 0x48}, - {"I", 0x49}, - {"J", 0x4A}, - {"K", 0x4B}, - {"L", 0x4C}, - {"M", 0x4D}, - {"N", 0x4E}, - {"O", 0x4F}, - {"P", 0x50}, - {"Q", 0x51}, - {"R", 0x52}, - {"S", 0x53}, - {"T", 0x54}, - {"U", 0x55}, - {"V", 0x56}, - {"W", 0x57}, - {"X", 0x58}, - {"Y", 0x59}, - {"Z", 0x5A}, - {"0", 0x30}, - {"1", 0x31}, - {"2", 0x32}, - {"3", 0x33}, - {"4", 0x34}, - {"5", 0x35}, - {"6", 0x36}, - {"7", 0x37}, - {"8", 0x38}, - {"9", 0x39}, - {"MOUSE1", VK_LBUTTON}, - {"MOUSE2", VK_RBUTTON}, - {"MOUSE3", VK_MBUTTON}, - {"MOUSE4", VK_XBUTTON1}, - {"MOUSE5", VK_XBUTTON2}, - {"Backspace", VK_BACK}, - {"Tab", VK_TAB}, - {"Clear", VK_CLEAR}, - {"Enter", VK_RETURN}, - {"LSHIFT", VK_LSHIFT}, - {"RSHIFT", VK_RSHIFT}, - {"LCTRL", VK_LCONTROL}, - {"RCTRL", VK_RCONTROL}, - {"LALT", VK_LMENU}, - {"RALT", VK_RMENU}, - {"Pause", VK_PAUSE}, - {"Caps Lock", VK_CAPITAL}, - {"IME Kana mode", VK_KANA}, - {"IME Hangul mode", VK_HANGUL}, - {"IME On", VK_IME_ON}, - {"IME Junja mode", VK_JUNJA}, - {"IME final mode", VK_FINAL}, - {"IME Hanja mode", VK_HANJA}, - {"IME Kanji mode", VK_KANJI}, - {"IME Off", VK_IME_OFF}, - {"Esc", VK_ESCAPE}, - {"IME convert", VK_CONVERT}, - {"IME nonconvert", VK_NONCONVERT}, - {"IME accept", VK_ACCEPT}, - {"IME mode change request", VK_MODECHANGE}, - {"Space", VK_SPACE}, - {"Page Up", VK_PRIOR}, - {"Page Down", VK_NEXT}, - {"End", VK_END}, - {"Home", VK_HOME}, - {"Left Arrow", VK_LEFT}, - {"Up Arrow", VK_UP}, - {"Right Arrow", VK_RIGHT}, - {"Down Arrow", VK_DOWN}, - {"Select", VK_SELECT}, - {"Print", VK_PRINT}, - {"Execute", VK_EXECUTE}, - {"PrtSc", VK_SNAPSHOT}, - {"Insert", VK_INSERT}, - {"Delete", VK_DELETE}, - {"Help", VK_HELP}, - {"LWIN", VK_LWIN}, - {"RWIN", VK_RWIN}, - {"Applications", VK_APPS}, - {"Sleep", VK_SLEEP}, - {"NUMPAD0", VK_NUMPAD0}, - {"NUMPAD1", VK_NUMPAD1}, - {"NUMPAD2", VK_NUMPAD2}, - {"NUMPAD3", VK_NUMPAD3}, - {"NUMPAD4", VK_NUMPAD4}, - {"NUMPAD5", VK_NUMPAD5}, - {"NUMPAD6", VK_NUMPAD6}, - {"NUMPAD7", VK_NUMPAD7}, - {"NUMPAD8", VK_NUMPAD8}, - {"NUMPAD9", VK_NUMPAD9}, - {"*", VK_MULTIPLY}, - {"Add", VK_ADD}, - {"Separator", VK_SEPARATOR}, - {"Subtract", VK_SUBTRACT}, - {"Decimal", VK_DECIMAL}, - {"Divide", VK_DIVIDE}, - {"F1", VK_F1}, - {"F2", VK_F2}, - {"F3", VK_F3}, - {"F4", VK_F4}, - {"F5", VK_F5}, - {"F6", VK_F6}, - {"F7", VK_F7}, - {"F8", VK_F8}, - {"F9", VK_F9}, - {"F10", VK_F10}, - {"F11", VK_F11}, - {"F12", VK_F12}, - {"F13", VK_F13}, - {"F14", VK_F14}, - {"F15", VK_F15}, - {"F16", VK_F16}, - {"F17", VK_F17}, - {"F18", VK_F18}, - {"F19", VK_F19}, - {"F20", VK_F20}, - {"F21", VK_F21}, - {"F22", VK_F22}, - {"F23", VK_F23}, - {"F24", VK_F24}, - {"Num Lock", VK_NUMLOCK}, - {"Scroll Lock", VK_SCROLL}, - {"Browser Back", VK_BROWSER_BACK}, - {"Browser Forward", VK_BROWSER_FORWARD}, - {"Browser Refresh", VK_BROWSER_REFRESH}, - {"Browser Stop", VK_BROWSER_STOP}, - {"Browser Search", VK_BROWSER_SEARCH}, - {"Browser Favorites", VK_BROWSER_FAVORITES}, - {"Browser Stard and Home", VK_BROWSER_HOME}, - {"Volume Mute", VK_VOLUME_MUTE}, - {"Volume Down", VK_VOLUME_DOWN}, - {"Volume Up", VK_VOLUME_UP}, - {"Next Track", VK_MEDIA_NEXT_TRACK}, - {"Previous Track", VK_MEDIA_PREV_TRACK}, - {"Stop Media", VK_MEDIA_STOP}, - {"Play/Pause Media", VK_MEDIA_PLAY_PAUSE}, - {"Start Mail", VK_LAUNCH_MAIL}, - {"Select Media", VK_LAUNCH_MEDIA_SELECT}, - {"Start Application 1", VK_LAUNCH_APP1}, - {"Start Application 2", VK_LAUNCH_APP2}, - {"=", VK_OEM_PLUS}, // <-- EQUALS???? - {",", VK_OEM_COMMA}, - {"-", VK_OEM_MINUS}, - {".", VK_OEM_PERIOD}, - {";", VK_OEM_1}, - {"/", VK_OEM_2}, - {"`", VK_OEM_3}, - {"[", VK_OEM_4}, - {"\\", VK_OEM_5}, - {"]", VK_OEM_6}, - {"'", VK_OEM_7}, - {"IME PROCESS", VK_PROCESSKEY}, - {"Attn", VK_ATTN}, - {"CrSel", VK_CRSEL}, - {"ExSel", VK_EXSEL}, - {"Erase EOF", VK_EREOF}, - {"Play", VK_PLAY}, - {"Zoom", VK_ZOOM}, - {"PA1", VK_PA1}, - {"Clear", VK_OEM_CLEAR} - }; - - const TiltedPhoques::Map m_directInputKeys - { - {0x41, DIK_A}, - {0x42, DIK_B}, - {0x43, DIK_C}, - {0x44, DIK_D}, - {0x45, DIK_E}, - {0x46, DIK_F}, - {0x47, DIK_G}, - {0x48, DIK_H}, - {0x49, DIK_I}, - {0x4A, DIK_J}, - {0x4B, DIK_K}, - {0x4C, DIK_L}, - {0x4D, DIK_M}, - {0x4E, DIK_N}, - {0x4F, DIK_O}, - {0x50, DIK_P}, - {0x51, DIK_Q}, - {0x52, DIK_R}, - {0x53, DIK_S}, - {0x54, DIK_T}, - {0x55, DIK_U}, - {0x56, DIK_V}, - {0x57, DIK_W}, - {0x58, DIK_X}, - {0x59, DIK_Y}, - {0x5A, DIK_Z}, - {0x30, DIK_0}, - {0x31, DIK_1}, - {0x32, DIK_2}, - {0x33, DIK_3}, - {0x34, DIK_4}, - {0x35, DIK_5}, - {0x36, DIK_6}, - {0x37, DIK_7}, - {0x38, DIK_8}, - {0x39, DIK_9}, - {VK_LBUTTON, DIMOUSE_BUTTON0}, - {VK_RBUTTON, DIMOUSE_BUTTON1}, - {VK_MBUTTON, DIMOUSE_BUTTON2}, - {VK_XBUTTON1, DIMOUSE_BUTTON3}, - {VK_XBUTTON2, DIMOUSE_BUTTON4}, - {VK_BACK, DIK_BACK}, - {VK_TAB, DIK_TAB}, - {VK_CLEAR, VK_CLEAR}, - {VK_RETURN, DIK_RETURN}, - {VK_LSHIFT, DIK_LSHIFT}, - {VK_RSHIFT, DIK_RSHIFT}, - {VK_LCONTROL, DIK_LCONTROL}, - {VK_RCONTROL, DIK_RCONTROL}, - {VK_LMENU, DIK_LMENU}, - {VK_RMENU, DIK_RMENU}, - {VK_PAUSE, DIK_PAUSE}, - {VK_CAPITAL, DIK_CAPITAL}, - {VK_KANA, DIK_KANA}, - {VK_HANGUL, VK_HANGUL}, - {VK_IME_ON, VK_IME_ON}, - {VK_JUNJA, VK_JUNJA}, - {VK_FINAL, VK_FINAL}, - {VK_HANJA, VK_HANJA}, - {VK_KANJI, DIK_KANJI}, - {VK_IME_OFF, VK_IME_OFF}, - {VK_ESCAPE, DIK_ESCAPE}, - {VK_CONVERT, DIK_CONVERT}, - {VK_NONCONVERT, DIK_NOCONVERT}, - {VK_ACCEPT, VK_ACCEPT}, - {VK_MODECHANGE, VK_MODECHANGE}, - {VK_SPACE, DIK_SPACE}, - {VK_PRIOR, DIK_PRIOR}, - {VK_NEXT, DIK_NEXT}, - {VK_END, DIK_END}, - {VK_HOME, DIK_HOME}, - {VK_LEFT, DIK_LEFT}, - {VK_UP, DIK_UP}, - {VK_RIGHT, DIK_RIGHT}, - {VK_DOWN, DIK_DOWN}, - {VK_SELECT, VK_SELECT}, - {VK_PRINT, VK_PRINT}, - {VK_EXECUTE, VK_EXECUTE}, - {VK_SNAPSHOT, VK_SNAPSHOT}, - {VK_INSERT, DIK_INSERT}, - {VK_DELETE, DIK_DELETE}, - {VK_HELP, VK_HELP}, - {VK_LWIN, DIK_LWIN}, - {VK_RWIN, DIK_RWIN}, - {VK_APPS, DIK_APPS}, - {VK_SLEEP, DIK_SLEEP}, - {VK_NUMPAD0, DIK_NUMPAD0}, - {VK_NUMPAD1, DIK_NUMPAD1}, - {VK_NUMPAD2, DIK_NUMPAD2}, - {VK_NUMPAD3, DIK_NUMPAD3}, - {VK_NUMPAD4, DIK_NUMPAD4}, - {VK_NUMPAD5, DIK_NUMPAD5}, - {VK_NUMPAD6, DIK_NUMPAD6}, - {VK_NUMPAD7, DIK_NUMPAD7}, - {VK_NUMPAD8, DIK_NUMPAD8}, - {VK_NUMPAD9, DIK_NUMPAD9}, - {VK_MULTIPLY, DIK_MULTIPLY}, - {VK_ADD, DIK_NUMPADPLUS}, - {VK_SEPARATOR, DIK_PERIOD}, - {VK_SUBTRACT, DIK_SUBTRACT}, - {VK_DECIMAL, DIK_DECIMAL}, - {VK_DIVIDE, DIK_DIVIDE}, - {VK_F1, DIK_F1}, - {VK_F2, DIK_F2}, - {VK_F3, DIK_F3}, - {VK_F4, DIK_F4}, - {VK_F5, DIK_F5}, - {VK_F6, DIK_F6}, - {VK_F7, DIK_F7}, - {VK_F8, DIK_F8}, - {VK_F9, DIK_F9}, - {VK_F10, DIK_F10}, - {VK_F11, DIK_F11}, - {VK_F12, DIK_F12}, - {VK_F13, DIK_F13}, - {VK_F14, DIK_F14}, - {VK_F15, DIK_F15}, - {VK_F16, VK_F16}, - {VK_F17, VK_F17}, - {VK_F18, VK_F18}, - {VK_F19, VK_F19}, - {VK_F20, VK_F20}, - {VK_F21, VK_F21}, - {VK_F22, VK_F22}, - {VK_F23, VK_F23}, - {VK_F24, VK_F24}, - {VK_NUMLOCK, DIK_NUMLOCK}, - {VK_SCROLL, DIK_SCROLL}, - {VK_BROWSER_BACK, DIK_WEBBACK}, - {VK_BROWSER_FORWARD, DIK_WEBFORWARD}, - {VK_BROWSER_REFRESH, DIK_WEBREFRESH}, - {VK_BROWSER_STOP, DIK_WEBSTOP}, - {VK_BROWSER_SEARCH, DIK_WEBSEARCH}, - {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}, - {VK_BROWSER_HOME, DIK_WEBHOME}, - {VK_VOLUME_MUTE, DIK_MUTE}, - {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}, - {VK_VOLUME_UP, DIK_VOLUMEUP}, - {VK_MEDIA_NEXT_TRACK, DIK_NEXTTRACK}, - {VK_MEDIA_PREV_TRACK, DIK_PREVTRACK}, - {VK_MEDIA_STOP, DIK_MEDIASTOP}, - {VK_MEDIA_PLAY_PAUSE, DIK_PLAYPAUSE}, - {VK_LAUNCH_MAIL, DIK_MAIL}, - {VK_LAUNCH_MEDIA_SELECT, DIK_MEDIASELECT}, - {VK_LAUNCH_APP1, VK_LAUNCH_APP1}, - {VK_LAUNCH_APP2, VK_LAUNCH_APP2}, - {VK_OEM_PLUS, DIK_EQUALS}, - {VK_OEM_COMMA, DIK_COMMA}, - {VK_OEM_MINUS, DIK_MINUS}, - {VK_OEM_PERIOD, DIK_PERIOD}, - {VK_OEM_1, DIK_SEMICOLON}, - {VK_OEM_2, DIK_SLASH}, - {VK_OEM_3, DIK_GRAVE}, - {VK_OEM_4, DIK_LBRACKET}, - {VK_OEM_5, DIK_BACKSLASH}, - {VK_OEM_6, DIK_RBRACKET}, - {VK_OEM_7, DIK_APOSTROPHE}, - {VK_PROCESSKEY, VK_PROCESSKEY}, - {VK_ATTN, VK_ATTN}, - {VK_CRSEL, VK_CRSEL}, - {VK_EXSEL, VK_EXSEL}, - {VK_EREOF, VK_EREOF}, - {VK_PLAY, VK_PLAY}, - {VK_ZOOM, VK_ZOOM}, - {VK_PA1, VK_PA1}, - {VK_OEM_CLEAR, VK_OEM_CLEAR} - }; - - std::pair m_uiKey{"F2", VK_F2}; +private: + // RebindService should handle any mutations of this key + RebindService::Key m_pUiKey; TP_NOCOPYMOVE(InputService); }; diff --git a/Code/client/Services/RebindService.h b/Code/client/Services/RebindService.h new file mode 100644 index 000000000..bda2fe490 --- /dev/null +++ b/Code/client/Services/RebindService.h @@ -0,0 +1,235 @@ +#pragma once + +#include + +struct InputService; + +struct RebindService +{ + struct KeyCodes + { + enum + { + Error = -1 + }; + + int32_t vkKeyCode = Error; + int32_t diKeyCode = Error; + + bool operator==(const KeyCodes& acKeyCodes) const + { + return this->vkKeyCode == acKeyCodes.vkKeyCode && this->diKeyCode == acKeyCodes.diKeyCode; + } + }; + + /*struct Key + { + TiltedPhoques::String keyName; + KeyCodes keyCodes; + + Key() : keyName(""), keyCodes({KeyCodes::Error, KeyCodes::Error}) + { + } + + Key(const TiltedPhoques::String& acKeyName, const KeyCodes& acKeyCodes) : + keyName(acKeyName), keyCodes(acKeyCodes) + { + } + + Key(const Key& acKey) + { + keyName = acKey.keyName; + keyCodes = acKey.keyCodes; + } + + Key(const std::pair& acKey) + { + keyName = acKey.first; + keyCodes = acKey.second; + } + + bool operator==(const Key& acKey) const + { + return this->keyName == acKey.keyName && this->keyCodes == acKey.keyCodes; + } + + bool operator==(const std::pair& acKey) const + { + return this->keyName == acKey.first && this->keyCodes == acKey.second; + } + };*/ + + using Key = std::pair; + + + RebindService(InputService& aInputService); + ~RebindService() = default; + + TP_NOCOPYMOVE(RebindService); + + const Key& GetUIKey() const noexcept { return m_pUiKey; } + const Key& GetDebugKey() const noexcept { return m_pDebugKey; } + + bool SetUIKey(const Key& apKey) noexcept; + bool SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept; + bool SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept; + bool SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept; + + const Key& GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept; + const Key& GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept; + const Key& GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept; + + TiltedPhoques::Map GetKeys() const noexcept { return m_keys; } + //const TiltedPhoques::Map& GetKeys() const noexcept { return m_keys; } + + // Get DirectInput KeyCode + int32_t GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; + // Get VirtualKey KeyCode + int32_t GetVKKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; + +private: + + const TiltedPhoques::Map m_keys + { + {"", {KeyCodes::Error, KeyCodes::Error}}, + {"A", {0x41, DIK_A}}, + {"B", {0x42, DIK_B}}, + {"C", {0x43, DIK_C}}, + {"D", {0x44, DIK_D}}, + {"E", {0x45, DIK_E}}, + {"F", {0x46, DIK_F}}, + {"G", {0x47, DIK_G}}, + {"H", {0x48, DIK_H}}, + {"I", {0x49, DIK_I}}, + {"J", {0x4A, DIK_J}}, + {"K", {0x4B, DIK_K}}, + {"L", {0x4C, DIK_L}}, + {"M", {0x4D, DIK_M}}, + {"N", {0x4E, DIK_N}}, + {"O", {0x4F, DIK_O}}, + {"P", {0x50, DIK_P}}, + {"Q", {0x51, DIK_Q}}, + {"R", {0x52, DIK_R}}, + {"S", {0x53, DIK_S}}, + {"T", {0x54, DIK_T}}, + {"U", {0x55, DIK_U}}, + {"V", {0x56, DIK_V}}, + {"W", {0x57, DIK_W}}, + {"X", {0x58, DIK_X}}, + {"Y", {0x59, DIK_Y}}, + {"Z", {0x5A, DIK_Z}}, + {"0", {0x30, DIK_0}}, + {"1", {0x31, DIK_1}}, + {"2", {0x32, DIK_2}}, + {"3", {0x33, DIK_3}}, + {"4", {0x34, DIK_4}}, + {"5", {0x35, DIK_5}}, + {"6", {0x36, DIK_6}}, + {"7", {0x37, DIK_7}}, + {"8", {0x38, DIK_8}}, + {"9", {0x39, DIK_9}}, + /*{"MOUSE1", {VK_LBUTTON, DIMOUSE_BUTTON0}}, + {"MOUSE2", {VK_RBUTTON, DIMOUSE_BUTTON1}}, + {"MOUSE3", {VK_MBUTTON, DIMOUSE_BUTTON2}}, + {"MOUSE4", {VK_XBUTTON1, DIMOUSE_BUTTON3}}, + {"MOUSE5", {VK_XBUTTON2, DIMOUSE_BUTTON4}},*/ + {"Backspace", {VK_BACK, DIK_BACK}}, + {"Tab", {VK_TAB, DIK_TAB}}, + {"Enter", {VK_RETURN, DIK_RETURN}}, + {"LSHIFT", {VK_LSHIFT, DIK_LSHIFT}}, + {"RSHIFT", {VK_RSHIFT, DIK_RSHIFT}}, + {"LCTRL", {VK_LCONTROL, DIK_LCONTROL}}, + {"RCTRL", {VK_RCONTROL, DIK_RCONTROL}}, + {"LALT", {VK_LMENU, DIK_LMENU}}, + {"RALT", {VK_RMENU, DIK_RMENU}}, + {"Pause", {VK_PAUSE, DIK_PAUSE}}, + {"Caps Lock", {VK_CAPITAL, DIK_CAPITAL}}, + {"IME Kana mode", {VK_KANA, DIK_KANA}}, + {"IME Kanji mode", {VK_KANJI, DIK_KANJI}}, + {"Esc", {VK_ESCAPE, DIK_ESCAPE}}, + {"IME convert", {VK_CONVERT, DIK_CONVERT}}, + {"IME nonconvert", {VK_NONCONVERT, DIK_NOCONVERT}}, + {"Space", {VK_SPACE, DIK_SPACE}}, + {"Page Up", {VK_PRIOR, DIK_PRIOR}}, + {"Page Down", {VK_NEXT, DIK_NEXT}}, + {"End", {VK_END, DIK_END}}, + {"Home", {VK_HOME, DIK_HOME}}, + {"Arrow Left", {VK_LEFT, DIK_LEFT}}, + {"Arrow Up", {VK_UP, DIK_UP}}, + {"Arrow Right", {VK_RIGHT, DIK_RIGHT}}, + {"Arrow Down", {VK_DOWN, DIK_DOWN}}, + {"Ins", {VK_INSERT, DIK_INSERT}}, + {"Del", {VK_DELETE, DIK_DELETE}}, + {"LWIN", {VK_LWIN, DIK_LWIN}}, + {"RWIN", {VK_RWIN, DIK_RWIN}}, + {"Applications", {VK_APPS, DIK_APPS}}, + {"Sleep", {VK_SLEEP, DIK_SLEEP}}, + {"NUMPAD 0", {VK_NUMPAD0, DIK_NUMPAD0}}, + {"NUMPAD 1", {VK_NUMPAD1, DIK_NUMPAD1}}, + {"NUMPAD 2", {VK_NUMPAD2, DIK_NUMPAD2}}, + {"NUMPAD 3", {VK_NUMPAD3, DIK_NUMPAD3}}, + {"NUMPAD 4", {VK_NUMPAD4, DIK_NUMPAD4}}, + {"NUMPAD 5", {VK_NUMPAD5, DIK_NUMPAD5}}, + {"NUMPAD 6", {VK_NUMPAD6, DIK_NUMPAD6}}, + {"NUMPAD 7", {VK_NUMPAD7, DIK_NUMPAD7}}, + {"NUMPAD 8", {VK_NUMPAD8, DIK_NUMPAD8}}, + {"NUMPAD 9", {VK_NUMPAD9, DIK_NUMPAD9}}, + {"NUMPAD *", {VK_MULTIPLY, DIK_MULTIPLY}}, + {"NUMPAD +", {VK_ADD, DIK_ADD}}, + {"NUMPAD -", {VK_SUBTRACT, DIK_SUBTRACT}}, + {"NUMPAD .", {VK_DECIMAL, DIK_DECIMAL}}, + {"NUMPAD /", {VK_DIVIDE, DIK_DIVIDE}}, + {"F1", {VK_F1, DIK_F1}}, + {"F2", {VK_F2, DIK_F2}}, + {"F3", {VK_F3, DIK_F3}}, + {"F4", {VK_F4, DIK_F4}}, + {"F5", {VK_F5, DIK_F5}}, + {"F6", {VK_F6, DIK_F6}}, + {"F7", {VK_F7, DIK_F7}}, + {"F8", {VK_F8, DIK_F8}}, + {"F9", {VK_F9, DIK_F9}}, + {"F10", {VK_F10, DIK_F10}}, + {"F11", {VK_F11, DIK_F11}}, + {"F12", {VK_F12, DIK_F12}}, + {"F13", {VK_F13, DIK_F13}}, + {"F14", {VK_F14, DIK_F14}}, + {"F15", {VK_F15, DIK_F15}}, + {"Num Lock", {VK_NUMLOCK, DIK_NUMLOCK}}, + {"ScrLk", {VK_SCROLL, DIK_SCROLL}}, + {"Browser Back", {VK_BROWSER_BACK, DIK_WEBBACK}}, + {"Browser Forward", {VK_BROWSER_FORWARD, DIK_WEBFORWARD}}, + {"Browser Refresh", {VK_BROWSER_REFRESH, DIK_WEBREFRESH}}, + {"Browser Stop", {VK_BROWSER_STOP, DIK_WEBSTOP}}, + {"Browser Search", {VK_BROWSER_SEARCH, DIK_WEBSEARCH}}, + {"Browser Favorites", {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}}, + {"Browser Stard and Home", {VK_BROWSER_HOME, DIK_WEBHOME}}, + {"Volume Mute", {VK_VOLUME_MUTE, DIK_MUTE}}, + {"Volume Down", {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}}, + {"Volume Up", {VK_VOLUME_UP, DIK_VOLUMEUP}}, + {"Next Track", {VK_MEDIA_NEXT_TRACK, DIK_NEXTTRACK}}, + {"Previous Track", {VK_MEDIA_PREV_TRACK, DIK_PREVTRACK}}, + {"Stop Media", {VK_MEDIA_STOP, DIK_MEDIASTOP}}, + {"Play/Pause Media", {VK_MEDIA_PLAY_PAUSE, DIK_PLAYPAUSE}}, + {"Start Mail", {VK_LAUNCH_MAIL, DIK_MAIL}}, + {"Select Media", {VK_LAUNCH_MEDIA_SELECT, DIK_MEDIASELECT}}, + {"=", {VK_OEM_PLUS, DIK_EQUALS}}, + {",", {VK_OEM_COMMA, DIK_COMMA}}, + {"-", {VK_OEM_MINUS, DIK_MINUS}}, + {".", {VK_OEM_PERIOD, DIK_PERIOD}}, + {";", {VK_OEM_1, DIK_SEMICOLON}}, + {"/", {VK_OEM_2, DIK_SLASH}}, + {"`", {VK_OEM_3, DIK_GRAVE}}, + {"[", {VK_OEM_4, DIK_LBRACKET}}, + {"\\", {VK_OEM_5, DIK_BACKSLASH}}, + {"]", {VK_OEM_6, DIK_RBRACKET}}, + {"'", {VK_OEM_7, DIK_APOSTROPHE}}, + }; + + +private: + Key m_pUiKey = {"F2", {VK_F2, DIK_F2}}; + Key m_pDebugKey = {"F3", {VK_F3, DIK_F3}}; + Key m_errorKey = {"", {KeyCodes::Error, KeyCodes::Error}}; + + InputService& m_inputService; +}; diff --git a/Code/client/World.cpp b/Code/client/World.cpp index f974efcab..40cbcbaa2 100644 --- a/Code/client/World.cpp +++ b/Code/client/World.cpp @@ -35,6 +35,7 @@ World::World() ctx().emplace(*this, m_dispatcher); ctx().emplace(*this, m_transport, m_dispatcher); ctx().emplace(ctx().at()); + ctx().emplace(ctx().at()); ctx().emplace(*this, m_dispatcher, m_transport); ctx().emplace(m_dispatcher, *this, m_transport, ctx().at()); ctx().emplace(m_dispatcher); diff --git a/Code/client/World.h b/Code/client/World.h index 96dc4d4db..5eccb52a6 100644 --- a/Code/client/World.h +++ b/Code/client/World.h @@ -9,6 +9,7 @@ #include #include #include "Services/InputService.h" +#include "Services/RebindService.h" #include @@ -35,6 +36,9 @@ struct World : entt::registry const DebugService& GetDebugService() const noexcept { return ctx().at(); } InputService& GetInputService() noexcept { return ctx().at(); } const InputService& GetInputService() const noexcept { return ctx().at(); } + RebindService& GetRebindService() noexcept { return ctx().at(); } + const RebindService& GetRebindService() const noexcept { return ctx().at(); } + auto& GetDispatcher() noexcept { return m_dispatcher; } From e474c22810b602949d8e8f2ab2b3c1a6a2dcaff1 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 25 Sep 2024 22:29:43 -0400 Subject: [PATCH 03/28] tweak: cleanup + add shared_ptrs --- .../Services/Debug/Views/RebindView.cpp | 22 ++--- Code/client/Services/DebugService.h | 2 + Code/client/Services/Generic/InputService.cpp | 6 +- .../client/Services/Generic/RebindService.cpp | 46 +++++----- Code/client/Services/InputService.h | 2 +- Code/client/Services/RebindService.h | 84 ++++--------------- 6 files changed, 57 insertions(+), 105 deletions(-) diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/RebindView.cpp index 3bb5771f9..a15e7089d 100644 --- a/Code/client/Services/Debug/Views/RebindView.cpp +++ b/Code/client/Services/Debug/Views/RebindView.cpp @@ -13,19 +13,18 @@ void DebugService::DrawRebindView() auto& inputService = World::Get().GetInputService(); auto& rebindService = World::Get().GetRebindService(); auto uiKey = inputService.GetUIKey(); - static bool s_bindingActive = false; ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); ImGui::Begin("Rebind"); if (ImGui::CollapsingHeader("UI")) { - if (ImGui::Button("Open/Close", ImVec2(100, 30)) || s_bindingActive) + if (ImGui::Button("Open/Close", ImVec2(100, 30)) || m_rebindActive) { ImGui::SameLine(0); - s_bindingActive = true; + m_rebindActive = true; - if (s_bindingActive) + if (m_rebindActive) ImGui::Text("Press a key..."); else ImGui::Text(uiKey.first.c_str()); @@ -36,16 +35,19 @@ void DebugService::DrawRebindView() if (GetAsyncKeyState(key) & 0x8000) { if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) + { + m_rebindActive = false; break; + } - auto& newKey = rebindService.GetKeyFromVKKeyCode(key); - - if (!newKey.first.empty()) + auto newKey = rebindService.GetKeyFromVKKeyCode(key); + + if (!newKey->first.empty()) { - s_bindingActive = false; - uiKey = newKey; + m_rebindActive = false; + uiKey = *newKey; - if(rebindService.SetUIKey(uiKey)) + if(rebindService.SetUIKey(std::move(newKey))) { TiltedPhoques::DInputHook::Get().SetToggleKeys({DIK_RCONTROL, static_cast(uiKey.second.diKeyCode)}); break; diff --git a/Code/client/Services/DebugService.h b/Code/client/Services/DebugService.h index 020540894..5473ccaa9 100644 --- a/Code/client/Services/DebugService.h +++ b/Code/client/Services/DebugService.h @@ -81,6 +81,8 @@ struct DebugService String SubtitleText = ""; uint32_t TopicID = 0; + bool m_rebindActive = false; + entt::scoped_connection m_updateConnection; entt::scoped_connection m_drawImGuiConnection; entt::scoped_connection m_dialogueConnection; diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index a9d48592d..846b3e8bf 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -458,12 +458,12 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } -bool InputService::SetUIKey(const RebindService::Key& acKey) noexcept +bool InputService::SetUIKey(std::shared_ptr acKey) noexcept { - if (acKey.first.empty() || acKey.second.diKeyCode == -1 || acKey.second.vkKeyCode == -1) + if (acKey->first.empty() || acKey->second.diKeyCode == -1 || acKey->second.vkKeyCode == -1) return false; - m_pUiKey = acKey; + m_pUiKey = *acKey; return true; } diff --git a/Code/client/Services/Generic/RebindService.cpp b/Code/client/Services/Generic/RebindService.cpp index 1736575fa..2854f116b 100644 --- a/Code/client/Services/Generic/RebindService.cpp +++ b/Code/client/Services/Generic/RebindService.cpp @@ -5,47 +5,46 @@ RebindService::RebindService(InputService& aInputService) : { } -const RebindService::Key& RebindService::GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept +std::shared_ptr RebindService::GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept { const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [acKeyName](const Key& aKey) { return aKey.first == acKeyName; }); - Key pKey; + std::shared_ptr newKey = std::make_shared(*key); if (key != m_keys.end()) { - pKey = *key; + *newKey = *key; } - return pKey; + return newKey; } - -const RebindService::Key& RebindService::GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept +std::shared_ptr RebindService::GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept { const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.vkKeyCode == aKeyCode; }); - Key pKey; + std::shared_ptr newKey = std::make_shared(*key); if (key != m_keys.end()) { - pKey = *key; + *newKey = *key; } - return pKey; + return newKey; } -const RebindService::Key& RebindService::GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept +std::shared_ptr RebindService::GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept { const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.diKeyCode == aKeyCode; }); - Key pKey; + std::shared_ptr newKey = std::make_shared(*key); if (key != m_keys.end()) { - pKey = *key; + *newKey = *key; } - return pKey; + return newKey; } int32_t RebindService::GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept @@ -80,10 +79,10 @@ int32_t RebindService::GetVKKeyCode(const TiltedPhoques::String& aKeyName) const return KeyCodes::Error; } -bool RebindService::SetUIKey(const Key& apKey) noexcept +bool RebindService::SetUIKey(std::shared_ptr apKey) noexcept { - m_inputService.SetUIKey(apKey); - m_pUiKey = apKey; + m_pUiKey = *apKey; + m_inputService.SetUIKey(std::move(apKey)); return true; } @@ -91,10 +90,10 @@ bool RebindService::SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept { const auto& key = GetKeyFromVKKeyCode(aKeyCode); - if (key != m_errorKey) + if (!key->first.empty()) { - m_inputService.SetUIKey(key); - m_pUiKey = key; + m_pUiKey = *key; + m_inputService.SetUIKey(std::move(key)); return true; } @@ -105,10 +104,10 @@ bool RebindService::SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept { const auto& key = GetKeyFromDIKeyCode(aKeyCode); - if (key != m_errorKey) + if (!key->first.empty()) { + m_pUiKey = *key; m_inputService.SetUIKey(key); - m_pUiKey = key; return true; } @@ -117,11 +116,10 @@ bool RebindService::SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept bool RebindService::SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept { - if (const auto& key = GetKeyFromName(acKeyName); key != m_errorKey) + if (const auto& key = GetKeyFromName(acKeyName); !key->first.empty()) { - //World::Get().GetInputService().SetUIKey(key); + m_pUiKey = *key; m_inputService.SetUIKey(key); - m_pUiKey = key; return true; } diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index 98a4d650f..265c23bc1 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -14,7 +14,7 @@ struct InputService // Use this function to get the player's current UI key RebindService::Key GetUIKey() const noexcept { return m_pUiKey; } - bool SetUIKey(const RebindService::Key& apKey) noexcept; + bool SetUIKey(std::shared_ptr apKey) noexcept; static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/Code/client/Services/RebindService.h b/Code/client/Services/RebindService.h index bda2fe490..b42d777dc 100644 --- a/Code/client/Services/RebindService.h +++ b/Code/client/Services/RebindService.h @@ -8,87 +8,45 @@ struct RebindService { struct KeyCodes { - enum - { - Error = -1 - }; + enum { Error = -1 }; int32_t vkKeyCode = Error; int32_t diKeyCode = Error; - - bool operator==(const KeyCodes& acKeyCodes) const - { - return this->vkKeyCode == acKeyCodes.vkKeyCode && this->diKeyCode == acKeyCodes.diKeyCode; - } }; - /*struct Key - { - TiltedPhoques::String keyName; - KeyCodes keyCodes; - - Key() : keyName(""), keyCodes({KeyCodes::Error, KeyCodes::Error}) - { - } - - Key(const TiltedPhoques::String& acKeyName, const KeyCodes& acKeyCodes) : - keyName(acKeyName), keyCodes(acKeyCodes) - { - } - - Key(const Key& acKey) - { - keyName = acKey.keyName; - keyCodes = acKey.keyCodes; - } - - Key(const std::pair& acKey) - { - keyName = acKey.first; - keyCodes = acKey.second; - } - - bool operator==(const Key& acKey) const - { - return this->keyName == acKey.keyName && this->keyCodes == acKey.keyCodes; - } - - bool operator==(const std::pair& acKey) const - { - return this->keyName == acKey.first && this->keyCodes == acKey.second; - } - };*/ - using Key = std::pair; - RebindService(InputService& aInputService); ~RebindService() = default; TP_NOCOPYMOVE(RebindService); - const Key& GetUIKey() const noexcept { return m_pUiKey; } - const Key& GetDebugKey() const noexcept { return m_pDebugKey; } + TiltedPhoques::Map GetKeys() const noexcept { return m_keys; } - bool SetUIKey(const Key& apKey) noexcept; + // UI Key + const Key& GetUIKey() const noexcept { return m_pUiKey; } + bool SetUIKey(std::shared_ptr apKey) noexcept; bool SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept; bool SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept; bool SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept; - const Key& GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept; - const Key& GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept; - const Key& GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept; - - TiltedPhoques::Map GetKeys() const noexcept { return m_keys; } - //const TiltedPhoques::Map& GetKeys() const noexcept { return m_keys; } + // Debug Key + const Key& GetDebugKey() const noexcept { return m_pDebugKey; } - // Get DirectInput KeyCode - int32_t GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; - // Get VirtualKey KeyCode + // General Key + std::shared_ptr GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept; + std::shared_ptr GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept; int32_t GetVKKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; + std::shared_ptr GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept; + int32_t GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; + bool IsValidKey(const TiltedPhoques::String& acKeyName) const noexcept { return m_keys.find(acKeyName) != m_keys.end(); } private: + Key m_pUiKey = {"F2", {VK_F2, DIK_F2}}; + Key m_pDebugKey = {"F3", {VK_F3, DIK_F3}}; + InputService& m_inputService; + const TiltedPhoques::Map m_keys { {"", {KeyCodes::Error, KeyCodes::Error}}, @@ -224,12 +182,4 @@ struct RebindService {"]", {VK_OEM_6, DIK_RBRACKET}}, {"'", {VK_OEM_7, DIK_APOSTROPHE}}, }; - - -private: - Key m_pUiKey = {"F2", {VK_F2, DIK_F2}}; - Key m_pDebugKey = {"F3", {VK_F3, DIK_F3}}; - Key m_errorKey = {"", {KeyCodes::Error, KeyCodes::Error}}; - - InputService& m_inputService; }; From fb3bbf9a48530d975ea763373ef08a4d14624077 Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 26 Sep 2024 01:42:17 -0400 Subject: [PATCH 04/28] refactor: `GetKey`s --- .../Services/Debug/Views/RebindView.cpp | 2 +- .../client/Services/Generic/RebindService.cpp | 40 +++++-------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/RebindView.cpp index a15e7089d..aec38741b 100644 --- a/Code/client/Services/Debug/Views/RebindView.cpp +++ b/Code/client/Services/Debug/Views/RebindView.cpp @@ -42,7 +42,7 @@ void DebugService::DrawRebindView() auto newKey = rebindService.GetKeyFromVKKeyCode(key); - if (!newKey->first.empty()) + if (newKey != nullptr) { m_rebindActive = false; uiKey = *newKey; diff --git a/Code/client/Services/Generic/RebindService.cpp b/Code/client/Services/Generic/RebindService.cpp index 2854f116b..57efecdb4 100644 --- a/Code/client/Services/Generic/RebindService.cpp +++ b/Code/client/Services/Generic/RebindService.cpp @@ -7,44 +7,34 @@ RebindService::RebindService(InputService& aInputService) : std::shared_ptr RebindService::GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept { - const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [acKeyName](const Key& aKey) { return aKey.first == acKeyName; }); - - std::shared_ptr newKey = std::make_shared(*key); - - if (key != m_keys.end()) + if (const auto& key = std::ranges::find_if(m_keys, [acKeyName](const Key& aKey) { return aKey.first == acKeyName; }); key != m_keys.end()) { - *newKey = *key; + return std::make_shared(*key); } - return newKey; + return nullptr; } std::shared_ptr RebindService::GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept { - const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.vkKeyCode == aKeyCode; }); - - std::shared_ptr newKey = std::make_shared(*key); - - if (key != m_keys.end()) + // Toe Knee: small chance it might not find the key in time before checking for it? + if (const auto& key = std::ranges::find_if(m_keys, [aKeyCode](const Key& aKey) { return aKey.second.vkKeyCode == aKeyCode; }); key != m_keys.end()) { - *newKey = *key; + return std::make_shared(*key); } - return newKey; + return nullptr; } std::shared_ptr RebindService::GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept { - const auto& key = std::find_if(m_keys.begin(), m_keys.end(), [aKeyCode](const Key& aKey) { return aKey.second.diKeyCode == aKeyCode; }); - - std::shared_ptr newKey = std::make_shared(*key); - if (key != m_keys.end()) + if (const auto& key = std::ranges::find_if(m_keys, [aKeyCode](const Key& aKey) { return aKey.second.diKeyCode == aKeyCode; }); key != m_keys.end()) { - *newKey = *key; + return std::make_shared(*key); } - return newKey; + return nullptr; } int32_t RebindService::GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept @@ -55,11 +45,6 @@ int32_t RebindService::GetDIKeyCode(const TiltedPhoques::String& aKeyName) const return key.second.diKeyCode; } - /*if (const auto& key = m_keys.find(aKeyName); key != m_keys.end()) - { - return m_keys.find(aKeyName)->second.diKeyCode; - }*/ - return KeyCodes::Error; } @@ -71,11 +56,6 @@ int32_t RebindService::GetVKKeyCode(const TiltedPhoques::String& aKeyName) const return key.second.vkKeyCode; } - /*if (const auto& key = m_keys.find(aKeyName); key != m_keys.end()) - { - return m_keys.find(aKeyName)->second.vkKeyCode; - }*/ - return KeyCodes::Error; } From 78a06eb94c4207ff212a619fbe1d70418fc88322 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 30 Sep 2024 13:51:07 -0400 Subject: [PATCH 05/28] add: fully dynamic UI key setting --- .../Services/Debug/Views/RebindView.cpp | 85 +++--- Code/client/Services/Generic/InputService.cpp | 10 +- .../client/Services/Generic/RebindService.cpp | 210 +++++++++---- Code/client/Services/InputService.h | 2 +- Code/client/Services/RebindService.h | 289 ++++++++---------- 5 files changed, 337 insertions(+), 259 deletions(-) diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/RebindView.cpp index aec38741b..8829ab1a5 100644 --- a/Code/client/Services/Debug/Views/RebindView.cpp +++ b/Code/client/Services/Debug/Views/RebindView.cpp @@ -7,61 +7,68 @@ #include -void DebugService::DrawRebindView() +const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool& aBindActive) { -#if TP_SKYRIM64 - auto& inputService = World::Get().GetInputService(); auto& rebindService = World::Get().GetRebindService(); - auto uiKey = inputService.GetUIKey(); + TiltedPhoques::String keyName = aKeyName; + + ImGui::SameLine(0); + aBindActive = true; + + for (int key = 255; key > 1; key--) + { + if (GetAsyncKeyState(key) & 0x8000) + { + if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) + { + aBindActive = false; + break; + } + aBindActive = false; + rebindService.BindNewKey(key); + + break; + } + } + + if (aBindActive) + { + ImGui::Text("Press a key..."); + } + else + { + ImGui::Text(keyName.c_str()); + } + + return keyName; +} + +void DebugService::DrawRebindView() +{ +#if TP_SKYRIM64 ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); ImGui::Begin("Rebind"); + if (ImGui::CollapsingHeader("UI")) { + const auto& uiKey = World::Get().GetInputService().GetUIKey(); + TiltedPhoques::String keyName = uiKey.first; + spdlog::info("{}", uiKey.first); + if (ImGui::Button("Open/Close", ImVec2(100, 30)) || m_rebindActive) { - ImGui::SameLine(0); m_rebindActive = true; - if (m_rebindActive) - ImGui::Text("Press a key..."); - else - ImGui::Text(uiKey.first.c_str()); - - // Loop through all virtual keys to find which key is pressed - for (int key = 1; key < 256; key++) - { - if (GetAsyncKeyState(key) & 0x8000) - { - if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) - { - m_rebindActive = false; - break; - } - - auto newKey = rebindService.GetKeyFromVKKeyCode(key); - - if (newKey != nullptr) - { - m_rebindActive = false; - uiKey = *newKey; - - if(rebindService.SetUIKey(std::move(newKey))) - { - TiltedPhoques::DInputHook::Get().SetToggleKeys({DIK_RCONTROL, static_cast(uiKey.second.diKeyCode)}); - break; - } - - spdlog::warn("{} key was not found", uiKey.first); - } - } - } + keyName = BindKey(uiKey.first, m_rebindActive); } else { ImGui::SameLine(0); - ImGui::Text("%s", uiKey.first.c_str()); + ImGui::Text("%s", keyName.c_str()); + + m_rebindActive = false; } } diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 846b3e8bf..7206875b2 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -458,12 +458,9 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } -bool InputService::SetUIKey(std::shared_ptr acKey) noexcept +bool InputService::SetUIKey(std::shared_ptr apKey) noexcept { - if (acKey->first.empty() || acKey->second.diKeyCode == -1 || acKey->second.vkKeyCode == -1) - return false; - - m_pUiKey = *acKey; + m_pUiKey = *apKey; return true; } @@ -472,7 +469,8 @@ InputService::InputService(OverlayService& aOverlay) noexcept { s_pOverlay = &aOverlay; s_currentACP = GetRealACP(); - m_pUiKey = {"F2", {VK_F2, DIK_F2}}; + + m_pUiKey = {}; } InputService::~InputService() noexcept diff --git a/Code/client/Services/Generic/RebindService.cpp b/Code/client/Services/Generic/RebindService.cpp index 57efecdb4..f23904061 100644 --- a/Code/client/Services/Generic/RebindService.cpp +++ b/Code/client/Services/Generic/RebindService.cpp @@ -1,108 +1,200 @@ #include "Services/RebindService.h" +#include "DInputHook.hpp" + RebindService::RebindService(InputService& aInputService) : m_inputService(aInputService) { + m_inputHook = &TiltedPhoques::DInputHook::Get(); + + m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&RebindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + + SetupConfig(); } -std::shared_ptr RebindService::GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept +void RebindService::SetupConfig() noexcept { - if (const auto& key = std::ranges::find_if(m_keys, [acKeyName](const Key& aKey) { return aKey.first == acKeyName; }); key != m_keys.end()) + config.ini.SetUnicode(true); + + const auto modPath = TiltedPhoques::GetPath(); + config.path = modPath / Config::kConfigPathName / Config::kKeybindsFileName; + + if (!exists(modPath / Config::kConfigPathName)) { - return std::make_shared(*key); + create_directory(modPath / Config::kConfigPathName); } - return nullptr; -} + if (!exists(config.path)) + { + spdlog::info("{} not found, creating...", Config::kKeybindsFileName); -std::shared_ptr RebindService::GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept -{ - // Toe Knee: small chance it might not find the key in time before checking for it? - if (const auto& key = std::ranges::find_if(m_keys, [aKeyCode](const Key& aKey) { return aKey.second.vkKeyCode == aKeyCode; }); key != m_keys.end()) + if(!config.Create()) + { + //SetUIKeyFromKeyName("F2"); + //SetDebugKeyFromKeyName("F3"); + } + } + else { - return std::make_shared(*key); + spdlog::info("{} found, loading...", Config::kKeybindsFileName); + + if (config.Load()) + { + spdlog::info("Successfully loaded {}", Config::kKeybindsFileName); + + m_pUiKey.first = config.ini.GetValue("UI", "sUiKey", "F2"); + m_pDebugKey.first = config.ini.GetValue("UI", "sDebugKey", "F3"); + } + else + { + spdlog::warn("{} Failed to load {}", __FUNCTION__, Config::kKeybindsFileName); + } } - - return nullptr; } -std::shared_ptr RebindService::GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept +bool RebindService::SetDebugKey(std::shared_ptr apKey) noexcept { + m_pDebugKey = *apKey; + config.SetKey("UI", "sDebugKey", m_pDebugKey.first.c_str()); - if (const auto& key = std::ranges::find_if(m_keys, [aKeyCode](const Key& aKey) { return aKey.second.diKeyCode == aKeyCode; }); key != m_keys.end()) - { - return std::make_shared(*key); - } - - return nullptr; + return true; } -int32_t RebindService::GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept +void RebindService::BindNewKey(int32_t aKeyCode) noexcept { - for (const auto& key : m_keys) + m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&RebindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + + m_keybindConfirmed = false; + m_keyCode = aKeyCode; + + TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(aKeyCode)))}; + m_convertedToUnicode = true; + + // Still inserts a null terminator if not found :/ + if (newName.starts_with('\0') && newName.length() == 1) { - if (key.first == aKeyName) - return key.second.diKeyCode; + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + if (modKey != m_modifiedKeys.end()) + { + newName = modKey->first; + m_keyCode = modKey->second; + } } - return KeyCodes::Error; + m_pUiKey = {newName, {m_keyCode, 0}}; + m_inputService.SetUIKey(std::make_shared(m_pUiKey)); + config.SetKey("UI", "sUiKey", newName.c_str()); } -int32_t RebindService::GetVKKeyCode(const TiltedPhoques::String& aKeyName) const noexcept +void RebindService::OnDirectInputKeyPress(unsigned long aKeyCode) { - for (const auto& key : m_keys) + m_newKeyPressed = true; + m_lastKeyPressed = aKeyCode; + + if (!m_keybindConfirmed || m_keyCode != 0) { - if (key.first == aKeyName) - return key.second.vkKeyCode; + m_keybindConfirmed = true; + + if (m_keyCode == 0) + { + for (int key = 255; key > 1; key--) + { + if (GetAsyncKeyState(key) & 0x8000) + { + m_keyCode = key; + break; + } + } + } + + if (m_keyCode != 0) + { + const TiltedPhoques::String& key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; + bool foundKey = false; + + spdlog::info("{} {}", key.c_str(), m_pUiKey.first.c_str()); + + if (key != m_pUiKey.first) + { + // If keyname does not match, check if it is a modified key we are looking for + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + if (modKey != m_modifiedKeys.end()) + { + m_pUiKey.first = modKey->first; + m_keyCode = modKey->second; + foundKey = true; + } + } + else + { + foundKey = true; + } + + if (foundKey) + { + m_pUiKey = {m_pUiKey.first, {m_keyCode, aKeyCode}}; + m_inputService.SetUIKey(std::make_shared(m_pUiKey)); + m_inputHook->SetToggleKeys({m_pUiKey.second.diKeyCode}); + config.SetKey("UI", "sUiKey", m_pUiKey.first.c_str()); + + m_keyCode = 0; + m_inputHook->OnKeyPress.Disconnect(m_keyPressConnection); + } + } } - - return KeyCodes::Error; } -bool RebindService::SetUIKey(std::shared_ptr apKey) noexcept +wchar_t RebindService::ConvertToUnicode(int32_t aKeyCode) noexcept { - m_pUiKey = *apKey; - m_inputService.SetUIKey(std::move(apKey)); - return true; + wchar_t buffer[10]; + BYTE keyboardState[256]; + GetKeyboardState(keyboardState); + + ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); + + return buffer[0]; } -bool RebindService::SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept -{ - const auto& key = GetKeyFromVKKeyCode(aKeyCode); - if (!key->first.empty()) - { - m_pUiKey = *key; - m_inputService.SetUIKey(std::move(key)); - return true; - } - return false; -} -bool RebindService::SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept +bool RebindService::Config::Create() noexcept { - const auto& key = GetKeyFromDIKeyCode(aKeyCode); - - if (!key->first.empty()) + if (this->ini.SaveFile(this->path.c_str(), true) == SI_OK) { - m_pUiKey = *key; - m_inputService.SetUIKey(key); + spdlog::info("Successfully created {}", kKeybindsFileName); + + this->ini.SetValue("UI", "sUiKey", "F2"); + this->ini.SetValue("UI", "sDebugKey", "F3"); + + if (!this->Save()) + { + spdlog::warn("Failed to save {}", kKeybindsFileName); + return false; + } + return true; } + spdlog::warn("{}: Failed to create {}, using defaults instead", __FUNCTION__, kKeybindsFileName); return false; } -bool RebindService::SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept +bool RebindService::Config::Save() const noexcept { - if (const auto& key = GetKeyFromName(acKeyName); !key->first.empty()) - { - m_pUiKey = *key; - m_inputService.SetUIKey(key); - return true; - } + return this->ini.SaveFile(this->path.c_str(), true) == SI_OK; +} - return false; +bool RebindService::Config::Load() noexcept +{ + return this->ini.LoadFile(this->path.c_str()) == SI_OK; } +bool RebindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription) noexcept +{ + this->ini.SetValue(acpSection, acpKey, acpValue, acpDescription); + + return this->Save(); +} diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index 265c23bc1..f41704203 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -13,7 +13,7 @@ struct InputService ~InputService() noexcept; // Use this function to get the player's current UI key - RebindService::Key GetUIKey() const noexcept { return m_pUiKey; } + const RebindService::Key& GetUIKey() const noexcept { return m_pUiKey; } bool SetUIKey(std::shared_ptr apKey) noexcept; static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/Code/client/Services/RebindService.h b/Code/client/Services/RebindService.h index b42d777dc..2903db271 100644 --- a/Code/client/Services/RebindService.h +++ b/Code/client/Services/RebindService.h @@ -1,17 +1,45 @@ #pragma once +#include "DInputHook.hpp" +#include "simpleini/SimpleIni.h" + #include struct InputService; +namespace fs = std::filesystem; + +/** + * @brief Handles keybinds + * + * @details Loads a config when constructing, a key name will be set. The key will not actually be set until it is pressed. + * This is due to needing separate VirtualKey and DirectInput keycodes that can only be done after being pressed. The service only + * connects to the DInputHook OnKeyPress Signal when it is checking for keycodes, disconnected otherwise. + */ struct RebindService { + struct Config + { + static constexpr char kConfigPathName[] = "config"; + static constexpr char kKeybindsFileName[] = "keybinds.ini"; + + bool Create() noexcept; + bool Save() const noexcept; + bool Load() noexcept; + + bool SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription = nullptr) noexcept; + + CSimpleIniA ini{}; + fs::path path{}; + }; + + struct KeyCodes { - enum { Error = -1 }; + enum { Error = 0 }; int32_t vkKeyCode = Error; - int32_t diKeyCode = Error; + unsigned long diKeyCode = Error; }; using Key = std::pair; @@ -21,165 +49,118 @@ struct RebindService TP_NOCOPYMOVE(RebindService); - TiltedPhoques::Map GetKeys() const noexcept { return m_keys; } - - // UI Key const Key& GetUIKey() const noexcept { return m_pUiKey; } - bool SetUIKey(std::shared_ptr apKey) noexcept; - bool SetUIKeyFromKeyName(const TiltedPhoques::String& acKeyName) noexcept; - bool SetUIKeyFromVKKeyCode(int32_t aKeyCode) noexcept; - bool SetUIKeyFromDIKeyCode(int32_t aKeyCode) noexcept; - - // Debug Key const Key& GetDebugKey() const noexcept { return m_pDebugKey; } + bool SetDebugKey(std::shared_ptr apKey) noexcept; + void BindNewKey(int32_t aKeyCode) noexcept; + void OnDirectInputKeyPress(unsigned long aKeyCode); + wchar_t ConvertToUnicode(int32_t aKeyCode) noexcept; + + // Config + void SetupConfig() noexcept; - // General Key - std::shared_ptr GetKeyFromName(const TiltedPhoques::String& acKeyName) const noexcept; - std::shared_ptr GetKeyFromVKKeyCode(int32_t aKeyCode) const noexcept; - int32_t GetVKKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; - std::shared_ptr GetKeyFromDIKeyCode(int32_t aKeyCode) const noexcept; - int32_t GetDIKeyCode(const TiltedPhoques::String& aKeyName) const noexcept; - bool IsValidKey(const TiltedPhoques::String& acKeyName) const noexcept { return m_keys.find(acKeyName) != m_keys.end(); } + Config config{}; private: - Key m_pUiKey = {"F2", {VK_F2, DIK_F2}}; - Key m_pDebugKey = {"F3", {VK_F3, DIK_F3}}; - InputService& m_inputService; + TiltedPhoques::DInputHook* m_inputHook; - const TiltedPhoques::Map m_keys + unsigned long m_lastKeyPressed{0}; + int32_t m_keyCode{0}; + bool m_newKeyPressed{false}; + bool m_bindActive{false}; + // Flag for checking if key is being rebound during OnDirectInputKeyPress + bool m_keybindConfirmed{false}; + bool m_convertedToUnicode{false}; + + size_t m_keyPressConnection; + + // Keys not actually "set" until pressed + Key m_pUiKey{}; + Key m_pDebugKey{}; + + // Keys that have custom names + TiltedPhoques::Map m_modifiedKeys { - {"", {KeyCodes::Error, KeyCodes::Error}}, - {"A", {0x41, DIK_A}}, - {"B", {0x42, DIK_B}}, - {"C", {0x43, DIK_C}}, - {"D", {0x44, DIK_D}}, - {"E", {0x45, DIK_E}}, - {"F", {0x46, DIK_F}}, - {"G", {0x47, DIK_G}}, - {"H", {0x48, DIK_H}}, - {"I", {0x49, DIK_I}}, - {"J", {0x4A, DIK_J}}, - {"K", {0x4B, DIK_K}}, - {"L", {0x4C, DIK_L}}, - {"M", {0x4D, DIK_M}}, - {"N", {0x4E, DIK_N}}, - {"O", {0x4F, DIK_O}}, - {"P", {0x50, DIK_P}}, - {"Q", {0x51, DIK_Q}}, - {"R", {0x52, DIK_R}}, - {"S", {0x53, DIK_S}}, - {"T", {0x54, DIK_T}}, - {"U", {0x55, DIK_U}}, - {"V", {0x56, DIK_V}}, - {"W", {0x57, DIK_W}}, - {"X", {0x58, DIK_X}}, - {"Y", {0x59, DIK_Y}}, - {"Z", {0x5A, DIK_Z}}, - {"0", {0x30, DIK_0}}, - {"1", {0x31, DIK_1}}, - {"2", {0x32, DIK_2}}, - {"3", {0x33, DIK_3}}, - {"4", {0x34, DIK_4}}, - {"5", {0x35, DIK_5}}, - {"6", {0x36, DIK_6}}, - {"7", {0x37, DIK_7}}, - {"8", {0x38, DIK_8}}, - {"9", {0x39, DIK_9}}, - /*{"MOUSE1", {VK_LBUTTON, DIMOUSE_BUTTON0}}, - {"MOUSE2", {VK_RBUTTON, DIMOUSE_BUTTON1}}, - {"MOUSE3", {VK_MBUTTON, DIMOUSE_BUTTON2}}, - {"MOUSE4", {VK_XBUTTON1, DIMOUSE_BUTTON3}}, - {"MOUSE5", {VK_XBUTTON2, DIMOUSE_BUTTON4}},*/ - {"Backspace", {VK_BACK, DIK_BACK}}, - {"Tab", {VK_TAB, DIK_TAB}}, - {"Enter", {VK_RETURN, DIK_RETURN}}, - {"LSHIFT", {VK_LSHIFT, DIK_LSHIFT}}, - {"RSHIFT", {VK_RSHIFT, DIK_RSHIFT}}, - {"LCTRL", {VK_LCONTROL, DIK_LCONTROL}}, - {"RCTRL", {VK_RCONTROL, DIK_RCONTROL}}, - {"LALT", {VK_LMENU, DIK_LMENU}}, - {"RALT", {VK_RMENU, DIK_RMENU}}, - {"Pause", {VK_PAUSE, DIK_PAUSE}}, - {"Caps Lock", {VK_CAPITAL, DIK_CAPITAL}}, - {"IME Kana mode", {VK_KANA, DIK_KANA}}, - {"IME Kanji mode", {VK_KANJI, DIK_KANJI}}, - {"Esc", {VK_ESCAPE, DIK_ESCAPE}}, - {"IME convert", {VK_CONVERT, DIK_CONVERT}}, - {"IME nonconvert", {VK_NONCONVERT, DIK_NOCONVERT}}, - {"Space", {VK_SPACE, DIK_SPACE}}, - {"Page Up", {VK_PRIOR, DIK_PRIOR}}, - {"Page Down", {VK_NEXT, DIK_NEXT}}, - {"End", {VK_END, DIK_END}}, - {"Home", {VK_HOME, DIK_HOME}}, - {"Arrow Left", {VK_LEFT, DIK_LEFT}}, - {"Arrow Up", {VK_UP, DIK_UP}}, - {"Arrow Right", {VK_RIGHT, DIK_RIGHT}}, - {"Arrow Down", {VK_DOWN, DIK_DOWN}}, - {"Ins", {VK_INSERT, DIK_INSERT}}, - {"Del", {VK_DELETE, DIK_DELETE}}, - {"LWIN", {VK_LWIN, DIK_LWIN}}, - {"RWIN", {VK_RWIN, DIK_RWIN}}, - {"Applications", {VK_APPS, DIK_APPS}}, - {"Sleep", {VK_SLEEP, DIK_SLEEP}}, - {"NUMPAD 0", {VK_NUMPAD0, DIK_NUMPAD0}}, - {"NUMPAD 1", {VK_NUMPAD1, DIK_NUMPAD1}}, - {"NUMPAD 2", {VK_NUMPAD2, DIK_NUMPAD2}}, - {"NUMPAD 3", {VK_NUMPAD3, DIK_NUMPAD3}}, - {"NUMPAD 4", {VK_NUMPAD4, DIK_NUMPAD4}}, - {"NUMPAD 5", {VK_NUMPAD5, DIK_NUMPAD5}}, - {"NUMPAD 6", {VK_NUMPAD6, DIK_NUMPAD6}}, - {"NUMPAD 7", {VK_NUMPAD7, DIK_NUMPAD7}}, - {"NUMPAD 8", {VK_NUMPAD8, DIK_NUMPAD8}}, - {"NUMPAD 9", {VK_NUMPAD9, DIK_NUMPAD9}}, - {"NUMPAD *", {VK_MULTIPLY, DIK_MULTIPLY}}, - {"NUMPAD +", {VK_ADD, DIK_ADD}}, - {"NUMPAD -", {VK_SUBTRACT, DIK_SUBTRACT}}, - {"NUMPAD .", {VK_DECIMAL, DIK_DECIMAL}}, - {"NUMPAD /", {VK_DIVIDE, DIK_DIVIDE}}, - {"F1", {VK_F1, DIK_F1}}, - {"F2", {VK_F2, DIK_F2}}, - {"F3", {VK_F3, DIK_F3}}, - {"F4", {VK_F4, DIK_F4}}, - {"F5", {VK_F5, DIK_F5}}, - {"F6", {VK_F6, DIK_F6}}, - {"F7", {VK_F7, DIK_F7}}, - {"F8", {VK_F8, DIK_F8}}, - {"F9", {VK_F9, DIK_F9}}, - {"F10", {VK_F10, DIK_F10}}, - {"F11", {VK_F11, DIK_F11}}, - {"F12", {VK_F12, DIK_F12}}, - {"F13", {VK_F13, DIK_F13}}, - {"F14", {VK_F14, DIK_F14}}, - {"F15", {VK_F15, DIK_F15}}, - {"Num Lock", {VK_NUMLOCK, DIK_NUMLOCK}}, - {"ScrLk", {VK_SCROLL, DIK_SCROLL}}, - {"Browser Back", {VK_BROWSER_BACK, DIK_WEBBACK}}, - {"Browser Forward", {VK_BROWSER_FORWARD, DIK_WEBFORWARD}}, - {"Browser Refresh", {VK_BROWSER_REFRESH, DIK_WEBREFRESH}}, - {"Browser Stop", {VK_BROWSER_STOP, DIK_WEBSTOP}}, - {"Browser Search", {VK_BROWSER_SEARCH, DIK_WEBSEARCH}}, - {"Browser Favorites", {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}}, - {"Browser Stard and Home", {VK_BROWSER_HOME, DIK_WEBHOME}}, - {"Volume Mute", {VK_VOLUME_MUTE, DIK_MUTE}}, - {"Volume Down", {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}}, - {"Volume Up", {VK_VOLUME_UP, DIK_VOLUMEUP}}, - {"Next Track", {VK_MEDIA_NEXT_TRACK, DIK_NEXTTRACK}}, - {"Previous Track", {VK_MEDIA_PREV_TRACK, DIK_PREVTRACK}}, - {"Stop Media", {VK_MEDIA_STOP, DIK_MEDIASTOP}}, - {"Play/Pause Media", {VK_MEDIA_PLAY_PAUSE, DIK_PLAYPAUSE}}, - {"Start Mail", {VK_LAUNCH_MAIL, DIK_MAIL}}, - {"Select Media", {VK_LAUNCH_MEDIA_SELECT, DIK_MEDIASELECT}}, - {"=", {VK_OEM_PLUS, DIK_EQUALS}}, - {",", {VK_OEM_COMMA, DIK_COMMA}}, - {"-", {VK_OEM_MINUS, DIK_MINUS}}, - {".", {VK_OEM_PERIOD, DIK_PERIOD}}, - {";", {VK_OEM_1, DIK_SEMICOLON}}, - {"/", {VK_OEM_2, DIK_SLASH}}, - {"`", {VK_OEM_3, DIK_GRAVE}}, - {"[", {VK_OEM_4, DIK_LBRACKET}}, - {"\\", {VK_OEM_5, DIK_BACKSLASH}}, - {"]", {VK_OEM_6, DIK_RBRACKET}}, - {"'", {VK_OEM_7, DIK_APOSTROPHE}}, + {"Backspace", VK_BACK}, + {"Tab", VK_TAB}, + {"Enter", VK_RETURN}, + {"LSHIFT", VK_LSHIFT}, + {"RSHIFT", VK_RSHIFT}, + {"LCTRL", VK_LCONTROL}, + {"RCTRL", VK_RCONTROL}, + {"LALT", VK_LMENU}, + {"RALT", VK_RMENU}, + {"Pause", VK_PAUSE}, + {"Caps Lock", VK_CAPITAL}, + {"IME Kana mode", VK_KANA}, + {"IME Kanji mode", VK_KANJI}, + {"Esc", VK_ESCAPE}, + {"IME convert", VK_CONVERT}, + {"IME nonconvert", VK_NONCONVERT}, + {"Space", VK_SPACE}, + {"Page Up", VK_PRIOR}, + {"Page Down", VK_NEXT}, + {"End", VK_END}, + {"Home", VK_HOME}, + {"Arrow Left", VK_LEFT}, + {"Arrow Up", VK_UP}, + {"Arrow Right", VK_RIGHT}, + {"Arrow Down", VK_DOWN}, + {"Ins", VK_INSERT}, + {"Del", VK_DELETE}, + {"LWIN", VK_LWIN}, + {"RWIN", VK_RWIN}, + {"Applications", VK_APPS}, + {"Sleep", VK_SLEEP}, + {"NUMPAD 0", VK_NUMPAD0}, + {"NUMPAD 1", VK_NUMPAD1}, + {"NUMPAD 2", VK_NUMPAD2}, + {"NUMPAD 3", VK_NUMPAD3}, + {"NUMPAD 4", VK_NUMPAD4}, + {"NUMPAD 5", VK_NUMPAD5}, + {"NUMPAD 6", VK_NUMPAD6}, + {"NUMPAD 7", VK_NUMPAD7}, + {"NUMPAD 8", VK_NUMPAD8}, + {"NUMPAD 9", VK_NUMPAD9}, + {"NUMPAD *", VK_MULTIPLY}, + {"NUMPAD +", VK_ADD}, + {"NUMPAD -", VK_SUBTRACT}, + {"NUMPAD .", VK_DECIMAL}, + {"NUMPAD /", VK_DIVIDE}, + {"F1", VK_F1}, + {"F2", VK_F2}, + {"F3", VK_F3}, + {"F4", VK_F4}, + {"F5", VK_F5}, + {"F6", VK_F6}, + {"F7", VK_F7}, + {"F8", VK_F8}, + {"F9", VK_F9}, + {"F10", VK_F10}, + {"F11", VK_F11}, + {"F12", VK_F12}, + {"F13", VK_F13}, + {"F14", VK_F14}, + {"F15", VK_F15}, + {"Num Lock", VK_NUMLOCK}, + {"ScrLk", VK_SCROLL}, + {"Browser Back", VK_BROWSER_BACK}, + {"Browser Forward", VK_BROWSER_FORWARD}, + {"Browser Refresh", VK_BROWSER_REFRESH}, + {"Browser Stop", VK_BROWSER_STOP}, + {"Browser Search", VK_BROWSER_SEARCH}, + {"Browser Favorites", VK_BROWSER_FAVORITES}, + {"Browser Stard and Home", VK_BROWSER_HOME}, + {"Volume Mute", VK_VOLUME_MUTE}, + {"Volume Down", VK_VOLUME_DOWN}, + {"Volume Up", VK_VOLUME_UP}, + {"Next Track", VK_MEDIA_NEXT_TRACK}, + {"Previous Track", VK_MEDIA_PREV_TRACK}, + {"Stop Media", VK_MEDIA_STOP}, + {"Play/Pause Media", VK_MEDIA_PLAY_PAUSE}, + {"Start Mail", VK_LAUNCH_MAIL}, + {"Select Media", VK_LAUNCH_MEDIA_SELECT} + }; }; From 921ae2ca01570c2f9ec6f00ef4c3f727386587e4 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 30 Sep 2024 16:20:08 -0400 Subject: [PATCH 06/28] tweak: rename to KeybindService --- Code/client/Services/Debug/DebugService.cpp | 8 +-- .../Views/{RebindView.cpp => KeybindView.cpp} | 10 ++- Code/client/Services/DebugService.h | 2 +- Code/client/Services/Generic/InputService.cpp | 2 +- .../{RebindService.cpp => KeybindService.cpp} | 69 ++++++++++--------- Code/client/Services/InputService.h | 10 +-- .../{RebindService.h => KeybindService.h} | 25 +++---- Code/client/World.cpp | 2 +- Code/client/World.h | 6 +- 9 files changed, 67 insertions(+), 67 deletions(-) rename Code/client/Services/Debug/Views/{RebindView.cpp => KeybindView.cpp} (88%) rename Code/client/Services/Generic/{RebindService.cpp => KeybindService.cpp} (65%) rename Code/client/Services/{RebindService.h => KeybindService.h} (86%) diff --git a/Code/client/Services/Debug/DebugService.cpp b/Code/client/Services/Debug/DebugService.cpp index e1479825d..14781f413 100644 --- a/Code/client/Services/Debug/DebugService.cpp +++ b/Code/client/Services/Debug/DebugService.cpp @@ -236,7 +236,7 @@ static bool g_enableWeatherWindow{false}; static bool g_enableCombatWindow{false}; static bool g_enableCalendarWindow{false}; static bool g_enableDragonSpawnerWindow{false}; -static bool g_enableRebindWindow{false}; +static bool g_enableKeybindWindow{false}; void DebugService::DrawServerView() noexcept { @@ -337,7 +337,7 @@ void DebugService::OnDraw() noexcept ImGui::MenuItem("Server", nullptr, &g_enableServerWindow); ImGui::MenuItem("Party", nullptr, &g_enablePartyWindow); ImGui::MenuItem("Dragon spawner", nullptr, &g_enableDragonSpawnerWindow); - ImGui::MenuItem("Rebind", nullptr, &g_enableRebindWindow); + ImGui::MenuItem("Keybinds", nullptr, &g_enableKeybindWindow); #if (!IS_MASTER) ImGui::MenuItem("Network", nullptr, &g_enableNetworkWindow); @@ -384,8 +384,8 @@ void DebugService::OnDraw() noexcept DrawPartyView(); if (g_enableDragonSpawnerWindow) DrawDragonSpawnerView(); - if (g_enableRebindWindow) - DrawRebindView(); + if (g_enableKeybindWindow) + DrawKeybindView(); #if (!IS_MASTER) if (g_enableNetworkWindow) diff --git a/Code/client/Services/Debug/Views/RebindView.cpp b/Code/client/Services/Debug/Views/KeybindView.cpp similarity index 88% rename from Code/client/Services/Debug/Views/RebindView.cpp rename to Code/client/Services/Debug/Views/KeybindView.cpp index 8829ab1a5..60c079b69 100644 --- a/Code/client/Services/Debug/Views/RebindView.cpp +++ b/Code/client/Services/Debug/Views/KeybindView.cpp @@ -1,7 +1,5 @@ -#include "DInputHook.hpp" - -#include -#include +#include +#include #include "World.h" @@ -9,7 +7,7 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool& aBindActive) { - auto& rebindService = World::Get().GetRebindService(); + auto& rebindService = World::Get().GetKeybindService(); TiltedPhoques::String keyName = aKeyName; ImGui::SameLine(0); @@ -44,7 +42,7 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool return keyName; } -void DebugService::DrawRebindView() +void DebugService::DrawKeybindView() { #if TP_SKYRIM64 ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); diff --git a/Code/client/Services/DebugService.h b/Code/client/Services/DebugService.h index 5473ccaa9..3584feb7a 100644 --- a/Code/client/Services/DebugService.h +++ b/Code/client/Services/DebugService.h @@ -60,7 +60,7 @@ struct DebugService void DrawCombatView(); void DrawCalendarView(); void DrawDragonSpawnerView(); - void DrawRebindView(); + void DrawKeybindView(); public: bool m_showDebugStuff = false; diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 7206875b2..1149ff9dc 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -458,7 +458,7 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } -bool InputService::SetUIKey(std::shared_ptr apKey) noexcept +bool InputService::SetUIKey(std::shared_ptr apKey) noexcept { m_pUiKey = *apKey; return true; diff --git a/Code/client/Services/Generic/RebindService.cpp b/Code/client/Services/Generic/KeybindService.cpp similarity index 65% rename from Code/client/Services/Generic/RebindService.cpp rename to Code/client/Services/Generic/KeybindService.cpp index f23904061..5bb6e5566 100644 --- a/Code/client/Services/Generic/RebindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -1,18 +1,18 @@ -#include "Services/RebindService.h" +#include "Services/KeybindService.h" #include "DInputHook.hpp" -RebindService::RebindService(InputService& aInputService) : - m_inputService(aInputService) +KeybindService::KeybindService(InputService& aInputService) : m_inputService(aInputService) { m_inputHook = &TiltedPhoques::DInputHook::Get(); - m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&RebindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_keyPressConnection = + m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); SetupConfig(); } -void RebindService::SetupConfig() noexcept +void KeybindService::SetupConfig() noexcept { config.ini.SetUnicode(true); @@ -28,10 +28,10 @@ void RebindService::SetupConfig() noexcept { spdlog::info("{} not found, creating...", Config::kKeybindsFileName); - if(!config.Create()) + if (!config.Create()) { - //SetUIKeyFromKeyName("F2"); - //SetDebugKeyFromKeyName("F3"); + m_uiKey.first = "F2"; + m_debugKey.first = "F3"; } } else @@ -42,8 +42,8 @@ void RebindService::SetupConfig() noexcept { spdlog::info("Successfully loaded {}", Config::kKeybindsFileName); - m_pUiKey.first = config.ini.GetValue("UI", "sUiKey", "F2"); - m_pDebugKey.first = config.ini.GetValue("UI", "sDebugKey", "F3"); + m_uiKey.first = config.ini.GetValue("UI", "sUiKey", "F2"); + m_debugKey.first = config.ini.GetValue("UI", "sDebugKey", "F3"); } else { @@ -52,17 +52,18 @@ void RebindService::SetupConfig() noexcept } } -bool RebindService::SetDebugKey(std::shared_ptr apKey) noexcept +bool KeybindService::SetDebugKey(std::shared_ptr apKey) noexcept { - m_pDebugKey = *apKey; - config.SetKey("UI", "sDebugKey", m_pDebugKey.first.c_str()); + m_debugKey = *apKey; + config.SetKey("UI", "sDebugKey", m_debugKey.first.c_str()); return true; } -void RebindService::BindNewKey(int32_t aKeyCode) noexcept +void KeybindService::BindNewKey(int32_t aKeyCode) noexcept { - m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&RebindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_keyPressConnection = + m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); m_keybindConfirmed = false; m_keyCode = aKeyCode; @@ -73,7 +74,9 @@ void RebindService::BindNewKey(int32_t aKeyCode) noexcept // Still inserts a null terminator if not found :/ if (newName.starts_with('\0') && newName.length() == 1) { - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { + return acKey.second == m_keyCode; + }); if (modKey != m_modifiedKeys.end()) { @@ -82,12 +85,12 @@ void RebindService::BindNewKey(int32_t aKeyCode) noexcept } } - m_pUiKey = {newName, {m_keyCode, 0}}; - m_inputService.SetUIKey(std::make_shared(m_pUiKey)); + m_uiKey = {newName, {m_keyCode, 0}}; + m_inputService.SetUIKey(std::make_shared(m_uiKey)); config.SetKey("UI", "sUiKey", newName.c_str()); } -void RebindService::OnDirectInputKeyPress(unsigned long aKeyCode) +void KeybindService::OnDirectInputKeyPress(unsigned long aKeyCode) { m_newKeyPressed = true; m_lastKeyPressed = aKeyCode; @@ -113,16 +116,16 @@ void RebindService::OnDirectInputKeyPress(unsigned long aKeyCode) const TiltedPhoques::String& key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; bool foundKey = false; - spdlog::info("{} {}", key.c_str(), m_pUiKey.first.c_str()); + spdlog::info("{} {}", key.c_str(), m_uiKey.first.c_str()); - if (key != m_pUiKey.first) + if (key != m_uiKey.first) { // If keyname does not match, check if it is a modified key we are looking for auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); if (modKey != m_modifiedKeys.end()) { - m_pUiKey.first = modKey->first; + m_uiKey.first = modKey->first; m_keyCode = modKey->second; foundKey = true; } @@ -134,10 +137,10 @@ void RebindService::OnDirectInputKeyPress(unsigned long aKeyCode) if (foundKey) { - m_pUiKey = {m_pUiKey.first, {m_keyCode, aKeyCode}}; - m_inputService.SetUIKey(std::make_shared(m_pUiKey)); - m_inputHook->SetToggleKeys({m_pUiKey.second.diKeyCode}); - config.SetKey("UI", "sUiKey", m_pUiKey.first.c_str()); + m_uiKey = {m_uiKey.first, {m_keyCode, aKeyCode}}; + m_inputService.SetUIKey(std::make_shared(m_uiKey)); + m_inputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); + config.SetKey("UI", "sUiKey", m_uiKey.first.c_str()); m_keyCode = 0; m_inputHook->OnKeyPress.Disconnect(m_keyPressConnection); @@ -146,7 +149,7 @@ void RebindService::OnDirectInputKeyPress(unsigned long aKeyCode) } } -wchar_t RebindService::ConvertToUnicode(int32_t aKeyCode) noexcept +wchar_t KeybindService::ConvertToUnicode(int32_t aKeyCode) noexcept { wchar_t buffer[10]; BYTE keyboardState[256]; @@ -157,10 +160,7 @@ wchar_t RebindService::ConvertToUnicode(int32_t aKeyCode) noexcept return buffer[0]; } - - - -bool RebindService::Config::Create() noexcept +bool KeybindService::Config::Create() noexcept { if (this->ini.SaveFile(this->path.c_str(), true) == SI_OK) { @@ -182,17 +182,18 @@ bool RebindService::Config::Create() noexcept return false; } -bool RebindService::Config::Save() const noexcept +bool KeybindService::Config::Save() const noexcept { return this->ini.SaveFile(this->path.c_str(), true) == SI_OK; } -bool RebindService::Config::Load() noexcept +bool KeybindService::Config::Load() noexcept { return this->ini.LoadFile(this->path.c_str()) == SI_OK; } -bool RebindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription) noexcept +bool KeybindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, + const char* acpDescription) noexcept { this->ini.SetValue(acpSection, acpKey, acpValue, acpDescription); diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index f41704203..b1040ec10 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct OverlayService; @@ -13,14 +13,14 @@ struct InputService ~InputService() noexcept; // Use this function to get the player's current UI key - const RebindService::Key& GetUIKey() const noexcept { return m_pUiKey; } - bool SetUIKey(std::shared_ptr apKey) noexcept; + const KeybindService::Key& GetUIKey() const noexcept { return m_pUiKey; } + bool SetUIKey(std::shared_ptr apKey) noexcept; static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); private: - // RebindService should handle any mutations of this key - RebindService::Key m_pUiKey; + // KeybindService should handle any mutations of this key + KeybindService::Key m_pUiKey; TP_NOCOPYMOVE(InputService); }; diff --git a/Code/client/Services/RebindService.h b/Code/client/Services/KeybindService.h similarity index 86% rename from Code/client/Services/RebindService.h rename to Code/client/Services/KeybindService.h index 2903db271..5be9d5945 100644 --- a/Code/client/Services/RebindService.h +++ b/Code/client/Services/KeybindService.h @@ -12,11 +12,11 @@ namespace fs = std::filesystem; /** * @brief Handles keybinds * - * @details Loads a config when constructing, a key name will be set. The key will not actually be set until it is pressed. - * This is due to needing separate VirtualKey and DirectInput keycodes that can only be done after being pressed. The service only + * @details Loads a config during construction, a key name will be set. The key will not actually be set until it is pressed. + * This is due to needing separate VirtualKey and DirectInput keycodes that can only be determined after being pressed. The service only * connects to the DInputHook OnKeyPress Signal when it is checking for keycodes, disconnected otherwise. */ -struct RebindService +struct KeybindService { struct Config { @@ -44,14 +44,14 @@ struct RebindService using Key = std::pair; - RebindService(InputService& aInputService); - ~RebindService() = default; + KeybindService(InputService& aInputService); + ~KeybindService() = default; - TP_NOCOPYMOVE(RebindService); + TP_NOCOPYMOVE(KeybindService); - const Key& GetUIKey() const noexcept { return m_pUiKey; } - const Key& GetDebugKey() const noexcept { return m_pDebugKey; } - bool SetDebugKey(std::shared_ptr apKey) noexcept; + const Key& GetUIKey() const noexcept { return m_uiKey; } + const Key& GetDebugKey() const noexcept { return m_debugKey; } + bool SetDebugKey(std::shared_ptr apKey) noexcept; void BindNewKey(int32_t aKeyCode) noexcept; void OnDirectInputKeyPress(unsigned long aKeyCode); wchar_t ConvertToUnicode(int32_t aKeyCode) noexcept; @@ -69,15 +69,16 @@ struct RebindService int32_t m_keyCode{0}; bool m_newKeyPressed{false}; bool m_bindActive{false}; + // Flag for checking if key is being rebound during OnDirectInputKeyPress bool m_keybindConfirmed{false}; bool m_convertedToUnicode{false}; size_t m_keyPressConnection; - // Keys not actually "set" until pressed - Key m_pUiKey{}; - Key m_pDebugKey{}; + // Keys not actually "set" until they are pressed from both UI and ingame + Key m_uiKey{}; + Key m_debugKey{}; // Keys that have custom names TiltedPhoques::Map m_modifiedKeys diff --git a/Code/client/World.cpp b/Code/client/World.cpp index 40cbcbaa2..ff9ca828e 100644 --- a/Code/client/World.cpp +++ b/Code/client/World.cpp @@ -35,7 +35,7 @@ World::World() ctx().emplace(*this, m_dispatcher); ctx().emplace(*this, m_transport, m_dispatcher); ctx().emplace(ctx().at()); - ctx().emplace(ctx().at()); + ctx().emplace(ctx().at()); ctx().emplace(*this, m_dispatcher, m_transport); ctx().emplace(m_dispatcher, *this, m_transport, ctx().at()); ctx().emplace(m_dispatcher); diff --git a/Code/client/World.h b/Code/client/World.h index 5eccb52a6..7c5df4468 100644 --- a/Code/client/World.h +++ b/Code/client/World.h @@ -9,7 +9,7 @@ #include #include #include "Services/InputService.h" -#include "Services/RebindService.h" +#include "Services/KeybindService.h" #include @@ -36,8 +36,8 @@ struct World : entt::registry const DebugService& GetDebugService() const noexcept { return ctx().at(); } InputService& GetInputService() noexcept { return ctx().at(); } const InputService& GetInputService() const noexcept { return ctx().at(); } - RebindService& GetRebindService() noexcept { return ctx().at(); } - const RebindService& GetRebindService() const noexcept { return ctx().at(); } + KeybindService& GetKeybindService() noexcept { return ctx().at(); } + const KeybindService& GetKeybindService() const noexcept { return ctx().at(); } auto& GetDispatcher() noexcept { return m_dispatcher; } From 676442e9623ac8be4a23d255fc1ed0bc99fbcb7a Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 30 Sep 2024 16:31:27 -0400 Subject: [PATCH 07/28] refactor: remove unused --- Code/client/Services/Generic/KeybindService.cpp | 14 +++----------- Code/client/Services/KeybindService.h | 14 ++++++-------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index 5bb6e5566..ac35db5f6 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -6,8 +6,7 @@ KeybindService::KeybindService(InputService& aInputService) : m_inputService(aIn { m_inputHook = &TiltedPhoques::DInputHook::Get(); - m_keyPressConnection = - m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); SetupConfig(); } @@ -62,21 +61,17 @@ bool KeybindService::SetDebugKey(std::shared_ptr apKey) noe void KeybindService::BindNewKey(int32_t aKeyCode) noexcept { - m_keyPressConnection = - m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); m_keybindConfirmed = false; m_keyCode = aKeyCode; TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(aKeyCode)))}; - m_convertedToUnicode = true; // Still inserts a null terminator if not found :/ if (newName.starts_with('\0') && newName.length() == 1) { - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { - return acKey.second == m_keyCode; - }); + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); if (modKey != m_modifiedKeys.end()) { @@ -92,9 +87,6 @@ void KeybindService::BindNewKey(int32_t aKeyCode) noexcept void KeybindService::OnDirectInputKeyPress(unsigned long aKeyCode) { - m_newKeyPressed = true; - m_lastKeyPressed = aKeyCode; - if (!m_keybindConfirmed || m_keyCode != 0) { m_keybindConfirmed = true; diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index 5be9d5945..78b0cd30e 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -53,29 +53,27 @@ struct KeybindService const Key& GetDebugKey() const noexcept { return m_debugKey; } bool SetDebugKey(std::shared_ptr apKey) noexcept; void BindNewKey(int32_t aKeyCode) noexcept; + void OnDirectInputKeyPress(unsigned long aKeyCode); - wchar_t ConvertToUnicode(int32_t aKeyCode) noexcept; - // Config void SetupConfig() noexcept; + const Config& GetConfig() const noexcept { return config; } - Config config{}; private: + wchar_t ConvertToUnicode(int32_t aKeyCode) noexcept; + InputService& m_inputService; TiltedPhoques::DInputHook* m_inputHook; - unsigned long m_lastKeyPressed{0}; int32_t m_keyCode{0}; - bool m_newKeyPressed{false}; - bool m_bindActive{false}; - // Flag for checking if key is being rebound during OnDirectInputKeyPress bool m_keybindConfirmed{false}; - bool m_convertedToUnicode{false}; size_t m_keyPressConnection; + Config config{}; + // Keys not actually "set" until they are pressed from both UI and ingame Key m_uiKey{}; Key m_debugKey{}; From a052a451b04bcd7f08c5b4cd4128546411bd2ede Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 3 Oct 2024 11:57:51 -0400 Subject: [PATCH 08/28] add: KeyPressEvent, debug key rebinding, UI toggle instability, shared ptr fixes --- Code/client/Events/KeyPressEvent.h | 13 + Code/client/Services/Debug/DebugService.cpp | 16 +- .../Services/Debug/Views/KeybindView.cpp | 60 ++-- Code/client/Services/DebugService.h | 11 +- Code/client/Services/Generic/InputService.cpp | 71 +++-- .../Services/Generic/KeybindService.cpp | 259 +++++++++++++----- Code/client/Services/InputService.h | 7 +- Code/client/Services/KeybindService.h | 66 +++-- Code/client/World.cpp | 2 +- 9 files changed, 369 insertions(+), 136 deletions(-) create mode 100644 Code/client/Events/KeyPressEvent.h diff --git a/Code/client/Events/KeyPressEvent.h b/Code/client/Events/KeyPressEvent.h new file mode 100644 index 000000000..78b4d133d --- /dev/null +++ b/Code/client/Events/KeyPressEvent.h @@ -0,0 +1,13 @@ +#pragma once + +/** + * @brief Dispatched when VirtualKey is pressed. + */ +struct KeyPressEvent +{ + KeyPressEvent(const uint16_t acKeyCode) : VirtualKey(acKeyCode) + { + } + + uint16_t VirtualKey{}; +}; diff --git a/Code/client/Services/Debug/DebugService.cpp b/Code/client/Services/Debug/DebugService.cpp index 14781f413..0fcff426c 100644 --- a/Code/client/Services/Debug/DebugService.cpp +++ b/Code/client/Services/Debug/DebugService.cpp @@ -164,9 +164,11 @@ void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept static std::atomic s_f7Pressed = false; static std::atomic s_f6Pressed = false; - if (GetAsyncKeyState(VK_F3) & 0x01) + // Bool state handled via KeybindService due to sometimes missing the key state changes + if (m_debugKeyPressed) { m_showDebugStuff = !m_showDebugStuff; + m_debugKeyPressed = false; } #if (!IS_MASTER) @@ -330,6 +332,18 @@ void DebugService::OnDraw() noexcept ImGui::EndMenu(); } #endif + if (ImGui::BeginMenu("Keybinds")) + { + ImGui::MenuItem("Open rebind window", nullptr, &g_enableKeybindWindow); + if (ImGui::BeginMenu("Current binds")) + { + ImGui::Text("Show/Hide UI: %s", World::Get().GetInputService().GetUIKey().first.c_str()); + ImGui::Text("Show/Hide Debug: %s", m_debugKeybind.first.c_str()); + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } if (ImGui::BeginMenu("Debuggers")) { ImGui::MenuItem("Quests", nullptr, &g_enableQuestWindow); diff --git a/Code/client/Services/Debug/Views/KeybindView.cpp b/Code/client/Services/Debug/Views/KeybindView.cpp index 60c079b69..545e246d8 100644 --- a/Code/client/Services/Debug/Views/KeybindView.cpp +++ b/Code/client/Services/Debug/Views/KeybindView.cpp @@ -5,15 +5,15 @@ #include -const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool& aBindActive) +const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, bool& aBindActive, const bool& acDebugKey) { auto& rebindService = World::Get().GetKeybindService(); - TiltedPhoques::String keyName = aKeyName; + TiltedPhoques::String keyName = acKeyName; ImGui::SameLine(0); aBindActive = true; - for (int key = 255; key > 1; key--) + for (uint16_t key = 255; key > 1; key--) { if (GetAsyncKeyState(key) & 0x8000) { @@ -24,7 +24,11 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool } aBindActive = false; - rebindService.BindNewKey(key); + + if (acDebugKey) + rebindService.BindDebugKey(key); + else + rebindService.BindUIKey(key); break; } @@ -45,34 +49,44 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& aKeyName, bool void DebugService::DrawKeybindView() { #if TP_SKYRIM64 - ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver); - ImGui::Begin("Rebind"); + ImGui::SetNextWindowSize(ImVec2(250, 300), ImGuiCond_FirstUseEver); + ImGui::Begin("Keybinds"); + ImGui::Text("UI"); - if (ImGui::CollapsingHeader("UI")) - { - const auto& uiKey = World::Get().GetInputService().GetUIKey(); - TiltedPhoques::String keyName = uiKey.first; - spdlog::info("{}", uiKey.first); + TiltedPhoques::String uiKeyName = World::Get().GetInputService().GetUIKey().first; - if (ImGui::Button("Open/Close", ImVec2(100, 30)) || m_rebindActive) - { - m_rebindActive = true; + if (ImGui::Button("Show/Hide", ImVec2(100, 30)) || m_rebindUI) + { + m_rebindUI = true; - keyName = BindKey(uiKey.first, m_rebindActive); - } - else - { - ImGui::SameLine(0); - ImGui::Text("%s", keyName.c_str()); + uiKeyName = BindKey(uiKeyName, m_rebindUI, false); + } + else + { + ImGui::SameLine(0); + ImGui::Text("%s", uiKeyName.c_str()); - m_rebindActive = false; - } + m_rebindUI = false; } - if (ImGui::CollapsingHeader("Debug")) + ImGui::NewLine(); + ImGui::Text("Debug"); + + TiltedPhoques::String debugKeyName = World::Get().GetDebugService().GetDebugKey().first; + + if (ImGui::Button("Show/Hide", ImVec2(100, 30)) || m_rebindDebug) + { + m_rebindDebug = true; + + debugKeyName = BindKey(debugKeyName, m_rebindDebug, true); + } + else { + ImGui::SameLine(0); + ImGui::Text("%s", debugKeyName.c_str()); + m_rebindDebug = false; } ImGui::End(); diff --git a/Code/client/Services/DebugService.h b/Code/client/Services/DebugService.h index 3584feb7a..fcd306aba 100644 --- a/Code/client/Services/DebugService.h +++ b/Code/client/Services/DebugService.h @@ -1,5 +1,7 @@ #pragma once +#include "KeybindService.h" + #include struct World; @@ -30,6 +32,10 @@ struct DebugService void SetDebugId(const uint32_t aFormId) noexcept; + const KeybindService::Key& GetDebugKey() const noexcept { return m_debugKeybind; } + void SetDebugKey(const TiltedPhoques::SharedPtr& acpKey) noexcept { m_debugKeybind = *acpKey; } + void DebugPressed() noexcept { m_debugKeyPressed = !m_debugKeyPressed; } + protected: void OnDraw() noexcept; @@ -81,7 +87,10 @@ struct DebugService String SubtitleText = ""; uint32_t TopicID = 0; - bool m_rebindActive = false; + KeybindService::Key m_debugKeybind{}; + bool m_debugKeyPressed{false}; + bool m_rebindUI{false}; + bool m_rebindDebug{false}; entt::scoped_connection m_updateConnection; entt::scoped_connection m_drawImGuiConnection; diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 1149ff9dc..e37548b32 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -8,13 +8,14 @@ #include #include -#include #include #include #include #include "Games/Skyrim/Interface/MenuControls.h" +#include "Events/KeyPressEvent.h" + static OverlayService* s_pOverlay = nullptr; static UINT s_currentACP = CP_ACP; @@ -123,12 +124,52 @@ void SetUIActive(OverlayService& aOverlay, auto apRenderer, bool aActive) while (ShowCursor(FALSE) >= 0) ; } + +void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept +{ + auto& overlay = *s_pOverlay; + + const auto pApp = overlay.GetOverlayApp(); + if (!pApp) + return; + + const auto pClient = pApp->GetClient(); + if (!pClient) + return; + + const auto pRenderer = pClient->GetOverlayRenderHandler(); + if (!pRenderer) + return; + + const auto active = overlay.GetActive(); + + if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active))) + { + if (!overlay.GetInGame()) + { + TiltedPhoques::DInputHook::Get().SetEnabled(false); + } + else if (aType == KEYEVENT_KEYUP) + { + SetUIActive(overlay, pRenderer, !active); + } + } + else if (active) + { + pApp->InjectKey(aType, GetCefModifiers(aKey), aKey, aScanCode); + } +} #endif void ProcessKeyboard(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType, bool aE0, bool aE1) { if (aType != KEYEVENT_CHAR) { + if (aType == KEYEVENT_KEYUP) + { + World::Get().GetDispatcher().trigger(KeyPressEvent{aKey}); + } + if (!aKey || aKey == 255) { return; @@ -204,21 +245,7 @@ void ProcessKeyboard(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aTy spdlog::debug("ProcessKey, type: {}, key: {}, active: {}", aType, aKey, active); - if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active))) - { - if (!overlay.GetInGame()) - { - TiltedPhoques::DInputHook::Get().SetEnabled(false); - } - else if (aType == KEYEVENT_KEYUP) - { - SetUIActive(overlay, pRenderer, !active); - } - } - else if (active) - { - pApp->InjectKey(aType, GetCefModifiers(aKey), aKey, aScanCode); - } + Toggle(aKey, aScanCode, aType); #else const auto active = pRenderer->IsVisible(); @@ -333,6 +360,7 @@ UINT GetRealACP() LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + const auto pApp = s_pOverlay->GetOverlayApp(); if (!pApp) return 0; @@ -438,7 +466,8 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR if (!IsWindowUnicode(hwnd)) { wchar_t wch; - ::MultiByteToWideChar(s_currentACP, MB_PRECOMPOSED, reinterpret_cast(&virtualKey), 2, &wch, sizeof(wchar_t)); + ::MultiByteToWideChar(s_currentACP, MB_PRECOMPOSED, reinterpret_cast(&virtualKey), 2, &wch, + sizeof(wchar_t)); virtualKey = wch; } ProcessKeyboard(virtualKey, scancode, KEYEVENT_CHAR, false, false); @@ -458,12 +487,16 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR return 0; } -bool InputService::SetUIKey(std::shared_ptr apKey) noexcept +bool InputService::SetUIKey(const TiltedPhoques::SharedPtr& acpKey) noexcept { - m_pUiKey = *apKey; + m_pUiKey = *acpKey; return true; } +void InputService::Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept +{ + ::Toggle(aKey, aScanCode, aType); +} InputService::InputService(OverlayService& aOverlay) noexcept { diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index ac35db5f6..028f767cf 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -1,155 +1,276 @@ #include "Services/KeybindService.h" #include "DInputHook.hpp" +#include "OverlayApp.hpp" -KeybindService::KeybindService(InputService& aInputService) : m_inputService(aInputService) +#include "Events/KeyPressEvent.h" + +wchar_t ConvertToUnicode(const uint16_t& aKeyCode) noexcept { - m_inputHook = &TiltedPhoques::DInputHook::Get(); + wchar_t buffer[10]; + BYTE keyboardState[256]; + GetKeyboardState(keyboardState); + + ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); - m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + return buffer[0]; +} + +KeybindService::KeybindService(entt::dispatcher& aDispatcher, InputService& aInputService, DebugService& aDebugService) + : + m_dispatcher(aDispatcher), + m_inputService(aInputService), + m_debugService(aDebugService) +{ + m_pInputHook = &TiltedPhoques::DInputHook::Get(); + + m_dikKeyPressConnection = m_pInputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_vkKeyPressConnection = m_dispatcher.sink().connect<&KeybindService::OnVirtualKeyKeyPress>(this); SetupConfig(); } +KeybindService::~KeybindService() +{ + m_pInputHook = nullptr; +} + void KeybindService::SetupConfig() noexcept { - config.ini.SetUnicode(true); + m_config.ini.SetUnicode(true); const auto modPath = TiltedPhoques::GetPath(); - config.path = modPath / Config::kConfigPathName / Config::kKeybindsFileName; + m_config.path = modPath / Config::kConfigPathName / Config::kKeybindsFileName; if (!exists(modPath / Config::kConfigPathName)) { create_directory(modPath / Config::kConfigPathName); } - if (!exists(config.path)) + if (!exists(m_config.path)) { spdlog::info("{} not found, creating...", Config::kKeybindsFileName); - if (!config.Create()) + if (!m_config.Create()) { - m_uiKey.first = "F2"; - m_debugKey.first = "F3"; + m_uiKey = {"F2", {VK_F2, DIK_F2}}; + m_debugKey = {"F3", {VK_F3, DIK_F3}}; + + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); } } else { spdlog::info("{} found, loading...", Config::kKeybindsFileName); - if (config.Load()) + if (m_config.Load()) { - spdlog::info("Successfully loaded {}", Config::kKeybindsFileName); + spdlog::debug("Successfully loaded {}", Config::kKeybindsFileName); - m_uiKey.first = config.ini.GetValue("UI", "sUiKey", "F2"); - m_debugKey.first = config.ini.GetValue("UI", "sDebugKey", "F3"); + m_uiKey.first = m_config.ini.GetValue("UI", "sUiKey", "F2"); + m_debugKey.first = m_config.ini.GetValue("UI", "sDebugKey", "F3"); + + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); } else { spdlog::warn("{} Failed to load {}", __FUNCTION__, Config::kKeybindsFileName); } } + + spdlog::debug("Debug key: {} | UI key: {}", m_debugKey.first.c_str(), m_uiKey.first.c_str()); } -bool KeybindService::SetDebugKey(std::shared_ptr apKey) noexcept +bool KeybindService::SetDebugKey(const unsigned long& acKeyCode) noexcept { - m_debugKey = *apKey; - config.SetKey("UI", "sDebugKey", m_debugKey.first.c_str()); + m_debugKey = {m_debugKey.first, {m_keyCode, acKeyCode}}; + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); - return true; + if (m_debugKeybindConfirmed) + { + // DebugService would check if the key was pressed before it gets set here, + // so this is necessary to toggle ImGui without having to press the key again + m_debugService.DebugPressed(); + } + + return m_config.SetKey("UI", "sDebugKey", m_debugKey.first.c_str()); } -void KeybindService::BindNewKey(int32_t aKeyCode) noexcept +bool KeybindService::SetUIKey(const unsigned long& acKeyCode) noexcept { - m_keyPressConnection = m_inputHook->OnKeyPress.Connect(std::bind(&KeybindService::OnDirectInputKeyPress, this, std::placeholders::_1)); + m_uiKey = {m_uiKey.first, {m_keyCode, acKeyCode}}; + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + m_pInputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); - m_keybindConfirmed = false; - m_keyCode = aKeyCode; + if (m_uiKeybindConfirmed) + { + // InputService would check if the key was pressed before it gets set here, + // so these are necessary to toggle the UI without having to press the key again + m_pInputHook->SetEnabled(true); + m_inputService.Toggle(m_keyCode, MapVirtualKey(m_uiKey.second.vkKeyCode, MAPVK_VK_TO_VSC), KEYEVENT_CHAR); + } - TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(aKeyCode)))}; + return m_config.SetKey("UI", "sUiKey", m_uiKey.first.c_str()); +} - // Still inserts a null terminator if not found :/ - if (newName.starts_with('\0') && newName.length() == 1) +bool KeybindService::BindUIKey(const uint16_t& acKeyCode) noexcept +{ + m_uiKeybindConfirmed = false; + //m_keyCode = acKeyCode; + + /*TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + if (modKey != m_modifiedKeys.end()) { - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + newName = modKey->first; + m_keyCode = modKey->second; + }*/ + const auto& key = MakeKey(acKeyCode); + + m_uiKey.first = newName; + return SetUIKey(KeyCodes::Error); +} +bool KeybindService::BindDebugKey(const uint16_t& acKeyCode) noexcept +{ + m_debugKeybindConfirmed = false; + //m_keyCode = acKeyCode; + + /*TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + if (modKey != m_modifiedKeys.end()) + { if (modKey != m_modifiedKeys.end()) { newName = modKey->first; m_keyCode = modKey->second; } - } + }*/ + const auto& modKey = MakeKey(acKeyCode); + + m_debugKey.first = modKey.first; + return SetDebugKey(KeyCodes::Error); +} + +void KeybindService::OnVirtualKeyKeyPress(const KeyPressEvent& acEvent) noexcept +{ + m_keyCode = acEvent.VirtualKey; - m_uiKey = {newName, {m_keyCode, 0}}; - m_inputService.SetUIKey(std::make_shared(m_uiKey)); - config.SetKey("UI", "sUiKey", newName.c_str()); + if (acEvent.VirtualKey == m_debugKey.second.vkKeyCode) + m_debugService.DebugPressed(); } -void KeybindService::OnDirectInputKeyPress(unsigned long aKeyCode) +void KeybindService::OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept { - if (!m_keybindConfirmed || m_keyCode != 0) + if (m_keyCode == 0) { - m_keybindConfirmed = true; + // Attempt to reconcile the VirtualKey + m_keyCode = ReconcileKeyPress(); + } - if (m_keyCode == 0) - { - for (int key = 255; key > 1; key--) - { - if (GetAsyncKeyState(key) & 0x8000) - { - m_keyCode = key; - break; - } - } - } + if (m_keyCode != 0) + { + // DebugService would sometimes miss debug key's state change so it is handled here + if (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode) + m_debugService.DebugPressed(); - if (m_keyCode != 0) + if (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed) { const TiltedPhoques::String& key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; - bool foundKey = false; - spdlog::info("{} {}", key.c_str(), m_uiKey.first.c_str()); + bool localUIKeybindConfirmed = false; + bool localDebugKeybindConfirmed = false; - if (key != m_uiKey.first) + // Check if it is a modified key we are looking for + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + if (modKey != m_modifiedKeys.end()) { - // If keyname does not match, check if it is a modified key we are looking for - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + m_keyCode = modKey->second; - if (modKey != m_modifiedKeys.end()) + // UI key pressed + if (modKey->first == m_uiKey.first && !m_uiKeybindConfirmed) { + m_uiKey = {modKey->first, {m_keyCode, m_uiKey.second.diKeyCode}}; m_uiKey.first = modKey->first; - m_keyCode = modKey->second; - foundKey = true; + m_uiKey.second.vkKeyCode = m_keyCode; + m_uiKeybindConfirmed = true; + localUIKeybindConfirmed = true; } + // Debug key pressed + else if (modKey->first == m_debugKey.first && !m_debugKeybindConfirmed) + { + m_debugKey.first = modKey->first; + m_debugKey.second.vkKeyCode = m_keyCode; + m_debugKeybindConfirmed = true; + localDebugKeybindConfirmed = true; + } + } + // UI key was pressed + else if (key == m_uiKey.first && !m_uiKeybindConfirmed) + { + m_uiKeybindConfirmed = true; + localUIKeybindConfirmed = true; } - else + // Debug key was pressed + else if (key == m_debugKey.first && !m_debugKeybindConfirmed) { - foundKey = true; + m_debugKeybindConfirmed = true; + localDebugKeybindConfirmed = true; } - if (foundKey) + // UI key pressed this iteration + if (localUIKeybindConfirmed) { - m_uiKey = {m_uiKey.first, {m_keyCode, aKeyCode}}; - m_inputService.SetUIKey(std::make_shared(m_uiKey)); - m_inputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); - config.SetKey("UI", "sUiKey", m_uiKey.first.c_str()); + SetUIKey(acKeyCode); + } - m_keyCode = 0; - m_inputHook->OnKeyPress.Disconnect(m_keyPressConnection); + // Debug key pressed this iteration + if (localDebugKeybindConfirmed) + { + SetDebugKey(acKeyCode); } } + + m_keyCode = 0; } } -wchar_t KeybindService::ConvertToUnicode(int32_t aKeyCode) noexcept +const KeybindService::Key& KeybindService::MakeKey(const uint16_t& acKeyCode) noexcept { - wchar_t buffer[10]; - BYTE keyboardState[256]; - GetKeyboardState(keyboardState); + m_keyCode = acKeyCode; - ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); + TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; + // Check if key has a custom name + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); - return buffer[0]; + if (modKey != m_modifiedKeys.end()) + { + if (modKey != m_modifiedKeys.end()) + { + newName = modKey->first; + m_keyCode = modKey->second; + } + } + + return {newName, {m_keyCode, KeyCodes::Error}}; +} + +uint16_t KeybindService::ReconcileKeyPress() noexcept +{ + for (uint16_t key = 255; key > 1; key--) + { + if (GetAsyncKeyState(key) & 0x8000) + { + return key; + } + } + + return 0; } bool KeybindService::Config::Create() noexcept @@ -170,7 +291,7 @@ bool KeybindService::Config::Create() noexcept return true; } - spdlog::warn("{}: Failed to create {}, using defaults instead", __FUNCTION__, kKeybindsFileName); + spdlog::warn("{} Failed to create {}, using defaults instead", __FUNCTION__, kKeybindsFileName); return false; } @@ -185,7 +306,7 @@ bool KeybindService::Config::Load() noexcept } bool KeybindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, - const char* acpDescription) noexcept + const char* acpDescription) noexcept { this->ini.SetValue(acpSection, acpKey, acpValue, acpDescription); diff --git a/Code/client/Services/InputService.h b/Code/client/Services/InputService.h index b1040ec10..380629d49 100644 --- a/Code/client/Services/InputService.h +++ b/Code/client/Services/InputService.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct OverlayService; @@ -12,15 +13,17 @@ struct InputService InputService(OverlayService& aOverlay) noexcept; ~InputService() noexcept; - // Use this function to get the player's current UI key const KeybindService::Key& GetUIKey() const noexcept { return m_pUiKey; } - bool SetUIKey(std::shared_ptr apKey) noexcept; + bool SetUIKey(const TiltedPhoques::SharedPtr& acpKey) noexcept; static LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept; + private: // KeybindService should handle any mutations of this key KeybindService::Key m_pUiKey; + bool m_toggleKeyPressed{false}; TP_NOCOPYMOVE(InputService); }; diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index 78b0cd30e..af5360ef0 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -5,16 +5,29 @@ #include +namespace TiltedPhoques +{ +struct OverlayClient; +struct OverlayRenderHandler; +} + struct InputService; +struct DebugService; +struct OverlayService; + +struct KeyPressEvent; namespace fs = std::filesystem; +// TODO (Toe Knee): Cache away an internal-use Key somewhere after a keybind is "set" to not require the key to be pressed to remap an already confirmed Key layout + /** * @brief Handles keybinds * * @details Loads a config during construction, a key name will be set. The key will not actually be set until it is pressed. - * This is due to needing separate VirtualKey and DirectInput keycodes that can only be determined after being pressed. The service only - * connects to the DInputHook OnKeyPress Signal when it is checking for keycodes, disconnected otherwise. + * This is due to needing separate VirtualKey and DirectInput keycodes that can only be determined after being pressed. This service + * needs to stay connected to DInputHook OnKeyPress Signal due to handling UI toggling (sometimes misses otherwise) + * Does not currently support wide characters. */ struct KeybindService { @@ -38,48 +51,61 @@ struct KeybindService { enum { Error = 0 }; - int32_t vkKeyCode = Error; + uint16_t vkKeyCode = Error; unsigned long diKeyCode = Error; }; using Key = std::pair; - KeybindService(InputService& aInputService); - ~KeybindService() = default; + KeybindService(entt::dispatcher& aDispatcher, InputService& aInputService, DebugService& aDebugService); + ~KeybindService(); TP_NOCOPYMOVE(KeybindService); + // BindKey functions configure 2/3 of setting a key, + // DirectInput keycode value gets set in OnDirectInputKeyPress + bool BindUIKey(const uint16_t& acKeyCode) noexcept; + bool BindDebugKey(const uint16_t& acKeyCode) noexcept; + const Key& GetUIKey() const noexcept { return m_uiKey; } const Key& GetDebugKey() const noexcept { return m_debugKey; } - bool SetDebugKey(std::shared_ptr apKey) noexcept; - void BindNewKey(int32_t aKeyCode) noexcept; - void OnDirectInputKeyPress(unsigned long aKeyCode); + const Config& GetConfig() const noexcept { return m_config; } - void SetupConfig() noexcept; - const Config& GetConfig() const noexcept { return config; } +private: + void OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept; + void OnVirtualKeyKeyPress(const KeyPressEvent& acKeyCode) noexcept; + bool SetDebugKey(const unsigned long& acKeyCode) noexcept; + bool SetUIKey(const unsigned long& acKeyCode) noexcept; -private: - wchar_t ConvertToUnicode(int32_t aKeyCode) noexcept; + uint16_t ReconcileKeyPress() noexcept; + + const Key& MakeKey(const uint16_t& acKeyCode) noexcept; + + void SetupConfig() noexcept; + entt::dispatcher& m_dispatcher; InputService& m_inputService; - TiltedPhoques::DInputHook* m_inputHook; + DebugService& m_debugService; + TiltedPhoques::DInputHook* m_pInputHook; - int32_t m_keyCode{0}; + uint16_t m_keyCode{0}; - bool m_keybindConfirmed{false}; + bool m_uiKeybindConfirmed{false}; + bool m_debugKeybindConfirmed{false}; - size_t m_keyPressConnection; + size_t m_dikKeyPressConnection{0}; + entt::scoped_connection m_vkKeyPressConnection{}; - Config config{}; + Config m_config{}; - // Keys not actually "set" until they are pressed from both UI and ingame + // Keys are not actually "set" until they are pressed from both UI and ingame (to tie together VirtualKeys with DirectInput) Key m_uiKey{}; Key m_debugKey{}; - // Keys that have custom names - TiltedPhoques::Map m_modifiedKeys + // Keys with custom names + TiltedPhoques::Map m_modifiedKeys { {"Backspace", VK_BACK}, {"Tab", VK_TAB}, diff --git a/Code/client/World.cpp b/Code/client/World.cpp index ff9ca828e..66ceac676 100644 --- a/Code/client/World.cpp +++ b/Code/client/World.cpp @@ -35,7 +35,6 @@ World::World() ctx().emplace(*this, m_dispatcher); ctx().emplace(*this, m_transport, m_dispatcher); ctx().emplace(ctx().at()); - ctx().emplace(ctx().at()); ctx().emplace(*this, m_dispatcher, m_transport); ctx().emplace(m_dispatcher, *this, m_transport, ctx().at()); ctx().emplace(m_dispatcher); @@ -53,6 +52,7 @@ World::World() ctx().emplace(*this, m_transport, m_dispatcher); ctx().emplace(*this, m_transport, m_dispatcher); ctx().emplace(*this, m_dispatcher, m_transport); + ctx().emplace(m_dispatcher, ctx().at(), ctx().at()); } World::~World() = default; From 345d8704496697e836d992cbcd7f3ec4aeed5fed Mon Sep 17 00:00:00 2001 From: Tony Date: Sat, 5 Oct 2024 01:12:17 -0400 Subject: [PATCH 09/28] add: KeyPressEvent, UI toggle stability, rebinding additions, cleanup rebinding additions: - user can hit escape while rebinding and not close the STR UI - debug key rebinding --- .../Services/Debug/Views/KeybindView.cpp | 21 +- Code/client/Services/DebugService.h | 1 + Code/client/Services/Generic/InputService.cpp | 4 +- .../Services/Generic/KeybindService.cpp | 246 +++++++++--------- Code/client/Services/KeybindService.h | 17 +- 5 files changed, 139 insertions(+), 150 deletions(-) diff --git a/Code/client/Services/Debug/Views/KeybindView.cpp b/Code/client/Services/Debug/Views/KeybindView.cpp index 545e246d8..3471526cc 100644 --- a/Code/client/Services/Debug/Views/KeybindView.cpp +++ b/Code/client/Services/Debug/Views/KeybindView.cpp @@ -17,11 +17,15 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, boo { if (GetAsyncKeyState(key) & 0x8000) { - if (key == VK_ESCAPE || key == VK_LBUTTON || key == VK_RBUTTON) + if (key == VK_ESCAPE) { aBindActive = false; break; } + if (key == VK_LBUTTON || key == VK_RBUTTON) + { + continue; + } aBindActive = false; @@ -35,13 +39,9 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, boo } if (aBindActive) - { ImGui::Text("Press a key..."); - } else - { ImGui::Text(keyName.c_str()); - } return keyName; } @@ -49,14 +49,12 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, boo void DebugService::DrawKeybindView() { #if TP_SKYRIM64 - ImGui::SetNextWindowSize(ImVec2(250, 300), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(350, 100), ImGuiCond_FirstUseEver); ImGui::Begin("Keybinds"); - ImGui::Text("UI"); - TiltedPhoques::String uiKeyName = World::Get().GetInputService().GetUIKey().first; - if (ImGui::Button("Show/Hide", ImVec2(100, 30)) || m_rebindUI) + if (ImGui::Button("Show/Hide STR UI", ImVec2(200, 30)) || m_rebindUI) { m_rebindUI = true; @@ -70,12 +68,9 @@ void DebugService::DrawKeybindView() m_rebindUI = false; } - ImGui::NewLine(); - ImGui::Text("Debug"); - TiltedPhoques::String debugKeyName = World::Get().GetDebugService().GetDebugKey().first; - if (ImGui::Button("Show/Hide", ImVec2(100, 30)) || m_rebindDebug) + if (ImGui::Button("Show/Hide Debug UI", ImVec2(200, 30)) || m_rebindDebug) { m_rebindDebug = true; diff --git a/Code/client/Services/DebugService.h b/Code/client/Services/DebugService.h index fcd306aba..3dca9af7b 100644 --- a/Code/client/Services/DebugService.h +++ b/Code/client/Services/DebugService.h @@ -34,6 +34,7 @@ struct DebugService const KeybindService::Key& GetDebugKey() const noexcept { return m_debugKeybind; } void SetDebugKey(const TiltedPhoques::SharedPtr& acpKey) noexcept { m_debugKeybind = *acpKey; } + bool IsRebinding() const noexcept { return m_rebindUI || m_rebindDebug; } void DebugPressed() noexcept { m_debugKeyPressed = !m_debugKeyPressed; } protected: diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index e37548b32..d4c4f54d9 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -143,7 +143,9 @@ void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexc const auto active = overlay.GetActive(); - if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active))) + const auto& isRebinding = World::Get().GetDebugService().IsRebinding(); + + if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active && isRebinding))) { if (!overlay.GetInGame()) { diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index 028f767cf..4ed81cc23 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -5,17 +5,6 @@ #include "Events/KeyPressEvent.h" -wchar_t ConvertToUnicode(const uint16_t& aKeyCode) noexcept -{ - wchar_t buffer[10]; - BYTE keyboardState[256]; - GetKeyboardState(keyboardState); - - ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); - - return buffer[0]; -} - KeybindService::KeybindService(entt::dispatcher& aDispatcher, InputService& aInputService, DebugService& aDebugService) : m_dispatcher(aDispatcher), @@ -49,30 +38,22 @@ void KeybindService::SetupConfig() noexcept if (!exists(m_config.path)) { - spdlog::info("{} not found, creating...", Config::kKeybindsFileName); + spdlog::debug("{} not found, creating...", Config::kKeybindsFileName); - if (!m_config.Create()) + if (m_config.Create()) { - m_uiKey = {"F2", {VK_F2, DIK_F2}}; - m_debugKey = {"F3", {VK_F3, DIK_F3}}; - - m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); - m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + InitializeKeys(true); } } else { - spdlog::info("{} found, loading...", Config::kKeybindsFileName); + spdlog::debug("{} found, loading...", Config::kKeybindsFileName); if (m_config.Load()) { spdlog::debug("Successfully loaded {}", Config::kKeybindsFileName); - m_uiKey.first = m_config.ini.GetValue("UI", "sUiKey", "F2"); - m_debugKey.first = m_config.ini.GetValue("UI", "sDebugKey", "F3"); - - m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); - m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + InitializeKeys(false); } else { @@ -80,15 +61,35 @@ void KeybindService::SetupConfig() noexcept } } - spdlog::debug("Debug key: {} | UI key: {}", m_debugKey.first.c_str(), m_uiKey.first.c_str()); + spdlog::info("UI key: {} | Debug key: {}", m_uiKey.first.c_str(), m_debugKey.first.c_str()); } -bool KeybindService::SetDebugKey(const unsigned long& acKeyCode) noexcept +void KeybindService::InitializeKeys(bool aLoadDefaults) noexcept { - m_debugKey = {m_debugKey.first, {m_keyCode, acKeyCode}}; + if (aLoadDefaults) + { + m_uiKey = {"F2", {VK_F2, DIK_F2}}; + m_debugKey = {"F3", {VK_F3, DIK_F3}}; + + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + } + else + { + m_uiKey.first = m_config.ini.GetValue("UI", "sUiKey", "F2"); + m_debugKey.first = m_config.ini.GetValue("UI", "sDebugKey", "F3"); + + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + } +} + +bool KeybindService::SetDebugKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept +{ + m_debugKey = {acKeyName, {m_keyCode, acKeyCode}}; m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); - if (m_debugKeybindConfirmed) + if (acKeyCode != KeyCodes::Error) { // DebugService would check if the key was pressed before it gets set here, // so this is necessary to toggle ImGui without having to press the key again @@ -98,154 +99,128 @@ bool KeybindService::SetDebugKey(const unsigned long& acKeyCode) noexcept return m_config.SetKey("UI", "sDebugKey", m_debugKey.first.c_str()); } -bool KeybindService::SetUIKey(const unsigned long& acKeyCode) noexcept +bool KeybindService::SetUIKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept { - m_uiKey = {m_uiKey.first, {m_keyCode, acKeyCode}}; + m_uiKey = {acKeyName, {m_keyCode, acKeyCode}}; m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); - m_pInputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); - if (m_uiKeybindConfirmed) - { - // InputService would check if the key was pressed before it gets set here, - // so these are necessary to toggle the UI without having to press the key again - m_pInputHook->SetEnabled(true); - m_inputService.Toggle(m_keyCode, MapVirtualKey(m_uiKey.second.vkKeyCode, MAPVK_VK_TO_VSC), KEYEVENT_CHAR); - } + if (m_uiKey.second.diKeyCode != 0) + m_pInputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); + + // InputService would check if the key was pressed before it gets set here, + // so these are necessary to toggle the UI without having to press the key again + m_pInputHook->SetEnabled(true); + m_inputService.Toggle(m_keyCode, MapVirtualKey(m_uiKey.second.vkKeyCode, MAPVK_VK_TO_VSC), KEYEVENT_CHAR); return m_config.SetKey("UI", "sUiKey", m_uiKey.first.c_str()); } bool KeybindService::BindUIKey(const uint16_t& acKeyCode) noexcept { - m_uiKeybindConfirmed = false; - //m_keyCode = acKeyCode; + if (acKeyCode == m_debugKey.second.vkKeyCode) + return false; - /*TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + m_uiKeybindConfirmed = false; - if (modKey != m_modifiedKeys.end()) - { - newName = modKey->first; - m_keyCode = modKey->second; - }*/ const auto& key = MakeKey(acKeyCode); - m_uiKey.first = newName; - return SetUIKey(KeyCodes::Error); + return SetUIKey(KeyCodes::Error, key.first); } bool KeybindService::BindDebugKey(const uint16_t& acKeyCode) noexcept { - m_debugKeybindConfirmed = false; - //m_keyCode = acKeyCode; + if (acKeyCode == m_uiKey.second.vkKeyCode) + return false; - /*TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + m_debugKeybindConfirmed = false; - if (modKey != m_modifiedKeys.end()) - { - if (modKey != m_modifiedKeys.end()) - { - newName = modKey->first; - m_keyCode = modKey->second; - } - }*/ - const auto& modKey = MakeKey(acKeyCode); + const auto& key = MakeKey(acKeyCode); - m_debugKey.first = modKey.first; - return SetDebugKey(KeyCodes::Error); + return SetDebugKey(KeyCodes::Error, key.first); } void KeybindService::OnVirtualKeyKeyPress(const KeyPressEvent& acEvent) noexcept { m_keyCode = acEvent.VirtualKey; - if (acEvent.VirtualKey == m_debugKey.second.vkKeyCode) + if (!m_debugKeybindConfirmed) + { + HandleKeybind(KeyCodes::Error); + } + + if (acEvent.VirtualKey == m_debugKey.second.vkKeyCode && m_debugKeybindConfirmed) m_debugService.DebugPressed(); + + spdlog::info("{}", m_keyCode); } void KeybindService::OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept { - if (m_keyCode == 0) + if (m_keyCode == 0 || m_keyCode == m_uiKey.second.vkKeyCode) { // Attempt to reconcile the VirtualKey m_keyCode = ReconcileKeyPress(); } - if (m_keyCode != 0) + // DebugService would sometimes miss debug key's state change so it is handled here + if (CanToggleDebug(acKeyCode)) + { + m_debugService.DebugPressed(); + spdlog::info("THING HAPPENED"); + } + + if (m_keyCode != 0 && (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed)) + { + HandleKeybind(acKeyCode); + } + + m_keyCode = 0; +} + +void KeybindService::HandleKeybind(const unsigned long& acKeyCode) noexcept +{ + TiltedPhoques::String key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; + auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + + // Key has custom name + if (modKey != m_modifiedKeys.end()) { - // DebugService would sometimes miss debug key's state change so it is handled here - if (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode) - m_debugService.DebugPressed(); + m_keyCode = modKey->second; - if (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed) + // UI key pressed + if (modKey->first == m_uiKey.first && !m_uiKeybindConfirmed) { - const TiltedPhoques::String& key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; - - bool localUIKeybindConfirmed = false; - bool localDebugKeybindConfirmed = false; - - // Check if it is a modified key we are looking for - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); - - if (modKey != m_modifiedKeys.end()) - { - m_keyCode = modKey->second; - - // UI key pressed - if (modKey->first == m_uiKey.first && !m_uiKeybindConfirmed) - { - m_uiKey = {modKey->first, {m_keyCode, m_uiKey.second.diKeyCode}}; - m_uiKey.first = modKey->first; - m_uiKey.second.vkKeyCode = m_keyCode; - m_uiKeybindConfirmed = true; - localUIKeybindConfirmed = true; - } - // Debug key pressed - else if (modKey->first == m_debugKey.first && !m_debugKeybindConfirmed) - { - m_debugKey.first = modKey->first; - m_debugKey.second.vkKeyCode = m_keyCode; - m_debugKeybindConfirmed = true; - localDebugKeybindConfirmed = true; - } - } - // UI key was pressed - else if (key == m_uiKey.first && !m_uiKeybindConfirmed) - { - m_uiKeybindConfirmed = true; - localUIKeybindConfirmed = true; - } - // Debug key was pressed - else if (key == m_debugKey.first && !m_debugKeybindConfirmed) - { - m_debugKeybindConfirmed = true; - localDebugKeybindConfirmed = true; - } - - // UI key pressed this iteration - if (localUIKeybindConfirmed) - { - SetUIKey(acKeyCode); - } - - // Debug key pressed this iteration - if (localDebugKeybindConfirmed) - { - SetDebugKey(acKeyCode); - } + key = modKey->first; + m_uiKeybindConfirmed = true; + SetUIKey(acKeyCode, key); + } + // Debug key pressed + else if (modKey->first == m_debugKey.first && !m_debugKeybindConfirmed) + { + key = modKey->first; + m_debugKeybindConfirmed = true; + SetDebugKey(acKeyCode, key); } - - m_keyCode = 0; + } + // UI key was pressed + else if (key == m_uiKey.first && !m_uiKeybindConfirmed) + { + m_uiKeybindConfirmed = true; + SetUIKey(acKeyCode, key); + } + // Debug key was pressed + else if (key == m_debugKey.first && !m_debugKeybindConfirmed) + { + m_debugKeybindConfirmed = true; + SetDebugKey(acKeyCode, key); } } -const KeybindService::Key& KeybindService::MakeKey(const uint16_t& acKeyCode) noexcept +KeybindService::Key KeybindService::MakeKey(const uint16_t& acKeyCode) noexcept { m_keyCode = acKeyCode; TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; - // Check if key has a custom name auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); if (modKey != m_modifiedKeys.end()) @@ -257,7 +232,7 @@ const KeybindService::Key& KeybindService::MakeKey(const uint16_t& acKeyCode) no } } - return {newName, {m_keyCode, KeyCodes::Error}}; + return Key{newName, {m_keyCode, KeyCodes::Error}}; } uint16_t KeybindService::ReconcileKeyPress() noexcept @@ -273,6 +248,17 @@ uint16_t KeybindService::ReconcileKeyPress() noexcept return 0; } +wchar_t KeybindService::ConvertToUnicode(const uint16_t& aKeyCode) noexcept +{ + wchar_t buffer[10]; + BYTE keyboardState[256]; + GetKeyboardState(keyboardState); + + ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); + + return buffer[0]; +} + bool KeybindService::Config::Create() noexcept { if (this->ini.SaveFile(this->path.c_str(), true) == SI_OK) diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index af5360ef0..d3b38f8f4 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -27,7 +27,7 @@ namespace fs = std::filesystem; * @details Loads a config during construction, a key name will be set. The key will not actually be set until it is pressed. * This is due to needing separate VirtualKey and DirectInput keycodes that can only be determined after being pressed. This service * needs to stay connected to DInputHook OnKeyPress Signal due to handling UI toggling (sometimes misses otherwise) - * Does not currently support wide characters. + * Does not currently support wide characters or mouse buttons. */ struct KeybindService { @@ -62,8 +62,8 @@ struct KeybindService TP_NOCOPYMOVE(KeybindService); - // BindKey functions configure 2/3 of setting a key, - // DirectInput keycode value gets set in OnDirectInputKeyPress + // BindKey functions set 2/3 of a key, + // DirectInput keycode value gets set in HandleKeybind bool BindUIKey(const uint16_t& acKeyCode) noexcept; bool BindDebugKey(const uint16_t& acKeyCode) noexcept; @@ -76,12 +76,17 @@ struct KeybindService void OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept; void OnVirtualKeyKeyPress(const KeyPressEvent& acKeyCode) noexcept; - bool SetDebugKey(const unsigned long& acKeyCode) noexcept; - bool SetUIKey(const unsigned long& acKeyCode) noexcept; + void InitializeKeys(bool aLoadDefaults) noexcept; + bool SetDebugKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; + bool CanToggleDebug(const unsigned long& acKeyCode) const noexcept { return (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode);} + bool SetUIKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; + void HandleKeybind(const unsigned long& acKeyCode) noexcept; uint16_t ReconcileKeyPress() noexcept; - const Key& MakeKey(const uint16_t& acKeyCode) noexcept; + Key MakeKey(const uint16_t& acKeyCode) noexcept; + + wchar_t ConvertToUnicode(const uint16_t& aKeyCode) noexcept; void SetupConfig() noexcept; From 345bc8aac439295172685eff7636665c8f7ebcba Mon Sep 17 00:00:00 2001 From: Tony Date: Sat, 5 Oct 2024 02:52:51 -0400 Subject: [PATCH 10/28] tweak: cleanup + clang format --- Code/client/Events/KeyPressEvent.h | 3 ++- Code/client/Services/Generic/InputService.cpp | 9 ++------- Code/client/Services/Generic/KeybindService.cpp | 13 ++++--------- Code/client/Services/KeybindService.h | 15 ++++++++------- Code/client/World.h | 2 -- 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/Code/client/Events/KeyPressEvent.h b/Code/client/Events/KeyPressEvent.h index 78b4d133d..d54e44a80 100644 --- a/Code/client/Events/KeyPressEvent.h +++ b/Code/client/Events/KeyPressEvent.h @@ -5,7 +5,8 @@ */ struct KeyPressEvent { - KeyPressEvent(const uint16_t acKeyCode) : VirtualKey(acKeyCode) + KeyPressEvent(const uint16_t acKeyCode) + : VirtualKey(acKeyCode) { } diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index d4c4f54d9..74f345fe7 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -353,16 +353,12 @@ UINT GetRealACP() // Call the GetLocaleInfo function to retrieve the default ANSI code page // associated with that language ID. UINT acp = CP_ACP; - GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT), - LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, - (LPTSTR) &acp, - sizeof(acp) / sizeof(TCHAR)); + GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (LPTSTR)&acp, sizeof(acp) / sizeof(TCHAR)); return acp; } LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - const auto pApp = s_pOverlay->GetOverlayApp(); if (!pApp) return 0; @@ -468,8 +464,7 @@ LRESULT CALLBACK InputService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR if (!IsWindowUnicode(hwnd)) { wchar_t wch; - ::MultiByteToWideChar(s_currentACP, MB_PRECOMPOSED, reinterpret_cast(&virtualKey), 2, &wch, - sizeof(wchar_t)); + ::MultiByteToWideChar(s_currentACP, MB_PRECOMPOSED, reinterpret_cast(&virtualKey), 2, &wch, sizeof(wchar_t)); virtualKey = wch; } ProcessKeyboard(virtualKey, scancode, KEYEVENT_CHAR, false, false); diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index 4ed81cc23..8695d0676 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -6,10 +6,9 @@ #include "Events/KeyPressEvent.h" KeybindService::KeybindService(entt::dispatcher& aDispatcher, InputService& aInputService, DebugService& aDebugService) - : - m_dispatcher(aDispatcher), - m_inputService(aInputService), - m_debugService(aDebugService) + : m_dispatcher(aDispatcher) + , m_inputService(aInputService) + , m_debugService(aDebugService) { m_pInputHook = &TiltedPhoques::DInputHook::Get(); @@ -150,8 +149,6 @@ void KeybindService::OnVirtualKeyKeyPress(const KeyPressEvent& acEvent) noexcept if (acEvent.VirtualKey == m_debugKey.second.vkKeyCode && m_debugKeybindConfirmed) m_debugService.DebugPressed(); - - spdlog::info("{}", m_keyCode); } void KeybindService::OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept @@ -166,7 +163,6 @@ void KeybindService::OnDirectInputKeyPress(const unsigned long& acKeyCode) noexc if (CanToggleDebug(acKeyCode)) { m_debugService.DebugPressed(); - spdlog::info("THING HAPPENED"); } if (m_keyCode != 0 && (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed)) @@ -291,8 +287,7 @@ bool KeybindService::Config::Load() noexcept return this->ini.LoadFile(this->path.c_str()) == SI_OK; } -bool KeybindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, - const char* acpDescription) noexcept +bool KeybindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription) noexcept { this->ini.SetValue(acpSection, acpKey, acpValue, acpDescription); diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index d3b38f8f4..8311f6424 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -9,7 +9,7 @@ namespace TiltedPhoques { struct OverlayClient; struct OverlayRenderHandler; -} +} // namespace TiltedPhoques struct InputService; struct DebugService; @@ -46,10 +46,12 @@ struct KeybindService fs::path path{}; }; - struct KeyCodes { - enum { Error = 0 }; + enum + { + Error = 0 + }; uint16_t vkKeyCode = Error; unsigned long diKeyCode = Error; @@ -78,7 +80,7 @@ struct KeybindService void InitializeKeys(bool aLoadDefaults) noexcept; bool SetDebugKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; - bool CanToggleDebug(const unsigned long& acKeyCode) const noexcept { return (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode);} + bool CanToggleDebug(const unsigned long& acKeyCode) const noexcept { return (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode); } bool SetUIKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; void HandleKeybind(const unsigned long& acKeyCode) noexcept; @@ -101,7 +103,7 @@ struct KeybindService bool m_debugKeybindConfirmed{false}; size_t m_dikKeyPressConnection{0}; - entt::scoped_connection m_vkKeyPressConnection{}; + entt::scoped_connection m_vkKeyPressConnection{}; Config m_config{}; @@ -110,8 +112,7 @@ struct KeybindService Key m_debugKey{}; // Keys with custom names - TiltedPhoques::Map m_modifiedKeys - { + TiltedPhoques::Map m_modifiedKeys{ {"Backspace", VK_BACK}, {"Tab", VK_TAB}, {"Enter", VK_RETURN}, diff --git a/Code/client/World.h b/Code/client/World.h index 7c5df4468..6662d8f3c 100644 --- a/Code/client/World.h +++ b/Code/client/World.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include @@ -39,7 +38,6 @@ struct World : entt::registry KeybindService& GetKeybindService() noexcept { return ctx().at(); } const KeybindService& GetKeybindService() const noexcept { return ctx().at(); } - auto& GetDispatcher() noexcept { return m_dispatcher; } const ServerSettings& GetServerSettings() const noexcept { return m_serverSettings; } From b34a1f87a96f1f967bea06572334c3a8fc0c4549 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 16 Oct 2024 10:49:43 -0400 Subject: [PATCH 11/28] add: wide char support, UI stability fix: config key loading refactor: general cleanup/clarifications, clang format --- Code/client/Services/Debug/DebugService.cpp | 11 +- .../Services/Debug/Views/KeybindView.cpp | 41 ++- Code/client/Services/Generic/InputService.cpp | 9 +- .../Services/Generic/KeybindService.cpp | 341 ++++++++++++------ Code/client/Services/KeybindService.h | 234 ++++++------ 5 files changed, 407 insertions(+), 229 deletions(-) diff --git a/Code/client/Services/Debug/DebugService.cpp b/Code/client/Services/Debug/DebugService.cpp index 0fcff426c..40b125ba8 100644 --- a/Code/client/Services/Debug/DebugService.cpp +++ b/Code/client/Services/Debug/DebugService.cpp @@ -213,7 +213,7 @@ void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept { s_f8Pressed = true; - //PlaceActorInWorld(); + // PlaceActorInWorld(); } } else @@ -334,12 +334,11 @@ void DebugService::OnDraw() noexcept #endif if (ImGui::BeginMenu("Keybinds")) { - ImGui::MenuItem("Open rebind window", nullptr, &g_enableKeybindWindow); - if (ImGui::BeginMenu("Current binds")) + ImGui::MenuItem("Show keybinds menu", nullptr, &g_enableKeybindWindow); + if (ImGui::Button("Reset all binds to default")) { - ImGui::Text("Show/Hide UI: %s", World::Get().GetInputService().GetUIKey().first.c_str()); - ImGui::Text("Show/Hide Debug: %s", m_debugKeybind.first.c_str()); - ImGui::EndMenu(); + World::Get().GetKeybindService().BindUIKey(VK_F2); + World::Get().GetKeybindService().BindDebugKey(VK_F3); } ImGui::EndMenu(); diff --git a/Code/client/Services/Debug/Views/KeybindView.cpp b/Code/client/Services/Debug/Views/KeybindView.cpp index 3471526cc..69428567a 100644 --- a/Code/client/Services/Debug/Views/KeybindView.cpp +++ b/Code/client/Services/Debug/Views/KeybindView.cpp @@ -5,10 +5,25 @@ #include -const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, bool& aBindActive, const bool& acDebugKey) +TiltedPhoques::String ConvertWstringToString(const TiltedPhoques::WString& acWideString) +{ + if (acWideString.empty()) + { + return {}; + } + + int size_needed = WideCharToMultiByte(CP_UTF8, 0, acWideString.c_str(), static_cast(acWideString.length()), NULL, 0, NULL, NULL); + + TiltedPhoques::String str(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, acWideString.c_str(), static_cast(acWideString.length()), &str[0], size_needed, NULL, NULL); + + return str; +} + +const TiltedPhoques::WString& BindKey(const TiltedPhoques::WString& acKeyName, bool& aBindActive, const bool& acDebugKey) { auto& rebindService = World::Get().GetKeybindService(); - TiltedPhoques::String keyName = acKeyName; + TiltedPhoques::WString keyName = acKeyName; ImGui::SameLine(0); aBindActive = true; @@ -41,18 +56,24 @@ const TiltedPhoques::String& BindKey(const TiltedPhoques::String& acKeyName, boo if (aBindActive) ImGui::Text("Press a key..."); else - ImGui::Text(keyName.c_str()); + { + const auto& narrowString = ConvertWstringToString(keyName); + ImGui::Text("%s", narrowString.c_str()); + } - return keyName; + return {keyName}; } void DebugService::DrawKeybindView() { #if TP_SKYRIM64 - ImGui::SetNextWindowSize(ImVec2(350, 100), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(350, 150), ImGuiCond_FirstUseEver); ImGui::Begin("Keybinds"); - TiltedPhoques::String uiKeyName = World::Get().GetInputService().GetUIKey().first; + TiltedPhoques::WString uiKeyName = World::Get().GetInputService().GetUIKey().first; + + if (IsRebinding()) + ImGui::Text("Press Escape to cancel"); if (ImGui::Button("Show/Hide STR UI", ImVec2(200, 30)) || m_rebindUI) { @@ -63,12 +84,13 @@ void DebugService::DrawKeybindView() else { ImGui::SameLine(0); - ImGui::Text("%s", uiKeyName.c_str()); + const auto& narrowString = ConvertWstringToString(uiKeyName); + ImGui::Text("%s", narrowString.c_str()); m_rebindUI = false; } - TiltedPhoques::String debugKeyName = World::Get().GetDebugService().GetDebugKey().first; + TiltedPhoques::WString debugKeyName = World::Get().GetDebugService().GetDebugKey().first; if (ImGui::Button("Show/Hide Debug UI", ImVec2(200, 30)) || m_rebindDebug) { @@ -79,7 +101,8 @@ void DebugService::DrawKeybindView() else { ImGui::SameLine(0); - ImGui::Text("%s", debugKeyName.c_str()); + const auto& narrowString = ConvertWstringToString(debugKeyName); + ImGui::Text("%s", narrowString.c_str()); m_rebindDebug = false; } diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 74f345fe7..7af60cf8e 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -143,7 +143,9 @@ void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexc const auto active = overlay.GetActive(); - const auto& isRebinding = World::Get().GetDebugService().IsRebinding(); + const auto& debugService = World::Get().GetDebugService(); + const auto& isRebinding = debugService.IsRebinding(); + const auto& isDebugKey = aKey == debugService.GetDebugKey().second.vkKeyCode; if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active && isRebinding))) { @@ -156,7 +158,8 @@ void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexc SetUIActive(overlay, pRenderer, !active); } } - else if (active) + // If debug is visible, don't inject key + else if (active && (isDebugKey && !debugService.m_showDebugStuff)) { pApp->InjectKey(aType, GetCefModifiers(aKey), aKey, aScanCode); } @@ -167,7 +170,7 @@ void ProcessKeyboard(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aTy { if (aType != KEYEVENT_CHAR) { - if (aType == KEYEVENT_KEYUP) + if (aType == KEYEVENT_KEYDOWN) { World::Get().GetDispatcher().trigger(KeyPressEvent{aKey}); } diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index 8695d0676..ef2a29a48 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -27,12 +27,12 @@ void KeybindService::SetupConfig() noexcept { m_config.ini.SetUnicode(true); - const auto modPath = TiltedPhoques::GetPath(); - m_config.path = modPath / Config::kConfigPathName / Config::kKeybindsFileName; + const auto cModPath = TiltedPhoques::GetPath(); + m_config.path = cModPath / Config::kConfigPathName / Config::kKeybindsFileName; - if (!exists(modPath / Config::kConfigPathName)) + if (!exists(cModPath / Config::kConfigPathName)) { - create_directory(modPath / Config::kConfigPathName); + create_directory(cModPath / Config::kConfigPathName); } if (!exists(m_config.path)) @@ -60,155 +60,222 @@ void KeybindService::SetupConfig() noexcept } } - spdlog::info("UI key: {} | Debug key: {}", m_uiKey.first.c_str(), m_debugKey.first.c_str()); + // doesnt print out some characters correctly + spdlog::info("UI Key: {} | Debug Key: {}", ConvertToString(m_uiKey.first).c_str(), ConvertToString(m_debugKey.first).c_str()); } void KeybindService::InitializeKeys(bool aLoadDefaults) noexcept { if (aLoadDefaults) { - m_uiKey = {"F2", {VK_F2, DIK_F2}}; - m_debugKey = {"F3", {VK_F3, DIK_F3}}; - - m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); - m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + m_uiKey = DEFAULT_UI_KEY; + m_debugKey = DEFAULT_DEBUG_KEY; } else { - m_uiKey.first = m_config.ini.GetValue("UI", "sUiKey", "F2"); - m_debugKey.first = m_config.ini.GetValue("UI", "sDebugKey", "F3"); + m_uiKey.first = m_config.ini.GetValue(L"UI", L"sUiKey", L"F2"); + m_debugKey.first = m_config.ini.GetValue(L"UI", L"sDebugKey", L"F3"); - m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); - m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + // If attempting to bind both to one key, change debug to F3 (as key is less likely to be used) + // If UI is set to F3, reset UI key to ensure keys are different + if (m_uiKey.first == m_debugKey.first) + { + spdlog::warn("{} Cannot bind both Debug UI and STR UI to same key, resetting key", __FUNCTION__); + + if (m_uiKey.first != L"F3") + m_debugKey = DEFAULT_DEBUG_KEY; + else + m_uiKey = DEFAULT_UI_KEY; + } + + m_uiKey.second = m_config.GetKeyCodes(L"ui"); + m_debugKey.second = m_config.GetKeyCodes(L"debug"); } + + HandleKeybind(m_uiKey.second.vkKeyCode, m_uiKey.second.diKeyCode, true); + HandleKeybind(m_debugKey.second.vkKeyCode, m_debugKey.second.diKeyCode, true); } -bool KeybindService::SetDebugKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept +bool KeybindService::SetDebugKey(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const TiltedPhoques::WString& acKeyName, const bool& acLoadFromConfig) noexcept { - m_debugKey = {acKeyName, {m_keyCode, acKeyCode}}; - m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + if (m_debugKey.first == acKeyName) + { + if (acVkKeyCode != KeyCodes::Error) + m_debugKey.second.vkKeyCode = acVkKeyCode; + + if (acDiKeyCode != KeyCodes::Error) + m_debugKey.second.diKeyCode = acDiKeyCode; - if (acKeyCode != KeyCodes::Error) + if (!acKeyName.empty()) + m_debugKey.first = acKeyName; + + m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); + + if (!m_debugKeybindConfirmed && m_debugKey.second.vkKeyCode != KeyCodes::Error && m_debugKey.second.diKeyCode != KeyCodes::Error) + { + m_debugKeybindConfirmed = true; + } + } + else { - // DebugService would check if the key was pressed before it gets set here, - // so this is necessary to toggle ImGui without having to press the key again - m_debugService.DebugPressed(); + // Keybind may have been changed via config file, start reconciling the key + m_debugKey.second = {KeyCodes::Error, KeyCodes::Error}; + m_debugKeybindConfirmed = false; } - return m_config.SetKey("UI", "sDebugKey", m_debugKey.first.c_str()); + if (!acLoadFromConfig) + return m_config.SetKey(L"sDebugKey", m_debugKey.first.c_str()) && m_config.SetKeyCodes(L"debug", m_debugKey.second); + + return true; } -bool KeybindService::SetUIKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept +bool KeybindService::SetUIKey(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const TiltedPhoques::WString& acKeyName, const bool& acLoadFromConfig) noexcept { - m_uiKey = {acKeyName, {m_keyCode, acKeyCode}}; - m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); + if (m_uiKey.first == acKeyName) + { + if (acVkKeyCode != KeyCodes::Error) + m_uiKey.second.vkKeyCode = acVkKeyCode; - if (m_uiKey.second.diKeyCode != 0) + if (acDiKeyCode != KeyCodes::Error) + m_uiKey.second.diKeyCode = acDiKeyCode; + + if (!acKeyName.empty()) + m_uiKey.first = acKeyName; + + m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); m_pInputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); - // InputService would check if the key was pressed before it gets set here, - // so these are necessary to toggle the UI without having to press the key again - m_pInputHook->SetEnabled(true); - m_inputService.Toggle(m_keyCode, MapVirtualKey(m_uiKey.second.vkKeyCode, MAPVK_VK_TO_VSC), KEYEVENT_CHAR); + if (!m_uiKeybindConfirmed && m_uiKey.second.vkKeyCode != KeyCodes::Error && m_uiKey.second.diKeyCode != KeyCodes::Error) + { + m_uiKeybindConfirmed = true; + } + } + else + { + // Keybind may have been changed via config file, start reconciling the key + m_uiKey.second = {KeyCodes::Error, KeyCodes::Error}; + m_uiKeybindConfirmed = false; + } + + // Don't toggle UI if loading from config + if (!acLoadFromConfig) + { + m_pInputHook->SetEnabled(true); + m_inputService.Toggle(acVkKeyCode, MapVirtualKey(m_uiKey.second.vkKeyCode, MAPVK_VK_TO_VSC), KEYEVENT_CHAR); + + return m_config.SetKey(L"sUiKey", m_uiKey.first.c_str()) && m_config.SetKeyCodes(L"ui", m_uiKey.second); + } - return m_config.SetKey("UI", "sUiKey", m_uiKey.first.c_str()); + return true; } bool KeybindService::BindUIKey(const uint16_t& acKeyCode) noexcept { - if (acKeyCode == m_debugKey.second.vkKeyCode) + if (acKeyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_uiKey.second.vkKeyCode) return false; m_uiKeybindConfirmed = false; - const auto& key = MakeKey(acKeyCode); + const auto& cKey = MakeKey(acKeyCode); + m_uiKey = cKey; - return SetUIKey(KeyCodes::Error, key.first); + return SetUIKey(cKey.second.vkKeyCode, cKey.second.diKeyCode, cKey.first); } bool KeybindService::BindDebugKey(const uint16_t& acKeyCode) noexcept { - if (acKeyCode == m_uiKey.second.vkKeyCode) + if (acKeyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_uiKey.second.vkKeyCode) return false; m_debugKeybindConfirmed = false; - const auto& key = MakeKey(acKeyCode); + const auto& cKey = MakeKey(acKeyCode); + m_debugKey = cKey; - return SetDebugKey(KeyCodes::Error, key.first); + return SetDebugKey(cKey.second.vkKeyCode, cKey.second.diKeyCode, cKey.first); } void KeybindService::OnVirtualKeyKeyPress(const KeyPressEvent& acEvent) noexcept { - m_keyCode = acEvent.VirtualKey; + m_keyCode = acEvent.VirtualKey >= 0x10 && acEvent.VirtualKey <= 0x12 ? ResolveVkKeyModifier(acEvent.VirtualKey) : acEvent.VirtualKey; - if (!m_debugKeybindConfirmed) + if (!m_debugKeybindConfirmed || !m_uiKeybindConfirmed) { - HandleKeybind(KeyCodes::Error); + HandleKeybind(m_keyCode, KeyCodes::Error); } - if (acEvent.VirtualKey == m_debugKey.second.vkKeyCode && m_debugKeybindConfirmed) + if (CanToggleDebug(m_keyCode, KeyCodes::Error)) + { m_debugService.DebugPressed(); + } } void KeybindService::OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept { - if (m_keyCode == 0 || m_keyCode == m_uiKey.second.vkKeyCode) + if (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed) { - // Attempt to reconcile the VirtualKey - m_keyCode = ReconcileKeyPress(); + HandleKeybind(KeyCodes::Error, acKeyCode); } // DebugService would sometimes miss debug key's state change so it is handled here - if (CanToggleDebug(acKeyCode)) + if (CanToggleDebug(KeyCodes::Error, acKeyCode)) { m_debugService.DebugPressed(); } +} - if (m_keyCode != 0 && (!m_uiKeybindConfirmed || !m_debugKeybindConfirmed)) +void KeybindService::HandleKeybind(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const bool& acLoadFromConfig) noexcept +{ + m_keyCode = acVkKeyCode; + + if (m_keyCode == KeyCodes::Error && !acLoadFromConfig) { - HandleKeybind(acKeyCode); + BYTE keyboardState[256]{}; + // ensures windows input system is initialized/not considered "stale" before trying to get keyboard state + GetKeyState(0); + GetKeyboardState(keyboardState); + + for (uint16_t key = 256; key > 0; key--) + { + if (keyboardState[key] & 0x80) + { + m_keyCode = key; + break; + } + } } - m_keyCode = 0; -} + wchar_t keyChar = static_cast(MapVirtualKeyA(m_keyCode, MAPVK_VK_TO_CHAR)); -void KeybindService::HandleKeybind(const unsigned long& acKeyCode) noexcept -{ - TiltedPhoques::String key = {static_cast(toupper(ConvertToUnicode(m_keyCode)))}; - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + const TiltedPhoques::WString& cKeyName = {static_cast(toupper(keyChar))}; + const KeybindService::Key& cKey = {cKeyName, {acVkKeyCode, acDiKeyCode}}; + auto pModKey = std::ranges::find_if(m_modifiedKeys, [&](const KeybindService::Key& acKey) { return acKey.second.vkKeyCode == m_keyCode || acKey.second.diKeyCode == acDiKeyCode; }); // Key has custom name - if (modKey != m_modifiedKeys.end()) + if (pModKey != m_modifiedKeys.end()) { - m_keyCode = modKey->second; + m_keyCode = pModKey->second.vkKeyCode; // UI key pressed - if (modKey->first == m_uiKey.first && !m_uiKeybindConfirmed) + if (DoesKeyMatch(*pModKey, m_uiKey) && !m_uiKeybindConfirmed) { - key = modKey->first; - m_uiKeybindConfirmed = true; - SetUIKey(acKeyCode, key); + SetUIKey(m_keyCode, acDiKeyCode, pModKey->first, acLoadFromConfig); } // Debug key pressed - else if (modKey->first == m_debugKey.first && !m_debugKeybindConfirmed) + else if (DoesKeyMatch(*pModKey, m_debugKey) && !m_debugKeybindConfirmed) { - key = modKey->first; - m_debugKeybindConfirmed = true; - SetDebugKey(acKeyCode, key); + SetDebugKey(m_keyCode, acDiKeyCode, pModKey->first); } } - // UI key was pressed - else if (key == m_uiKey.first && !m_uiKeybindConfirmed) + // No custom key name, UI key was pressed + else if (DoesKeyMatch(cKey, m_uiKey) && !m_uiKeybindConfirmed) { - m_uiKeybindConfirmed = true; - SetUIKey(acKeyCode, key); + SetUIKey(m_keyCode, acDiKeyCode, cKeyName, acLoadFromConfig); } - // Debug key was pressed - else if (key == m_debugKey.first && !m_debugKeybindConfirmed) + // No custom key name, Debug key was pressed + else if (DoesKeyMatch(cKey, m_debugKey) && !m_debugKeybindConfirmed) { - m_debugKeybindConfirmed = true; - SetDebugKey(acKeyCode, key); + SetDebugKey(m_keyCode, acDiKeyCode, cKeyName); } } @@ -216,65 +283,116 @@ KeybindService::Key KeybindService::MakeKey(const uint16_t& acKeyCode) noexcept { m_keyCode = acKeyCode; - TiltedPhoques::String newName = {static_cast(toupper(ConvertToUnicode(acKeyCode)))}; - auto modKey = std::ranges::find_if(m_modifiedKeys, [&](const std::pair& acKey) { return acKey.second == m_keyCode; }); + TiltedPhoques::WString newName = {static_cast(MapVirtualKeyW(acKeyCode, MAPVK_VK_TO_CHAR))}; + auto pModKey = std::ranges::find_if(m_modifiedKeys, [&](const KeybindService::Key& acKey) { return acKey.second.vkKeyCode == m_keyCode; }); - if (modKey != m_modifiedKeys.end()) + if (pModKey != m_modifiedKeys.end()) { - if (modKey != m_modifiedKeys.end()) + if (pModKey != m_modifiedKeys.end()) { - newName = modKey->first; - m_keyCode = modKey->second; + newName = pModKey->first; + m_keyCode = pModKey->second.vkKeyCode; } } return Key{newName, {m_keyCode, KeyCodes::Error}}; } -uint16_t KeybindService::ReconcileKeyPress() noexcept +bool KeybindService::CanToggleDebug(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode) const noexcept { - for (uint16_t key = 255; key > 1; key--) + return (acVkKeyCode != KeyCodes::Error && acVkKeyCode == m_debugKey.second.vkKeyCode) || (acDiKeyCode != KeyCodes::Error && acDiKeyCode == m_debugKey.second.diKeyCode); +} + +bool KeybindService::DoesKeyMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept +{ + return acLeftKey.first == acRightKey.first || acLeftKey.second.vkKeyCode == acRightKey.second.vkKeyCode || acLeftKey.second.diKeyCode == acRightKey.second.diKeyCode; +} + +TiltedPhoques::WString KeybindService::ConvertToWString(const TiltedPhoques::String& acString) noexcept +{ + int nChars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, acString.data(), static_cast(acString.length()), NULL, 0); + + TiltedPhoques::WString wstrTo; + if (nChars > 0) { - if (GetAsyncKeyState(key) & 0x8000) + wstrTo.resize(nChars); + + if (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, acString.data(), static_cast(acString.length()), &wstrTo[0], nChars)) { - return key; + return wstrTo; } } - return 0; + return {}; } -wchar_t KeybindService::ConvertToUnicode(const uint16_t& aKeyCode) noexcept +TiltedPhoques::String KeybindService::ConvertToString(const TiltedPhoques::WString& aString) noexcept { - wchar_t buffer[10]; - BYTE keyboardState[256]; - GetKeyboardState(keyboardState); + int nChars = WideCharToMultiByte(CP_ACP, 0, aString.data(), static_cast(aString.length()), nullptr, 0, nullptr, nullptr); + + TiltedPhoques::String strTo{}; + if (nChars > 0) + { + strTo.resize(nChars); - ToUnicode(aKeyCode, 0, keyboardState, buffer, 10, 0); + if (WideCharToMultiByte(CP_ACP, 0, aString.data(), static_cast(aString.length()), &strTo[0], nChars, nullptr, nullptr)) + { + return strTo; + } + } - return buffer[0]; + return {}; +} + +uint16_t KeybindService::ResolveVkKeyModifier(const uint16_t& acKeyCode) noexcept +{ + switch (acKeyCode) + { + case VK_SHIFT: + if (GetAsyncKeyState(VK_LSHIFT) & 0x80) + return VK_LSHIFT; + else + return VK_RSHIFT; + case VK_CONTROL: + if (GetAsyncKeyState(VK_LCONTROL) & 0x80) + return VK_LCONTROL; + else + return VK_RCONTROL; + case VK_MENU: + if (GetAsyncKeyState(VK_LMENU) & 0x80) + return VK_LMENU; + else + return VK_RMENU; + default: return acKeyCode; + } } bool KeybindService::Config::Create() noexcept { - if (this->ini.SaveFile(this->path.c_str(), true) == SI_OK) + if (this->ini.SaveFile(this->path.c_str(), true) != SI_OK) { - spdlog::info("Successfully created {}", kKeybindsFileName); + spdlog::warn("{} Failed to create {}, using defaults instead", __FUNCTION__, kKeybindsFileName); + return false; + } - this->ini.SetValue("UI", "sUiKey", "F2"); - this->ini.SetValue("UI", "sDebugKey", "F3"); + spdlog::info("Successfully created {}", kKeybindsFileName); - if (!this->Save()) - { - spdlog::warn("Failed to save {}", kKeybindsFileName); - return false; - } + this->ini.SetValue(L"UI", L"sUiKey", L"F2"); + this->ini.SetValue(L"UI", L"sDebugKey", L"F3"); + + const TiltedPhoques::WString cUiKeyCodes{std::to_wstring(VK_F2) + L"," + std::to_wstring(DIK_F2)}; + const TiltedPhoques::WString cDebugKeyCodes{std::to_wstring(VK_F3) + L"," + std::to_wstring(DIK_F3)}; + + this->ini.SetValue(L"Internal", L"ui", cUiKeyCodes.c_str()); + this->ini.SetValue(L"Internal", L"debug", cDebugKeyCodes.c_str()); - return true; + if (!this->Save()) + { + spdlog::warn("Failed to save {}", kKeybindsFileName); + return false; } - spdlog::warn("{} Failed to create {}, using defaults instead", __FUNCTION__, kKeybindsFileName); - return false; + return true; } bool KeybindService::Config::Save() const noexcept @@ -287,9 +405,28 @@ bool KeybindService::Config::Load() noexcept return this->ini.LoadFile(this->path.c_str()) == SI_OK; } -bool KeybindService::Config::SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription) noexcept +bool KeybindService::Config::SetKey(const wchar_t* acpKey, const wchar_t* acpValue, const wchar_t* acpDescription) noexcept { - this->ini.SetValue(acpSection, acpKey, acpValue, acpDescription); + this->ini.SetValue(L"UI", acpKey, acpValue, acpDescription); return this->Save(); } + +bool KeybindService::Config::SetKeyCodes(const wchar_t* acpConfigKey, const KeybindService::KeyCodes& acKeyCodes) noexcept +{ + const TiltedPhoques::WString cKeyString{std::to_wstring(acKeyCodes.vkKeyCode) + L"," + std::to_wstring(acKeyCodes.diKeyCode)}; + + this->ini.SetValue(L"Internal", acpConfigKey, cKeyString.c_str()); + + return this->Save(); +} + +KeybindService::KeyCodes KeybindService::Config::GetKeyCodes(const wchar_t* acpKey) const noexcept +{ + const TiltedPhoques::WString& cKeyString = this->ini.GetValue(L"Internal", acpKey); + + const auto& vkKeyCode = static_cast(std::stoi(cKeyString.substr(cKeyString.find_first_of(L"=") + 1, cKeyString.find_first_of(L",")).c_str())); + const auto& diKeyCode = std::stoul(cKeyString.substr(cKeyString.find_first_of(L",") + 1).c_str()); + + return {vkKeyCode, diKeyCode}; +} diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index 8311f6424..aa32f2f62 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -19,18 +19,46 @@ struct KeyPressEvent; namespace fs = std::filesystem; -// TODO (Toe Knee): Cache away an internal-use Key somewhere after a keybind is "set" to not require the key to be pressed to remap an already confirmed Key layout +#define DEFAULT_UI_KEY \ + { \ + L"F2", \ + { \ + VK_F2, DIK_F2 \ + } \ + } +#define DEFAULT_DEBUG_KEY \ + { \ + L"F3", \ + { \ + VK_F3, DIK_F3 \ + } \ + } /** * @brief Handles keybinds * - * @details Loads a config during construction, a key name will be set. The key will not actually be set until it is pressed. + * @details Loads a config during construction. The key will not actually be set until it is pressed or loaded from config. * This is due to needing separate VirtualKey and DirectInput keycodes that can only be determined after being pressed. This service * needs to stay connected to DInputHook OnKeyPress Signal due to handling UI toggling (sometimes misses otherwise) - * Does not currently support wide characters or mouse buttons. + * Does not currently support mouse buttons. */ struct KeybindService { + struct KeyCodes + { + enum + { + Error = 0 + }; + + // VirtualKey + uint16_t vkKeyCode = Error; + // DirectInput + unsigned long diKeyCode = Error; + }; + + using Key = std::pair; + struct Config { static constexpr char kConfigPathName[] = "config"; @@ -40,32 +68,19 @@ struct KeybindService bool Save() const noexcept; bool Load() noexcept; - bool SetKey(const char* acpSection, const char* acpKey, const char* acpValue, const char* acpDescription = nullptr) noexcept; + bool SetKey(const wchar_t* acpKey, const wchar_t* acpValue, const wchar_t* acpDescription = nullptr) noexcept; + bool SetKeyCodes(const wchar_t* acpConfigKey, const KeybindService::KeyCodes& acKeyCodes) noexcept; + KeyCodes GetKeyCodes(const wchar_t* acpKey) const noexcept; - CSimpleIniA ini{}; + CSimpleIniW ini{}; fs::path path{}; }; - struct KeyCodes - { - enum - { - Error = 0 - }; - - uint16_t vkKeyCode = Error; - unsigned long diKeyCode = Error; - }; - - using Key = std::pair; - KeybindService(entt::dispatcher& aDispatcher, InputService& aInputService, DebugService& aDebugService); ~KeybindService(); TP_NOCOPYMOVE(KeybindService); - // BindKey functions set 2/3 of a key, - // DirectInput keycode value gets set in HandleKeybind bool BindUIKey(const uint16_t& acKeyCode) noexcept; bool BindDebugKey(const uint16_t& acKeyCode) noexcept; @@ -78,17 +93,18 @@ struct KeybindService void OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept; void OnVirtualKeyKeyPress(const KeyPressEvent& acKeyCode) noexcept; - void InitializeKeys(bool aLoadDefaults) noexcept; - bool SetDebugKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; - bool CanToggleDebug(const unsigned long& acKeyCode) const noexcept { return (m_keyCode == m_debugKey.second.vkKeyCode || acKeyCode == m_debugKey.second.diKeyCode); } - bool SetUIKey(const unsigned long& acKeyCode, const TiltedPhoques::String& acKeyName) noexcept; - void HandleKeybind(const unsigned long& acKeyCode) noexcept; - - uint16_t ReconcileKeyPress() noexcept; - Key MakeKey(const uint16_t& acKeyCode) noexcept; - wchar_t ConvertToUnicode(const uint16_t& aKeyCode) noexcept; + void InitializeKeys(bool aLoadDefaults) noexcept; + bool SetDebugKey(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const TiltedPhoques::WString& acKeyName, const bool& acLoadFromConfig = false) noexcept; + bool SetUIKey(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const TiltedPhoques::WString& acKeyName, const bool& acLoadFromConfig = false) noexcept; + void HandleKeybind(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const bool& acLoadFromConfig = false) noexcept; + bool CanToggleDebug(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode) const noexcept; + bool DoesKeyMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept; + + static TiltedPhoques::WString ConvertToWString(const TiltedPhoques::String& acString) noexcept; + static TiltedPhoques::String ConvertToString(const TiltedPhoques::WString& acString) noexcept; + static uint16_t ResolveVkKeyModifier(const uint16_t& acKeyCode) noexcept; void SetupConfig() noexcept; @@ -108,90 +124,90 @@ struct KeybindService Config m_config{}; // Keys are not actually "set" until they are pressed from both UI and ingame (to tie together VirtualKeys with DirectInput) + // or loaded from config Key m_uiKey{}; Key m_debugKey{}; // Keys with custom names - TiltedPhoques::Map m_modifiedKeys{ - {"Backspace", VK_BACK}, - {"Tab", VK_TAB}, - {"Enter", VK_RETURN}, - {"LSHIFT", VK_LSHIFT}, - {"RSHIFT", VK_RSHIFT}, - {"LCTRL", VK_LCONTROL}, - {"RCTRL", VK_RCONTROL}, - {"LALT", VK_LMENU}, - {"RALT", VK_RMENU}, - {"Pause", VK_PAUSE}, - {"Caps Lock", VK_CAPITAL}, - {"IME Kana mode", VK_KANA}, - {"IME Kanji mode", VK_KANJI}, - {"Esc", VK_ESCAPE}, - {"IME convert", VK_CONVERT}, - {"IME nonconvert", VK_NONCONVERT}, - {"Space", VK_SPACE}, - {"Page Up", VK_PRIOR}, - {"Page Down", VK_NEXT}, - {"End", VK_END}, - {"Home", VK_HOME}, - {"Arrow Left", VK_LEFT}, - {"Arrow Up", VK_UP}, - {"Arrow Right", VK_RIGHT}, - {"Arrow Down", VK_DOWN}, - {"Ins", VK_INSERT}, - {"Del", VK_DELETE}, - {"LWIN", VK_LWIN}, - {"RWIN", VK_RWIN}, - {"Applications", VK_APPS}, - {"Sleep", VK_SLEEP}, - {"NUMPAD 0", VK_NUMPAD0}, - {"NUMPAD 1", VK_NUMPAD1}, - {"NUMPAD 2", VK_NUMPAD2}, - {"NUMPAD 3", VK_NUMPAD3}, - {"NUMPAD 4", VK_NUMPAD4}, - {"NUMPAD 5", VK_NUMPAD5}, - {"NUMPAD 6", VK_NUMPAD6}, - {"NUMPAD 7", VK_NUMPAD7}, - {"NUMPAD 8", VK_NUMPAD8}, - {"NUMPAD 9", VK_NUMPAD9}, - {"NUMPAD *", VK_MULTIPLY}, - {"NUMPAD +", VK_ADD}, - {"NUMPAD -", VK_SUBTRACT}, - {"NUMPAD .", VK_DECIMAL}, - {"NUMPAD /", VK_DIVIDE}, - {"F1", VK_F1}, - {"F2", VK_F2}, - {"F3", VK_F3}, - {"F4", VK_F4}, - {"F5", VK_F5}, - {"F6", VK_F6}, - {"F7", VK_F7}, - {"F8", VK_F8}, - {"F9", VK_F9}, - {"F10", VK_F10}, - {"F11", VK_F11}, - {"F12", VK_F12}, - {"F13", VK_F13}, - {"F14", VK_F14}, - {"F15", VK_F15}, - {"Num Lock", VK_NUMLOCK}, - {"ScrLk", VK_SCROLL}, - {"Browser Back", VK_BROWSER_BACK}, - {"Browser Forward", VK_BROWSER_FORWARD}, - {"Browser Refresh", VK_BROWSER_REFRESH}, - {"Browser Stop", VK_BROWSER_STOP}, - {"Browser Search", VK_BROWSER_SEARCH}, - {"Browser Favorites", VK_BROWSER_FAVORITES}, - {"Browser Stard and Home", VK_BROWSER_HOME}, - {"Volume Mute", VK_VOLUME_MUTE}, - {"Volume Down", VK_VOLUME_DOWN}, - {"Volume Up", VK_VOLUME_UP}, - {"Next Track", VK_MEDIA_NEXT_TRACK}, - {"Previous Track", VK_MEDIA_PREV_TRACK}, - {"Stop Media", VK_MEDIA_STOP}, - {"Play/Pause Media", VK_MEDIA_PLAY_PAUSE}, - {"Start Mail", VK_LAUNCH_MAIL}, - {"Select Media", VK_LAUNCH_MEDIA_SELECT} + const TiltedPhoques::Map& m_modifiedKeys{ + {L"Backspace", {VK_BACK, DIK_BACK}}, + {L"Tab", {VK_TAB, DIK_TAB}}, + {L"Enter", {VK_RETURN, DIK_RETURN}}, + {L"LSHIFT", {VK_LSHIFT, DIK_LSHIFT}}, + {L"RSHIFT", {VK_RSHIFT, DIK_RSHIFT}}, + {L"LCTRL", {VK_LCONTROL, DIK_LCONTROL}}, + {L"RCTRL", {VK_RCONTROL, DIK_RCONTROL}}, + {L"LALT", {VK_LMENU, DIK_LMENU}}, + {L"RALT", {VK_RMENU, DIK_RMENU}}, + {L"Pause", {VK_PAUSE, DIK_PAUSE}}, + {L"Caps Lock", {VK_CAPITAL, DIK_CAPSLOCK}}, + {L"IME Kana mode", {VK_KANA, DIK_KANA}}, + {L"IME Kanji mode", {VK_KANJI, DIK_KANJI}}, + {L"Esc", {VK_ESCAPE, DIK_ESCAPE}}, + {L"IME convert", {VK_CONVERT, DIK_CONVERT}}, + {L"IME nonconvert", {VK_NONCONVERT, DIK_NOCONVERT}}, + {L"Space", {VK_SPACE, DIK_SPACE}}, + {L"Page Up", {VK_PRIOR, DIK_PRIOR}}, + {L"Page Down", {VK_NEXT, DIK_NEXT}}, + {L"End", {VK_END, DIK_END}}, + {L"Home", {VK_HOME, DIK_HOME}}, + {L"Arrow Left", {VK_LEFT, DIK_LEFT}}, + {L"Arrow Up", {VK_UP, DIK_UP}}, + {L"Arrow Right", {VK_RIGHT, DIK_RIGHT}}, + {L"Arrow Down", {VK_DOWN, DIK_DOWN}}, + {L"Ins", {VK_INSERT, DIK_INSERT}}, + {L"Del", {VK_DELETE, DIK_DELETE}}, + {L"LWIN", {VK_LWIN, DIK_LWIN}}, + {L"RWIN", {VK_RWIN, DIK_RWIN}}, + {L"Applications", {VK_APPS, DIK_APPS}}, + {L"Sleep", {VK_SLEEP, DIK_SLEEP}}, + {L"NUMPAD 0", {VK_NUMPAD0, DIK_NUMPAD0}}, + {L"NUMPAD 1", {VK_NUMPAD1, DIK_NUMPAD1}}, + {L"NUMPAD 2", {VK_NUMPAD2, DIK_NUMPAD2}}, + {L"NUMPAD 3", {VK_NUMPAD3, DIK_NUMPAD3}}, + {L"NUMPAD 4", {VK_NUMPAD4, DIK_NUMPAD4}}, + {L"NUMPAD 5", {VK_NUMPAD5, DIK_NUMPAD5}}, + {L"NUMPAD 6", {VK_NUMPAD6, DIK_NUMPAD6}}, + {L"NUMPAD 7", {VK_NUMPAD7, DIK_NUMPAD7}}, + {L"NUMPAD 8", {VK_NUMPAD8, DIK_NUMPAD8}}, + {L"NUMPAD 9", {VK_NUMPAD9, DIK_NUMPAD9}}, + {L"NUMPAD *", {VK_MULTIPLY, DIK_MULTIPLY}}, + {L"NUMPAD +", {VK_ADD, DIK_ADD}}, + {L"NUMPAD -", {VK_SUBTRACT, DIK_SUBTRACT}}, + {L"NUMPAD .", {VK_DECIMAL, DIK_DECIMAL}}, + {L"NUMPAD /", {VK_DIVIDE, DIK_DIVIDE}}, + {L"F1", {VK_F1, DIK_F1}}, + {L"F2", {VK_F2, DIK_F2}}, + {L"F3", {VK_F3, DIK_F3}}, + {L"F4", {VK_F4, DIK_F4}}, + {L"F5", {VK_F5, DIK_F5}}, + {L"F6", {VK_F6, DIK_F6}}, + {L"F7", {VK_F7, DIK_F7}}, + {L"F8", {VK_F8, DIK_F8}}, + {L"F9", {VK_F9, DIK_F9}}, + {L"F10", {VK_F10, DIK_F10}}, + {L"F11", {VK_F11, DIK_F11}}, + {L"F12", {VK_F12, DIK_F12}}, + {L"F13", {VK_F13, DIK_F13}}, + {L"F14", {VK_F14, DIK_F14}}, + {L"F15", {VK_F15, DIK_F15}}, + {L"Num Lock", {VK_NUMLOCK, DIK_NUMLOCK}}, + {L"ScrLk", {VK_SCROLL, DIK_SCROLL}}, + {L"Browser Back", {VK_BROWSER_BACK, DIK_WEBBACK}}, + {L"Browser Forward", {VK_BROWSER_FORWARD, DIK_WEBFORWARD}}, + {L"Browser Refresh", {VK_BROWSER_REFRESH, DIK_WEBREFRESH}}, + {L"Browser Stop", {VK_BROWSER_STOP, DIK_WEBSTOP}}, + {L"Browser Search", {VK_BROWSER_SEARCH, DIK_WEBSEARCH}}, + {L"Browser Favorites", {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}}, + {L"Browser Stard and Home", {VK_BROWSER_HOME, DIK_WEBHOME}}, + {L"Volume Mute", {VK_VOLUME_MUTE, DIK_MUTE}}, + {L"Volume Down", {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}}, + {L"Volume Up", {VK_VOLUME_UP, DIK_VOLUMEUP}}, + {L"Next Track", {VK_MEDIA_NEXT_TRACK, DIK_NEXTTRACK}}, + {L"Previous Track", {VK_MEDIA_PREV_TRACK, DIK_PREVTRACK}}, + {L"Stop Media", {VK_MEDIA_STOP, DIK_MEDIASTOP}}, + {L"Start Mail", {VK_LAUNCH_MAIL, DIK_MAIL}}, + {L"Select Media", {VK_LAUNCH_MEDIA_SELECT, DIK_MEDIASELECT}} }; }; From dd335c785cf46608ec967bfa336541127fdacb2e Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 16 Oct 2024 12:39:32 -0400 Subject: [PATCH 12/28] fix: rebinding to wide char key, cleanup --- Code/client/Services/Generic/KeybindService.cpp | 17 +++++++++-------- Code/client/Services/KeybindService.h | 4 +++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index ef2a29a48..cebf0b3dd 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -245,7 +245,7 @@ void KeybindService::HandleKeybind(const uint16_t& acVkKeyCode, const unsigned l } } - wchar_t keyChar = static_cast(MapVirtualKeyA(m_keyCode, MAPVK_VK_TO_CHAR)); + wchar_t keyChar = static_cast(MapVirtualKeyW(m_keyCode, MAPVK_VK_TO_CHAR)); const TiltedPhoques::WString& cKeyName = {static_cast(toupper(keyChar))}; const KeybindService::Key& cKey = {cKeyName, {acVkKeyCode, acDiKeyCode}}; @@ -257,23 +257,23 @@ void KeybindService::HandleKeybind(const uint16_t& acVkKeyCode, const unsigned l m_keyCode = pModKey->second.vkKeyCode; // UI key pressed - if (DoesKeyMatch(*pModKey, m_uiKey) && !m_uiKeybindConfirmed) + if (DoKeysMatch(*pModKey, m_uiKey) && !m_uiKeybindConfirmed) { SetUIKey(m_keyCode, acDiKeyCode, pModKey->first, acLoadFromConfig); } // Debug key pressed - else if (DoesKeyMatch(*pModKey, m_debugKey) && !m_debugKeybindConfirmed) + else if (DoKeysMatch(*pModKey, m_debugKey) && !m_debugKeybindConfirmed) { SetDebugKey(m_keyCode, acDiKeyCode, pModKey->first); } } // No custom key name, UI key was pressed - else if (DoesKeyMatch(cKey, m_uiKey) && !m_uiKeybindConfirmed) + else if (DoKeysMatch(cKey, m_uiKey) && !m_uiKeybindConfirmed) { SetUIKey(m_keyCode, acDiKeyCode, cKeyName, acLoadFromConfig); } // No custom key name, Debug key was pressed - else if (DoesKeyMatch(cKey, m_debugKey) && !m_debugKeybindConfirmed) + else if (DoKeysMatch(cKey, m_debugKey) && !m_debugKeybindConfirmed) { SetDebugKey(m_keyCode, acDiKeyCode, cKeyName); } @@ -303,14 +303,15 @@ bool KeybindService::CanToggleDebug(const uint16_t& acVkKeyCode, const unsigned return (acVkKeyCode != KeyCodes::Error && acVkKeyCode == m_debugKey.second.vkKeyCode) || (acDiKeyCode != KeyCodes::Error && acDiKeyCode == m_debugKey.second.diKeyCode); } -bool KeybindService::DoesKeyMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept +bool KeybindService::DoKeysMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept { - return acLeftKey.first == acRightKey.first || acLeftKey.second.vkKeyCode == acRightKey.second.vkKeyCode || acLeftKey.second.diKeyCode == acRightKey.second.diKeyCode; + return (!acLeftKey.first.empty() && acLeftKey.first == acRightKey.first) || (acLeftKey.second.vkKeyCode != KeyCodes::Error && acLeftKey.second.vkKeyCode == acRightKey.second.vkKeyCode) || + (acLeftKey.second.diKeyCode != KeyCodes::Error && acLeftKey.second.diKeyCode == acRightKey.second.diKeyCode); } TiltedPhoques::WString KeybindService::ConvertToWString(const TiltedPhoques::String& acString) noexcept { - int nChars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, acString.data(), static_cast(acString.length()), NULL, 0); + int nChars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, acString.data(), static_cast(acString.length()), nullptr, 0); TiltedPhoques::WString wstrTo; if (nChars > 0) diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index aa32f2f62..38bdbbbef 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -55,6 +55,8 @@ struct KeybindService uint16_t vkKeyCode = Error; // DirectInput unsigned long diKeyCode = Error; + + friend bool operator==(const KeyCodes& acLhs, const KeyCodes& acRhs) noexcept { return acLhs.vkKeyCode == acRhs.vkKeyCode && acLhs.diKeyCode == acRhs.diKeyCode; } }; using Key = std::pair; @@ -100,7 +102,7 @@ struct KeybindService bool SetUIKey(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const TiltedPhoques::WString& acKeyName, const bool& acLoadFromConfig = false) noexcept; void HandleKeybind(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode, const bool& acLoadFromConfig = false) noexcept; bool CanToggleDebug(const uint16_t& acVkKeyCode, const unsigned long& acDiKeyCode) const noexcept; - bool DoesKeyMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept; + bool DoKeysMatch(const KeybindService::Key& acLeftKey, const KeybindService::Key& acRightKey) const noexcept; static TiltedPhoques::WString ConvertToWString(const TiltedPhoques::String& acString) noexcept; static TiltedPhoques::String ConvertToString(const TiltedPhoques::WString& acString) noexcept; From 5debd2ef76fefef4e1b058e9d8c664ac63c1b10b Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 16 Oct 2024 12:45:18 -0400 Subject: [PATCH 13/28] refactor: key name --- Code/client/Services/KeybindService.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index 38bdbbbef..f5c0b784d 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -201,7 +201,7 @@ struct KeybindService {L"Browser Stop", {VK_BROWSER_STOP, DIK_WEBSTOP}}, {L"Browser Search", {VK_BROWSER_SEARCH, DIK_WEBSEARCH}}, {L"Browser Favorites", {VK_BROWSER_FAVORITES, DIK_WEBFAVORITES}}, - {L"Browser Stard and Home", {VK_BROWSER_HOME, DIK_WEBHOME}}, + {L"Browser Home", {VK_BROWSER_HOME, DIK_WEBHOME}}, {L"Volume Mute", {VK_VOLUME_MUTE, DIK_MUTE}}, {L"Volume Down", {VK_VOLUME_DOWN, DIK_VOLUMEDOWN}}, {L"Volume Up", {VK_VOLUME_UP, DIK_VOLUMEUP}}, From d635c2372db4fa619040cd0f7aca083d25e5f196 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 22 Oct 2024 23:51:21 -0400 Subject: [PATCH 14/28] tweak: bump tiltedhooks ref --- Libraries/TiltedHooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/TiltedHooks b/Libraries/TiltedHooks index 523bdfe2c..3b39b12d2 160000 --- a/Libraries/TiltedHooks +++ b/Libraries/TiltedHooks @@ -1 +1 @@ -Subproject commit 523bdfe2c6e1ddcf50da58055c353c2ef3c4a451 +Subproject commit 3b39b12d2c5dedbc8df725254c39234bec4e6467 From 1b65220fe5d7a3991237f642794a39edeec02eea Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 23 Oct 2024 00:38:08 -0400 Subject: [PATCH 15/28] fix: build --- Code/client/Services/Generic/InputService.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 7af60cf8e..60aeda03b 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -125,7 +125,7 @@ void SetUIActive(OverlayService& aOverlay, auto apRenderer, bool aActive) ; } -void Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept +void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept { auto& overlay = *s_pOverlay; @@ -250,7 +250,7 @@ void ProcessKeyboard(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aTy spdlog::debug("ProcessKey, type: {}, key: {}, active: {}", aType, aKey, active); - Toggle(aKey, aScanCode, aType); + ToggleUI(aKey, aScanCode, aType); #else const auto active = pRenderer->IsVisible(); @@ -495,7 +495,7 @@ bool InputService::SetUIKey(const TiltedPhoques::SharedPtr& void InputService::Toggle(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept { - ::Toggle(aKey, aScanCode, aType); + ToggleUI(aKey, aScanCode, aType); } InputService::InputService(OverlayService& aOverlay) noexcept From c90fa5421122936559c4a498698a6c4539ed057a Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 23 Oct 2024 01:19:08 -0400 Subject: [PATCH 16/28] fix: ft build i misread an #if :) --- Code/client/Services/Generic/InputService.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 60aeda03b..655a7b02a 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -124,6 +124,7 @@ void SetUIActive(OverlayService& aOverlay, auto apRenderer, bool aActive) while (ShowCursor(FALSE) >= 0) ; } +#endif void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noexcept { @@ -155,7 +156,11 @@ void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noe } else if (aType == KEYEVENT_KEYUP) { +#if defined(TP_SKYRIM) SetUIActive(overlay, pRenderer, !active); +#else + pRenderer->SetVisible(!active); +#endif } } // If debug is visible, don't inject key @@ -164,7 +169,6 @@ void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noe pApp->InjectKey(aType, GetCefModifiers(aKey), aKey, aScanCode); } } -#endif void ProcessKeyboard(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType, bool aE0, bool aE1) { From 6978cb0b8c8261eced42e2f6a8bded7f5caed805 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 11 Nov 2024 18:23:50 -0500 Subject: [PATCH 17/28] fix: able to type toggle key when input field is focused also more cleanup --- .../Services/Debug/Views/KeybindView.cpp | 6 +++--- Code/client/Services/Generic/InputService.cpp | 9 ++++---- .../Services/Generic/KeybindService.cpp | 21 +++++-------------- .../client/Services/Generic/OverlayClient.cpp | 8 +++++++ Code/client/Services/KeybindService.h | 9 ++++++-- Code/client/Services/OverlayClient.h | 1 + .../app/components/chat/chat.component.html | 2 ++ .../src/app/components/chat/chat.component.ts | 2 ++ .../components/connect/connect.component.html | 4 ++++ .../components/connect/connect.component.ts | 9 ++++++++ .../src/app/services/client.service.ts | 4 ++++ Code/skyrim_ui/src/typings.d.ts | 5 +++++ Code/tp_process/ProcessHandler.cpp | 1 + 13 files changed, 56 insertions(+), 25 deletions(-) diff --git a/Code/client/Services/Debug/Views/KeybindView.cpp b/Code/client/Services/Debug/Views/KeybindView.cpp index 69428567a..c44ea8bbb 100644 --- a/Code/client/Services/Debug/Views/KeybindView.cpp +++ b/Code/client/Services/Debug/Views/KeybindView.cpp @@ -22,7 +22,7 @@ TiltedPhoques::String ConvertWstringToString(const TiltedPhoques::WString& acWid const TiltedPhoques::WString& BindKey(const TiltedPhoques::WString& acKeyName, bool& aBindActive, const bool& acDebugKey) { - auto& rebindService = World::Get().GetKeybindService(); + auto& keybindService = World::Get().GetKeybindService(); TiltedPhoques::WString keyName = acKeyName; ImGui::SameLine(0); @@ -45,9 +45,9 @@ const TiltedPhoques::WString& BindKey(const TiltedPhoques::WString& acKeyName, b aBindActive = false; if (acDebugKey) - rebindService.BindDebugKey(key); + keybindService.BindDebugKey(key); else - rebindService.BindUIKey(key); + keybindService.BindUIKey(key); break; } diff --git a/Code/client/Services/Generic/InputService.cpp b/Code/client/Services/Generic/InputService.cpp index 655a7b02a..3b193bf4c 100644 --- a/Code/client/Services/Generic/InputService.cpp +++ b/Code/client/Services/Generic/InputService.cpp @@ -146,9 +146,11 @@ void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noe const auto& debugService = World::Get().GetDebugService(); const auto& isRebinding = debugService.IsRebinding(); - const auto& isDebugKey = aKey == debugService.GetDebugKey().second.vkKeyCode; - if (aType != KEYEVENT_CHAR && (IsToggleKey(aKey) || (IsDisableKey(aKey) && active && isRebinding))) + const auto& isToggleKey = IsToggleKey(aKey); + const auto& textInputFocused = World::Get().GetKeybindService().GetTextInputFocus(); + + if (aType != KEYEVENT_CHAR && ((isToggleKey && !textInputFocused) || (IsDisableKey(aKey) && active && isRebinding))) { if (!overlay.GetInGame()) { @@ -163,8 +165,7 @@ void ToggleUI(uint16_t aKey, uint16_t aScanCode, cef_key_event_type_t aType) noe #endif } } - // If debug is visible, don't inject key - else if (active && (isDebugKey && !debugService.m_showDebugStuff)) + else if ((active && !isToggleKey) || (isToggleKey && textInputFocused)) { pApp->InjectKey(aType, GetCefModifiers(aKey), aKey, aScanCode); } diff --git a/Code/client/Services/Generic/KeybindService.cpp b/Code/client/Services/Generic/KeybindService.cpp index cebf0b3dd..2befe437d 100644 --- a/Code/client/Services/Generic/KeybindService.cpp +++ b/Code/client/Services/Generic/KeybindService.cpp @@ -60,8 +60,7 @@ void KeybindService::SetupConfig() noexcept } } - // doesnt print out some characters correctly - spdlog::info("UI Key: {} | Debug Key: {}", ConvertToString(m_uiKey.first).c_str(), ConvertToString(m_debugKey.first).c_str()); + spdlog::info(L"UI Key: {} | Debug Key: {}", m_uiKey.first.c_str(), m_debugKey.first.c_str()); } void KeybindService::InitializeKeys(bool aLoadDefaults) noexcept @@ -111,10 +110,7 @@ bool KeybindService::SetDebugKey(const uint16_t& acVkKeyCode, const unsigned lon m_debugService.SetDebugKey(TiltedPhoques::MakeShared(m_debugKey)); - if (!m_debugKeybindConfirmed && m_debugKey.second.vkKeyCode != KeyCodes::Error && m_debugKey.second.diKeyCode != KeyCodes::Error) - { - m_debugKeybindConfirmed = true; - } + m_debugKeybindConfirmed = m_debugKey.second.vkKeyCode != KeyCodes::Error && m_debugKey.second.diKeyCode != KeyCodes::Error; } else { @@ -145,10 +141,7 @@ bool KeybindService::SetUIKey(const uint16_t& acVkKeyCode, const unsigned long& m_inputService.SetUIKey(TiltedPhoques::MakeShared(m_uiKey)); m_pInputHook->SetToggleKeys({m_uiKey.second.diKeyCode}); - if (!m_uiKeybindConfirmed && m_uiKey.second.vkKeyCode != KeyCodes::Error && m_uiKey.second.diKeyCode != KeyCodes::Error) - { - m_uiKeybindConfirmed = true; - } + m_uiKeybindConfirmed = m_uiKey.second.vkKeyCode != KeyCodes::Error && m_uiKey.second.diKeyCode != KeyCodes::Error; } else { @@ -230,14 +223,10 @@ void KeybindService::HandleKeybind(const uint16_t& acVkKeyCode, const unsigned l if (m_keyCode == KeyCodes::Error && !acLoadFromConfig) { - BYTE keyboardState[256]{}; - // ensures windows input system is initialized/not considered "stale" before trying to get keyboard state - GetKeyState(0); - GetKeyboardState(keyboardState); - + // TODO: this can still miss but is the lesser of two evils... for (uint16_t key = 256; key > 0; key--) { - if (keyboardState[key] & 0x80) + if (GetAsyncKeyState(key) & 0x8000) { m_keyCode = key; break; diff --git a/Code/client/Services/Generic/OverlayClient.cpp b/Code/client/Services/Generic/OverlayClient.cpp index 3d18380be..28d6540b1 100644 --- a/Code/client/Services/Generic/OverlayClient.cpp +++ b/Code/client/Services/Generic/OverlayClient.cpp @@ -77,6 +77,8 @@ bool OverlayClient::OnProcessMessageReceived(CefRefPtr browser, CefR ProcessTeleportMessage(eventArgs); else if (eventName == "toggleDebugUI") ProcessToggleDebugUI(); + else if (eventName == "textInputFocus") + ProcessIsTextInputFocused(eventArgs); return true; } @@ -140,3 +142,9 @@ void OverlayClient::ProcessToggleDebugUI() { World::Get().GetDebugService().m_showDebugStuff = !World::Get().GetDebugService().m_showDebugStuff; } + +void OverlayClient::ProcessIsTextInputFocused(CefRefPtr aEventArgs) +{ + World::Get().GetKeybindService().SetTextInputFocus(aEventArgs->GetBool(0)); + spdlog::debug("{} : [{}]", __FUNCTION__, aEventArgs->GetBool(0)); +} diff --git a/Code/client/Services/KeybindService.h b/Code/client/Services/KeybindService.h index f5c0b784d..3d3f0b3ef 100644 --- a/Code/client/Services/KeybindService.h +++ b/Code/client/Services/KeybindService.h @@ -46,7 +46,7 @@ struct KeybindService { struct KeyCodes { - enum + enum : uint8_t { Error = 0 }; @@ -91,7 +91,10 @@ struct KeybindService const Config& GetConfig() const noexcept { return m_config; } -private: + bool GetTextInputFocus() const noexcept { return m_isTextInputFocused; } + void SetTextInputFocus(bool aTextInputFocused) noexcept { m_isTextInputFocused = aTextInputFocused; } + + private: void OnDirectInputKeyPress(const unsigned long& acKeyCode) noexcept; void OnVirtualKeyKeyPress(const KeyPressEvent& acKeyCode) noexcept; @@ -115,6 +118,8 @@ struct KeybindService DebugService& m_debugService; TiltedPhoques::DInputHook* m_pInputHook; + bool m_isTextInputFocused{false}; + uint16_t m_keyCode{0}; bool m_uiKeybindConfirmed{false}; diff --git a/Code/client/Services/OverlayClient.h b/Code/client/Services/OverlayClient.h index faab826e5..b844374e8 100644 --- a/Code/client/Services/OverlayClient.h +++ b/Code/client/Services/OverlayClient.h @@ -28,6 +28,7 @@ struct OverlayClient : TiltedPhoques::OverlayClient void ProcessSetTimeCommand(CefRefPtr aEventArgs); void ProcessTeleportMessage(CefRefPtr aEventArgs); void ProcessToggleDebugUI(); + void ProcessIsTextInputFocused(CefRefPtr aEventArgs); TransportService& m_transport; }; diff --git a/Code/skyrim_ui/src/app/components/chat/chat.component.html b/Code/skyrim_ui/src/app/components/chat/chat.component.html index 5ecc4cf8b..cd4e94592 100644 --- a/Code/skyrim_ui/src/app/components/chat/chat.component.html +++ b/Code/skyrim_ui/src/app/components/chat/chat.component.html @@ -27,6 +27,8 @@ spellcheck="false" [(ngModel)]="message" (keydown.enter)="sendMessage()" + (focus)="focus()" + (blur)="blur()" />