上传文件至 'source-code/source/plugins/TLAC/Input/DirectInput/GenericUsb'
Add support for generic usb controller.
This commit is contained in:
@@ -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), ¤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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user