haxis/Source/UnrealProject/External/InputManager.cpp

688 lines
20 KiB
C++

#include "UnrealProject.h"
#if PLATFORM_SPECIFIC_WIN == 0
#define _SOURCE_INPUT_MANAGER
#include "InputManager.hpp"
#include "AllowWindowsPlatformTypes.h"
#pragma comment(lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
#define DIRECTINPUT_VERSION 0x0800
#include <Windows.h>
#include <dinput.h>
#include <map>
using namespace std;
#define DUALSHOCK4PRODUCTDATA (0x05C4054CUL)
#define DUALSHOCK4DEVTYPE (0x00010318UL)
#define WIREDXBOXDEVTYPE (0x00010215UL)
#define PI 3.14159265359f
namespace Input
{
struct GUID_Impl
{
GUID instance;
DWORD devType;
unsigned long productData1;
};
LPDIRECTINPUT8 g_DirectInput;
HWND g_HWND;
InputManager* InputManager::s_instance;
bool InputManager::s_isInitialized = false;
vector<GUID_Impl> g_GUIDs;
bool InputManager::IsInitialized()
{
return s_isInitialized;
}
bool InputManager::Initialize()
{
if (!IsInitialized())
{
g_HWND = GetActiveWindow();
HRESULT hr;
HINSTANCE hInstance = GetModuleHandle(nullptr);
hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_DirectInput, NULL);
if (FAILED(hr))
{
return false;
}
s_instance = new InputManager();
s_isInitialized = true;
return true;
}
return false;
}
void InputManager::Cleanup()
{
if (IsInitialized())
{
delete s_instance;
s_instance = nullptr;
g_DirectInput->Release();
s_isInitialized = false;
}
}
InputManager* InputManager::GetInstance()
{
if (!s_isInitialized)
Initialize();
return s_instance;
}
// Implementation of Input Devices
class Keyboard_Impl : public Keyboard
{
public:
Keyboard_Impl()
{
HRESULT hr;
hr = g_DirectInput->CreateDevice(GUID_SysKeyboard, &m_Device, NULL);
if (FAILED(hr))
{
}
hr = m_Device->SetDataFormat(&c_dfDIKeyboard);
if (FAILED(hr))
{
}
hr = m_Device->SetCooperativeLevel(g_HWND, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(hr))
{
}
}
~Keyboard_Impl()
{
m_Device->Unacquire();
}
virtual void Update() override final
{
HRESULT hr;
hr = m_Device->Acquire();
memcpy(m_PreviousState, m_CurrentState, sizeof(BYTE) * 256);
m_Device->GetDeviceState(sizeof(m_CurrentState), (LPVOID)&m_CurrentState);
}
virtual bool GetKey(const InputKey a_Key) override final
{
return (m_CurrentState[a_Key] & 0x80) != 0;
}
virtual bool GetKeyDown(const InputKey a_Key) override final
{
return m_CurrentState[a_Key] & 0x80 && !(m_PreviousState[a_Key] & 0x80);
}
private:
IDirectInputDevice8* m_Device;
BYTE m_CurrentState[256];
BYTE m_PreviousState[256];
};
class Joystick_Impl : public Joystick
{
public:
Joystick_Impl(IDirectInputDevice8* a_Device)
{
HRESULT hr;
m_Device = a_Device;
hr = m_Device->SetDataFormat(&c_dfDIJoystick);
if (FAILED(hr))
{
}
hr = m_Device->SetCooperativeLevel(g_HWND, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(hr))
{
}
}
virtual ~Joystick_Impl()
{
m_Device->Unacquire();
m_Device->Release();
}
virtual void Update() override final
{
HRESULT hr;
m_PreviousState = m_CurrentState;
hr = m_Device->Acquire();
if (FAILED(hr))
{
m_IsValid = false;
return;
}
hr = m_Device->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&m_CurrentState);
if (FAILED(hr))
{
m_IsValid = false;
return;
}
m_IsValid = true;
}
virtual bool IsValid() override final
{
return m_IsValid;
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton)
{
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton)
{
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton)
{
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick)
{
if (IsValid())
{
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX, (float)m_CurrentState.lY) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx, (float)m_CurrentState.lRy) / 32767.0f;
case Input::IJA_LRTRIGGER:
return TeaLib::Math::Vector2f((float)m_CurrentState.lZ, (float)m_CurrentState.lRz) / 32767.0f;
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual InputDeviceType GetDeviceType()
{
return IDT_NOTDEFINED;
}
protected:
bool m_IsValid = false;
IDirectInputDevice8* m_Device;
DIJOYSTATE m_CurrentState, m_PreviousState;
};
class JoystickDS4_Impl : public Joystick_Impl
{
public:
JoystickDS4_Impl(IDirectInputDevice8* a_Device) : Joystick_Impl(a_Device)
{
m_PhysicalBindings[IJP_FACEDOWN] = IJB_DS4CROSS;
m_PhysicalBindings[IJP_FACERIGHT] = IJB_DS4CIRCLE;
m_PhysicalBindings[IJP_FACELEFT] = IJB_BUTTON0;
m_PhysicalBindings[IJP_FACEUP] = IJB_BUTTON3;
m_PhysicalBindings[IJP_DPADDOWN] = IJB_DS4DPADDOWN;
m_PhysicalBindings[IJP_DPADRIGHT] = IJB_DS4DPADRIGHT;
m_PhysicalBindings[IJP_DPADLEFT] = IJB_DS4DPADLEFT;
m_PhysicalBindings[IJP_DPADUP] = IJB_DS4DPADUP;
m_PhysicalBindings[IJP_SHOULDERRIGHT] = IJB_DS4R1;
m_PhysicalBindings[IJP_SHOULDERLEFT] = IJB_DS4L1;
m_PhysicalBindings[IJP_TRIGGERRIGHT] = IJB_DS4R2;
m_PhysicalBindings[IJP_TRIGGERLEFT] = IJB_DS4L2;
m_PhysicalBindings[IJP_START] = IJB_DS4OPTIONS;
m_PhysicalBindings[IJP_SELECT] = IJB_DS4SHARE;
m_PhysicalBindings[IJP_STICKLEFT] = IJB_DS4LEFTSTICK;
m_PhysicalBindings[IJP_STICKRIGHT] = IJB_DS4RIGHTSTICK;
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_CurrentState.rgdwPOV[0] < 36000 && m_CurrentState.rgdwPOV[0] > 27000 || m_CurrentState.rgdwPOV[0] < 9000)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_CurrentState.rgdwPOV[0] > 0 && m_CurrentState.rgdwPOV[0] < 18000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_CurrentState.rgdwPOV[0] > 9000 && m_CurrentState.rgdwPOV[0] < 27000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_CurrentState.rgdwPOV[0] > 18000 && m_CurrentState.rgdwPOV[0] < 36000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButton(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_CurrentState.rgdwPOV[0] == 0 && m_PreviousState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_CurrentState.rgdwPOV[0] == 9000 && m_PreviousState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_CurrentState.rgdwPOV[0] == 18000 && m_PreviousState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_CurrentState.rgdwPOV[0] == 27000 && m_PreviousState.rgdwPOV[0] != 27000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButtonDown(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_PreviousState.rgdwPOV[0] == 0 && m_CurrentState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_PreviousState.rgdwPOV[0] == 9000 && m_CurrentState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_PreviousState.rgdwPOV[0] == 18000 && m_CurrentState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_PreviousState.rgdwPOV[0] == 27000 && m_CurrentState.rgdwPOV[0] != 27000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButtonUp(m_PhysicalBindings[a_JoystickButton]);
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick) override final
{
if (IsValid())
{
float angle;
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX - 32767.0f, (float)m_CurrentState.lY - 32767.0f) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lZ - 32767.0f, (float)m_CurrentState.lRz - 32767.0f) / 32767.0f;
case Input::IJA_LRTRIGGER:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx, (float)m_CurrentState.lRy) / 65534.0f;
case Input::IJA_DPAD:
if (m_PreviousState.rgdwPOV[0] < 90000)
{
angle = (((float)m_PreviousState.rgdwPOV[0] / 100.0f) * PI / 180.0f);
return TeaLib::Math::Vector2f(sinf(angle), -cosf(angle));
}
return TeaLib::Math::Vector2f();
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual InputDeviceType GetDeviceType() override final
{
return IDT_DS4;
}
private:
map<InputJoystickPhysical, InputJoystickButton> m_PhysicalBindings;
};
class JoystickXbox360_Impl : public Joystick_Impl
{
public:
JoystickXbox360_Impl(IDirectInputDevice8* a_Device) : Joystick_Impl(a_Device)
{
m_PhysicalBindings[IJP_FACEDOWN] = IJB_XBOXA;
m_PhysicalBindings[IJP_FACERIGHT] = IJB_XBOXB;
m_PhysicalBindings[IJP_FACELEFT] = IJB_XBOXX;
m_PhysicalBindings[IJP_FACEUP] = IJB_XBOXY;
m_PhysicalBindings[IJP_DPADDOWN] = IJB_XBOXDPADDOWN;
m_PhysicalBindings[IJP_DPADRIGHT] = IJB_XBOXDPADRIGHT;
m_PhysicalBindings[IJP_DPADLEFT] = IJB_XBOXDPADLEFT;
m_PhysicalBindings[IJP_DPADUP] = IJB_XBOXDPADUP;
m_PhysicalBindings[IJP_SHOULDERRIGHT] = IJB_XBOXRB;
m_PhysicalBindings[IJP_SHOULDERLEFT] = IJB_XBOXLB;
m_PhysicalBindings[IJP_TRIGGERRIGHT] = IJB_XBOXRT;
m_PhysicalBindings[IJP_TRIGGERLEFT] = IJB_XBOXLT;
m_PhysicalBindings[IJP_START] = IJB_XBOXSTART;
m_PhysicalBindings[IJP_SELECT] = IJB_XBOXBACK;
m_PhysicalBindings[IJP_STICKLEFT] = IJB_XBOXLEFTSTICK;
m_PhysicalBindings[IJP_STICKRIGHT] = IJB_XBOXRIGHTSTICK;
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick) override final
{
if (IsValid())
{
float result;
float angle;
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX - 32767.0f, (float)m_CurrentState.lY - 32767.0f) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx - 32767.0f, (float)m_CurrentState.lRy - 32767.0f) / 32767.0f;
case Input::IJA_LRTRIGGER:
result = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
return TeaLib::Math::Vector2f(result, result);
case Input::IJA_DPAD:
if (m_PreviousState.rgdwPOV[0] < 90000)
{
angle = (((float)m_PreviousState.rgdwPOV[0] / 100.0f) * PI / 180.0f);
return TeaLib::Math::Vector2f(sinf(angle), -cosf(angle));
}
return TeaLib::Math::Vector2f();
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
else
{
float val;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_CurrentState.rgdwPOV[0] < 36000 && m_CurrentState.rgdwPOV[0] > 27000 || m_CurrentState.rgdwPOV[0] < 9000)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_CurrentState.rgdwPOV[0] > 0 && m_CurrentState.rgdwPOV[0] < 18000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_CurrentState.rgdwPOV[0] > 9000 && m_CurrentState.rgdwPOV[0] < 27000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_CurrentState.rgdwPOV[0] > 18000 && m_CurrentState.rgdwPOV[0] < 36000)
return true;
break;
case Input::IJB_XBOXLT:
val = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;;
return val > 0.1f;
case Input::IJB_XBOXRT:
val = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;;
return val < -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButton(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
else
{
float curr, prev;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_CurrentState.rgdwPOV[0] == 0 && m_PreviousState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_CurrentState.rgdwPOV[0] == 9000 && m_PreviousState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_CurrentState.rgdwPOV[0] == 18000 && m_PreviousState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_CurrentState.rgdwPOV[0] == 27000 && m_PreviousState.rgdwPOV[0] != 27000)
return true;
break;
case Input::IJB_XBOXLT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr > 0.1f && prev <= 0.1f;
case Input::IJB_XBOXRT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr < -0.1f && prev >= -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton) override final
{
if (m_PhysicalBindings.find(a_JoystickButton) != m_PhysicalBindings.end())
return GetButtonDown(m_PhysicalBindings[a_JoystickButton]);
return false;
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
else
{
float curr, prev;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_PreviousState.rgdwPOV[0] == 0 && m_CurrentState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_PreviousState.rgdwPOV[0] == 9000 && m_CurrentState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_PreviousState.rgdwPOV[0] == 18000 && m_CurrentState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_PreviousState.rgdwPOV[0] == 27000 && m_CurrentState.rgdwPOV[0] != 27000)
return true;
break;
case Input::IJB_XBOXLT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr <= 0.1f && prev > 0.1f;
case Input::IJB_XBOXRT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr >= -0.1f && prev < -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton) override final
{
if (m_PhysicalBindings.find(a_JoystickButton) != m_PhysicalBindings.end())
return GetButtonUp(m_PhysicalBindings[a_JoystickButton]);
return false;
}
virtual InputDeviceType GetDeviceType() override final
{
return IDT_XBOX;
}
private:
map<InputJoystickPhysical, InputJoystickButton> m_PhysicalBindings;
};
InputManager::InputManager() : joystick(nullptr)
{
keyboard = new Keyboard_Impl();
}
void InputManager::Update()
{
keyboard->Update();
if (joystick)
{
joystick->Update();
if (joystick->IsValid())
{
for (auto it : m_joystickCallbacks)
{
switch (it.first.second)
{
case IME_PRESSED:
if (joystick->GetButtonDown(it.first.first))
{
it.second->Call();
}
break;
case IME_RELEASED:
if (joystick->GetButtonUp(it.first.first))
{
it.second->Call();
}
break;
case IME_REPEAT:
if (joystick->GetButton(it.first.first))
{
it.second->Call();
}
break;
}
}
}
}
}
BOOL __stdcall JoystickEnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
InputManager* inputInstance = InputManager::GetInstance();
inputInstance->AddJoystickName(lpddi->tszProductName);
GUID_Impl newGUID;
newGUID.devType = lpddi->dwDevType;
newGUID.instance = lpddi->guidInstance;
newGUID.productData1 = lpddi->guidProduct.Data1;
g_GUIDs.push_back(newGUID);
return DIENUM_CONTINUE;
}
void InputManager::AddJoystickName(std::wstring a_name)
{
m_joystickNames.push_back(a_name);
}
void InputManager::SearchForJoystick()
{
m_joystickNames.clear();
g_GUIDs.clear();
g_DirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, &JoystickEnumCallback, NULL, DIEDFL_ATTACHEDONLY);
}
vector<wstring>& InputManager::GetJoystickNames()
{
return m_joystickNames;
}
void InputManager::ConnectJoystickByIndex(size_t a_index)
{
if (joystick)
delete joystick;
if (a_index >= g_GUIDs.size())
return;
HRESULT hr;
IDirectInputDevice8* device;
hr = g_DirectInput->CreateDevice(g_GUIDs[a_index].instance, &device, NULL);
if (!FAILED(hr))
{
if (g_GUIDs[a_index].devType == DUALSHOCK4DEVTYPE || g_GUIDs[a_index].productData1 == DUALSHOCK4PRODUCTDATA)
joystick = new JoystickDS4_Impl(device);
else if (g_GUIDs[a_index].devType == WIREDXBOXDEVTYPE)
joystick = new JoystickXbox360_Impl(device);
else
joystick = new Joystick_Impl(device);
}
}
InputManager::~InputManager()
{
delete keyboard;
delete joystick;
ClearCallbacks();
}
void InputManager::ClearCallbacks()
{
for (auto it : m_joystickCallbacks)
{
delete it.second;
}
m_joystickCallbacks.clear();
}
}
#endif