ObjFW  Check-in [5547016712]

Overview
Comment:OFGameController: Change API for analog sticks
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | gamecontroller
Files: files | file ages | folders
SHA3-256: 5547016712c97d7802418fbcc7b642ed794cdbb684948e8b2e6fbae886f1642d
User & Date: js on 2024-05-09 15:39:10
Other Links: branch diff | manifest | tags
Context
2024-05-09
17:39
OFGameController: Correctly scale axes on Linux check-in: 87fa51ae2e user: js tags: gamecontroller
15:39
OFGameController: Change API for analog sticks check-in: 5547016712 user: js tags: gamecontroller
15:24
OFGameController: Handle analog triggers on Linux check-in: 55a1492876 user: js tags: gamecontroller
Changes

Modified src/OFGameController.h from [64229ea449] to [618d42f152].

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@interface OFGameController: OFObject
{
#ifdef OF_LINUX
	OFString *_path;
	int _fd;
	OFString *_name;
	OFMutableSet *_buttons, *_pressedButtons;
	size_t _numAnalogSticks;
	OFPoint _analogStickPositions[2];
#endif
}

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







|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@interface OFGameController: OFObject
{
#ifdef OF_LINUX
	OFString *_path;
	int _fd;
	OFString *_name;
	OFMutableSet *_buttons, *_pressedButtons;
	bool _hasLeftAnalogStick, _hasRightAnalogStick;
	OFPoint _leftAnalogStickPosition, _rightAnalogStickPosition;
#endif
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFArray <OFGameController *> *controllers;
#endif
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
/**
 * @brief The currently pressed buttons on the controller.
 */
@property (readonly, nonatomic, copy)
    OFSet OF_GENERIC(OFString *) *pressedButtons;

/**



 * @brief The number of analog sticks the controller has.




 */





@property (readonly, nonatomic) size_t numAnalogSticks;








/**
 * @brief Returns the available controllers.
 *
 * @return The available controllers
 */
+ (OFArray OF_GENERIC(OFGameController *) *)controllers;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Returns the current position of the specified analog stick.
 *
 * The range is from (-1, -1) to (1, 1).
 *
 * @param index The index of the analog stick whose position to return
 * @return The current position of the specified analog stick
 */
- (OFPoint)positionOfAnalogStickWithIndex: (size_t)index;
@end

OF_ASSUME_NONNULL_END







>
>
>
|
>
>
>
>

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









<
<
<
<
<
<
<
<
<
<



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
/**
 * @brief The currently pressed buttons on the controller.
 */
@property (readonly, nonatomic, copy)
    OFSet OF_GENERIC(OFString *) *pressedButtons;

/**
 * @brief Whether the controller has a left analog stick.
 */
@property (readonly, nonatomic) bool hasLeftAnalogStick;

/**
 * @brief The position of the left analog stick.
 *
 * The range is from (-1, -1) to (1, 1).
 */
@property (readonly, nonatomic) OFPoint leftAnalogStickPosition;

/**
 * @brief Whether the controller has a right analog stick.
 */
@property (readonly, nonatomic) bool hasRightAnalogStick;

/**
 * @brief The position of the right analog stick.
 *
 * The range is from (-1, -1) to (1, 1).
 */
@property (readonly, nonatomic) OFPoint rightAnalogStickPosition;

/**
 * @brief Returns the available controllers.
 *
 * @return The available controllers
 */
+ (OFArray OF_GENERIC(OFGameController *) *)controllers;

- (instancetype)init OF_UNAVAILABLE;










@end

OF_ASSUME_NONNULL_END

Modified src/OFGameController.m from [aa9bbd9994] to [07bd6ec7f8].

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
# include "platform/Linux/OFGameController.m"
#elif defined(OF_NINTENDO_DS)
# include "platform/NintendoDS/OFGameController.m"
#elif defined(OF_NINTENDO_3DS)
# include "platform/Nintendo3DS/OFGameController.m"
#else
@implementation OFGameController
@dynamic name, buttons, pressedButtons, numAnalogSticks;


+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	return [OFArray array];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (OFPoint)positionOfAnalogStickWithIndex: (size_t)index
{
	OF_UNRECOGNIZED_SELECTOR
}
@end
#endif







|
>










<
<
<
<
<


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46





47
48
# include "platform/Linux/OFGameController.m"
#elif defined(OF_NINTENDO_DS)
# include "platform/NintendoDS/OFGameController.m"
#elif defined(OF_NINTENDO_3DS)
# include "platform/Nintendo3DS/OFGameController.m"
#else
@implementation OFGameController
@dynamic name, buttons, pressedButtons, hasLeftAnalogStick;
@dynamic leftAnalogStickPosition, hasRightAnalogStick, rightAnalogStickPosition;

+ (OFArray OF_GENERIC(OFGameController *) *)controllers
{
	return [OFArray array];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}





@end
#endif

Modified src/platform/Linux/OFGameController.m from [564dd9be04] to [9d006d5b77].

94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
	}

	return nil;
}

@implementation OFGameController
@synthesize name = _name, buttons = _buttons;
@synthesize numAnalogSticks = _numAnalogSticks;


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

	for (OFString *device in [[OFFileManager defaultManager]







|
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	}

	return nil;
}

@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]
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
		if (OFBitSetIsSet(evBits, EV_ABS)) {
			if (ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(absBits)),
			    absBits) == -1)
				@throw [OFInitializationFailedException
				    exception];

			if (OFBitSetIsSet(absBits, ABS_X) &&
			    OFBitSetIsSet(absBits, ABS_Y)) {
				_numAnalogSticks++;

				if (OFBitSetIsSet(absBits, ABS_RX) &&
				    OFBitSetIsSet(absBits, ABS_RY))
					_numAnalogSticks++;
			}

			if (OFBitSetIsSet(absBits, ABS_HAT0X) &&
			    OFBitSetIsSet(absBits, ABS_HAT0Y)) {
				[_buttons addObject: @"D-Pad Left"];
				[_buttons addObject: @"D-Pad Right"];
				[_buttons addObject: @"D-Pad Up"];
				[_buttons addObject: @"D-Pad Down"];







|
|

|
|
|
<







196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
		if (OFBitSetIsSet(evBits, EV_ABS)) {
			if (ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(absBits)),
			    absBits) == -1)
				@throw [OFInitializationFailedException
				    exception];

			if (OFBitSetIsSet(absBits, ABS_X) &&
			    OFBitSetIsSet(absBits, ABS_Y))
				_hasLeftAnalogStick = true;

			if (OFBitSetIsSet(absBits, ABS_RX) &&
			    OFBitSetIsSet(absBits, ABS_RY))
				_hasRightAnalogStick = true;


			if (OFBitSetIsSet(absBits, ABS_HAT0X) &&
			    OFBitSetIsSet(absBits, ABS_HAT0Y)) {
				[_buttons addObject: @"D-Pad Left"];
				[_buttons addObject: @"D-Pad Right"];
				[_buttons addObject: @"D-Pad Up"];
				[_buttons addObject: @"D-Pad Down"];
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
			else
				[_pressedButtons removeObject:
				    buttonToName(event.code)];
			break;
		case EV_ABS:
			switch (event.code) {
			case ABS_X:
				_analogStickPositions[0].x =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_Y:
				_analogStickPositions[0].y =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_RX:
				_analogStickPositions[1].x =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_RY:
				_analogStickPositions[1].y =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_HAT0X:
				if (event.value < 0) {
					[_pressedButtons addObject:
					    @"D-Pad Left"];







|




|




|




|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
			else
				[_pressedButtons removeObject:
				    buttonToName(event.code)];
			break;
		case EV_ABS:
			switch (event.code) {
			case ABS_X:
				_leftAnalogStickPosition.x =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_Y:
				_leftAnalogStickPosition.y =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_RX:
				_rightAnalogStickPosition.x =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_RY:
				_rightAnalogStickPosition.y =
				    (float)event.value /
				    (event.value < 0 ? -INT16_MIN : INT16_MAX);
				break;
			case ABS_HAT0X:
				if (event.value < 0) {
					[_pressedButtons addObject:
					    @"D-Pad Left"];
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381

382

383
384
385
386
387
388
389
390

	return OFOrderedSame;
}

- (OFSet *)pressedButtons
{
	[self of_processEvents];

	return [[_pressedButtons copy] autorelease];
}

- (OFPoint)positionOfAnalogStickWithIndex: (size_t)index
{

	if (index + 1 > _numAnalogSticks)
		@throw [OFOutOfRangeException exception];

	[self of_processEvents];



	return _analogStickPositions[index];
}

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







<



|

>
|
<
|
|
>
|
>
|







365
366
367
368
369
370
371

372
373
374
375
376
377
378

379
380
381
382
383
384
385
386
387
388
389
390
391

	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;
}

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

Modified src/platform/Nintendo3DS/OFGameController.m from [7d43ae2b1e] to [f6f05e83f5].

43
44
45
46
47
48
49


50
51
52
53
54
55
56
	controllers = [[OFArray alloc] initWithObject:
	    [[[OFGameController alloc] of_init] autorelease]];

	objc_autoreleasePoolPop(pool);
}

@implementation OFGameController


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

	OFOnce(&onceControl, initControllers);

	return [[controllers retain] autorelease];







>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	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];
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
		[pressedButtons addObject: @"C-Stick Down"];

	[pressedButtons makeImmutable];

	return pressedButtons;
}

- (size_t)numAnalogSticks
{
	return 1;
}

- (OFPoint)positionOfAnalogStickWithIndex: (size_t)index
{
	circlePosition pos;

	if (index > 0)
		@throw [OFOutOfRangeException exception];


	hidCircleRead(&pos);

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

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







|

|


|

|
|
|
|
|
>












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
		[pressedButtons addObject: @"C-Stick Down"];

	[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));
}

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

Modified src/platform/NintendoDS/OFGameController.m from [ae87665579] to [178427af22].

43
44
45
46
47
48
49


50
51
52
53
54
55
56
	controllers = [[OFArray alloc] initWithObject:
	    [[[OFGameController alloc] of_init] autorelease]];

	objc_autoreleasePoolPop(pool);
}

@implementation OFGameController


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

	OFOnce(&onceControl, initControllers);

	return [[controllers retain] autorelease];







>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	controllers = [[OFArray alloc] initWithObject:
	    [[[OFGameController alloc] of_init] autorelease]];

	objc_autoreleasePoolPop(pool);
}

@implementation OFGameController
@dynamic leftAnalogStickPosition, rightAnalogStickPosition;

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

	OFOnce(&onceControl, initControllers);

	return [[controllers retain] autorelease];
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
		[pressedButtons addObject: @"Y"];

	[pressedButtons makeImmutable];

	return pressedButtons;
}

- (size_t)numAnalogSticks
{
	return 0;
}

- (OFPoint)positionOfAnalogStickWithIndex: (size_t)index
{
	@throw [OFOutOfRangeException exception];
}

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







|

|


|

|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
		[pressedButtons addObject: @"Y"];

	[pressedButtons makeImmutable];

	return pressedButtons;
}

- (bool)hasLeftAnalogStick
{
	return false;
}

- (bool)hasRightAnalogStick
{
	return false;
}

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

Modified tests/gamecontroller/GameControllerTests.m from [783f64a599] to [0632be0ddf].

64
65
66
67
68
69
70
71
72
73
74
75






76
77
78
79
80
81
82
					i = 0;
				} else
					[OFStdOut writeString: @" "];
			}
			[OFStdOut setForegroundColor: [OFColor gray]];
			[OFStdOut writeString: @"\n"];

			for (i = 0; i < controller.numAnalogSticks; i++) {
				OFPoint position = [controller
				    positionOfAnalogStickWithIndex: i];
				[OFStdOut writeFormat: @"(%5.2f, %5.2f) ",
						       position.x, position.y];






			}
			[OFStdOut writeString: @"\n"];
		}

		[OFThread sleepForTimeInterval: 0.1];
	}
}







|
|
|


>
>
>
>
>
>







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
					i = 0;
				} else
					[OFStdOut writeString: @" "];
			}
			[OFStdOut setForegroundColor: [OFColor gray]];
			[OFStdOut writeString: @"\n"];

			if (controller.hasLeftAnalogStick) {
				OFPoint position =
				    controller.leftAnalogStickPosition;
				[OFStdOut writeFormat: @"(%5.2f, %5.2f) ",
						       position.x, position.y];
			}
			if (controller.hasRightAnalogStick) {
				OFPoint position =
				    controller.rightAnalogStickPosition;
				[OFStdOut writeFormat: @"(%5.2f, %5.2f)",
						       position.x, position.y];
			}
			[OFStdOut writeString: @"\n"];
		}

		[OFThread sleepForTimeInterval: 0.1];
	}
}