From 9e241ca7c2bfe759accdcb8b3a008d890f0ec0ff Mon Sep 17 00:00:00 2001 From: zsccat Date: Thu, 4 Jun 2020 13:09:25 +0000 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20'source-code/source/plugins/TLAC/Input/DirectInput/GenericUs?= =?UTF-8?q?b'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for generic usb controller. --- .../GenericUsb/GenericUsbInput.cpp | 181 ++++++++++++++++++ .../DirectInput/GenericUsb/GenericUsbInput.h | 53 +++++ .../Input/DirectInput/GenericUsb/GuButton.h | 52 +++++ .../Input/DirectInput/GenericUsb/GuState.cpp | 14 ++ .../Input/DirectInput/GenericUsb/GuState.h | 39 ++++ 5 files changed, 339 insertions(+) create mode 100644 source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.cpp create mode 100644 source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.h create mode 100644 source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuButton.h create mode 100644 source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.cpp create mode 100644 source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.h diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.cpp b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.cpp new file mode 100644 index 0000000..e2a9b22 --- /dev/null +++ b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.cpp @@ -0,0 +1,181 @@ +#include "GenericUsbInput.h" +#include "../../../Utilities/Math.h" +#include "../../../framework.h" +#include "../../../FileSystem/ConfigFile.h" +#include + +const std::string GU_CONFIG_FILE_NAME = "genericusbinput.ini"; + +namespace TLAC::Input +{ + GenericUsbInput* GenericUsbInput::instance; + + GenericUsbInput::GenericUsbInput() + { + } + + GenericUsbInput::~GenericUsbInput() + { + DI_Dispose(); + } + + bool GenericUsbInput::TryInitializeInstance() + { + if (InstanceInitialized()) + return true; + + if (!DirectInputInitialized()) + return false; + + GenericUsbInput *genericUsbInput = new GenericUsbInput (); + + bool success = genericUsbInput->Initialize(); + instance = success ? genericUsbInput : nullptr; + + if (!success) + delete genericUsbInput; + + return success; + } + + bool GenericUsbInput::Initialize() + { + HRESULT result = NULL; + + FileSystem::ConfigFile configFile(framework::GetModuleDirectory(), GU_CONFIG_FILE_NAME); + configFile.OpenRead(); + + std::string stt = "0x"; + std::string vid = configFile.GetStringValue("VID"); + std::string pid = configFile.GetStringValue("PID"); + + unsigned int gid = std::strtoul((stt + pid + vid).c_str(), 0, 16); + + GUID GUID_GenericUsb = { gid, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } }; + + result = DI_CreateDevice(GUID_GenericUsb); + + if (!FAILED(result)) + { + if (FAILED(result = DI_SetDataFormat(&c_dfDIJoystick2))) + return false; + + result = DI_Acquire(); + + return true; + } + else + { + return false; + } + } + + bool GenericUsbInput::PollInput() + { + lastState = currentState; + + HRESULT result = NULL; + result = DI_Poll(); + result = DI_GetDeviceState(sizeof(DIJOYSTATE2), ¤tState.DI_JoyState); + + if (result != DI_OK) + return false; + + UpdateInternalGuState(currentState); + + for (int button = 0; button < GU_BUTTON_MAX; button++) + currentState.Buttons[button] = GetButtonState(currentState, (GuButton)button); + + return true; + } + + void GenericUsbInput::UpdateInternalGuState(GuState &state) + { + if (state.Dpad.IsDown = state.DI_JoyState.rgdwPOV[0] != -1) + { + state.Dpad.Angle = (state.DI_JoyState.rgdwPOV[0] / 100.0f); + + auto direction = Utilities::GetDirection(state.Dpad.Angle); + state.Dpad.Stick = { direction.Y, -direction.X }; + } + else + { + state.Dpad.Angle = 0; + state.Dpad.Stick = GuJoystick(); + } + + state.LeftStick = NormalizeStick(state.DI_JoyState.lX, state.DI_JoyState.lY); + state.RightStick = NormalizeStick(state.DI_JoyState.lZ, state.DI_JoyState.lRz); + + state.LeftTrigger = { NormalizeTrigger(state.DI_JoyState.lRx) }; + state.RightTrigger = { NormalizeTrigger(state.DI_JoyState.lRy) }; + } + + bool GenericUsbInput::IsDown(GuButton button) + { + return currentState.Buttons[button]; + } + + bool GenericUsbInput::IsUp(GuButton button) + { + return !IsDown(button); + } + + bool GenericUsbInput::IsTapped(GuButton button) + { + return IsDown(button) && WasUp(button); + } + + bool GenericUsbInput::IsReleased(GuButton button) + { + return IsUp(button) && WasDown(button); + } + + bool GenericUsbInput::WasDown(GuButton button) + { + return lastState.Buttons[button]; + } + + bool GenericUsbInput::WasUp(GuButton button) + { + return !WasDown(button); + } + + bool GenericUsbInput::MatchesDirection(GuJoystick joystick, GuDirection directionEnum, float threshold) + { + switch (directionEnum) + { + case TLAC::Input::GU_DIR_UP: + return joystick.YAxis <= -threshold; + + case TLAC::Input::GU_DIR_RIGHT: + return joystick.XAxis >= +threshold; + + case TLAC::Input::GU_DIR_DOWN: + return joystick.YAxis >= +threshold; + + case TLAC::Input::GU_DIR_LEFT: + return joystick.XAxis <= -threshold; + + default: + return false; + } + } + + bool GenericUsbInput::GetButtonState(GuState &state, GuButton button) + { + if (button >= GU_BUTTON1 && button <= GU_BUTTON13) + return state.DI_JoyState.rgbButtons[button]; + + if (button >= GU_DPAD_UP && button <= GU_DPAD_LEFT) + return state.Dpad.IsDown ? MatchesDirection(state.Dpad.Stick, (GuDirection)(button - GU_DPAD_UP), dpadThreshold) : false; + + if (button >= GU_L_STICK_UP && button <= GU_L_STICK_LEFT) + return MatchesDirection(state.LeftStick, (GuDirection)(button - GU_L_STICK_UP), joystickThreshold); + + if (button >= GU_R_STICK_UP && button <= GU_R_STICK_LEFT) + return MatchesDirection(state.RightStick, (GuDirection)(button - GU_R_STICK_UP), joystickThreshold); + + return false; + } +} diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.h b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.h new file mode 100644 index 0000000..898b7ce --- /dev/null +++ b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GenericUsbInput.h @@ -0,0 +1,53 @@ +#pragma once +#include "../Controller.h" +#include "../../IInputDevice.h" +#include "GuState.h" + +namespace TLAC::Input +{ + class GenericUsbInput : public Controller, public IInputDevice + { + public: + GenericUsbInput(); + ~GenericUsbInput(); + + static bool TryInitializeInstance(); + + bool Initialize(); + bool PollInput() override; + + bool IsDown(GuButton button); + bool IsUp(GuButton button); + bool IsTapped(GuButton button); + bool IsReleased(GuButton button); + bool WasDown(GuButton button); + bool WasUp(GuButton button); + + inline GuJoystick GetLeftStick() { return currentState.LeftStick; }; + inline GuJoystick GetRightStick() { return currentState.RightStick; }; + inline GuJoystick GetDpad() { return currentState.Dpad.Stick; }; + + static inline bool InstanceInitialized() { return instance != nullptr; }; + static inline GenericUsbInput* GetInstance() { return instance; }; + static inline void DeleteInstance() { delete instance; instance = nullptr; }; + + private: + static GenericUsbInput* instance; + + GuState lastState; + GuState currentState; + + const float triggerThreshold = 0.5f; + const float joystickThreshold = 0.5f; + const float dpadThreshold = 0.5f; + + inline float NormalizeTrigger(long value) { return (float)value / USHRT_MAX; }; + inline float NormalizeStick(long value) { return (float)value / USHRT_MAX * 2.0f - 1.0f; }; + inline GuJoystick NormalizeStick(long x, long y) { return GuJoystick(NormalizeStick(x), NormalizeStick(y)); }; + + void UpdateInternalGuState(GuState &state); + + bool MatchesDirection(GuJoystick joystick, GuDirection directionEnum, float threshold); + bool GetButtonState(GuState &state, GuButton button); + }; +} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuButton.h b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuButton.h new file mode 100644 index 0000000..1df2e2a --- /dev/null +++ b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuButton.h @@ -0,0 +1,52 @@ +#pragma once + +namespace TLAC::Input +{ + enum GuDirection + { + GU_DIR_UP, + GU_DIR_RIGHT, + GU_DIR_DOWN, + GU_DIR_LEFT + }; + + enum GuButton : int + { + GU_BUTTON1 = 0, + GU_BUTTON2 = 1, + GU_BUTTON3 = 2, + GU_BUTTON4 = 3, + + GU_BUTTON5 = 4, + GU_BUTTON6 = 5, + + GU_BUTTON7 = 6, + GU_BUTTON8 = 7, + + GU_BUTTON9 = 8, + GU_BUTTON10 = 9, + + GU_BUTTON11 = 10, + GU_BUTTON12 = 11, + + GU_BUTTON13 = 12, + + + GU_DPAD_UP = 14, + GU_DPAD_RIGHT = 15, + GU_DPAD_DOWN = 16, + GU_DPAD_LEFT = 17, + + GU_L_STICK_UP = 18, + GU_L_STICK_RIGHT = 19, + GU_L_STICK_DOWN = 20, + GU_L_STICK_LEFT = 21, + + GU_R_STICK_UP = 22, + GU_R_STICK_RIGHT = 23, + GU_R_STICK_DOWN = 24, + GU_R_STICK_LEFT = 25, + + GU_BUTTON_MAX = 26, + }; +} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.cpp b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.cpp new file mode 100644 index 0000000..cc60409 --- /dev/null +++ b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.cpp @@ -0,0 +1,14 @@ +#include "GuState.h" + +namespace TLAC::Input +{ + GuJoystick::GuJoystick() : XAxis(0.0f), YAxis(0.0f) + { + return; + }; + + GuJoystick::GuJoystick(float xAxis, float yAxis) : XAxis(xAxis), YAxis(yAxis) + { + return; + }; +} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.h b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.h new file mode 100644 index 0000000..9060e8d --- /dev/null +++ b/source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb/GuState.h @@ -0,0 +1,39 @@ +#pragma once +#include "../DirectInput.h" +#include "GuButton.h" + +namespace TLAC::Input +{ + struct GuJoystick + { + FLOAT XAxis, YAxis; + + GuJoystick(); + GuJoystick(float xAxis, float yAxis); + }; + + struct GuDpad + { + BOOL IsDown; + FLOAT Angle; + GuJoystick Stick; + }; + + struct GuTrigger + { + FLOAT Axis; + }; + + struct GuState + { + DIJOYSTATE2 DI_JoyState; + + BYTE Buttons[GU_BUTTON_MAX]; + + GuDpad Dpad; + GuJoystick LeftStick; + GuJoystick RightStick; + GuTrigger LeftTrigger; + GuTrigger RightTrigger; + }; +} \ No newline at end of file