reflexion 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/reflex/application.cpp +16 -0
- data/.doc/ext/reflex/device.cpp +46 -3
- data/.doc/ext/reflex/device_event.cpp +62 -0
- data/.doc/ext/reflex/key_event.cpp +49 -19
- data/.doc/ext/reflex/native.cpp +6 -4
- data/.doc/ext/reflex/reflex.cpp +7 -6
- data/ChangeLog.md +8 -0
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +18 -0
- data/ext/reflex/device.cpp +48 -3
- data/ext/reflex/device_event.cpp +65 -0
- data/ext/reflex/key_event.cpp +49 -19
- data/ext/reflex/native.cpp +6 -4
- data/ext/reflex/reflex.cpp +7 -6
- data/include/reflex/application.h +4 -0
- data/include/reflex/defs.h +58 -21
- data/include/reflex/device.h +22 -0
- data/include/reflex/event.h +25 -0
- data/include/reflex/gamepad.h +175 -0
- data/include/reflex/ruby/application.h +18 -0
- data/include/reflex/ruby/device.h +40 -0
- data/include/reflex/ruby/event.h +11 -0
- data/reflex.gemspec +3 -3
- data/src/application.cpp +67 -0
- data/src/application.h +9 -0
- data/src/device.cpp +24 -0
- data/src/event.cpp +38 -0
- data/src/gamepad.cpp +176 -0
- data/src/gamepad.h +74 -0
- data/src/ios/app_delegate.mm +2 -2
- data/src/ios/application.mm +0 -25
- data/src/ios/event.h +0 -5
- data/src/ios/event.mm +1 -85
- data/src/ios/gamepad.mm +313 -0
- data/src/ios/reflex.mm +0 -5
- data/src/osx/app_delegate.mm +2 -2
- data/src/osx/application.mm +0 -25
- data/src/osx/event.h +1 -3
- data/src/osx/event.mm +9 -86
- data/src/osx/gamepad.mm +40 -0
- data/src/osx/gamepad_gc.mm +299 -0
- data/src/osx/gamepad_hid.mm +567 -0
- data/src/osx/reflex.mm +0 -5
- data/src/win32/application.cpp +5 -26
- data/src/win32/event.cpp +6 -89
- data/src/win32/event.h +3 -1
- data/src/win32/gamepad.cpp +110 -0
- data/src/win32/gamepad.h +20 -0
- data/src/win32/window.cpp +2 -1
- metadata +28 -14
@@ -0,0 +1,567 @@
|
|
1
|
+
// -*- objc -*-
|
2
|
+
#include "../gamepad.h"
|
3
|
+
|
4
|
+
|
5
|
+
#include <memory>
|
6
|
+
#include <vector>
|
7
|
+
#include <map>
|
8
|
+
#import <IOKit/hid/IOHIDManager.h>
|
9
|
+
#import <IOKit/hid/IOHIDDevice.h>
|
10
|
+
#import <GameController/GameController.h>
|
11
|
+
#include <xot/util.h>
|
12
|
+
#include "reflex/exception.h"
|
13
|
+
#include "reflex/debug.h"
|
14
|
+
#include "event.h"
|
15
|
+
#include "window.h"
|
16
|
+
|
17
|
+
|
18
|
+
namespace Reflex
|
19
|
+
{
|
20
|
+
|
21
|
+
|
22
|
+
static int
|
23
|
+
get_int_property (IOHIDDeviceRef device, CFStringRef key)
|
24
|
+
{
|
25
|
+
CFNumberRef ref = (CFNumberRef) IOHIDDeviceGetProperty(device, key);
|
26
|
+
if (!ref) return 0;
|
27
|
+
|
28
|
+
int value = 0;
|
29
|
+
CFNumberGetValue(ref, kCFNumberIntType, &value);
|
30
|
+
return value;
|
31
|
+
}
|
32
|
+
|
33
|
+
static String
|
34
|
+
get_string_property (IOHIDDeviceRef device, CFStringRef key)
|
35
|
+
{
|
36
|
+
return Xot::to_s((CFStringRef) IOHIDDeviceGetProperty(device, key));
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
struct HIDGamepadData : Gamepad::Data
|
41
|
+
{
|
42
|
+
|
43
|
+
typedef Gamepad::Data Super;
|
44
|
+
|
45
|
+
enum Mapping {RSTICK_UNKNOWN, RSTICK_RxRy, RSTICK_ZRz};
|
46
|
+
|
47
|
+
IOHIDDeviceRef device;
|
48
|
+
|
49
|
+
Mapping mapping = RSTICK_UNKNOWN;
|
50
|
+
|
51
|
+
CFIndex prev_hatswitch = 8;// neutral
|
52
|
+
|
53
|
+
mutable String name_cache;
|
54
|
+
|
55
|
+
HIDGamepadData (IOHIDDeviceRef device)
|
56
|
+
: device(device)
|
57
|
+
{
|
58
|
+
if (!device)
|
59
|
+
argument_error(__FILE__, __LINE__);
|
60
|
+
|
61
|
+
CFRetain(device);
|
62
|
+
prev.reset(new Gamepad());
|
63
|
+
}
|
64
|
+
|
65
|
+
~HIDGamepadData ()
|
66
|
+
{
|
67
|
+
CFRelease(device);
|
68
|
+
}
|
69
|
+
|
70
|
+
const char* name () const override
|
71
|
+
{
|
72
|
+
if (name_cache.empty())
|
73
|
+
{
|
74
|
+
String& name = name_cache;
|
75
|
+
name = get_string_property(device, CFSTR(kIOHIDManufacturerKey));
|
76
|
+
String product = get_string_property(device, CFSTR(kIOHIDProductKey));
|
77
|
+
String serial = get_string_property(device, CFSTR(kIOHIDSerialNumberKey));
|
78
|
+
|
79
|
+
if (!product.empty())
|
80
|
+
{
|
81
|
+
if (!name.empty() && name[name.size() - 1] != ' ') name_cache += " ";
|
82
|
+
name += product;
|
83
|
+
}
|
84
|
+
|
85
|
+
if (!serial.empty())
|
86
|
+
{
|
87
|
+
if (!name.empty() && name[name.size() - 1] != ' ')
|
88
|
+
{
|
89
|
+
name += " ";
|
90
|
+
serial = "[" + serial + "]";
|
91
|
+
}
|
92
|
+
name += serial;
|
93
|
+
}
|
94
|
+
|
95
|
+
if (name.empty()) name = "Unknown";
|
96
|
+
}
|
97
|
+
return name_cache;
|
98
|
+
}
|
99
|
+
|
100
|
+
bool is_valid () const override
|
101
|
+
{
|
102
|
+
return Super::is_valid() && device;
|
103
|
+
}
|
104
|
+
|
105
|
+
bool has_handle (void* handle) const override
|
106
|
+
{
|
107
|
+
return handle == device;
|
108
|
+
}
|
109
|
+
|
110
|
+
};// HIDGamepadData
|
111
|
+
|
112
|
+
|
113
|
+
static Gamepad*
|
114
|
+
Gamepad_create (IOHIDDeviceRef device)
|
115
|
+
{
|
116
|
+
Gamepad* g = Gamepad_create();
|
117
|
+
g->self.reset(new HIDGamepadData(device));
|
118
|
+
return g;
|
119
|
+
}
|
120
|
+
|
121
|
+
static HIDGamepadData*
|
122
|
+
get_data (Gamepad* gamepad)
|
123
|
+
{
|
124
|
+
return (HIDGamepadData*) gamepad->self.get();
|
125
|
+
}
|
126
|
+
|
127
|
+
static std::map<IOHIDElementRef, IOHIDDeviceRef> element2device;
|
128
|
+
|
129
|
+
static void
|
130
|
+
each_element (IOHIDDeviceRef device, std::function<bool(IOHIDElementRef)> fun)
|
131
|
+
{
|
132
|
+
std::shared_ptr<const __CFArray> elements(
|
133
|
+
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone),
|
134
|
+
Xot::safe_cfrelease);
|
135
|
+
if (!elements) return;
|
136
|
+
|
137
|
+
CFIndex count = CFArrayGetCount(elements.get());
|
138
|
+
for (CFIndex i = 0; i < count; ++i)
|
139
|
+
{
|
140
|
+
IOHIDElementRef element =
|
141
|
+
(IOHIDElementRef) CFArrayGetValueAtIndex(elements.get(), i);
|
142
|
+
if (!element) continue;
|
143
|
+
|
144
|
+
if (!fun(element)) break;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
static void
|
149
|
+
register_to_device_map (IOHIDDeviceRef device)
|
150
|
+
{
|
151
|
+
if (@available(macOS 11.0, *))
|
152
|
+
return;
|
153
|
+
|
154
|
+
each_element(device, [&](IOHIDElementRef element)
|
155
|
+
{
|
156
|
+
element2device[element] = device;
|
157
|
+
return true;
|
158
|
+
});
|
159
|
+
}
|
160
|
+
|
161
|
+
static void
|
162
|
+
unregister_to_device_map (IOHIDDeviceRef device)
|
163
|
+
{
|
164
|
+
if (@available(macOS 11.0, *))
|
165
|
+
return;
|
166
|
+
|
167
|
+
std::erase_if(
|
168
|
+
element2device,
|
169
|
+
[&](const auto& e) {return e.second == device;});
|
170
|
+
}
|
171
|
+
|
172
|
+
static IOHIDDeviceRef
|
173
|
+
get_device (IOHIDElementRef element)
|
174
|
+
{
|
175
|
+
if (@available(macOS 11.0, *))
|
176
|
+
return IOHIDElementGetDevice(element);
|
177
|
+
else
|
178
|
+
{
|
179
|
+
auto it = element2device.find(element);
|
180
|
+
if (it == element2device.end())
|
181
|
+
return NULL;
|
182
|
+
|
183
|
+
return it->second;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
static float
|
188
|
+
get_current_value (IOHIDDeviceRef device, uint32_t usage)
|
189
|
+
{
|
190
|
+
float value = 0;
|
191
|
+
each_element(device, [&](IOHIDElementRef element)
|
192
|
+
{
|
193
|
+
if (IOHIDElementGetUsage(element) != usage)
|
194
|
+
return true;
|
195
|
+
|
196
|
+
IOHIDValueRef valref = NULL;
|
197
|
+
IOReturn result = IOHIDDeviceGetValue(device, element, &valref);
|
198
|
+
if (result != kIOReturnSuccess || !valref)
|
199
|
+
return true;
|
200
|
+
|
201
|
+
CFIndex val = IOHIDValueGetIntegerValue(valref);
|
202
|
+
CFIndex min = IOHIDElementGetLogicalMin(element);
|
203
|
+
CFIndex max = IOHIDElementGetLogicalMax(element);
|
204
|
+
|
205
|
+
value = (val - min) / (float) (max - min);
|
206
|
+
return false;
|
207
|
+
});
|
208
|
+
|
209
|
+
return value;
|
210
|
+
}
|
211
|
+
|
212
|
+
static HIDGamepadData::Mapping
|
213
|
+
get_mapping (IOHIDDeviceRef device)
|
214
|
+
{
|
215
|
+
float Z = get_current_value(device, kHIDUsage_GD_Z);
|
216
|
+
float Rx = get_current_value(device, kHIDUsage_GD_Rx);
|
217
|
+
if (0.4 < Z && Z < 0.6) return HIDGamepadData::RSTICK_ZRz;
|
218
|
+
if (0.4 < Rx && Rx < 0.6) return HIDGamepadData::RSTICK_RxRy;
|
219
|
+
return HIDGamepadData::RSTICK_UNKNOWN;
|
220
|
+
}
|
221
|
+
|
222
|
+
static void
|
223
|
+
add_gamepad (Application* app, IOHIDDeviceRef device)
|
224
|
+
{
|
225
|
+
Gamepad* gamepad = Gamepad_create(device);
|
226
|
+
get_data(gamepad)->mapping = get_mapping(device);
|
227
|
+
Gamepad_add(app, gamepad);
|
228
|
+
}
|
229
|
+
|
230
|
+
static void
|
231
|
+
remove_gamepad (Application* app, IOHIDDeviceRef device)
|
232
|
+
{
|
233
|
+
Gamepad* gamepad = Gamepad_find(device);
|
234
|
+
if (!gamepad) return;
|
235
|
+
|
236
|
+
Gamepad_remove(app, gamepad);
|
237
|
+
}
|
238
|
+
|
239
|
+
static bool
|
240
|
+
can_handle (IOHIDDeviceRef device)
|
241
|
+
{
|
242
|
+
int page = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
|
243
|
+
int usage = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
|
244
|
+
return
|
245
|
+
page == kHIDPage_GenericDesktop &&
|
246
|
+
(usage == kHIDUsage_GD_GamePad || usage == kHIDUsage_GD_Joystick);
|
247
|
+
}
|
248
|
+
|
249
|
+
static void
|
250
|
+
handle_disconnect_event (void* context, IOReturn result, void* sender)
|
251
|
+
{
|
252
|
+
IOHIDDeviceRef device = (IOHIDDeviceRef) context;
|
253
|
+
|
254
|
+
remove_gamepad(app(), device);
|
255
|
+
unregister_to_device_map(device);
|
256
|
+
}
|
257
|
+
|
258
|
+
static void
|
259
|
+
handle_connect_event (
|
260
|
+
void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
|
261
|
+
{
|
262
|
+
Application* app = (Application*) context;
|
263
|
+
|
264
|
+
if (!can_handle(device))
|
265
|
+
return;
|
266
|
+
|
267
|
+
if (@available(macOS 11.0, *))
|
268
|
+
{
|
269
|
+
if ([GCController supportsHIDDevice: device])
|
270
|
+
return;
|
271
|
+
}
|
272
|
+
|
273
|
+
IOHIDDeviceRegisterRemovalCallback(device, handle_disconnect_event, device);
|
274
|
+
|
275
|
+
register_to_device_map(device);
|
276
|
+
add_gamepad(app, device);
|
277
|
+
}
|
278
|
+
|
279
|
+
enum
|
280
|
+
{
|
281
|
+
DPAD_UP = Xot::bit(0),
|
282
|
+
DPAD_RIGHT = Xot::bit(1),
|
283
|
+
DPAD_DOWN = Xot::bit(2),
|
284
|
+
DPAD_LEFT = Xot::bit(3)
|
285
|
+
};
|
286
|
+
|
287
|
+
static uint
|
288
|
+
to_dpad (CFIndex hatswitch)
|
289
|
+
{
|
290
|
+
switch (hatswitch)
|
291
|
+
{
|
292
|
+
case 0: return DPAD_UP;
|
293
|
+
case 1: return DPAD_UP | DPAD_RIGHT;
|
294
|
+
case 2: return DPAD_RIGHT;
|
295
|
+
case 3: return DPAD_RIGHT | DPAD_DOWN;
|
296
|
+
case 4: return DPAD_DOWN;
|
297
|
+
case 5: return DPAD_DOWN | DPAD_LEFT;
|
298
|
+
case 6: return DPAD_LEFT;
|
299
|
+
case 7: return DPAD_LEFT | DPAD_UP;
|
300
|
+
}
|
301
|
+
return 0;
|
302
|
+
}
|
303
|
+
|
304
|
+
static void
|
305
|
+
call_gamepad_event (int key_code, bool pressed)
|
306
|
+
{
|
307
|
+
Window* win = Window_get_active();
|
308
|
+
if (!win) return;
|
309
|
+
|
310
|
+
auto action = pressed ? KeyEvent::DOWN : KeyEvent::UP;
|
311
|
+
KeyEvent e(action, NULL, key_code, get_key_modifiers(), 0);
|
312
|
+
Window_call_key_event(win, &e);
|
313
|
+
}
|
314
|
+
|
315
|
+
static void
|
316
|
+
call_button_event (
|
317
|
+
Gamepad* gamepad, ulonglong button, int key_code, float value)
|
318
|
+
{
|
319
|
+
Gamepad::Data* self = gamepad->self.get();
|
320
|
+
|
321
|
+
bool pressed = value > Gamepad_get_button_press_threshold();
|
322
|
+
bool current = self->state.buttons & button;
|
323
|
+
if (pressed == current) return;
|
324
|
+
|
325
|
+
self->update_prev();
|
326
|
+
if (pressed)
|
327
|
+
self->state.buttons |= button;
|
328
|
+
else
|
329
|
+
self->state.buttons &= ~button;
|
330
|
+
|
331
|
+
call_gamepad_event(key_code, pressed);
|
332
|
+
}
|
333
|
+
|
334
|
+
static void
|
335
|
+
handle_hatswitch_event (
|
336
|
+
Gamepad* gamepad, IOHIDElementRef element, CFIndex hatswitch)
|
337
|
+
{
|
338
|
+
HIDGamepadData* data = get_data(gamepad);
|
339
|
+
|
340
|
+
CFIndex prev = data->prev_hatswitch;
|
341
|
+
data->prev_hatswitch = hatswitch;
|
342
|
+
|
343
|
+
uint prev_dpad = to_dpad(prev);
|
344
|
+
uint dpad = to_dpad(hatswitch);
|
345
|
+
uint diff = prev_dpad ^ dpad;
|
346
|
+
|
347
|
+
#define HANDLE_BUTTON(button, value) \
|
348
|
+
call_button_event( \
|
349
|
+
gamepad, \
|
350
|
+
Gamepad::button, KEY_GAMEPAD_##button, \
|
351
|
+
(value) ? 1 : 0)
|
352
|
+
|
353
|
+
if (diff & DPAD_UP) HANDLE_BUTTON(UP, dpad & DPAD_UP);
|
354
|
+
if (diff & DPAD_RIGHT) HANDLE_BUTTON(RIGHT, dpad & DPAD_RIGHT);
|
355
|
+
if (diff & DPAD_DOWN) HANDLE_BUTTON(DOWN, dpad & DPAD_DOWN);
|
356
|
+
if (diff & DPAD_LEFT) HANDLE_BUTTON(LEFT, dpad & DPAD_LEFT);
|
357
|
+
|
358
|
+
#undef HANDLE_BUTTON
|
359
|
+
}
|
360
|
+
|
361
|
+
static void
|
362
|
+
handle_stick_dpad_event (
|
363
|
+
Gamepad* gamepad, auto* state, float value,
|
364
|
+
ulonglong button_negative, int key_code_negative,
|
365
|
+
ulonglong button_positive, int key_code_positive)
|
366
|
+
{
|
367
|
+
*state = value;
|
368
|
+
|
369
|
+
if (value < 0)
|
370
|
+
call_button_event(gamepad, button_negative, key_code_negative, -value);
|
371
|
+
else
|
372
|
+
call_button_event(gamepad, button_positive, key_code_positive, value);
|
373
|
+
}
|
374
|
+
|
375
|
+
static void
|
376
|
+
handle_trigger_event (Gamepad* gamepad, auto* state, float value)
|
377
|
+
{
|
378
|
+
*state = value;
|
379
|
+
}
|
380
|
+
|
381
|
+
static void
|
382
|
+
handle_analog_event (
|
383
|
+
Gamepad* gamepad, uint32_t usage, IOHIDElementRef element, CFIndex intval)
|
384
|
+
{
|
385
|
+
int value = (int) intval;
|
386
|
+
int min = (int) IOHIDElementGetLogicalMin(element);
|
387
|
+
int max = (int) IOHIDElementGetLogicalMax(element);
|
388
|
+
float range = min == max ? max : max - min;
|
389
|
+
if (range == 0) range = 1;
|
390
|
+
|
391
|
+
float linear = (value - min) / range;
|
392
|
+
float centered = linear * 2 - 1;
|
393
|
+
|
394
|
+
#define HANDLE_DPAD(stick, neg, pos, var, value) \
|
395
|
+
handle_stick_dpad_event( \
|
396
|
+
gamepad, \
|
397
|
+
&gamepad->self->state.var, \
|
398
|
+
value, \
|
399
|
+
Gamepad::stick##_##neg, KEY_GAMEPAD_##stick##_##neg, \
|
400
|
+
Gamepad::stick##_##pos, KEY_GAMEPAD_##stick##_##pos)
|
401
|
+
|
402
|
+
#define HANDLE_TRIGGER(trigger, var, value) \
|
403
|
+
handle_trigger_event( \
|
404
|
+
gamepad, \
|
405
|
+
&gamepad->self->state.var, \
|
406
|
+
value)
|
407
|
+
|
408
|
+
switch (get_data(gamepad)->mapping)
|
409
|
+
{
|
410
|
+
case HIDGamepadData::RSTICK_RxRy:
|
411
|
+
switch (usage)
|
412
|
+
{
|
413
|
+
case kHIDUsage_GD_X: HANDLE_DPAD(LSTICK, LEFT, RIGHT, sticks[0].x, centered); break;
|
414
|
+
case kHIDUsage_GD_Y: HANDLE_DPAD(LSTICK, UP, DOWN, sticks[0].y, -centered); break;
|
415
|
+
case kHIDUsage_GD_Rx: HANDLE_DPAD(RSTICK, LEFT, RIGHT, sticks[1].x, centered); break;
|
416
|
+
case kHIDUsage_GD_Ry: HANDLE_DPAD(RSTICK, UP, DOWN, sticks[1].y, -centered); break;
|
417
|
+
case kHIDUsage_GD_Z: HANDLE_TRIGGER(LTRIGGER, triggers[0], linear); break;
|
418
|
+
case kHIDUsage_GD_Rz: HANDLE_TRIGGER(RTRIGGER, triggers[1], linear); break;
|
419
|
+
}
|
420
|
+
break;
|
421
|
+
|
422
|
+
case HIDGamepadData::RSTICK_ZRz:
|
423
|
+
switch (usage)
|
424
|
+
{
|
425
|
+
case kHIDUsage_GD_X: HANDLE_DPAD(LSTICK, LEFT, RIGHT, sticks[0].x, centered); break;
|
426
|
+
case kHIDUsage_GD_Y: HANDLE_DPAD(LSTICK, UP, DOWN, sticks[0].y, -centered); break;
|
427
|
+
case kHIDUsage_GD_Z: HANDLE_DPAD(RSTICK, LEFT, RIGHT, sticks[1].x, centered); break;
|
428
|
+
case kHIDUsage_GD_Rz: HANDLE_DPAD(RSTICK, UP, DOWN, sticks[1].y, -centered); break;
|
429
|
+
case kHIDUsage_GD_Rx: HANDLE_TRIGGER(LTRIGGER, triggers[0], linear); break;
|
430
|
+
case kHIDUsage_GD_Ry: HANDLE_TRIGGER(RTRIGGER, triggers[1], linear); break;
|
431
|
+
}
|
432
|
+
break;
|
433
|
+
|
434
|
+
default:
|
435
|
+
switch (usage)
|
436
|
+
{
|
437
|
+
case kHIDUsage_GD_X: HANDLE_DPAD(LSTICK, LEFT, RIGHT, sticks[0].x, centered); break;
|
438
|
+
case kHIDUsage_GD_Y: HANDLE_DPAD(LSTICK, UP, DOWN, sticks[0].y, -centered); break;
|
439
|
+
}
|
440
|
+
break;
|
441
|
+
}
|
442
|
+
|
443
|
+
#undef HANDLE_DPAD
|
444
|
+
#undef HANDLE_TRIGGER
|
445
|
+
}
|
446
|
+
|
447
|
+
static void
|
448
|
+
handle_gamepad_events (
|
449
|
+
void* context, IOReturn result, void* sender, IOHIDValueRef valref)
|
450
|
+
{
|
451
|
+
IOHIDElementRef element = IOHIDValueGetElement(valref);
|
452
|
+
if (!element) return;
|
453
|
+
|
454
|
+
Gamepad* gamepad = Gamepad_find(get_device(element));
|
455
|
+
if (!gamepad) return;
|
456
|
+
|
457
|
+
uint32_t page = IOHIDElementGetUsagePage(element);
|
458
|
+
uint32_t usage = IOHIDElementGetUsage(element);
|
459
|
+
CFIndex value = IOHIDValueGetIntegerValue(valref);
|
460
|
+
|
461
|
+
switch (page)
|
462
|
+
{
|
463
|
+
case kHIDPage_GenericDesktop:
|
464
|
+
switch (usage)
|
465
|
+
{
|
466
|
+
case kHIDUsage_GD_Hatswitch:
|
467
|
+
handle_hatswitch_event(gamepad, element, value);
|
468
|
+
break;
|
469
|
+
|
470
|
+
case kHIDUsage_GD_X:
|
471
|
+
case kHIDUsage_GD_Y:
|
472
|
+
case kHIDUsage_GD_Z:
|
473
|
+
case kHIDUsage_GD_Rx:
|
474
|
+
case kHIDUsage_GD_Ry:
|
475
|
+
case kHIDUsage_GD_Rz:
|
476
|
+
handle_analog_event(gamepad, usage, element, value);
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
break;
|
480
|
+
|
481
|
+
case kHIDPage_Button:
|
482
|
+
{
|
483
|
+
int nth = (int) usage - 1;
|
484
|
+
if (0 <= nth && nth < (KEY_GAMEPAD_BUTTON_MAX - KEY_GAMEPAD_BUTTON_0))
|
485
|
+
{
|
486
|
+
ulonglong button = Xot::bit<ulonglong>(nth, Gamepad::BUTTON_0);
|
487
|
+
int key_code = KEY_GAMEPAD_BUTTON_0 + nth;
|
488
|
+
call_button_event(gamepad, button, key_code, value > 0 ? 1 : 0);
|
489
|
+
}
|
490
|
+
break;
|
491
|
+
}
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
static IOHIDManagerRef manager = NULL;
|
496
|
+
|
497
|
+
static void
|
498
|
+
add_connected_gamepads (Application* app)
|
499
|
+
{
|
500
|
+
std::shared_ptr<const __CFSet> set(
|
501
|
+
IOHIDManagerCopyDevices(manager),
|
502
|
+
Xot::safe_cfrelease);
|
503
|
+
if (!set) return;
|
504
|
+
|
505
|
+
CFIndex count = CFSetGetCount(set.get());
|
506
|
+
std::vector<IOHIDDeviceRef> devices(count, NULL);
|
507
|
+
CFSetGetValues(set.get(), (const void**) &devices[0]);
|
508
|
+
|
509
|
+
for (CFIndex i = 0; i < count; ++i)
|
510
|
+
handle_connect_event(app, kIOReturnSuccess, manager, devices[i]);
|
511
|
+
}
|
512
|
+
|
513
|
+
void
|
514
|
+
init_hid_gamepads (Application* app)
|
515
|
+
{
|
516
|
+
if (manager)
|
517
|
+
invalid_state_error(__FILE__, __LINE__);
|
518
|
+
|
519
|
+
manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
520
|
+
if (!manager)
|
521
|
+
system_error(__FILE__, __LINE__);
|
522
|
+
|
523
|
+
add_connected_gamepads(app);
|
524
|
+
|
525
|
+
NSDictionary* gamepad =
|
526
|
+
@{
|
527
|
+
@kIOHIDDeviceUsagePageKey: @(kHIDPage_GenericDesktop),
|
528
|
+
@kIOHIDDeviceUsageKey: @(kHIDUsage_GD_GamePad)
|
529
|
+
};
|
530
|
+
NSDictionary* joystick =
|
531
|
+
@{
|
532
|
+
@kIOHIDDeviceUsagePageKey: @(kHIDPage_GenericDesktop),
|
533
|
+
@kIOHIDDeviceUsageKey: @(kHIDUsage_GD_Joystick)
|
534
|
+
};
|
535
|
+
NSArray* matchings = @[gamepad, joystick];
|
536
|
+
IOHIDManagerSetDeviceMatchingMultiple(
|
537
|
+
manager, (__bridge CFArrayRef) matchings);
|
538
|
+
|
539
|
+
IOHIDManagerRegisterDeviceMatchingCallback(
|
540
|
+
manager, handle_connect_event, app);
|
541
|
+
IOHIDManagerRegisterInputValueCallback(
|
542
|
+
manager, handle_gamepad_events, app);
|
543
|
+
|
544
|
+
IOHIDManagerScheduleWithRunLoop(
|
545
|
+
manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
546
|
+
|
547
|
+
IOReturn ret = IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
|
548
|
+
if (ret != kIOReturnSuccess)
|
549
|
+
system_error(__FILE__, __LINE__);
|
550
|
+
}
|
551
|
+
|
552
|
+
void
|
553
|
+
fin_hid_gamepads (Application* app)
|
554
|
+
{
|
555
|
+
if (!manager)
|
556
|
+
invalid_state_error(__FILE__, __LINE__);
|
557
|
+
|
558
|
+
IOHIDManagerUnscheduleFromRunLoop(
|
559
|
+
manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
560
|
+
IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
|
561
|
+
|
562
|
+
CFRelease(manager);
|
563
|
+
manager = NULL;
|
564
|
+
}
|
565
|
+
|
566
|
+
|
567
|
+
}// Reflex
|
data/src/osx/reflex.mm
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
#import <Cocoa/Cocoa.h>
|
6
6
|
#include "reflex/exception.h"
|
7
|
-
#include "event.h"
|
8
7
|
|
9
8
|
|
10
9
|
namespace Reflex
|
@@ -26,8 +25,6 @@ namespace Reflex
|
|
26
25
|
reflex_error(__FILE__, __LINE__, "already initialized.");
|
27
26
|
|
28
27
|
global::pool = [[NSAutoreleasePool alloc] init];
|
29
|
-
|
30
|
-
init_game_controllers();
|
31
28
|
}
|
32
29
|
|
33
30
|
void
|
@@ -36,8 +33,6 @@ namespace Reflex
|
|
36
33
|
if (!global::pool)
|
37
34
|
reflex_error(__FILE__, __LINE__, "not initialized.");
|
38
35
|
|
39
|
-
fin_game_controllers();
|
40
|
-
|
41
36
|
[global::pool release];
|
42
37
|
global::pool = nil;
|
43
38
|
}
|
data/src/win32/application.cpp
CHANGED
@@ -42,7 +42,7 @@ namespace Reflex
|
|
42
42
|
Application::start ()
|
43
43
|
{
|
44
44
|
Event e;
|
45
|
-
|
45
|
+
Application_call_start(this, &e);
|
46
46
|
|
47
47
|
timeBeginPeriod(1);
|
48
48
|
|
@@ -84,27 +84,11 @@ namespace Reflex
|
|
84
84
|
void
|
85
85
|
Application::quit ()
|
86
86
|
{
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
void
|
91
|
-
Application::on_start (Event* e)
|
92
|
-
{
|
93
|
-
}
|
94
|
-
|
95
|
-
void
|
96
|
-
Application::on_quit (Event* e)
|
97
|
-
{
|
98
|
-
}
|
99
|
-
|
100
|
-
void
|
101
|
-
Application::on_motion (MotionEvent* e)
|
102
|
-
{
|
103
|
-
}
|
87
|
+
Event e;
|
88
|
+
Application_call_quit(this, &e);
|
89
|
+
if (e.is_blocked()) return;
|
104
90
|
|
105
|
-
|
106
|
-
Application::on_preference (Event* e)
|
107
|
-
{
|
91
|
+
PostQuitMessage(0);
|
108
92
|
}
|
109
93
|
|
110
94
|
void
|
@@ -112,10 +96,5 @@ namespace Reflex
|
|
112
96
|
{
|
113
97
|
}
|
114
98
|
|
115
|
-
Application::operator bool () const
|
116
|
-
{
|
117
|
-
return true;
|
118
|
-
}
|
119
|
-
|
120
99
|
|
121
100
|
}// Reflex
|