cgv
Loading...
Searching...
No Matches
gamepad_server.cxx
1#include "gamepad_server.h"
2#include <cgv/gui/application.h>
3#include <cgv/signal/rebind.h>
4#include <cgv/gui/trigger.h>
5#include <iomanip>
6
7namespace cgv {
8 namespace gui {
10 gamepad_key_event::gamepad_key_event(void* _device_handle, const gamepad::gamepad_state& _state, unsigned short _key, KeyAction _action, unsigned char _char, double _time)
11 : key_event(_key, _action, _char, 0, 0, _time), device_handle(_device_handle), state(_state)
12 {
13 flags = EF_PAD;
14 }
15
17 void gamepad_key_event::stream_out(std::ostream& os) const
18 {
20 os << gamepad::get_key_string(key);
21 switch (action) {
22 case KA_RELEASE:
23 os << " up ";
24 break;
25 case KA_PRESS:
26 if (get_char())
27 os << " = '" << get_char() << "'";
28 break;
29 case KA_REPEAT:
30 os << " repeat ";
31 break;
32 }
33 os << "*" << device_handle << "*";
34 }
35
38 float _x, float _dx, unsigned _player_index, unsigned _controller_index, unsigned _throttle_index, double _time)
39 : throttle_event(_x,_dx,_player_index,_controller_index,_throttle_index, _time),
40 device_handle(_device_handle), state(_state)
41 {
42 flags = EF_PAD;
43 }
45 void gamepad_throttle_event::stream_out(std::ostream& os) const
46 {
48 os << "*" << device_handle << "*";
49 }
50
53 StickAction _action, float _x, float _y, float _dx, float _dy,
54 unsigned _player_index, unsigned _controller_index, unsigned _stick_index, double _time)
55 : stick_event(_action, _x, _y, _dx, _dy, _player_index, _controller_index, _stick_index, _time),
56 device_handle(_device_handle), state(_state)
57 {
58 flags = EF_PAD;
59 }
64
66 void gamepad_stick_event::stream_out(std::ostream& os) const
67 {
69 os << "*" << device_handle << "*";
70 }
71
73 {
74 last_device_scan = -1;
75 device_scan_interval = 2;
76 event_flags = GPE_ALL;
77 }
80 {
81 device_scan_interval = duration;
82 }
85 {
86 event_flags = flags;
87 }
88
91 {
92 if ((last_device_scan < 0) || (time > last_device_scan + device_scan_interval)) {
93 last_device_scan = time;
94 gamepad::scan_devices();
95 std::vector<void*> new_device_handles;
96 for (const auto& di : gamepad::get_device_infos())
97 new_device_handles.push_back(di.device_handle);
98 std::vector<gamepad::gamepad_state> new_states(new_device_handles.size());
99 for (void* dh : device_handles) {
100 auto iter = std::find(new_device_handles.begin(), new_device_handles.end(), dh);
101 if (iter == new_device_handles.end()) {
102 if ((event_flags&GPE_DEVICE) != 0)
103 on_device_change(dh, false);
104 }
105 else {
106 size_t i = iter - new_device_handles.begin();
107 new_states[i] = last_states[i];
108 }
109 }
110 for (void* ndh : new_device_handles) {
111 auto iter = std::find(device_handles.begin(), device_handles.end(), ndh);
112 if (iter == device_handles.end()) {
113 if ((event_flags&GPE_DEVICE) != 0)
114 on_device_change(ndh, true);
115 }
116 }
117 last_states = new_states;
118 device_handles = new_device_handles;
119 }
120 gamepad::GamepadKeys key;
121 gamepad::KeyAction action;
123 // loop all devices
124 for (unsigned i = 0; i < device_handles.size(); ++i) {
125 // if state query unsuccessful continue loop
126 if (!get_state(device_handles[i], state))
127 continue;
128 // process key events
129 while (query_key_event(device_handles[i], key, action)) {
130 if ((event_flags&GPE_KEY) != 0) {
131 char c = 0;
132 if (key >= gamepad::GPK_A && key <= gamepad::GPK_Y)
133 c = std::string("ABXY")[key - gamepad::GPK_A];
134 gamepad_key_event gp_ke(device_handles[i], state, key, KeyAction(action - gamepad::KA_RELEASE + KA_RELEASE), c, time);
135 on_event(gp_ke);
136 }
137 }
138 // only check for events in case of time stamp change
139 if (state.time_stamp != last_states[i].time_stamp) {
140 // check for throttle events
141 if ((event_flags&GPE_THROTTLE) != 0) {
142 for (int ti = 0; ti < 2; ++ti) {
143 float x = state.trigger_position[ti];
144 float dx = x - last_states[i].trigger_position[ti];
145 if (dx != 0) {
146 gamepad_throttle_event gp_te(device_handles[i], state, x, dx,
147 i, 0, ti, time);
148 on_event(gp_te);
149 }
150 }
151 }
152 // check for stick press / release events
153 if ((event_flags&(GPE_STICK+GPE_STICK_KEY)) != 0) {
154 for (int si = 0; si < 2; ++si) {
155 unsigned stick_flag = (si == 0 ? gamepad::GBF_LEFT_STICK : gamepad::GBF_RIGHT_STICK);
156 if ((state.button_flags&stick_flag) != (last_states[i].button_flags&stick_flag)) {
157 float x = (si == 0 ? state.left_stick_position[0] : state.right_stick_position[0]);
158 float y = (si == 0 ? state.left_stick_position[1] : state.right_stick_position[1]);
159 if ((event_flags&GPE_STICK) != 0) {
160 StickAction action = ((state.button_flags&stick_flag) != 0 ? SA_PRESS : SA_RELEASE);
161 gamepad_stick_event gp_se(device_handles[i], state, action, x, y, 0, 0, i, 0, si, time);
162 on_event(gp_se);
163 }
164 if ((event_flags&GPE_STICK_KEY) != 0) {
165 int qx = x > 0.5f ? 1 : (x < -0.5f ? -1 : 0);
166 int qy = y > 0.5f ? 1 : (y < -0.5f ? -1 : 0);
167 short key_index = si*9 + 3 * (qy+1) + qx+1;
168 static gamepad::GamepadKeys key_lookup[18] = {
169 gamepad::GPK_LEFT_STICK_DOWNLEFT,
170 gamepad::GPK_LEFT_STICK_DOWN,
171 gamepad::GPK_LEFT_STICK_DOWNRIGHT,
172 gamepad::GPK_LEFT_STICK_LEFT,
173 gamepad::GPK_LEFT_STICK_PRESS,
174 gamepad::GPK_LEFT_STICK_RIGHT,
175 gamepad::GPK_LEFT_STICK_UPLEFT,
176 gamepad::GPK_LEFT_STICK_UP,
177 gamepad::GPK_LEFT_STICK_UPRIGHT,
178 gamepad::GPK_RIGHT_STICK_DOWNLEFT,
179 gamepad::GPK_RIGHT_STICK_DOWN,
180 gamepad::GPK_RIGHT_STICK_DOWNRIGHT,
181 gamepad::GPK_RIGHT_STICK_LEFT,
182 gamepad::GPK_RIGHT_STICK_PRESS,
183 gamepad::GPK_RIGHT_STICK_RIGHT,
184 gamepad::GPK_RIGHT_STICK_UPLEFT,
185 gamepad::GPK_RIGHT_STICK_UP,
186 gamepad::GPK_RIGHT_STICK_UPRIGHT
187 };
188 KeyAction action = ((state.button_flags&stick_flag) != 0 ? KA_PRESS : KA_RELEASE);
189 gamepad_key_event gp_ke(device_handles[i], state,
190 key_lookup[key_index], action, 0, time);
191 on_event(gp_ke);
192 }
193 }
194 }
195 }
196 // check for stick move and drag events
197 if ((event_flags&GPE_STICK) != 0) {
198 float x = state.left_stick_position[0];
199 float y = state.left_stick_position[1];
200 float dx = x - last_states[i].left_stick_position[0];
201 float dy = y - last_states[i].left_stick_position[1];
202 if (dx != 0 || dy != 0) {
203 StickAction action = SA_MOVE;
204 if ((state.button_flags & gamepad::GBF_LEFT_STICK) != 0)
205 action = SA_DRAG;
206
207 gamepad_stick_event gp_se(device_handles[i], state,
208 action, x, y, dx, dy, i, 0, 0, time);
209 on_event(gp_se);
210 }
211 x = state.right_stick_position[0];
212 y = state.right_stick_position[1];
213 dx = x - last_states[i].right_stick_position[0];
214 dy = y - last_states[i].right_stick_position[1];
215 if (dx != 0 || dy != 0) {
216 StickAction action = SA_MOVE;
217 if ((state.button_flags & gamepad::GBF_RIGHT_STICK) != 0)
218 action = SA_DRAG;
219
220 gamepad_stick_event gp_se(device_handles[i], state,
221 action, x, y, dx, dy, i, 0, 1, time);
222 on_event(gp_se);
223 }
224 }
225 last_states[i] = state;
226 }
227 }
228 }
231 {
232 static gamepad_server server;
233 return server;
234 }
235
236 window_ptr& ref_dispatch_window_pointer()
237 {
238 static window_ptr w;
239 return w;
240 }
241 bool dispatch_gamepad_event(cgv::gui::event& e)
242 {
244 }
245
248 {
249 if (w.empty())
251 ref_dispatch_window_pointer() = w;
252 connect(ref_gamepad_server().on_event, dispatch_gamepad_event);
253 connect_copy(get_animation_trigger().shoot, cgv::signal::rebind(&ref_gamepad_server(), &gamepad_server::check_and_emit_events, cgv::signal::_1));
254 }
255
256 }
257}
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
static window_ptr get_window(unsigned int i)
return the i-th created window
virtual void stream_out(std::ostream &os) const
write to stream
Definition event.cxx:139
unsigned char flags
store event flags
Definition event.h:64
gamepad key events use the key codes defined in gamepad::GamepadKeys
gamepad_key_event(void *_device_handle, const gamepad::gamepad_state &_state, unsigned short _key=0, KeyAction _action=KA_PRESS, unsigned char _char=0, double _time=0)
construct a key event from its textual description
void stream_out(std::ostream &os) const
write to stream
void * device_handle
store id of gamepad
cgv::signal::bool_signal< cgv::gui::event & > on_event
signal emitted to dispatch events
void check_and_emit_events(double time)
check enabled gamepad devices for new events and dispatch them through the on_event signal
cgv::signal::signal< void *, bool > on_device_change
signal emitted to notify about device changes, first argument is device handle and second whether dev...
void set_device_scan_interval(double duration)
set time interval in seconds to check for device connection changes
void set_event_type_flags(GamepadEventTypeFlags flags)
set the event type flags of to be emitted events
gamepad_server()
construct server with default configuration
gamepad extension of stick events
void stream_out(std::ostream &os) const
write to stream
const gamepad::gamepad_state & get_state() const
access to current gamepad state
void * device_handle
store id of gamepad
void * get_device_handle() const
return the device id, by default returns 0
const gamepad::gamepad_state & state
public access to game state allows skipping of library dependency
gamepad_stick_event(void *_device_handle, gamepad::gamepad_state &_state, StickAction _action, float _x, float _y, float _dx, float _dy, unsigned _player_index=0, unsigned _controller_index=0, unsigned _stick_index=0, double _time=0)
construct a key event from its textual description
gamepad extension of throttle events
void stream_out(std::ostream &os) const
write to stream
gamepad_throttle_event(void *_device_handle, gamepad::gamepad_state &_state, float _x, float _dx, unsigned _player_index=0, unsigned _controller_index=0, unsigned _throttle_index=0, double _time=0)
construct a key event from its textual description
void * device_handle
store id of gamepad
class to represent all possible keyboard events with the EID_KEY
Definition key_event.h:23
unsigned char get_char() const
return the key as a character
Definition key_event.cxx:61
unsigned char action
store whether
Definition key_event.h:28
unsigned short key
store the pressed key
Definition key_event.h:26
class to represent stick events with the EID_STICK
Definition stick_event.h:29
void stream_out(std::ostream &os) const
write to stream
class to represent events that inform on a change in a one axis controller with the EID_THROTTLE
void stream_out(std::ostream &os) const
write to stream
virtual bool dispatch_event(event &e)
dispatch a cgv event
Definition window.cxx:20
data::ref_ptr< window > window_ptr
ref counted pointer to &window
Definition window.h:31
KeyAction
different actions that a key can perform
Definition key_event.h:12
@ KA_REPEAT
key repeated press action
Definition key_event.h:15
@ KA_PRESS
key press action
Definition key_event.h:14
@ KA_RELEASE
key release action
Definition key_event.h:13
gamepad_server & ref_gamepad_server()
return a reference to gamepad server singleton
StickAction
different actions that a stick can perform
Definition stick_event.h:15
@ SA_DRAG
stick moved in pressed state
Definition stick_event.h:21
@ SA_RELEASE
stick release action
Definition stick_event.h:19
@ SA_PRESS
stick press action
Definition stick_event.h:17
@ SA_MOVE
stick moved with respect to last event
Definition stick_event.h:20
GamepadEventTypeFlags
flags to define which events should be generated by server
trigger & get_animation_trigger()
return the global trigger used for animation, which runs by default with 60 Hz
Definition trigger.cxx:81
@ EF_PAD
whether event is from gamepad
Definition event.h:34
void connect_gamepad_server(cgv::gui::window_ptr w)
connect the gamepad server to the given window or the first window of the application,...
the cgv namespace
Definition print.h:11
see https://upload.wikimedia.org/wikipedia/commons/2/2c/360_controller.svg for an explanation of the ...
Definition gamepad.h:152
float right_stick_position[2]
x and y position of left thumb in the range [-1,1]
Definition gamepad.h:160
unsigned time_stamp
time stamp can be used whether a change has happened between two states
Definition gamepad.h:154
float left_stick_position[2]
x and y position of left thumb in the range [-1,1]
Definition gamepad.h:158
unsigned button_flags
combination of flags in GamepadButtonStateFlags combined with the OR operation
Definition gamepad.h:156
float trigger_position[2]
values of left and right triggers in the range [0,1]
Definition gamepad.h:162