-
-
Notifications
You must be signed in to change notification settings - Fork 584
/
Copy pathinput_gamepad.cpp
128 lines (110 loc) · 4.59 KB
/
input_gamepad.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* Copyright (C) 2014 Patrick Mours
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "input_gamepad.hpp"
#include <cassert>
#include <shared_mutex>
#include <Windows.h>
#include <Xinput.h>
static std::shared_mutex s_xinput_mutex;
static std::weak_ptr<reshade::input_gamepad> s_xinput_instance;
reshade::input_gamepad::input_gamepad(void *module) : _xinput_module(module)
{
_xinput_get_state = reinterpret_cast<void *>(GetProcAddress(static_cast<HMODULE>(_xinput_module), "XInputGetState"));
assert(_xinput_get_state != nullptr);
}
reshade::input_gamepad::~input_gamepad()
{
FreeLibrary(static_cast<HMODULE>(_xinput_module));
}
std::shared_ptr<reshade::input_gamepad> reshade::input_gamepad::load()
{
const std::unique_lock<std::shared_mutex> lock(s_xinput_mutex);
if (!s_xinput_instance.expired())
return s_xinput_instance.lock();
const HMODULE module = LoadLibrary(XINPUT_DLL);
if (module == nullptr)
return nullptr;
const auto instance = std::make_shared<input_gamepad>(module);
s_xinput_instance = instance;
return instance;
}
bool reshade::input_gamepad::is_button_down(unsigned int button) const
{
static_assert(
input_gamepad::button_dpad_up == XINPUT_GAMEPAD_DPAD_UP ||
input_gamepad::button_dpad_down == XINPUT_GAMEPAD_DPAD_DOWN ||
input_gamepad::button_dpad_left == XINPUT_GAMEPAD_DPAD_LEFT ||
input_gamepad::button_dpad_right == XINPUT_GAMEPAD_DPAD_RIGHT ||
input_gamepad::button_start == XINPUT_GAMEPAD_START ||
input_gamepad::button_back == XINPUT_GAMEPAD_BACK ||
input_gamepad::button_left_thumb == XINPUT_GAMEPAD_LEFT_THUMB ||
input_gamepad::button_right_thumb == XINPUT_GAMEPAD_RIGHT_THUMB ||
input_gamepad::button_left_shoulder == XINPUT_GAMEPAD_LEFT_SHOULDER ||
input_gamepad::button_right_shoulder == XINPUT_GAMEPAD_RIGHT_SHOULDER ||
input_gamepad::button_a == XINPUT_GAMEPAD_A ||
input_gamepad::button_b == XINPUT_GAMEPAD_B ||
input_gamepad::button_x == XINPUT_GAMEPAD_X ||
input_gamepad::button_y == XINPUT_GAMEPAD_Y);
assert(
button == XINPUT_GAMEPAD_DPAD_UP ||
button == XINPUT_GAMEPAD_DPAD_DOWN ||
button == XINPUT_GAMEPAD_DPAD_LEFT ||
button == XINPUT_GAMEPAD_DPAD_RIGHT ||
button == XINPUT_GAMEPAD_START ||
button == XINPUT_GAMEPAD_BACK ||
button == XINPUT_GAMEPAD_LEFT_THUMB ||
button == XINPUT_GAMEPAD_RIGHT_THUMB ||
button == XINPUT_GAMEPAD_LEFT_SHOULDER ||
button == XINPUT_GAMEPAD_RIGHT_SHOULDER ||
button == XINPUT_GAMEPAD_A ||
button == XINPUT_GAMEPAD_B ||
button == XINPUT_GAMEPAD_X ||
button == XINPUT_GAMEPAD_Y);
return (_buttons & button) != 0;
}
bool reshade::input_gamepad::is_button_pressed(unsigned int button) const
{
return (_buttons & button) != 0 && (_last_buttons & button) == 0;
}
bool reshade::input_gamepad::is_button_released(unsigned int button) const
{
return (_buttons & button) == 0 && (_last_buttons & button) != 0;
}
void reshade::input_gamepad::next_frame()
{
XINPUT_STATE xstate;
if (static_cast<decltype(&XInputGetState)>(_xinput_get_state)(0, &xstate) != ERROR_SUCCESS)
{
_buttons = 0;
_last_buttons = 0;
_left_trigger = 0.0f;
_right_trigger = 0.0f;
_left_thumb_axis_x = 0.0f;
_left_thumb_axis_y = 0.0f;
_right_thumb_axis_x = 0.0f;
_right_thumb_axis_y = 0.0f;
_last_packet_num = 0;
return;
}
_last_buttons = _buttons;
if (xstate.dwPacketNumber == _last_packet_num)
return; // Nothing changed, so can skip the update
_buttons = xstate.Gamepad.wButtons;
_left_trigger = (xstate.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) ? xstate.Gamepad.bLeftTrigger / 255.0f : 0.0f;
_right_trigger = (xstate.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) ? xstate.Gamepad.bRightTrigger / 255.0f : 0.0f;
_left_thumb_axis_x =
(xstate.Gamepad.sThumbLX < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbLX / 32768.0f :
(xstate.Gamepad.sThumbLX > +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbLX / 32767.0f : 0.0f;
_left_thumb_axis_y =
(xstate.Gamepad.sThumbLY < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbLY / 32768.0f :
(xstate.Gamepad.sThumbLY > +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbLY / 32767.0f : 0.0f;
_right_thumb_axis_x =
(xstate.Gamepad.sThumbRX < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbRX / 32768.0f :
(xstate.Gamepad.sThumbRX > +XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbRX / 32767.0f : 0.0f;
_right_thumb_axis_y =
(xstate.Gamepad.sThumbRY < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbRY / 32768.0f :
(xstate.Gamepad.sThumbRY > +XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ? xstate.Gamepad.sThumbRY / 32767.0f : 0.0f;
_last_packet_num = xstate.dwPacketNumber;
}