ObjFW  Check-in [0f902d87eb]

Overview
Comment:OFGameController: Retrieve state explicitly

This avoids retrieving it multiple times when reading multiple things.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | gamecontroller
Files: files | file ages | folders
SHA3-256: 0f902d87eb05cb4981143c2bc4c63ef954859e2486919c0cc68c9266985be4a4
User & Date: js on 2024-05-09 23:41:48
Other Links: branch diff | manifest | tags
Context
2024-05-10
00:27
OFGameController: Add support for Windows check-in: 22f6f258d8 user: js tags: gamecontroller
2024-05-09
23:41
OFGameController: Retrieve state explicitly check-in: 0f902d87eb user: js tags: gamecontroller
21:23
OFGameController: Fix checking available buttons check-in: 90bd76b84d user: js tags: gamecontroller
Changes

Modified src/OFGameController.h from [62ce0aa0c9] to [6f8baafc94].

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209





210
211
212
213
214
215
216

/**
 * @brief A class for reading state from a game controller.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFGameController: OFObject
{
#ifdef OF_LINUX
	OFString *_path;
	int _fd;
	uint16_t _vendorID, _productID;
	OFString *_name;
	OFMutableSet *_buttons, *_pressedButtons;
	bool _hasLeftAnalogStick, _hasRightAnalogStick;
	bool _hasZLPressure, _hasZRPressure;
	OFPoint _leftAnalogStickPosition, _rightAnalogStickPosition;
	float _ZLPressure, _ZRPressure;
	int32_t _leftAnalogStickMinX, _leftAnalogStickMaxX;
	int32_t _leftAnalogStickMinY, _leftAnalogStickMaxY;
	int32_t _rightAnalogStickMinX, _rightAnalogStickMaxX;
	int32_t _rightAnalogStickMinY, _rightAnalogStickMaxY;
	int32_t _ZLMinPressure, _ZLMaxPressure, _ZRMinPressure, _ZRMaxPressure;





#endif
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFArray <OFGameController *> *controllers;
#endif







|














>
>
>
>
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

/**
 * @brief A class for reading state from a game controller.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFGameController: OFObject
{
#if defined(OF_LINUX)
	OFString *_path;
	int _fd;
	uint16_t _vendorID, _productID;
	OFString *_name;
	OFMutableSet *_buttons, *_pressedButtons;
	bool _hasLeftAnalogStick, _hasRightAnalogStick;
	bool _hasZLPressure, _hasZRPressure;
	OFPoint _leftAnalogStickPosition, _rightAnalogStickPosition;
	float _ZLPressure, _ZRPressure;
	int32_t _leftAnalogStickMinX, _leftAnalogStickMaxX;
	int32_t _leftAnalogStickMinY, _leftAnalogStickMaxY;
	int32_t _rightAnalogStickMinX, _rightAnalogStickMaxX;
	int32_t _rightAnalogStickMinY, _rightAnalogStickMaxY;
	int32_t _ZLMinPressure, _ZLMaxPressure, _ZRMinPressure, _ZRMaxPressure;
#elif defined(OF_NINTENDO_DS)
	OFMutableSet *_pressedButtons;
#elif defined(OF_NINTENDO_3DS)
	OFMutableSet *_pressedButtons;
	OFPoint _leftAnalogStickPosition;
#endif
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFArray <OFGameController *> *controllers;
#endif
261
262
263
264
265
266
267








268
269
270
271
272
273
274
275
276
277
278
279
 *
 * @return The available controllers
 */
+ (OFArray OF_GENERIC(OFGameController *) *)controllers;

- (instancetype)init OF_UNAVAILABLE;









/**
 * @brief Returns how hard the specified button is pressed.
 *
 * The returned value is in the range from 0 to 1.
 *
 * @param button The button for which to return how hard it is pressed.
 * @return How hard the specified button is pressed
 */
- (float)pressureForButton: (OFGameControllerButton)button;
@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>












266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 *
 * @return The available controllers
 */
+ (OFArray OF_GENERIC(OFGameController *) *)controllers;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Retrieve the current state from the game controller.
 *
 * The state returned by @ref OFGameController's messages does not change until
 * this method is called.
 */
- (void)retrieveState;

/**
 * @brief Returns how hard the specified button is pressed.
 *
 * The returned value is in the range from 0 to 1.
 *
 * @param button The button for which to return how hard it is pressed.
 * @return How hard the specified button is pressed
 */
- (float)pressureForButton: (OFGameControllerButton)button;
@end

OF_ASSUME_NONNULL_END

Modified src/OFGameController.m from [c9aa070e37] to [9e4bb86304].

65
66
67
68
69
70
71




72
73
74
75
76
77
78
	return [OFArray array];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}





- (float)pressureForButton: (OFGameControllerButton)button
{
	return 0;
}
@end
#endif







>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	return [OFArray array];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)retrieveState
{
}

- (float)pressureForButton: (OFGameControllerButton)button
{
	return 0;
}
@end
#endif

Modified src/platform/Linux/OFGameController.m from [36b2c982f2] to [ff55e4dc62].

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "OFReadFailedException.h"

static const uint16_t vendorIDNintendo = 0x057E;
static const uint16_t productIDN64Controller = 0x2019;

@interface OFGameController ()
- (instancetype)of_initWithPath: (OFString *)path OF_METHOD_FAMILY(init);
- (void)of_processEvents;
@end

static const uint16_t buttons[] = {
	BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2,
	BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_THUMBL, BTN_THUMBR,
	BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT
};







<







39
40
41
42
43
44
45

46
47
48
49
50
51
52
#import "OFReadFailedException.h"

static const uint16_t vendorIDNintendo = 0x057E;
static const uint16_t productIDN64Controller = 0x2019;

@interface OFGameController ()
- (instancetype)of_initWithPath: (OFString *)path OF_METHOD_FAMILY(init);

@end

static const uint16_t buttons[] = {
	BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2,
	BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_THUMBL, BTN_THUMBR,
	BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT
};
130
131
132
133
134
135
136


137
138
139
140
141
142
143
	return ((value - min) / (max - min) * 2) - 1;
}

@implementation OFGameController
@synthesize name = _name, buttons = _buttons;
@synthesize hasLeftAnalogStick = _hasLeftAnalogStick;
@synthesize hasRightAnalogStick = _hasRightAnalogStick;



+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	OFMutableArray *controllers = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	for (OFString *device in [[OFFileManager defaultManager]







>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
	return ((value - min) / (max - min) * 2) - 1;
}

@implementation OFGameController
@synthesize name = _name, buttons = _buttons;
@synthesize hasLeftAnalogStick = _hasLeftAnalogStick;
@synthesize hasRightAnalogStick = _hasRightAnalogStick;
@synthesize leftAnalogStickPosition = _leftAnalogStickPosition;
@synthesize rightAnalogStickPosition = _rightAnalogStickPosition;

+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	OFMutableArray *controllers = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	for (OFString *device in [[OFFileManager defaultManager]
323
324
325
326
327
328
329


330
331
332
333
334
335
336
				_ZRMaxPressure = info.maximum;

				[_buttons addObject: OFGameControllerButtonZR];
			}
		}

		[_buttons makeImmutable];


	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







>
>







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
				_ZRMaxPressure = info.maximum;

				[_buttons addObject: OFGameControllerButtonZR];
			}
		}

		[_buttons makeImmutable];

		[self retrieveState];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	[_name release];
	[_buttons release];
	[_pressedButtons release];

	[super dealloc];
}

- (void)of_processEvents
{
	struct input_event event;

	for (;;) {
		errno = 0;

		if (read(_fd, &event, sizeof(event)) < (int)sizeof(event)) {







|







348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
	[_name release];
	[_buttons release];
	[_pressedButtons release];

	[super dealloc];
}

- (void)retrieveState
{
	struct input_event event;

	for (;;) {
		errno = 0;

		if (read(_fd, &event, sizeof(event)) < (int)sizeof(event)) {
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
		return OFOrderedAscending;

	return OFOrderedSame;
}

- (OFSet *)pressedButtons
{
	[self of_processEvents];
	return [[_pressedButtons copy] autorelease];
}

- (OFPoint)leftAnalogStickPosition
{
	[self of_processEvents];
	return _leftAnalogStickPosition;
}

- (OFPoint)rightAnalogStickPosition
{
	[self of_processEvents];
	return _rightAnalogStickPosition;
}

- (float)pressureForButton: (OFGameControllerButton)button
{
	if ([button isEqual: OFGameControllerButtonZL] && _hasZLPressure) {
		[self of_processEvents];
		return _ZLPressure;
	}

	if ([button isEqual: OFGameControllerButtonZR] && _hasZRPressure) {
		[self of_processEvents];
		return _ZRPressure;
	}

	return ([self.pressedButtons containsObject: button] ? 1 : 0);
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name];
}
@end







<



<
<
<
<
<
<
<
<
<
<
<
<


|
<

|
<
|
<

<









480
481
482
483
484
485
486

487
488
489












490
491
492

493
494

495

496

497
498
499
500
501
502
503
504
505
		return OFOrderedAscending;

	return OFOrderedSame;
}

- (OFSet *)pressedButtons
{

	return [[_pressedButtons copy] autorelease];
}













- (float)pressureForButton: (OFGameControllerButton)button
{
	if (button == OFGameControllerButtonZL && _hasZLPressure)

		return _ZLPressure;


	if (button == OFGameControllerButtonZR && _hasZRPressure)

		return _ZRPressure;


	return ([self.pressedButtons containsObject: button] ? 1 : 0);
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name];
}
@end

Modified src/platform/Nintendo3DS/OFGameController.m from [adf29c8c87] to [52a27f332c].

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
	controllers = [[OFArray alloc] initWithObject:
	    [[[OFGameController alloc] of_init] autorelease]];

	objc_autoreleasePoolPop(pool);
}

@implementation OFGameController

@dynamic rightAnalogStickPosition;

+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	static OFOnceControl onceControl = OFOnceControlInitValue;

	OFOnce(&onceControl, initControllers);

	return [[controllers retain] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)of_init
{
	return [super init];








































































}

- (OFString *)name
{
	return @"Nintendo 3DS";
}








>


















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
	controllers = [[OFArray alloc] initWithObject:
	    [[[OFGameController alloc] of_init] autorelease]];

	objc_autoreleasePoolPop(pool);
}

@implementation OFGameController
@synthesize leftAnalogStickPosition = _leftAnalogStickPosition;
@dynamic rightAnalogStickPosition;

+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	static OFOnceControl onceControl = OFOnceControlInitValue;

	OFOnce(&onceControl, initControllers);

	return [[controllers retain] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)of_init
{
	self = [super init];

	@try {
		_pressedButtons = [[OFMutableSet alloc] initWithCapacity: 18];

		[self retrieveState];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_pressedButtons release];

	[super dealloc];
}

- (void)retrieveState
{
	u32 keys;
	circlePosition pos;

	hidScanInput();

	keys = hidKeysHeld();
	hidCircleRead(&pos);

	[_pressedButtons removeAllObjects];

	if (keys & KEY_A)
		[_pressedButtons addObject: OFGameControllerButtonA];
	if (keys & KEY_B)
		[_pressedButtons addObject: OFGameControllerButtonB];
	if (keys & KEY_SELECT)
		[_pressedButtons addObject: OFGameControllerButtonSelect];
	if (keys & KEY_START)
		[_pressedButtons addObject: OFGameControllerButtonStart];
	if (keys & KEY_DRIGHT)
		[_pressedButtons addObject: OFGameControllerButtonDPadRight];
	if (keys & KEY_DLEFT)
		[_pressedButtons addObject: OFGameControllerButtonDPadLeft];
	if (keys & KEY_DUP)
		[_pressedButtons addObject: OFGameControllerButtonDPadUp];
	if (keys & KEY_DDOWN)
		[_pressedButtons addObject: OFGameControllerButtonDPadDown];
	if (keys & KEY_R)
		[_pressedButtons addObject: OFGameControllerButtonR];
	if (keys & KEY_L)
		[_pressedButtons addObject: OFGameControllerButtonL];
	if (keys & KEY_X)
		[_pressedButtons addObject: OFGameControllerButtonX];
	if (keys & KEY_Y)
		[_pressedButtons addObject: OFGameControllerButtonY];
	if (keys & KEY_ZL)
		[_pressedButtons addObject: OFGameControllerButtonZL];
	if (keys & KEY_ZR)
		[_pressedButtons addObject: OFGameControllerButtonZR];
	if (keys & KEY_CSTICK_RIGHT)
		[_pressedButtons addObject: OFGameControllerButtonCPadRight];
	if (keys & KEY_CSTICK_LEFT)
		[_pressedButtons addObject: OFGameControllerButtonCPadLeft];
	if (keys & KEY_CSTICK_UP)
		[_pressedButtons addObject: OFGameControllerButtonCPadUp];
	if (keys & KEY_CSTICK_DOWN)
		[_pressedButtons addObject: OFGameControllerButtonCPadDown];

	_leftAnalogStickPosition = OFMakePoint(
	    (float)pos.dx / (pos.dx < 0 ? -INT16_MIN : INT16_MAX),
	    (float)pos.dy / (pos.dy < 0 ? -INT16_MIN : INT16_MAX));
}

- (OFString *)name
{
	return @"Nintendo 3DS";
}

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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	    OFGameControllerButtonZR, OFGameControllerButtonCPadRight,
	    OFGameControllerButtonCPadLeft, OFGameControllerButtonCPadUp,
	    OFGameControllerButtonCPadDown, nil];
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)pressedButtons
{
	OFMutableSet OF_GENERIC(OFGameControllerButton) *pressedButtons =
	    [OFMutableSet setWithCapacity: 18];
	u32 keys;

	hidScanInput();
	keys = hidKeysHeld();

	if (keys & KEY_A)
		[pressedButtons addObject: OFGameControllerButtonA];
	if (keys & KEY_B)
		[pressedButtons addObject: OFGameControllerButtonB];
	if (keys & KEY_SELECT)
		[pressedButtons addObject: OFGameControllerButtonSelect];
	if (keys & KEY_START)
		[pressedButtons addObject: OFGameControllerButtonStart];
	if (keys & KEY_DRIGHT)
		[pressedButtons addObject: OFGameControllerButtonDPadRight];
	if (keys & KEY_DLEFT)
		[pressedButtons addObject: OFGameControllerButtonDPadLeft];
	if (keys & KEY_DUP)
		[pressedButtons addObject: OFGameControllerButtonDPadUp];
	if (keys & KEY_DDOWN)
		[pressedButtons addObject: OFGameControllerButtonDPadDown];
	if (keys & KEY_R)
		[pressedButtons addObject: OFGameControllerButtonR];
	if (keys & KEY_L)
		[pressedButtons addObject: OFGameControllerButtonL];
	if (keys & KEY_X)
		[pressedButtons addObject: OFGameControllerButtonX];
	if (keys & KEY_Y)
		[pressedButtons addObject: OFGameControllerButtonY];
	if (keys & KEY_ZL)
		[pressedButtons addObject: OFGameControllerButtonZL];
	if (keys & KEY_ZR)
		[pressedButtons addObject: OFGameControllerButtonZR];
	if (keys & KEY_CSTICK_RIGHT)
		[pressedButtons addObject: OFGameControllerButtonCPadRight];
	if (keys & KEY_CSTICK_LEFT)
		[pressedButtons addObject: OFGameControllerButtonCPadLeft];
	if (keys & KEY_CSTICK_UP)
		[pressedButtons addObject: OFGameControllerButtonCPadUp];
	if (keys & KEY_CSTICK_DOWN)
		[pressedButtons addObject: OFGameControllerButtonCPadDown];

	[pressedButtons makeImmutable];

	return pressedButtons;
}

- (bool)hasLeftAnalogStick
{
	return true;
}

- (bool)hasRightAnalogStick
{
	return false;
}

- (OFPoint)leftAnalogStickPosition
{
	circlePosition pos;
	hidCircleRead(&pos);

	return OFMakePoint(
	    (float)pos.dx / (pos.dx < 0 ? -INT16_MIN : INT16_MAX),
	    (float)pos.dy / (pos.dy < 0 ? -INT16_MIN : INT16_MAX));
}

- (float)pressureForButton: (OFGameControllerButton)button
{
	return ([self.pressedButtons containsObject: button] ? 1 : 0);
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name];
}
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|












<
<
<
<
<
<
<
<
<
<










158
159
160
161
162
163
164














































165
166
167
168
169
170
171
172
173
174
175
176
177










178
179
180
181
182
183
184
185
186
187
	    OFGameControllerButtonZR, OFGameControllerButtonCPadRight,
	    OFGameControllerButtonCPadLeft, OFGameControllerButtonCPadUp,
	    OFGameControllerButtonCPadDown, nil];
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)pressedButtons
{














































	return [[_pressedButtons copy] autorelease];
}

- (bool)hasLeftAnalogStick
{
	return true;
}

- (bool)hasRightAnalogStick
{
	return false;
}











- (float)pressureForButton: (OFGameControllerButton)button
{
	return ([self.pressedButtons containsObject: button] ? 1 : 0);
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name];
}
@end

Modified src/platform/NintendoDS/OFGameController.m from [c449fe09b2] to [4b17f6e4a3].

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
129
130
- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)of_init
{
	return [super init];





















































}

- (OFString *)name
{
	return @"Nintendo DS";
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)buttons
{
	return [OFSet setWithObjects: OFGameControllerButtonA,
	    OFGameControllerButtonB, OFGameControllerButtonSelect,
	    OFGameControllerButtonStart, OFGameControllerButtonDPadRight,
	    OFGameControllerButtonDPadLeft, OFGameControllerButtonDPadUp,
	    OFGameControllerButtonDPadDown, OFGameControllerButtonR,
	    OFGameControllerButtonL, OFGameControllerButtonX,
	    OFGameControllerButtonY, nil];
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)pressedButtons
{
	OFMutableSet OF_GENERIC(OFGameControllerButton) *pressedButtons =
	    [OFMutableSet setWithCapacity: 12];
	uint32 keys;

	scanKeys();
	keys = keysCurrent();

	if (keys & KEY_A)
		[pressedButtons addObject: OFGameControllerButtonA];
	if (keys & KEY_B)
		[pressedButtons addObject: OFGameControllerButtonB];
	if (keys & KEY_SELECT)
		[pressedButtons addObject: OFGameControllerButtonSelect];
	if (keys & KEY_START)
		[pressedButtons addObject: OFGameControllerButtonStart];
	if (keys & KEY_RIGHT)
		[pressedButtons addObject: OFGameControllerButtonDPadRight];
	if (keys & KEY_LEFT)
		[pressedButtons addObject: OFGameControllerButtonDPadLeft];
	if (keys & KEY_UP)
		[pressedButtons addObject: OFGameControllerButtonDPadUp];
	if (keys & KEY_DOWN)
		[pressedButtons addObject: OFGameControllerButtonDPadDown];
	if (keys & KEY_R)
		[pressedButtons addObject: OFGameControllerButtonR];
	if (keys & KEY_L)
		[pressedButtons addObject: OFGameControllerButtonL];
	if (keys & KEY_X)
		[pressedButtons addObject: OFGameControllerButtonX];
	if (keys & KEY_Y)
		[pressedButtons addObject: OFGameControllerButtonY];

	[pressedButtons makeImmutable];

	return pressedButtons;
}

- (bool)hasLeftAnalogStick
{
	return false;
}








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







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
129
130
131
132
133
134
135
136
137
138
139
140
141


































142
143
144
145
146
147
148
149
- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)of_init
{
	self = [super init];

	@try {
		_pressedButtons = [[OFMutableSet alloc] initWithCapacity: 12];

		[self retrieveState];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_pressedButtons release];

	[super dealloc];
}

- (void)retrieveState
{
	uint32 keys;

	scanKeys();
	keys = keysCurrent();

	[_pressedButtons removeAllObjects];

	if (keys & KEY_A)
		[_pressedButtons addObject: OFGameControllerButtonA];
	if (keys & KEY_B)
		[_pressedButtons addObject: OFGameControllerButtonB];
	if (keys & KEY_SELECT)
		[_pressedButtons addObject: OFGameControllerButtonSelect];
	if (keys & KEY_START)
		[_pressedButtons addObject: OFGameControllerButtonStart];
	if (keys & KEY_RIGHT)
		[_pressedButtons addObject: OFGameControllerButtonDPadRight];
	if (keys & KEY_LEFT)
		[_pressedButtons addObject: OFGameControllerButtonDPadLeft];
	if (keys & KEY_UP)
		[_pressedButtons addObject: OFGameControllerButtonDPadUp];
	if (keys & KEY_DOWN)
		[_pressedButtons addObject: OFGameControllerButtonDPadDown];
	if (keys & KEY_R)
		[_pressedButtons addObject: OFGameControllerButtonR];
	if (keys & KEY_L)
		[_pressedButtons addObject: OFGameControllerButtonL];
	if (keys & KEY_X)
		[_pressedButtons addObject: OFGameControllerButtonX];
	if (keys & KEY_Y)
		[_pressedButtons addObject: OFGameControllerButtonY];
}

- (OFString *)name
{
	return @"Nintendo DS";
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)buttons
{
	return [OFSet setWithObjects: OFGameControllerButtonA,
	    OFGameControllerButtonB, OFGameControllerButtonSelect,
	    OFGameControllerButtonStart, OFGameControllerButtonDPadRight,
	    OFGameControllerButtonDPadLeft, OFGameControllerButtonDPadUp,
	    OFGameControllerButtonDPadDown, OFGameControllerButtonR,
	    OFGameControllerButtonL, OFGameControllerButtonX,
	    OFGameControllerButtonY, nil];
}

- (OFSet OF_GENERIC(OFGameControllerButton) *)pressedButtons
{


































	return [[_pressedButtons copy] autorelease];
}

- (bool)hasLeftAnalogStick
{
	return false;
}

Modified tests/gamecontroller/GameControllerTests.m from [234ef24ee3] to [97e82caa67].

45
46
47
48
49
50
51


52
53
54
55
56
57
58
		for (OFGameController *controller in controllers) {
			OFArray OF_GENERIC(OFGameControllerButton) *buttons =
			    controller.buttons.allObjects.sortedArray;
			size_t i = 0;

			[OFStdOut setForegroundColor: [OFColor green]];
			[OFStdOut writeLine: controller.name];



			for (OFGameControllerButton button in buttons) {
				float pressure =
				    [controller pressureForButton: button];

				if (pressure == 1)
					[OFStdOut setForegroundColor:







>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
		for (OFGameController *controller in controllers) {
			OFArray OF_GENERIC(OFGameControllerButton) *buttons =
			    controller.buttons.allObjects.sortedArray;
			size_t i = 0;

			[OFStdOut setForegroundColor: [OFColor green]];
			[OFStdOut writeLine: controller.name];

			[controller retrieveState];

			for (OFGameControllerButton button in buttons) {
				float pressure =
				    [controller pressureForButton: button];

				if (pressure == 1)
					[OFStdOut setForegroundColor: