1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-17 18:36:43 +02:00

#15 add XInput support for Windows

This commit is contained in:
XProger
2018-02-21 07:02:16 +03:00
parent b38747f50e
commit 0efa5aa90c
3 changed files with 166 additions and 61 deletions

View File

@@ -1046,7 +1046,7 @@ namespace Core {
ctrl.keys[ cDuck ] = KeySet( ikZ, jkLT ); ctrl.keys[ cDuck ] = KeySet( ikZ, jkLT );
ctrl.keys[ cDash ] = KeySet( ikX, jkRT ); ctrl.keys[ cDash ] = KeySet( ikX, jkRT );
ctrl.keys[ cRoll ] = KeySet( ikA, jkB ); ctrl.keys[ cRoll ] = KeySet( ikA, jkB );
ctrl.keys[ cInventory ] = KeySet( ikTab, jkSelect ); ctrl.keys[ cInventory ] = KeySet( ikEscape, jkSelect );
ctrl.keys[ cStart ] = KeySet( ikEnter, jkStart ); ctrl.keys[ cStart ] = KeySet( ikEnter, jkStart );
} }
@@ -1076,7 +1076,8 @@ namespace Core {
// use D key for jump in browsers // use D key for jump in browsers
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
settings.controls[0].keys[cJump].key = ikD; settings.controls[0].keys[ cJump ].key = ikD;
settings.controls[0].keys[ cInventory ].key = ikTab;
#endif #endif
#ifdef __RPI__ #ifdef __RPI__

View File

@@ -596,6 +596,7 @@ struct Lara : Character {
void reset(int room, const vec3 &pos, float angle, Stand forceStand = STAND_GROUND) { void reset(int room, const vec3 &pos, float angle, Stand forceStand = STAND_GROUND) {
visibleMask = 0xFFFFFFFF; visibleMask = 0xFFFFFFFF;
health = LARA_MAX_HEALTH;
if (room == TR::NO_ROOM) { if (room == TR::NO_ROOM) {
stand = STAND_AIR; stand = STAND_AIR;

View File

@@ -141,21 +141,85 @@ InputKey mouseToInputKey(int msg) {
} }
// joystick // joystick
typedef struct _XINPUT_GAMEPAD
{
WORD wButtons;
BYTE bLeftTrigger;
BYTE bRightTrigger;
SHORT sThumbLX;
SHORT sThumbLY;
SHORT sThumbRX;
SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
typedef struct _XINPUT_STATE
{
DWORD dwPacketNumber;
XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;
typedef struct _XINPUT_VIBRATION
{
WORD wLeftMotorSpeed;
WORD wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
DWORD (WINAPI *XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
DWORD (WINAPI *XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
#define JOY_DEAD_ZONE_STICK 0.3f #define JOY_DEAD_ZONE_STICK 0.3f
#define JOY_DEAD_ZONE_TRIGGER 0.01f #define JOY_DEAD_ZONE_TRIGGER 0.01f
#define JOY_MAX_COUNT 2
#define JOY_NONE 255
bool joyReady[2]; uint8 joyIndex[JOY_MAX_COUNT];
void joyInit(int index) { void osJoyVibrate(int index, float L, float R) {
if (XInputSetState && joyIndex[index] != JOY_NONE) {
XINPUT_VIBRATION vibration;
vibration.wLeftMotorSpeed = int(L * 65535.0f);
vibration.wRightMotorSpeed = int(R * 65535.0f);
XInputSetState(joyIndex[index], &vibration);
}
}
void joyInit() {
memset(joyIndex, JOY_NONE, sizeof(joyIndex));
int index = 0;
HMODULE h = LoadLibrary("xinput9_1_0.dll");
XInputGetState = (decltype(XInputGetState))GetProcAddress(h, "XInputGetState");
XInputSetState = (decltype(XInputSetState))GetProcAddress(h, "XInputSetState");
for (int j = 0; j < 4; j++) {
if (XInputGetState) { // XInput
XINPUT_STATE state;
if (XInputGetState(j, &state) == ERROR_SUCCESS)
joyIndex[index] = j;
} else { // mmSystem (legacy)
JOYINFOEX info; JOYINFOEX info;
info.dwSize = sizeof(info); info.dwSize = sizeof(info);
info.dwFlags = JOY_RETURNALL; info.dwFlags = JOY_RETURNALL;
joyReady[index] = joyGetPosEx(index, &info) == JOYERR_NOERROR; if (joyGetPosEx(j, &info) == JOYERR_NOERROR)
joyIndex[index] = j;
}
if (joyIndex[index] != JOY_NONE) {
index++;
if (index >= JOY_MAX_COUNT)
break;
}
}
} }
void joyFree(int index) { void joyFree() {
joyReady[index] = false; memset(joyIndex, JOY_NONE, sizeof(joyIndex));
memset(&Input::joy[index], 0, sizeof(Input::joy[index])); Input::reset();
} }
float joyAxis(int x, int xMin, int xMax) { float joyAxis(int x, int xMin, int xMax) {
@@ -170,16 +234,58 @@ vec2 joyDir(float ax, float ay) {
return dir.normal() * dist; return dir.normal() * dist;
} }
void joyUpdate(int index) { float joyGetPOV(int mask) {
if (!joyReady[index]) return; switch (mask) {
case 0b0001 : return 1;
case 0b1001 : return 2;
case 0b1000 : return 3;
case 0b1010 : return 4;
case 0b0010 : return 5;
case 0b0110 : return 6;
case 0b0100 : return 7;
case 0b0101 : return 8;
}
return 0;
}
int joyDeadZone(int value, int zone) {
return (value < -zone || value > zone) ? value : 0;
}
void joyUpdate() {
for (int j = 0; j < JOY_MAX_COUNT; j++) {
if (joyIndex[j] == JOY_NONE) break;
int index = joyIndex[j];
if (XInputGetState) { // XInput
XINPUT_STATE state;
if (XInputGetState(index, &state) == ERROR_SUCCESS) {
// osJoyVibrate(j, state.Gamepad.bLeftTrigger / 255.0f, state.Gamepad.bRightTrigger / 255.0f); // vibration test
Input::setJoyPos(j, jkL, joyDir(joyAxis(joyDeadZone( state.Gamepad.sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE), -32768, 32767),
joyAxis(joyDeadZone(-state.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE), -32768, 32767)));
Input::setJoyPos(j, jkR, joyDir(joyAxis(joyDeadZone( state.Gamepad.sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE), -32768, 32767),
joyAxis(joyDeadZone(-state.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE), -32768, 32767)));
Input::setJoyPos(j, jkLT, vec2(joyDeadZone(state.Gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD) / 255.0f, 0.0f));
Input::setJoyPos(j, jkRT, vec2(joyDeadZone(state.Gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD) / 255.0f, 0.0f));
Input::setJoyPos(j, jkPOV, vec2(joyGetPOV(state.Gamepad.wButtons & 15), 0));
static const JoyKey keys[] = { jkUp, jkDown, jkLeft, jkRight, jkStart, jkSelect, jkL, jkR, jkLB, jkRB, jkNone, jkNone, jkA, jkB, jkX, jkY };
for (int i = 4; i < 16; i++)
Input::setJoyDown(j, keys[i], (state.Gamepad.wButtons & (1 << i)) != 0);
} else {
joyFree();
joyInit();
break;
}
} else { // mmSystem (legacy)
JOYINFOEX info; JOYINFOEX info;
info.dwSize = sizeof(info); info.dwSize = sizeof(info);
info.dwFlags = JOY_RETURNALL; info.dwFlags = JOY_RETURNALL;
if (joyGetPosEx(index, &info) == JOYERR_NOERROR) { if (joyGetPosEx(index, &info) == JOYERR_NOERROR) {
JOYCAPS caps; JOYCAPS caps;
joyGetDevCaps(0, &caps, sizeof(caps)); joyGetDevCaps(index, &caps, sizeof(caps));
if (caps.wNumAxes > 0) { if (caps.wNumAxes > 0) {
Input::setJoyPos(index, jkL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax), Input::setJoyPos(index, jkL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax),
@@ -208,18 +314,19 @@ void joyUpdate(int index) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
Input::setJoyDown(index, JoyKey(jkA + i), (info.dwButtons & (1 << i)) > 0); Input::setJoyDown(index, JoyKey(jkA + i), (info.dwButtons & (1 << i)) > 0);
} else } else {
joyFree(index); joyFree();
joyInit();
break;
}
}
}
} }
// touch // touch
typedef BOOL (__stdcall *PREGISTERTOUCHWINDOW)(HWND, ULONG); BOOL (WINAPI *RegisterTouchWindowX)(HWND, ULONG);
typedef BOOL (__stdcall *PGETTOUCHINPUTINFO)(HTOUCHINPUT, UINT, PTOUCHINPUT, int); BOOL (WINAPI *GetTouchInputInfoX)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
typedef BOOL (__stdcall *PCLOSETOUCHINPUTHANDLE)(HTOUCHINPUT); BOOL (WINAPI *CloseTouchInputHandleX)(HTOUCHINPUT);
PREGISTERTOUCHWINDOW RegisterTouchWindowX;
PGETTOUCHINPUTINFO GetTouchInputInfoX;
PCLOSETOUCHINPUTHANDLE CloseTouchInputHandleX;
#define MAX_TOUCH_COUNT 6 #define MAX_TOUCH_COUNT 6
@@ -227,9 +334,9 @@ void touchInit(HWND hWnd) {
int value = GetSystemMetrics(SM_DIGITIZER); int value = GetSystemMetrics(SM_DIGITIZER);
if (value) { if (value) {
HMODULE hUser32 = LoadLibrary("user32.dll"); HMODULE hUser32 = LoadLibrary("user32.dll");
RegisterTouchWindowX = (PREGISTERTOUCHWINDOW)GetProcAddress(hUser32, "RegisterTouchWindow"); RegisterTouchWindowX = (decltype(RegisterTouchWindowX)) GetProcAddress(hUser32, "RegisterTouchWindow");
GetTouchInputInfoX = (PGETTOUCHINPUTINFO)GetProcAddress(hUser32, "GetTouchInputInfo"); GetTouchInputInfoX = (decltype(GetTouchInputInfoX)) GetProcAddress(hUser32, "GetTouchInputInfo");
CloseTouchInputHandleX = (PCLOSETOUCHINPUTHANDLE)GetProcAddress(hUser32, "CloseTouchInputHandle"); CloseTouchInputHandleX = (decltype(CloseTouchInputHandleX)) GetProcAddress(hUser32, "CloseTouchInputHandle");
if (RegisterTouchWindowX && GetTouchInputInfoX && CloseTouchInputHandleX) if (RegisterTouchWindowX && GetTouchInputInfoX && CloseTouchInputHandleX)
RegisterTouchWindowX(hWnd, 0); RegisterTouchWindowX(hWnd, 0);
} }
@@ -366,10 +473,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
break; break;
// joystick // joystick
case WM_DEVICECHANGE : case WM_DEVICECHANGE :
joyFree(0); joyFree();
joyFree(1); joyInit();
joyInit(0);
joyInit(1);
return 1; return 1;
// touch // touch
case WM_TOUCH : case WM_TOUCH :
@@ -557,8 +662,7 @@ int main(int argc, char** argv) {
osStartTime = osGetTime(); osStartTime = osGetTime();
touchInit(hWnd); touchInit(hWnd);
joyInit(0); joyInit();
joyInit(1);
sndInit(hWnd); sndInit(hWnd);
Game::init(argc > 1 ? argv[1] : NULL); Game::init(argc > 1 ? argv[1] : NULL);
@@ -580,8 +684,7 @@ int main(int argc, char** argv) {
if (msg.message == WM_QUIT) if (msg.message == WM_QUIT)
Core::quit(); Core::quit();
} else { } else {
joyUpdate(0); joyUpdate();
joyUpdate(1);
#ifdef VR_SUPPORT #ifdef VR_SUPPORT
vrUpdateInput(); vrUpdateInput();
#endif #endif