231 lines
8.5 KiB
C
231 lines
8.5 KiB
C
#include "input.h"
|
|
#pragma comment(lib, "dinput8.lib")
|
|
#pragma comment(lib, "dxguid.lib")
|
|
#include <GuidDef.h>
|
|
#include <Objbase.h>
|
|
#include <stdio.h>
|
|
|
|
#include "../lib/mice/log.h"
|
|
|
|
static PMICE_DI_DEVICE _MiceDIDevices = NULL;
|
|
static LPDIRECTINPUT8A _MiceDI = NULL;
|
|
|
|
void MiceInputPollDevices(void) {
|
|
PMICE_DI_DEVICE lpDevice = _MiceDIDevices;
|
|
while (lpDevice != NULL) {
|
|
lpDevice->m_lpInput->lpVtbl->Poll(lpDevice->m_lpInput);
|
|
|
|
switch (lpDevice->m_dwType) {
|
|
case DI8DEVTYPE_JOYSTICK:
|
|
case DI8DEVTYPE_GAMEPAD:
|
|
lpDevice->m_lpInput->lpVtbl->GetDeviceState(lpDevice->m_lpInput,
|
|
sizeof lpDevice->m_State.m_Joystate,
|
|
&lpDevice->m_State.m_Joystate);
|
|
break;
|
|
}
|
|
|
|
lpDevice = lpDevice->m_Next;
|
|
}
|
|
}
|
|
void MiceInputFreeDevices(void) {
|
|
PMICE_DI_DEVICE lpDevice = _MiceDIDevices;
|
|
while (lpDevice != NULL) {
|
|
lpDevice->m_lpInput->lpVtbl->Unacquire(lpDevice->m_lpInput);
|
|
lpDevice->m_lpInput->lpVtbl->Release(lpDevice->m_lpInput);
|
|
|
|
PMICE_DI_DEVICE next = lpDevice->m_Next;
|
|
free(lpDevice);
|
|
lpDevice = next;
|
|
}
|
|
_MiceDIDevices = NULL;
|
|
}
|
|
|
|
BOOL MiceInputGetNewBinding(PMICE_BUTTON_BINDING lpBinding) {
|
|
MiceInputPollDevices();
|
|
|
|
PMICE_DI_DEVICE lpDevice = _MiceDIDevices;
|
|
while (lpDevice != NULL) {
|
|
PMICE_DI_STATE state = &lpDevice->m_State;
|
|
PMICE_DI_STATE lastState = &lpDevice->m_LastState;
|
|
if (lpBinding != NULL) {
|
|
switch (lpDevice->m_dwType) {
|
|
case DI8DEVTYPE_JOYSTICK:
|
|
case DI8DEVTYPE_GAMEPAD:
|
|
for (int button = 0; button < 32; button++) {
|
|
if (state->m_Joystate.rgbButtons[button] &&
|
|
!lastState->m_Joystate.rgbButtons[button]) {
|
|
lpBinding->m_Type = MICE_BB_TYPE_DI_JOY;
|
|
lpBinding->m_DIJoy.m_lpDeviceGuid = lpDevice->m_GUID;
|
|
lpBinding->m_DIJoy.m_ButtonMajor = MICE_BUTTON_MAJOR_BUTTON;
|
|
lpBinding->m_DIJoy.m_ButtonMinor = button;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (state->m_Joystate.rgdwPOV[0] != lastState->m_Joystate.rgdwPOV[0]) {
|
|
BOOL bound = FALSE;
|
|
int to = -1;
|
|
if (state->m_Joystate.rgdwPOV[0] == 0) {
|
|
to = MICE_DPAD_UP;
|
|
bound = TRUE;
|
|
} else if (state->m_Joystate.rgdwPOV[0] == 18000) {
|
|
to = MICE_DPAD_DOWN;
|
|
bound = TRUE;
|
|
} else if (state->m_Joystate.rgdwPOV[0] == 27000) {
|
|
to = MICE_DPAD_LEFT;
|
|
bound = TRUE;
|
|
} else if (state->m_Joystate.rgdwPOV[0] == 9000) {
|
|
to = MICE_DPAD_RIGHT;
|
|
bound = TRUE;
|
|
}
|
|
if (bound) {
|
|
lpBinding->m_Type = MICE_BB_TYPE_DI_JOY;
|
|
lpBinding->m_DIJoy.m_lpDeviceGuid = lpDevice->m_GUID;
|
|
lpBinding->m_DIJoy.m_ButtonMajor = MICE_BUTTON_MAJOR_DPAD;
|
|
lpBinding->m_DIJoy.m_ButtonMinor = to;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// TODO: Axes
|
|
break;
|
|
}
|
|
}
|
|
memcpy(lastState, state, sizeof *lastState);
|
|
|
|
lpDevice = lpDevice->m_Next;
|
|
}
|
|
|
|
// Skip the mouse buttons
|
|
for (int i = 8; i < 0xff; i++) {
|
|
if (GetAsyncKeyState(i) < 0) {
|
|
lpBinding->m_AsyncKey.m_Key = (CHAR)i;
|
|
lpBinding->m_Type = MICE_BB_TYPE_GET_ASYNC_KEY;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL CALLBACK _DInputEnum(LPDIDEVICEINSTANCEA lpddi, LPVOID data) {
|
|
PMICE_DI_DEVICE lpTail = _MiceDIDevices;
|
|
PMICE_DI_DEVICE lpNew;
|
|
if (lpTail == NULL) {
|
|
lpNew = _MiceDIDevices = malloc(sizeof *lpNew);
|
|
} else {
|
|
while (lpTail->m_Next != NULL) lpTail = lpTail->m_Next;
|
|
lpNew = lpTail->m_Next = malloc(sizeof *lpNew);
|
|
}
|
|
|
|
ZeroMemory(lpNew, sizeof *lpNew);
|
|
lpNew->m_GUID = lpddi->guidInstance;
|
|
lpNew->m_dwType = lpddi->dwDevType & 0xff;
|
|
memcpy_s(lpNew->m_szName, sizeof lpNew->m_szName, lpddi->tszProductName,
|
|
sizeof lpddi->tszProductName);
|
|
lpNew->m_szName[sizeof lpNew->m_szName - 1] = '\0';
|
|
|
|
printf("Found device: %s\n", lpNew->m_szName);
|
|
|
|
return DIENUM_CONTINUE;
|
|
}
|
|
int MiceInputGrabDevices(HWND hWnd) {
|
|
if (_MiceDI == NULL) return -2;
|
|
|
|
// The first argument here is throwing warnings
|
|
#pragma warning(disable : 4090 4028)
|
|
_MiceDI->lpVtbl->EnumDevices(_MiceDI, DI8DEVTYPE_JOYSTICK, _DInputEnum, NULL,
|
|
DIEDFL_ATTACHEDONLY);
|
|
_MiceDI->lpVtbl->EnumDevices(_MiceDI, DI8DEVTYPE_GAMEPAD, _DInputEnum, NULL,
|
|
DIEDFL_ATTACHEDONLY);
|
|
#pragma warning(default : 4090 4028)
|
|
|
|
PMICE_DI_DEVICE lpDevice = _MiceDIDevices;
|
|
while (lpDevice != NULL) {
|
|
_MiceDI->lpVtbl->CreateDevice(_MiceDI, &lpDevice->m_GUID, &lpDevice->m_lpInput, NULL);
|
|
|
|
switch (lpDevice->m_dwType) {
|
|
case DI8DEVTYPE_GAMEPAD:
|
|
case DI8DEVTYPE_JOYSTICK:
|
|
lpDevice->m_lpInput->lpVtbl->SetCooperativeLevel(
|
|
lpDevice->m_lpInput, hWnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
|
|
lpDevice->m_lpInput->lpVtbl->SetDataFormat(lpDevice->m_lpInput, &c_dfDIJoystick);
|
|
lpDevice->m_lpInput->lpVtbl->Acquire(lpDevice->m_lpInput);
|
|
break;
|
|
}
|
|
lpDevice = lpDevice->m_Next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static BOOL _MiceInputHasInit = FALSE;
|
|
int MiceInputInit(HWND hWnd) {
|
|
if (_MiceInputHasInit) return 0;
|
|
_MiceInputHasInit = TRUE;
|
|
|
|
if (_MiceDI == NULL)
|
|
if (!(SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
|
|
&IID_IDirectInput8, (void **)&_MiceDI, NULL)))) {
|
|
log_error(plfMisc, "DirectInput8Create failed: %d", GetLastError());
|
|
_MiceDI = NULL;
|
|
return -1;
|
|
}
|
|
return MiceInputGrabDevices(hWnd);
|
|
}
|
|
void MiceInputDestroy(void) {
|
|
MiceInputFreeDevices();
|
|
|
|
_MiceDI->lpVtbl->Release(_MiceDI);
|
|
_MiceDI = NULL;
|
|
_MiceInputHasInit = FALSE;
|
|
}
|
|
|
|
BOOL MiceInputGetButtonState(PMICE_BUTTON_BINDING lpBinding) {
|
|
BOOL pressed = FALSE;
|
|
switch (lpBinding->m_Type) {
|
|
case MICE_BB_TYPE_GET_ASYNC_KEY: {
|
|
pressed = (GetAsyncKeyState(lpBinding->m_AsyncKey.m_Key) < 0);
|
|
break;
|
|
}
|
|
case MICE_BB_TYPE_DI_JOY: {
|
|
PMICE_DI_DEVICE lpDevice = _MiceDIDevices;
|
|
while (lpDevice != NULL) {
|
|
if (IsEqualGUID(&lpDevice->m_GUID, &lpBinding->m_DIJoy.m_lpDeviceGuid)) break;
|
|
lpDevice = lpDevice->m_Next;
|
|
}
|
|
if (lpDevice == NULL) break;
|
|
|
|
switch (lpBinding->m_DIJoy.m_ButtonMajor) {
|
|
case MICE_BUTTON_MAJOR_AXIS:
|
|
break;
|
|
case MICE_BUTTON_MAJOR_DPAD: {
|
|
DWORD pov = lpDevice->m_State.m_Joystate.rgdwPOV[0];
|
|
switch (lpBinding->m_DIJoy.m_ButtonMinor) {
|
|
case MICE_DPAD_UP:
|
|
pressed = pov == 0 || pov == 4500 || pov == 31500;
|
|
break;
|
|
case MICE_DPAD_DOWN:
|
|
pressed = pov == 18000 || pov == 22500 || pov == 13500;
|
|
break;
|
|
case MICE_DPAD_LEFT:
|
|
pressed = pov == 27000 || pov == 31500 || pov == 22500;
|
|
break;
|
|
case MICE_DPAD_RIGHT:
|
|
pressed = pov == 9000 || pov == 4500 || pov == 13500;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case MICE_BUTTON_MAJOR_BUTTON: {
|
|
DWORD button = lpBinding->m_DIJoy.m_ButtonMinor;
|
|
if (button <= 32) pressed = lpDevice->m_State.m_Joystate.rgbButtons[button] > 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (lpBinding->m_Invert) pressed = !pressed;
|
|
return pressed;
|
|
}
|