Index: src/OFGameController.h ================================================================== --- src/OFGameController.h +++ src/OFGameController.h @@ -304,10 +304,34 @@ * * The range is from (-1, -1) to (1, 1). */ @property (readonly, nonatomic) OFPoint rightAnalogStickPosition; +/** + * @brief The north button on the right diamond pad or `nil` if there is none. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + OFGameControllerButton northButton; + +/** + * @brief The south button on the right diamond pad or `nil` if there is none. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + OFGameControllerButton southButton; + +/** + * @brief The west button on the right diamond pad or `nil` if there is none. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + OFGameControllerButton westButton; + +/** + * @brief The east button on the right diamond pad or `nil` if there is none. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + OFGameControllerButton eastButton; + /** * @brief Returns the available controllers. * * @return The available controllers */ Index: src/OFGameController.m ================================================================== --- src/OFGameController.m +++ src/OFGameController.m @@ -62,10 +62,11 @@ # include "platform/Nintendo3DS/OFGameController.m" #else @implementation OFGameController @dynamic name, buttons, pressedButtons, hasLeftAnalogStick; @dynamic leftAnalogStickPosition, hasRightAnalogStick, rightAnalogStickPosition; +@dynamic northButton, southButton, westButton, eastButton; + (OFArray OF_GENERIC(OFGameController *) *)controllers { return [OFArray array]; } Index: src/platform/Linux/OFGameController.m ================================================================== --- src/platform/Linux/OFGameController.m +++ src/platform/Linux/OFGameController.m @@ -534,10 +534,62 @@ if (button == OFGameControllerButtonZR && _hasZRPressure) return _ZRPressure; return ([self.pressedButtons containsObject: button] ? 1 : 0); } + +- (OFGameControllerButton)northButton +{ + if (_vendorID == vendorIDNintendo && _productID == productIDLeftJoycon) + return nil; + if (_vendorID == vendorIDNintendo && _productID == productIDRightJoycon) + return OFGameControllerButtonX; + if (_vendorID == vendorIDNintendo && + _productID == productIDN64Controller) + return nil; + + return OFGameControllerButtonY; +} + +- (OFGameControllerButton)southButton +{ + if (_vendorID == vendorIDNintendo && _productID == productIDLeftJoycon) + return nil; + if (_vendorID == vendorIDNintendo && _productID == productIDRightJoycon) + return OFGameControllerButtonB; + if (_vendorID == vendorIDNintendo && + _productID == productIDN64Controller) + return nil; + + return OFGameControllerButtonA; +} + +- (OFGameControllerButton)westButton +{ + if (_vendorID == vendorIDNintendo && _productID == productIDLeftJoycon) + return nil; + if (_vendorID == vendorIDNintendo && _productID == productIDRightJoycon) + return OFGameControllerButtonY; + if (_vendorID == vendorIDNintendo && + _productID == productIDN64Controller) + return nil; + + return OFGameControllerButtonX; +} + +- (OFGameControllerButton)eastButton +{ + if (_vendorID == vendorIDNintendo && _productID == productIDLeftJoycon) + return nil; + if (_vendorID == vendorIDNintendo && _productID == productIDRightJoycon) + return OFGameControllerButtonA; + if (_vendorID == vendorIDNintendo && + _productID == productIDN64Controller) + return nil; + + return OFGameControllerButtonB; +} - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name]; } Index: src/platform/Nintendo3DS/OFGameController.m ================================================================== --- src/platform/Nintendo3DS/OFGameController.m +++ src/platform/Nintendo3DS/OFGameController.m @@ -187,10 +187,30 @@ - (float)pressureForButton: (OFGameControllerButton)button { return ([self.pressedButtons containsObject: button] ? 1 : 0); } + +- (OFGameControllerButton)northButton +{ + return OFGameControllerButtonX; +} + +- (OFGameControllerButton)southButton +{ + return OFGameControllerButtonB; +} + +- (OFGameControllerButton)westButton +{ + return OFGameControllerButtonY; +} + +- (OFGameControllerButton)eastButton +{ + return OFGameControllerButtonA; +} - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name]; } Index: src/platform/NintendoDS/OFGameController.m ================================================================== --- src/platform/NintendoDS/OFGameController.m +++ src/platform/NintendoDS/OFGameController.m @@ -164,10 +164,30 @@ - (float)pressureForButton: (OFGameControllerButton)button { return ([self.pressedButtons containsObject: button] ? 1 : 0); } + +- (OFGameControllerButton)northButton +{ + return OFGameControllerButtonX; +} + +- (OFGameControllerButton)southButton +{ + return OFGameControllerButtonB; +} + +- (OFGameControllerButton)westButton +{ + return OFGameControllerButtonY; +} + +- (OFGameControllerButton)eastButton +{ + return OFGameControllerButtonA; +} - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name]; } Index: src/platform/Windows/OFGameController.m ================================================================== --- src/platform/Windows/OFGameController.m +++ src/platform/Windows/OFGameController.m @@ -225,10 +225,30 @@ if (button == OFGameControllerButtonZR) return _ZRPressure; return ([self.pressedButtons containsObject: button] ? 1 : 0); } + +- (OFGameControllerButton)northButton +{ + return OFGameControllerButtonY; +} + +- (OFGameControllerButton)southButton +{ + return OFGameControllerButtonA; +} + +- (OFGameControllerButton)westButton +{ + return OFGameControllerButtonX; +} + +- (OFGameControllerButton)eastButton +{ + return OFGameControllerButtonB; +} - (OFString *)description { return [OFString stringWithFormat: @"<%@: %@>", self.class, self.name]; } Index: tests/gamecontroller/GameControllerTests.m ================================================================== --- tests/gamecontroller/GameControllerTests.m +++ tests/gamecontroller/GameControllerTests.m @@ -57,11 +57,15 @@ [OFStdOut writeFormat: @" [%04X:%04X]", controller.vendorID.unsignedShortValue, controller.productID.unsignedShortValue]; } - [OFStdOut writeString: @"\n"]; + [OFStdOut setForegroundColor: [OFColor blue]]; + [OFStdOut writeFormat: + @"\nNorth: %@ South: %@ West: %@ East: %@\n", + controller.northButton, controller.southButton, + controller.westButton, controller.eastButton]; [controller retrieveState]; for (OFGameControllerButton button in buttons) { float pressure =