mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-04-14 20:06:23 +00:00
added support for multiple controllers
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD391A7E05CE00872C98 /* ServerInfoResponse.m */; };
|
||||
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */; };
|
||||
FB9AFD401A7E127D00872C98 /* AppListResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3F1A7E127D00872C98 /* AppListResponse.m */; };
|
||||
FB9AFD431A7F0C6900872C98 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD421A7F0C6900872C98 /* Controller.m */; };
|
||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
|
||||
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
|
||||
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495219FF36FB002D2A60 /* SWRevealViewController.m */; };
|
||||
@@ -265,6 +266,8 @@
|
||||
FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppAssetResponse.m; sourceTree = "<group>"; };
|
||||
FB9AFD3E1A7E127D00872C98 /* AppListResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppListResponse.h; sourceTree = "<group>"; };
|
||||
FB9AFD3F1A7E127D00872C98 /* AppListResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppListResponse.m; sourceTree = "<group>"; };
|
||||
FB9AFD411A7F0C6900872C98 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
|
||||
FB9AFD421A7F0C6900872C98 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
|
||||
FBD3494119FC9C04002D2A60 /* AppAssetManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppAssetManager.h; sourceTree = "<group>"; };
|
||||
FBD3494219FC9C04002D2A60 /* AppAssetManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppAssetManager.m; sourceTree = "<group>"; };
|
||||
FBD3494E19FF2174002D2A60 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = "<group>"; };
|
||||
@@ -460,6 +463,8 @@
|
||||
children = (
|
||||
FB89460A19F646E200339C8A /* ControllerSupport.h */,
|
||||
FB89460B19F646E200339C8A /* ControllerSupport.m */,
|
||||
FB9AFD411A7F0C6900872C98 /* Controller.h */,
|
||||
FB9AFD421A7F0C6900872C98 /* Controller.m */,
|
||||
FB89460C19F646E200339C8A /* StreamView.h */,
|
||||
FB89460D19F646E200339C8A /* StreamView.m */,
|
||||
FB4678EB1A50C40900377732 /* OnScreenControls.h */,
|
||||
@@ -894,6 +899,7 @@
|
||||
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,
|
||||
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */,
|
||||
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
||||
FB9AFD431A7F0C6900872C98 /* Controller.m in Sources */,
|
||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */,
|
||||
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */,
|
||||
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
|
||||
|
||||
22
Limelight/Input/Controller.h
Normal file
22
Limelight/Input/Controller.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Controller.h
|
||||
// Limelight
|
||||
//
|
||||
// Created by Diego Waxemberg on 2/1/15.
|
||||
// Copyright (c) 2015 Limelight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Controller : NSObject
|
||||
|
||||
@property (nonatomic) int playerIndex;
|
||||
@property (nonatomic) int lastButtonFlags;
|
||||
@property (nonatomic) char lastLeftTrigger;
|
||||
@property (nonatomic) char lastRightTrigger;
|
||||
@property (nonatomic) short lastLeftStickX;
|
||||
@property (nonatomic) short lastLeftStickY;
|
||||
@property (nonatomic) short lastRightStickX;
|
||||
@property (nonatomic) short lastRightStickY;
|
||||
|
||||
@end
|
||||
15
Limelight/Input/Controller.m
Normal file
15
Limelight/Input/Controller.m
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Controller.m
|
||||
// Limelight
|
||||
//
|
||||
// Created by Diego Waxemberg on 2/1/15.
|
||||
// Copyright (c) 2015 Limelight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Controller.h"
|
||||
|
||||
@implementation Controller
|
||||
@synthesize playerIndex;
|
||||
@synthesize lastButtonFlags, lastLeftTrigger, lastRightTrigger;
|
||||
@synthesize lastLeftStickX, lastLeftStickY, lastRightStickX, lastRightStickY;
|
||||
@end
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Controller.h"
|
||||
|
||||
@class OnScreenControls;
|
||||
|
||||
@@ -16,18 +17,18 @@
|
||||
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc;
|
||||
-(void) cleanup;
|
||||
|
||||
-(void) updateLeftStick:(short)x y:(short)y;
|
||||
-(void) updateRightStick:(short)x y:(short)y;
|
||||
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y;
|
||||
-(void) updateRightStick:(Controller*)controller x:(short)x y:(short)y;
|
||||
|
||||
-(void) updateLeftTrigger:(char)left;
|
||||
-(void) updateRightTrigger:(char)right;
|
||||
-(void) updateTriggers:(char)left right:(char)right;
|
||||
-(void) updateLeftTrigger:(Controller*)controller left:(char)left;
|
||||
-(void) updateRightTrigger:(Controller*)controller right:(char)right;
|
||||
-(void) updateTriggers:(Controller*)controller left:(char)left right:(char)right;
|
||||
|
||||
-(void) updateButtonFlags:(int)flags;
|
||||
-(void) setButtonFlag:(int)flags;
|
||||
-(void) clearButtonFlag:(int)flags;
|
||||
-(void) updateButtonFlags:(Controller*)controller flags:(int)flags;
|
||||
-(void) setButtonFlag:(Controller*)controller flags:(int)flags;
|
||||
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags;
|
||||
|
||||
-(void) updateFinished;
|
||||
-(void) updateFinished:(Controller*)controller;
|
||||
|
||||
@property (nonatomic, strong) id connectObserver;
|
||||
@property (nonatomic, strong) id disconnectObserver;
|
||||
|
||||
@@ -8,20 +8,18 @@
|
||||
|
||||
#import "ControllerSupport.h"
|
||||
#import "OnScreenControls.h"
|
||||
#import "Controller.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
@import GameController;
|
||||
|
||||
@implementation ControllerSupport {
|
||||
NSLock *_controllerValueLock;
|
||||
NSLock *_controllerStreamLock;
|
||||
NSMutableDictionary *_controllers;
|
||||
|
||||
OnScreenControls *_osc;
|
||||
|
||||
int _lastButtonFlags;
|
||||
char _lastLeftTrigger, _lastRightTrigger;
|
||||
short _lastLeftStickX, _lastLeftStickY;
|
||||
short _lastRightStickX, _lastRightStickY;
|
||||
char _controllerNumbers;
|
||||
|
||||
#define EMULATING_SELECT 0x1
|
||||
#define EMULATING_SPECIAL 0x2
|
||||
@@ -29,122 +27,121 @@
|
||||
}
|
||||
|
||||
// UPDATE_BUTTON_FLAG(flag, pressed)
|
||||
#define UPDATE_BUTTON_FLAG(x, y) \
|
||||
((y) ? [self setButtonFlag:x] : [self clearButtonFlag:x])
|
||||
#define UPDATE_BUTTON_FLAG(controller, x, y) \
|
||||
((y) ? [self setButtonFlag:controller flags:x] : [self clearButtonFlag:controller flags:x])
|
||||
|
||||
-(void) updateLeftStick:(short)x y:(short)y
|
||||
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftStickX = x;
|
||||
_lastLeftStickY = y;
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastLeftStickX = x;
|
||||
controller.lastLeftStickY = y;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateRightStick:(short)x y:(short)y
|
||||
-(void) updateRightStick:(Controller*)controller x:(short)x y:(short)y
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastRightStickX = x;
|
||||
_lastRightStickY = y;
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastRightStickX = x;
|
||||
controller.lastRightStickY = y;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateLeftTrigger:(char)left
|
||||
-(void) updateLeftTrigger:(Controller*)controller left:(char)left
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftTrigger = left;
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastLeftTrigger = left;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateRightTrigger:(char)right
|
||||
-(void) updateRightTrigger:(Controller*)controller right:(char)right
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastRightTrigger = right;
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastRightTrigger = right;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateTriggers:(char)left right:(char)right
|
||||
-(void) updateTriggers:(Controller*) controller left:(char)left right:(char)right
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftTrigger = left;
|
||||
_lastRightTrigger = right;
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastLeftTrigger = left;
|
||||
controller.lastRightTrigger = right;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) handleSpecialCombosReleased:(int)releasedButtons
|
||||
-(void) handleSpecialCombosReleased:(Controller*)controller releasedButtons:(int)releasedButtons
|
||||
{
|
||||
if ((_emulatingButtonFlags & EMULATING_SELECT) &&
|
||||
((releasedButtons & LB_FLAG) || (releasedButtons & PLAY_FLAG))) {
|
||||
_lastButtonFlags &= ~BACK_FLAG;
|
||||
controller.lastButtonFlags &= ~BACK_FLAG;
|
||||
_emulatingButtonFlags &= ~EMULATING_SELECT;
|
||||
}
|
||||
if ((_emulatingButtonFlags & EMULATING_SPECIAL) &&
|
||||
((releasedButtons & RB_FLAG) || (releasedButtons & PLAY_FLAG) ||
|
||||
(releasedButtons & BACK_FLAG))) {
|
||||
_lastButtonFlags &= ~SPECIAL_FLAG;
|
||||
_emulatingButtonFlags &= ~EMULATING_SPECIAL;
|
||||
}
|
||||
controller.lastButtonFlags &= ~SPECIAL_FLAG;
|
||||
_emulatingButtonFlags &= ~EMULATING_SPECIAL;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) handleSpecialCombosPressed:(int)pressedButtons
|
||||
-(void) handleSpecialCombosPressed:(Controller*)controller pressedButtons:(int)pressedButtons
|
||||
{
|
||||
// Special button combos for select and special
|
||||
if (_lastButtonFlags & PLAY_FLAG) {
|
||||
if (controller.lastButtonFlags & PLAY_FLAG) {
|
||||
// If LB and start are down, trigger select
|
||||
if (_lastButtonFlags & LB_FLAG) {
|
||||
_lastButtonFlags |= BACK_FLAG;
|
||||
_lastButtonFlags &= ~(pressedButtons & (PLAY_FLAG | LB_FLAG));
|
||||
if (controller.lastButtonFlags & LB_FLAG) {
|
||||
controller.lastButtonFlags |= BACK_FLAG;
|
||||
controller.lastButtonFlags &= ~(pressedButtons & (PLAY_FLAG | LB_FLAG));
|
||||
_emulatingButtonFlags |= EMULATING_SELECT;
|
||||
}
|
||||
// If (RB or select) and start are down, trigger special
|
||||
else if ((_lastButtonFlags & RB_FLAG) || (_lastButtonFlags & BACK_FLAG)) {
|
||||
_lastButtonFlags |= SPECIAL_FLAG;
|
||||
_lastButtonFlags &= ~(pressedButtons & (PLAY_FLAG | RB_FLAG | BACK_FLAG));
|
||||
else if ((controller.lastButtonFlags & RB_FLAG) || (controller.lastButtonFlags & BACK_FLAG)) {
|
||||
controller.lastButtonFlags |= SPECIAL_FLAG;
|
||||
controller.lastButtonFlags &= ~(pressedButtons & (PLAY_FLAG | RB_FLAG | BACK_FLAG));
|
||||
_emulatingButtonFlags |= EMULATING_SPECIAL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-(void) updateButtonFlags:(int)flags
|
||||
-(void) updateButtonFlags:(Controller*)controller flags:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
int releasedButtons = (_lastButtonFlags ^ flags) & ~flags;
|
||||
int pressedButtons = (_lastButtonFlags ^ flags) & flags;
|
||||
|
||||
_lastButtonFlags = flags;
|
||||
|
||||
// This must be called before handleSpecialCombosPressed
|
||||
// because we clear the original button flags there
|
||||
[self handleSpecialCombosReleased: releasedButtons];
|
||||
|
||||
[self handleSpecialCombosPressed: pressedButtons];
|
||||
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
int releasedButtons = (controller.lastButtonFlags ^ flags) & ~flags;
|
||||
int pressedButtons = (controller.lastButtonFlags ^ flags) & flags;
|
||||
|
||||
controller.lastButtonFlags = flags;
|
||||
|
||||
// This must be called before handleSpecialCombosPressed
|
||||
// because we clear the original button flags there
|
||||
[self handleSpecialCombosReleased:controller releasedButtons:releasedButtons];
|
||||
|
||||
[self handleSpecialCombosPressed:controller pressedButtons:pressedButtons];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setButtonFlag:(int)flags
|
||||
-(void) setButtonFlag:(Controller*)controller flags:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastButtonFlags |= flags;
|
||||
[self handleSpecialCombosPressed: flags];
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastButtonFlags |= flags;
|
||||
[self handleSpecialCombosPressed:controller pressedButtons:flags];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) clearButtonFlag:(int)flags
|
||||
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastButtonFlags &= ~flags;
|
||||
[self handleSpecialCombosReleased: flags];
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
controller.lastButtonFlags &= ~flags;
|
||||
[self handleSpecialCombosReleased:controller releasedButtons:flags];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateFinished
|
||||
-(void) updateFinished:(Controller*)controller
|
||||
{
|
||||
[_controllerStreamLock lock];
|
||||
[_controllerValueLock lock];
|
||||
|
||||
LiSendControllerEvent(_lastButtonFlags, _lastLeftTrigger, _lastRightTrigger, _lastLeftStickX, _lastLeftStickY, _lastRightStickX, _lastRightStickY);
|
||||
|
||||
[_controllerValueLock unlock];
|
||||
@synchronized(controller) {
|
||||
LiSendControllerEvent(controller.lastButtonFlags, controller.lastLeftTrigger, controller.lastRightTrigger, controller.lastLeftStickX, controller.lastLeftStickY, controller.lastRightStickX, controller.lastRightStickY);
|
||||
}
|
||||
[_controllerStreamLock unlock];
|
||||
}
|
||||
|
||||
@@ -164,6 +161,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
[_controllers removeAllObjects];
|
||||
}
|
||||
|
||||
-(void) registerControllerCallbacks
|
||||
@@ -172,36 +170,37 @@
|
||||
GCController *controller = [GCController controllers][i];
|
||||
|
||||
if (controller != NULL) {
|
||||
NSLog(@"Controller connected!");
|
||||
controller.controllerPausedHandler = ^(GCController *controller) {
|
||||
[self setButtonFlag:PLAY_FLAG];
|
||||
[self updateFinished];
|
||||
Controller* limeController = [_controllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||
[self setButtonFlag:limeController flags:PLAY_FLAG];
|
||||
[self updateFinished:limeController];
|
||||
|
||||
// Pause for 100 ms
|
||||
usleep(100 * 1000);
|
||||
|
||||
[self clearButtonFlag:PLAY_FLAG];
|
||||
[self updateFinished];
|
||||
[self clearButtonFlag:limeController flags:PLAY_FLAG];
|
||||
[self updateFinished:limeController];
|
||||
};
|
||||
|
||||
if (controller.extendedGamepad != NULL) {
|
||||
controller.extendedGamepad.valueChangedHandler = ^(GCExtendedGamepad *gamepad, GCControllerElement *element) {
|
||||
Controller* limeController = [_controllers objectForKey:[NSNumber numberWithInteger:gamepad.controller.playerIndex]];
|
||||
short leftStickX, leftStickY;
|
||||
short rightStickX, rightStickY;
|
||||
char leftTrigger, rightTrigger;
|
||||
|
||||
UPDATE_BUTTON_FLAG(A_FLAG, gamepad.buttonA.pressed);
|
||||
UPDATE_BUTTON_FLAG(B_FLAG, gamepad.buttonB.pressed);
|
||||
UPDATE_BUTTON_FLAG(X_FLAG, gamepad.buttonX.pressed);
|
||||
UPDATE_BUTTON_FLAG(Y_FLAG, gamepad.buttonY.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, A_FLAG, gamepad.buttonA.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, B_FLAG, gamepad.buttonB.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, X_FLAG, gamepad.buttonX.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, Y_FLAG, gamepad.buttonY.pressed);
|
||||
|
||||
UPDATE_BUTTON_FLAG(UP_FLAG, gamepad.dpad.up.pressed);
|
||||
UPDATE_BUTTON_FLAG(DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||
UPDATE_BUTTON_FLAG(LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||
UPDATE_BUTTON_FLAG(RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, UP_FLAG, gamepad.dpad.up.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||
|
||||
UPDATE_BUTTON_FLAG(LB_FLAG, gamepad.leftShoulder.pressed);
|
||||
UPDATE_BUTTON_FLAG(RB_FLAG, gamepad.rightShoulder.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, LB_FLAG, gamepad.leftShoulder.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, RB_FLAG, gamepad.rightShoulder.pressed);
|
||||
|
||||
leftStickX = gamepad.leftThumbstick.xAxis.value * 0x7FFE;
|
||||
leftStickY = gamepad.leftThumbstick.yAxis.value * 0x7FFE;
|
||||
@@ -212,34 +211,34 @@
|
||||
leftTrigger = gamepad.leftTrigger.value * 0xFF;
|
||||
rightTrigger = gamepad.rightTrigger.value * 0xFF;
|
||||
|
||||
[self updateLeftStick:leftStickX y:leftStickY];
|
||||
[self updateRightStick:rightStickX y:rightStickY];
|
||||
[self updateTriggers:leftTrigger right:rightTrigger];
|
||||
[self updateFinished];
|
||||
[self updateLeftStick:limeController x:leftStickX y:leftStickY];
|
||||
[self updateRightStick:limeController x:rightStickX y:rightStickY];
|
||||
[self updateTriggers:limeController left:leftTrigger right:rightTrigger];
|
||||
[self updateFinished:limeController];
|
||||
};
|
||||
}
|
||||
else if (controller.gamepad != NULL) {
|
||||
controller.gamepad.valueChangedHandler = ^(GCGamepad *gamepad, GCControllerElement *element) {
|
||||
Controller* limeController = [_controllers objectForKey:[NSNumber numberWithInteger:gamepad.controller.playerIndex]];
|
||||
UPDATE_BUTTON_FLAG(limeController, A_FLAG, gamepad.buttonA.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, B_FLAG, gamepad.buttonB.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, X_FLAG, gamepad.buttonX.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, Y_FLAG, gamepad.buttonY.pressed);
|
||||
|
||||
UPDATE_BUTTON_FLAG(A_FLAG, gamepad.buttonA.pressed);
|
||||
UPDATE_BUTTON_FLAG(B_FLAG, gamepad.buttonB.pressed);
|
||||
UPDATE_BUTTON_FLAG(X_FLAG, gamepad.buttonX.pressed);
|
||||
UPDATE_BUTTON_FLAG(Y_FLAG, gamepad.buttonY.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, UP_FLAG, gamepad.dpad.up.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||
|
||||
UPDATE_BUTTON_FLAG(UP_FLAG, gamepad.dpad.up.pressed);
|
||||
UPDATE_BUTTON_FLAG(DOWN_FLAG, gamepad.dpad.down.pressed);
|
||||
UPDATE_BUTTON_FLAG(LEFT_FLAG, gamepad.dpad.left.pressed);
|
||||
UPDATE_BUTTON_FLAG(RIGHT_FLAG, gamepad.dpad.right.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, LB_FLAG, gamepad.leftShoulder.pressed);
|
||||
UPDATE_BUTTON_FLAG(limeController, RB_FLAG, gamepad.rightShoulder.pressed);
|
||||
|
||||
UPDATE_BUTTON_FLAG(LB_FLAG, gamepad.leftShoulder.pressed);
|
||||
UPDATE_BUTTON_FLAG(RB_FLAG, gamepad.rightShoulder.pressed);
|
||||
|
||||
[self updateFinished];
|
||||
[self updateFinished:limeController];
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
-(void) updateAutoOnScreenControlMode
|
||||
@@ -278,14 +277,40 @@
|
||||
[self updateAutoOnScreenControlMode];
|
||||
}
|
||||
|
||||
-(void) assignController:(GCController*)controller {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(_controllerNumbers & (1 << i))) {
|
||||
_controllerNumbers |= (1 << i);
|
||||
Controller* limeController = [[Controller alloc] init];
|
||||
controller.playerIndex = i;
|
||||
limeController.playerIndex = i;
|
||||
[_controllers setObject:limeController forKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||
|
||||
NSLog(@"Assigning controller index: %d", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(id) init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
_controllerStreamLock = [[NSLock alloc] init];
|
||||
_controllerValueLock = [[NSLock alloc] init];
|
||||
_controllers = [[NSMutableDictionary alloc] init];
|
||||
_controllerNumbers = 0;
|
||||
|
||||
NSLog(@"Number of controllers connected: %ld", [[GCController controllers] count]);
|
||||
for (GCController* controller in [GCController controllers]) {
|
||||
[self assignController:controller];
|
||||
}
|
||||
|
||||
self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
NSLog(@"Controller connected!");
|
||||
|
||||
GCController* controller = (GCController*) note.object;
|
||||
[self assignController:controller];
|
||||
|
||||
// Register callbacks on the new controller
|
||||
[self registerControllerCallbacks];
|
||||
|
||||
@@ -295,12 +320,10 @@
|
||||
self.disconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
NSLog(@"Controller disconnected!");
|
||||
|
||||
// Reset all controller state to be safe
|
||||
[self updateButtonFlags:0];
|
||||
[self updateLeftStick:0 y:0];
|
||||
[self updateRightStick:0 y:0];
|
||||
[self updateTriggers:0 right:0];
|
||||
[self updateFinished];
|
||||
GCController* controller = note.object;
|
||||
[_controllers removeObjectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||
_controllerNumbers &= ~(1 << controller.playerIndex);
|
||||
NSLog(@"Unassigning controller index: %ld", (long)controller.playerIndex);
|
||||
|
||||
// Re-evaluate the on-screen control mode
|
||||
[self updateAutoOnScreenControlMode];
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#import "OnScreenControls.h"
|
||||
#import "ControllerSupport.h"
|
||||
#import "Controller.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||
@@ -64,6 +65,7 @@
|
||||
OnScreenControlsLevel _level;
|
||||
|
||||
ControllerSupport *_controllerSupport;
|
||||
Controller *_controller;
|
||||
}
|
||||
|
||||
static const float BUTTON_SIZE = 50;
|
||||
@@ -117,6 +119,8 @@ static float L3_Y;
|
||||
self = [self init];
|
||||
_view = view;
|
||||
_controllerSupport = controllerSupport;
|
||||
_controller = [[Controller alloc] init];
|
||||
_controller.playerIndex = 0;
|
||||
|
||||
_aButton = [CALayer layer];
|
||||
_bButton = [CALayer layer];
|
||||
@@ -449,7 +453,7 @@ static float L3_Y;
|
||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||
|
||||
[_controllerSupport updateLeftStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
[_controllerSupport updateLeftStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
|
||||
updated = true;
|
||||
} else if (touch == _rsTouch) {
|
||||
@@ -466,7 +470,7 @@ static float L3_Y;
|
||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||
|
||||
[_controllerSupport updateRightStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
[_controllerSupport updateRightStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
|
||||
updated = true;
|
||||
} else if (touch == _aTouch) {
|
||||
@@ -504,7 +508,7 @@ static float L3_Y;
|
||||
}
|
||||
}
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
[_controllerSupport updateFinished:_controller];
|
||||
}
|
||||
return updated || buttonTouch;
|
||||
}
|
||||
@@ -516,67 +520,67 @@ static float L3_Y;
|
||||
CGPoint touchLocation = [touch locationInView:_view];
|
||||
|
||||
if ([_aButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:A_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:A_FLAG];
|
||||
_aTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_bButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:B_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:B_FLAG];
|
||||
_bTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_xButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:X_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:X_FLAG];
|
||||
_xTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_yButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:Y_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:Y_FLAG];
|
||||
_yTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:UP_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:UP_FLAG];
|
||||
_upTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:DOWN_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:DOWN_FLAG];
|
||||
_downTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:LEFT_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:LEFT_FLAG];
|
||||
_leftTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:RIGHT_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:RIGHT_FLAG];
|
||||
_rightTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_startButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:PLAY_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:PLAY_FLAG];
|
||||
_startTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_selectButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:BACK_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:BACK_FLAG];
|
||||
_selectTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_l1Button.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:LB_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:LB_FLAG];
|
||||
_l1Touch = touch;
|
||||
updated = true;
|
||||
} else if ([_r1Button.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:RB_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:RB_FLAG];
|
||||
_r1Touch = touch;
|
||||
updated = true;
|
||||
} else if ([_l2Button.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport updateLeftTrigger:0xFF];
|
||||
[_controllerSupport updateLeftTrigger:_controller left:0xFF];
|
||||
_l2Touch = touch;
|
||||
updated = true;
|
||||
} else if ([_r2Button.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport updateRightTrigger:0xFF];
|
||||
[_controllerSupport updateRightTrigger:_controller right:0xFF];
|
||||
_r2Touch = touch;
|
||||
updated = true;
|
||||
} else if ([_l3Button.presentationLayer hitTest:touchLocation]) {
|
||||
if (l3Set) {
|
||||
[_controllerSupport clearButtonFlag:LS_CLK_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:LS_CLK_FLAG];
|
||||
_l3Button.borderWidth = 0.0f;
|
||||
} else {
|
||||
[_controllerSupport setButtonFlag:LS_CLK_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:LS_CLK_FLAG];
|
||||
_l3Button.borderWidth = 2.0f;
|
||||
}
|
||||
l3Set = !l3Set;
|
||||
@@ -584,10 +588,10 @@ static float L3_Y;
|
||||
updated = true;
|
||||
} else if ([_r3Button.presentationLayer hitTest:touchLocation]) {
|
||||
if (r3Set) {
|
||||
[_controllerSupport clearButtonFlag:RS_CLK_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:RS_CLK_FLAG];
|
||||
_r3Button.borderWidth = 0.0f;
|
||||
} else {
|
||||
[_controllerSupport setButtonFlag:RS_CLK_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:RS_CLK_FLAG];
|
||||
_r3Button.borderWidth = 2.0f;
|
||||
}
|
||||
r3Set = !r3Set;
|
||||
@@ -599,7 +603,7 @@ static float L3_Y;
|
||||
// Use (-) modifier to conversion since receiver is earlier than now
|
||||
double l3TouchTime = [l3TouchStart timeIntervalSinceNow] * -1000.0;
|
||||
if (l3TouchTime < STICK_CLICK_RATE) {
|
||||
[_controllerSupport setButtonFlag:LS_CLK_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:LS_CLK_FLAG];
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@@ -611,7 +615,7 @@ static float L3_Y;
|
||||
// Use (-) modifier to conversion since receiver is earlier than now
|
||||
double r3TouchTime = [r3TouchStart timeIntervalSinceNow] * -1000.0;
|
||||
if (r3TouchTime < STICK_CLICK_RATE) {
|
||||
[_controllerSupport setButtonFlag:RS_CLK_FLAG];
|
||||
[_controllerSupport setButtonFlag:_controller flags:RS_CLK_FLAG];
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@@ -620,7 +624,7 @@ static float L3_Y;
|
||||
}
|
||||
}
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
[_controllerSupport updateFinished:_controller];
|
||||
}
|
||||
return updated || stickTouch;
|
||||
}
|
||||
@@ -630,72 +634,72 @@ static float L3_Y;
|
||||
BOOL touched = false;
|
||||
for (UITouch* touch in touches) {
|
||||
if (touch == _aTouch) {
|
||||
[_controllerSupport clearButtonFlag:A_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:A_FLAG];
|
||||
_aTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _bTouch) {
|
||||
[_controllerSupport clearButtonFlag:B_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:B_FLAG];
|
||||
_bTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _xTouch) {
|
||||
[_controllerSupport clearButtonFlag:X_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:X_FLAG];
|
||||
_xTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _yTouch) {
|
||||
[_controllerSupport clearButtonFlag:Y_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:Y_FLAG];
|
||||
_yTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _upTouch) {
|
||||
[_controllerSupport clearButtonFlag:UP_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:UP_FLAG];
|
||||
_upTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _downTouch) {
|
||||
[_controllerSupport clearButtonFlag:DOWN_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:DOWN_FLAG];
|
||||
_downTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _leftTouch) {
|
||||
[_controllerSupport clearButtonFlag:LEFT_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:LEFT_FLAG];
|
||||
_leftTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _rightTouch) {
|
||||
[_controllerSupport clearButtonFlag:RIGHT_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:RIGHT_FLAG];
|
||||
_rightTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _startTouch) {
|
||||
[_controllerSupport clearButtonFlag:PLAY_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:PLAY_FLAG];
|
||||
_startTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _selectTouch) {
|
||||
[_controllerSupport clearButtonFlag:BACK_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:BACK_FLAG];
|
||||
_selectTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _l1Touch) {
|
||||
[_controllerSupport clearButtonFlag:LB_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:LB_FLAG];
|
||||
_l1Touch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _r1Touch) {
|
||||
[_controllerSupport clearButtonFlag:RB_FLAG];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:RB_FLAG];
|
||||
_r1Touch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _l2Touch) {
|
||||
[_controllerSupport updateLeftTrigger:0];
|
||||
[_controllerSupport updateLeftTrigger:_controller left:0];
|
||||
_l2Touch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _r2Touch) {
|
||||
[_controllerSupport updateRightTrigger:0];
|
||||
[_controllerSupport updateRightTrigger:_controller right:0];
|
||||
_r2Touch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _lsTouch) {
|
||||
_leftStick.frame = CGRectMake(LS_CENTER_X - STICK_INNER_SIZE / 2, LS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
||||
[_controllerSupport updateLeftStick:0 y:0];
|
||||
[_controllerSupport clearButtonFlag:LS_CLK_FLAG];
|
||||
[_controllerSupport updateLeftStick:_controller x:0 y:0];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:LS_CLK_FLAG];
|
||||
l3TouchStart = [NSDate date];
|
||||
_lsTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _rsTouch) {
|
||||
_rightStick.frame = CGRectMake(RS_CENTER_X - STICK_INNER_SIZE / 2, RS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
||||
[_controllerSupport updateRightStick:0 y:0];
|
||||
[_controllerSupport clearButtonFlag:RS_CLK_FLAG];
|
||||
[_controllerSupport updateRightStick:_controller x:0 y:0];
|
||||
[_controllerSupport clearButtonFlag:_controller flags:RS_CLK_FLAG];
|
||||
r3TouchStart = [NSDate date];
|
||||
_rsTouch = nil;
|
||||
updated = true;
|
||||
@@ -710,7 +714,7 @@ static float L3_Y;
|
||||
}
|
||||
}
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
[_controllerSupport updateFinished:_controller];
|
||||
}
|
||||
return updated || touched;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
}
|
||||
|
||||
- (void) returnToMainFrame {
|
||||
[_controllerSupport cleanup];
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
|
||||
Submodule limelight-common-c updated: 0fa1a02e0a...975be33ff8
Reference in New Issue
Block a user