上传文件至 'source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb'

Add support for generic usb controller.
This commit is contained in:
zsccat
2020-06-04 13:09:25 +00:00
parent 4bc85246dd
commit 9e241ca7c2
5 changed files with 339 additions and 0 deletions
@@ -0,0 +1,181 @@
#include "GenericUsbInput.h"
#include "../../../Utilities/Math.h"
#include "../../../framework.h"
#include "../../../FileSystem/ConfigFile.h"
#include <stdio.h>
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), &currentState.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;
}
}
@@ -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);
};
}
@@ -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,
};
}
@@ -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;
};
}
@@ -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;
};
}