diff --git a/CHANGES.md b/CHANGES.md index 77b1eab..69c4e8d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ **Fixes:** * Added frame smoothing accumulator to delta time to correct for motion jitter caused by inconsistent frame times. * Fixed 3D crosshair enabling the HUD crosshair even if bShowCrosshair:Interface was set to false. +* Gamepad support for MCM keybindings. # Beta 1.6 * Bumped module and MCM version number to 15 diff --git a/SmoothCam/include/util.h b/SmoothCam/include/util.h index d6af65b..3442b29 100644 --- a/SmoothCam/include/util.h +++ b/SmoothCam/include/util.h @@ -6,6 +6,47 @@ namespace Render { #endif namespace Util { + enum + { + // first 256 for keyboard, then 8 mouse buttons, then mouse wheel up, wheel down, then 16 gamepad buttons + kMacro_KeyboardOffset = 0, // not actually used, just for self-documentation + kMacro_NumKeyboardKeys = 256, + + kMacro_MouseButtonOffset = kMacro_NumKeyboardKeys, // 256 + kMacro_NumMouseButtons = 8, + + kMacro_MouseWheelOffset = kMacro_MouseButtonOffset + kMacro_NumMouseButtons, // 264 + kMacro_MouseWheelDirections = 2, + + kMacro_GamepadOffset = kMacro_MouseWheelOffset + kMacro_MouseWheelDirections, // 266 + kMacro_NumGamepadButtons = 16, + + kMaxMacros = kMacro_GamepadOffset + kMacro_NumGamepadButtons // 282 + }; + + enum + { + kGamepadButtonOffset_DPAD_UP = kMacro_GamepadOffset, // 266 + kGamepadButtonOffset_DPAD_DOWN, + kGamepadButtonOffset_DPAD_LEFT, + kGamepadButtonOffset_DPAD_RIGHT, + kGamepadButtonOffset_START, + kGamepadButtonOffset_BACK, + kGamepadButtonOffset_LEFT_THUMB, + kGamepadButtonOffset_RIGHT_THUMB, + kGamepadButtonOffset_LEFT_SHOULDER, + kGamepadButtonOffset_RIGHT_SHOULDER, + kGamepadButtonOffset_A, + kGamepadButtonOffset_B, + kGamepadButtonOffset_X, + kGamepadButtonOffset_Y, + kGamepadButtonOffset_LT, + kGamepadButtonOffset_RT // 281 + }; + + uint32_t GamepadMaskToKeycode(uint32_t keyMask); + uint32_t GamepadKeycodeToMask(uint32_t keyCode); + // @Note: We are tagging the 3 0 bits (caused by pointer alignment rules) // Tags must be cleared before being dereferenced. template diff --git a/SmoothCam/source/camera.cpp b/SmoothCam/source/camera.cpp index dbb5590..5b2d111 100644 --- a/SmoothCam/source/camera.cpp +++ b/SmoothCam/source/camera.cpp @@ -35,6 +35,8 @@ void Camera::Camera::OnKeyPress(const RE::ButtonEvent* ev) noexcept { auto code = static_cast(ev->idCode); if (code <= 0x6 && ev->device == RE::INPUT_DEVICE::kMouse) code += 0x100; + else if (ev->device == RE::INPUT_DEVICE::kGamepad) + code = Util::GamepadMaskToKeycode(code); if (!inMenuMode) { // Cycle next preset @@ -347,7 +349,7 @@ void Camera::Camera::UpdateCamera(RE::PlayerCharacter* player, RE::PlayerCamera* wasCameraAPIControlled = apiControlled; apiControlled = false; } - + if (config->modDisabled || (wantsControl && !wantsUpdates)) { if (ranLastFrame) { if (activeCamera) activeCamera->OnEnd(player, camera, nullptr); diff --git a/SmoothCam/source/thirdperson.cpp b/SmoothCam/source/thirdperson.cpp index a6b0316..28776e1 100644 --- a/SmoothCam/source/thirdperson.cpp +++ b/SmoothCam/source/thirdperson.cpp @@ -470,6 +470,8 @@ bool Camera::Thirdperson::OnKeyPress(const RE::ButtonEvent* ev) noexcept { auto code = static_cast(ev->idCode); if (code <= 0x6 && ev->device == RE::INPUT_DEVICE::kMouse) code += 0x100; + else if (ev->device == RE::INPUT_DEVICE::kGamepad) + code = Util::GamepadMaskToKeycode(code); if (config->shoulderSwapKey >= 0 && config->shoulderSwapKey == code && ev->heldDownSecs <= 0.000001f) { shoulderSwap = shoulderSwap == 1 ? -1 : 1; diff --git a/SmoothCam/source/util.cpp b/SmoothCam/source/util.cpp index d793ba5..f65d0d6 100644 --- a/SmoothCam/source/util.cpp +++ b/SmoothCam/source/util.cpp @@ -1,5 +1,6 @@ #pragma once #include "util.h" +#include #ifdef DEBUG #include "render/line_drawer.h" @@ -109,4 +110,52 @@ void Util::DrawLine(const glm::vec3& from, const glm::vec3& to, const glm::vec4& Render::Point(Render::ToRenderScale(to), color) ); } -#endif \ No newline at end of file +#endif + +uint32_t Util::GamepadMaskToKeycode(uint32_t keyMask) +{ + switch (keyMask) + { + case XINPUT_GAMEPAD_DPAD_UP: return kGamepadButtonOffset_DPAD_UP; + case XINPUT_GAMEPAD_DPAD_DOWN: return kGamepadButtonOffset_DPAD_DOWN; + case XINPUT_GAMEPAD_DPAD_LEFT: return kGamepadButtonOffset_DPAD_LEFT; + case XINPUT_GAMEPAD_DPAD_RIGHT: return kGamepadButtonOffset_DPAD_RIGHT; + case XINPUT_GAMEPAD_START: return kGamepadButtonOffset_START; + case XINPUT_GAMEPAD_BACK: return kGamepadButtonOffset_BACK; + case XINPUT_GAMEPAD_LEFT_THUMB: return kGamepadButtonOffset_LEFT_THUMB; + case XINPUT_GAMEPAD_RIGHT_THUMB: return kGamepadButtonOffset_RIGHT_THUMB; + case XINPUT_GAMEPAD_LEFT_SHOULDER: return kGamepadButtonOffset_LEFT_SHOULDER; + case XINPUT_GAMEPAD_RIGHT_SHOULDER: return kGamepadButtonOffset_RIGHT_SHOULDER; + case XINPUT_GAMEPAD_A: return kGamepadButtonOffset_A; + case XINPUT_GAMEPAD_B: return kGamepadButtonOffset_B; + case XINPUT_GAMEPAD_X: return kGamepadButtonOffset_X; + case XINPUT_GAMEPAD_Y: return kGamepadButtonOffset_Y; + case 0x9: return kGamepadButtonOffset_LT; + case 0xA: return kGamepadButtonOffset_RT; + default: return kMaxMacros; // Invalid + } +} + +uint32_t Util::GamepadKeycodeToMask(uint32_t keyCode) +{ + switch (keyCode) + { + case kGamepadButtonOffset_DPAD_UP: return XINPUT_GAMEPAD_DPAD_UP; + case kGamepadButtonOffset_DPAD_DOWN: return XINPUT_GAMEPAD_DPAD_DOWN; + case kGamepadButtonOffset_DPAD_LEFT: return XINPUT_GAMEPAD_DPAD_LEFT; + case kGamepadButtonOffset_DPAD_RIGHT: return XINPUT_GAMEPAD_DPAD_RIGHT; + case kGamepadButtonOffset_START: return XINPUT_GAMEPAD_START; + case kGamepadButtonOffset_BACK: return XINPUT_GAMEPAD_BACK; + case kGamepadButtonOffset_LEFT_THUMB: return XINPUT_GAMEPAD_LEFT_THUMB; + case kGamepadButtonOffset_RIGHT_THUMB: return XINPUT_GAMEPAD_RIGHT_THUMB; + case kGamepadButtonOffset_LEFT_SHOULDER: return XINPUT_GAMEPAD_LEFT_SHOULDER; + case kGamepadButtonOffset_RIGHT_SHOULDER: return XINPUT_GAMEPAD_RIGHT_SHOULDER; + case kGamepadButtonOffset_A: return XINPUT_GAMEPAD_A; + case kGamepadButtonOffset_B: return XINPUT_GAMEPAD_B; + case kGamepadButtonOffset_X: return XINPUT_GAMEPAD_X; + case kGamepadButtonOffset_Y: return XINPUT_GAMEPAD_Y; + case kGamepadButtonOffset_LT: return 0x9; + case kGamepadButtonOffset_RT: return 0xA; + default: return 0xFF; // Invalid + } +} \ No newline at end of file