mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2025-07-01 23:35:59 +00:00
Rewrote a bunch of controller support. Added auto on-screen controls layouts (GCGamepad not finished). Added LB+Start and RB+Start shortcuts for select and special (same as Android).
This commit is contained in:
parent
afb7e930ee
commit
cdaf98398c
@ -8,12 +8,27 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OnScreenControls;
|
||||
|
||||
@interface ControllerSupport : NSObject
|
||||
|
||||
-(id) init;
|
||||
|
||||
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc;
|
||||
-(void) cleanup;
|
||||
|
||||
-(void) updateLeftStick:(short)x y:(short)y;
|
||||
-(void) updateRightStick:(short)x y:(short)y;
|
||||
|
||||
-(void) updateLeftTrigger:(char)left;
|
||||
-(void) updateRightTrigger:(char)right;
|
||||
-(void) updateTriggers:(char)left right:(char)right;
|
||||
|
||||
-(void) updateButtonFlags:(int)flags;
|
||||
-(void) setButtonFlag:(int)flags;
|
||||
-(void) clearButtonFlag:(int)flags;
|
||||
|
||||
-(void) updateFinished;
|
||||
|
||||
@property (nonatomic, strong) id connectObserver;
|
||||
@property (nonatomic, strong) id disconnectObserver;
|
||||
|
||||
|
@ -7,19 +7,166 @@
|
||||
//
|
||||
|
||||
#import "ControllerSupport.h"
|
||||
#import "OnScreenControls.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
@import GameController;
|
||||
|
||||
@implementation ControllerSupport
|
||||
@implementation ControllerSupport {
|
||||
NSLock *_controllerValueLock;
|
||||
NSLock *_controllerStreamLock;
|
||||
|
||||
OnScreenControls *_osc;
|
||||
|
||||
int _lastButtonFlags;
|
||||
char _lastLeftTrigger, _lastRightTrigger;
|
||||
short _lastLeftStickX, _lastLeftStickY;
|
||||
short _lastRightStickX, _lastRightStickY;
|
||||
|
||||
#define EMULATING_SELECT 0x1
|
||||
#define EMULATING_SPECIAL 0x2
|
||||
int _emulatingButtonFlags;
|
||||
}
|
||||
|
||||
// UPDATE_BUTTON(flag, pressed)
|
||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
||||
|
||||
static NSLock *controllerStreamLock;
|
||||
-(void) updateLeftStick:(short)x y:(short)y
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftStickX = x;
|
||||
_lastLeftStickY = y;
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
+(void) registerControllerCallbacks
|
||||
-(void) updateRightStick:(short)x y:(short)y
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastRightStickX = x;
|
||||
_lastRightStickY = y;
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) updateLeftTrigger:(char)left
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftTrigger = left;
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) updateRightTrigger:(char)right
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastRightTrigger = right;
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) updateTriggers:(char)left right:(char)right
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastLeftTrigger = left;
|
||||
_lastRightTrigger = right;
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) handleSpecialCombosReleased:(int)releasedButtons
|
||||
{
|
||||
if (releasedButtons & PLAY_FLAG) {
|
||||
if ((_emulatingButtonFlags & EMULATING_SELECT) &&
|
||||
(releasedButtons & LB_FLAG)) {
|
||||
_lastButtonFlags &= ~BACK_FLAG;
|
||||
_emulatingButtonFlags &= ~EMULATING_SELECT;
|
||||
}
|
||||
if ((_emulatingButtonFlags & EMULATING_SPECIAL) &&
|
||||
(releasedButtons & RB_FLAG)) {
|
||||
_lastButtonFlags &= ~SPECIAL_FLAG;
|
||||
_emulatingButtonFlags &= ~EMULATING_SPECIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) handleSpecialCombosPressed
|
||||
{
|
||||
// Special button combos for select and special
|
||||
if (_lastButtonFlags & PLAY_FLAG) {
|
||||
// If LB and start are down, trigger select
|
||||
if (_lastButtonFlags & LB_FLAG) {
|
||||
_lastButtonFlags |= BACK_FLAG;
|
||||
_lastButtonFlags &= ~(PLAY_FLAG | LB_FLAG);
|
||||
_emulatingButtonFlags |= EMULATING_SELECT;
|
||||
}
|
||||
// If RB and start are down, trigger special
|
||||
else if (_lastButtonFlags & RB_FLAG) {
|
||||
_lastButtonFlags |= SPECIAL_FLAG;
|
||||
_lastButtonFlags &= ~(PLAY_FLAG | RB_FLAG);
|
||||
_emulatingButtonFlags |= EMULATING_SPECIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateButtonFlags:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
int releasedButtons = (_lastButtonFlags ^ flags) & ~flags;
|
||||
|
||||
_lastButtonFlags = flags;
|
||||
|
||||
// This must be called before handleSpecialCombosPressed
|
||||
// because we clear the original button flags there
|
||||
[self handleSpecialCombosReleased: releasedButtons];
|
||||
|
||||
[self handleSpecialCombosPressed];
|
||||
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) setButtonFlag:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastButtonFlags |= flags;
|
||||
[self handleSpecialCombosPressed];
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) clearButtonFlag:(int)flags
|
||||
{
|
||||
[_controllerValueLock lock];
|
||||
_lastButtonFlags &= ~flags;
|
||||
[self handleSpecialCombosReleased: flags];
|
||||
[_controllerValueLock unlock];
|
||||
}
|
||||
|
||||
-(void) updateFinished
|
||||
{
|
||||
[_controllerStreamLock lock];
|
||||
[_controllerValueLock lock];
|
||||
|
||||
LiSendControllerEvent(_lastButtonFlags, _lastLeftTrigger, _lastRightTrigger, _lastLeftStickX, _lastLeftStickY, _lastRightStickX, _lastRightStickY);
|
||||
|
||||
[_controllerValueLock unlock];
|
||||
[_controllerStreamLock unlock];
|
||||
}
|
||||
|
||||
-(void) unregisterControllerCallbacks
|
||||
{
|
||||
for (int i = 0; i < [[GCController controllers] count]; i++) {
|
||||
GCController *controller = [GCController controllers][i];
|
||||
|
||||
if (controller != NULL) {
|
||||
controller.controllerPausedHandler = NULL;
|
||||
|
||||
if (controller.extendedGamepad != NULL) {
|
||||
controller.extendedGamepad.valueChangedHandler = NULL;
|
||||
}
|
||||
else if (controller.gamepad != NULL) {
|
||||
controller.gamepad.valueChangedHandler = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) registerControllerCallbacks
|
||||
{
|
||||
for (int i = 0; i < [[GCController controllers] count]; i++) {
|
||||
GCController *controller = [GCController controllers][i];
|
||||
@ -27,16 +174,14 @@ static NSLock *controllerStreamLock;
|
||||
if (controller != NULL) {
|
||||
NSLog(@"Controller connected!");
|
||||
controller.controllerPausedHandler = ^(GCController *controller) {
|
||||
// We call LiSendControllerEvent while holding a lock to prevent
|
||||
// multiple simultaneous calls since this function isn't thread safe.
|
||||
[controllerStreamLock lock];
|
||||
LiSendControllerEvent(PLAY_FLAG, 0, 0, 0, 0, 0, 0);
|
||||
[self setButtonFlag:PLAY_FLAG];
|
||||
[self updateFinished];
|
||||
|
||||
// Pause for 100 ms
|
||||
usleep(100 * 1000);
|
||||
|
||||
LiSendControllerEvent(0, 0, 0, 0, 0, 0, 0);
|
||||
[controllerStreamLock unlock];
|
||||
[self clearButtonFlag:PLAY_FLAG];
|
||||
[self updateFinished];
|
||||
};
|
||||
|
||||
if (controller.extendedGamepad != NULL) {
|
||||
@ -68,12 +213,11 @@ static NSLock *controllerStreamLock;
|
||||
leftTrigger = gamepad.leftTrigger.value * 0xFF;
|
||||
rightTrigger = gamepad.rightTrigger.value * 0xFF;
|
||||
|
||||
// We call LiSendControllerEvent while holding a lock to prevent
|
||||
// multiple simultaneous calls since this function isn't thread safe.
|
||||
[controllerStreamLock lock];
|
||||
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
[controllerStreamLock unlock];
|
||||
[self updateButtonFlags:buttonFlags];
|
||||
[self updateLeftStick:leftStickX y:leftStickY];
|
||||
[self updateRightStick:rightStickX y:rightStickY];
|
||||
[self updateTriggers:leftTrigger right:rightTrigger];
|
||||
[self updateFinished];
|
||||
};
|
||||
}
|
||||
else if (controller.gamepad != NULL) {
|
||||
@ -93,11 +237,8 @@ static NSLock *controllerStreamLock;
|
||||
UPDATE_BUTTON(LB_FLAG, gamepad.leftShoulder.pressed);
|
||||
UPDATE_BUTTON(RB_FLAG, gamepad.rightShoulder.pressed);
|
||||
|
||||
// We call LiSendControllerEvent while holding a lock to prevent
|
||||
// multiple simultaneous calls since this function isn't thread safe.
|
||||
[controllerStreamLock lock];
|
||||
LiSendControllerEvent(buttonFlags, 0, 0, 0, 0, 0, 0);
|
||||
[controllerStreamLock unlock];
|
||||
[self updateButtonFlags:buttonFlags];
|
||||
[self updateFinished];
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -105,22 +246,72 @@ static NSLock *controllerStreamLock;
|
||||
|
||||
}
|
||||
|
||||
-(void) updateAutoOnScreenControlMode
|
||||
{
|
||||
// Auto on-screen control support may not be enabled
|
||||
if (_osc == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnScreenControlsLevel level = OnScreenControlsLevelFull;
|
||||
|
||||
// We currently stop after the first controller we find.
|
||||
// Maybe we'll want to change that logic later.
|
||||
for (int i = 0; i < [[GCController controllers] count]; i++) {
|
||||
GCController *controller = [GCController controllers][i];
|
||||
|
||||
if (controller != NULL) {
|
||||
if (controller.extendedGamepad != NULL) {
|
||||
level = OnScreenControlsLevelAutoGCExtendedGamepad;
|
||||
break;
|
||||
}
|
||||
else if (controller.gamepad != NULL) {
|
||||
level = OnScreenControlsLevelAutoGCGamepad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[_osc setLevel:level];
|
||||
}
|
||||
|
||||
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc
|
||||
{
|
||||
_osc = osc;
|
||||
|
||||
[self updateAutoOnScreenControlMode];
|
||||
}
|
||||
|
||||
-(id) init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (controllerStreamLock == NULL) {
|
||||
controllerStreamLock = [[NSLock alloc] init];
|
||||
}
|
||||
_controllerStreamLock = [[NSLock alloc] init];
|
||||
_controllerValueLock = [[NSLock alloc] init];
|
||||
|
||||
self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[ControllerSupport registerControllerCallbacks];
|
||||
// Register callbacks on the new controller
|
||||
[self registerControllerCallbacks];
|
||||
|
||||
// Re-evaluate the on-screen control mode
|
||||
[self updateAutoOnScreenControlMode];
|
||||
}];
|
||||
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];
|
||||
|
||||
// Re-evaluate the on-screen control mode
|
||||
[self updateAutoOnScreenControlMode];
|
||||
}];
|
||||
|
||||
[ControllerSupport registerControllerCallbacks];
|
||||
// Register for controller callbacks on any existing controllers
|
||||
[self registerControllerCallbacks];
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -129,6 +320,8 @@ static NSLock *controllerStreamLock;
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.connectObserver];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self.disconnectObserver];
|
||||
|
||||
[self unregisterControllerCallbacks];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -8,15 +8,22 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ControllerSupport;
|
||||
|
||||
@interface OnScreenControls : NSObject
|
||||
|
||||
typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
|
||||
OnScreenControlsLevelOff,
|
||||
OnScreenControlsLevelAuto,
|
||||
OnScreenControlsLevelSimple,
|
||||
OnScreenControlsLevelFull
|
||||
OnScreenControlsLevelFull,
|
||||
|
||||
// Internal levels selected by ControllerSupport
|
||||
OnScreenControlsLevelAutoGCGamepad,
|
||||
OnScreenControlsLevelAutoGCExtendedGamepad,
|
||||
};
|
||||
|
||||
- (id) initWithView:(UIView*)view;
|
||||
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport;
|
||||
- (BOOL) handleTouchDownEvent:(NSSet*)touches;
|
||||
- (BOOL) handleTouchUpEvent:(NSSet*)touches;
|
||||
- (BOOL) handleTouchMovedEvent:(NSSet*)touches;
|
||||
|
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "OnScreenControls.h"
|
||||
#import "ControllerSupport.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||
@ -31,11 +32,6 @@
|
||||
CALayer* _r2Button;
|
||||
CALayer* _l1Button;
|
||||
CALayer* _l2Button;
|
||||
|
||||
short buttonFlags;
|
||||
short leftStickX, leftStickY;
|
||||
short rightStickX, rightStickY;
|
||||
char leftTrigger, rightTrigger;
|
||||
|
||||
UITouch* _aTouch;
|
||||
UITouch* _bTouch;
|
||||
@ -56,6 +52,8 @@
|
||||
|
||||
UIView* _view;
|
||||
OnScreenControlsLevel _level;
|
||||
|
||||
ControllerSupport *_controllerSupport;
|
||||
}
|
||||
|
||||
static const float BUTTON_SIZE = 50;
|
||||
@ -99,33 +97,10 @@ static float L1_Y;
|
||||
static float L2_X;
|
||||
static float L2_Y;
|
||||
|
||||
- (id) initWithView:(UIView*)view {
|
||||
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport {
|
||||
self = [self init];
|
||||
_view = view;
|
||||
|
||||
D_PAD_CENTER_X = _view.frame.size.width * .15;
|
||||
D_PAD_CENTER_Y = _view.frame.size.height * .55;
|
||||
BUTTON_CENTER_X = _view.frame.size.width * .85;
|
||||
BUTTON_CENTER_Y = _view.frame.size.height * .55;
|
||||
|
||||
LS_CENTER_X = _view.frame.size.width * .35;
|
||||
LS_CENTER_Y = _view.frame.size.height * .75;
|
||||
RS_CENTER_X = _view.frame.size.width * .65;
|
||||
RS_CENTER_Y = _view.frame.size.height * .75;
|
||||
|
||||
START_X = _view.frame.size.width * .55;
|
||||
START_Y = _view.frame.size.height * .1;
|
||||
SELECT_X = _view.frame.size.width * .45;
|
||||
SELECT_Y = _view.frame.size.height * .1;
|
||||
|
||||
L1_X = _view.frame.size.width * .15;
|
||||
L1_Y = _view.frame.size.height * .25;
|
||||
L2_X = _view.frame.size.width * .15;
|
||||
L2_Y = _view.frame.size.height * .1;
|
||||
R1_X = _view.frame.size.width * .85;
|
||||
R1_Y = _view.frame.size.height * .25;
|
||||
R2_X = _view.frame.size.width * .85;
|
||||
R2_Y = _view.frame.size.height * .1;
|
||||
_controllerSupport = controllerSupport;
|
||||
|
||||
_aButton = [CALayer layer];
|
||||
_bButton = [CALayer layer];
|
||||
@ -163,8 +138,32 @@ static float L2_Y;
|
||||
[self hideStartSelect];
|
||||
[self hideSticks];
|
||||
break;
|
||||
case OnScreenControlsLevelAutoGCGamepad:
|
||||
// GCGamepad is missing triggers, both analog sticks,
|
||||
// and the select button
|
||||
[self setupGamepadControls];
|
||||
|
||||
[self hideButtons];
|
||||
[self hideBumpers];
|
||||
[self drawTriggers];
|
||||
[self drawStartSelect];
|
||||
[self drawSticks];
|
||||
// TODO: Draw L3 and R3 buttons
|
||||
break;
|
||||
case OnScreenControlsLevelAutoGCExtendedGamepad:
|
||||
// GCExtendedGamepad is missing R3, L3, and select
|
||||
[self setupExtendedGamepadControls];
|
||||
|
||||
[self hideButtons];
|
||||
[self hideBumpers];
|
||||
[self hideTriggers];
|
||||
[self drawStartSelect];
|
||||
[self hideSticks];
|
||||
// TODO: Draw L3 and R3 buttons
|
||||
break;
|
||||
case OnScreenControlsLevelSimple:
|
||||
[self setupSimpleControls];
|
||||
|
||||
[self drawTriggers];
|
||||
[self drawStartSelect];
|
||||
[self hideButtons];
|
||||
@ -172,25 +171,81 @@ static float L2_Y;
|
||||
[self hideSticks];
|
||||
break;
|
||||
case OnScreenControlsLevelFull:
|
||||
[self setupComplexControls];
|
||||
|
||||
[self drawButtons];
|
||||
[self drawStartSelect];
|
||||
[self drawBumpers];
|
||||
[self drawTriggers];
|
||||
[self drawSticks];
|
||||
break;
|
||||
default:
|
||||
NSLog(@"Unknown on-screen controls level: %d", (int)_level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For GCExtendedGamepad controls we move start, select, L3, and R3 to the button
|
||||
- (void) setupExtendedGamepadControls {
|
||||
// Start with the default complex layout
|
||||
[self setupComplexControls];
|
||||
|
||||
START_Y = _view.frame.size.height * .9;
|
||||
SELECT_Y = _view.frame.size.height * .9;
|
||||
|
||||
// TODO: Position L3 and R3 at the bottom of the screen
|
||||
}
|
||||
|
||||
// For GCGamepad controls we move triggers, start, and select
|
||||
// to sit right above the analog sticks
|
||||
- (void) setupGamepadControls {
|
||||
// Start with the default complex layout
|
||||
[self setupComplexControls];
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
// For simple controls we move the triggers and buttons to the bottom
|
||||
- (void) setupSimpleControls {
|
||||
// Start with the default complex layout
|
||||
[self setupComplexControls];
|
||||
|
||||
START_Y = _view.frame.size.height * .9;
|
||||
SELECT_Y = _view.frame.size.height * .9;
|
||||
|
||||
L1_Y = _view.frame.size.height * .75;
|
||||
L2_Y = _view.frame.size.height * .9;
|
||||
R1_Y = _view.frame.size.height * .75;
|
||||
R2_Y = _view.frame.size.height * .9;
|
||||
}
|
||||
|
||||
- (void) setupComplexControls
|
||||
{
|
||||
D_PAD_CENTER_X = _view.frame.size.width * .15;
|
||||
D_PAD_CENTER_Y = _view.frame.size.height * .55;
|
||||
BUTTON_CENTER_X = _view.frame.size.width * .85;
|
||||
BUTTON_CENTER_Y = _view.frame.size.height * .55;
|
||||
|
||||
LS_CENTER_X = _view.frame.size.width * .35;
|
||||
LS_CENTER_Y = _view.frame.size.height * .75;
|
||||
RS_CENTER_X = _view.frame.size.width * .65;
|
||||
RS_CENTER_Y = _view.frame.size.height * .75;
|
||||
|
||||
START_X = _view.frame.size.width * .55;
|
||||
START_Y = _view.frame.size.height * .1;
|
||||
SELECT_X = _view.frame.size.width * .45;
|
||||
SELECT_Y = _view.frame.size.height * .1;
|
||||
|
||||
L1_X = _view.frame.size.width * .15;
|
||||
L1_Y = _view.frame.size.height * .25;
|
||||
L2_X = _view.frame.size.width * .15;
|
||||
L2_Y = _view.frame.size.height * .1;
|
||||
R1_X = _view.frame.size.width * .85;
|
||||
R1_Y = _view.frame.size.height * .25;
|
||||
R2_X = _view.frame.size.width * .85;
|
||||
R2_Y = _view.frame.size.height * .1;
|
||||
}
|
||||
|
||||
- (void) drawButtons {
|
||||
// create A button
|
||||
_aButton.contents = (id) [UIImage imageNamed:@"AButton"].CGImage;
|
||||
@ -325,7 +380,7 @@ static float L2_Y;
|
||||
}
|
||||
|
||||
- (BOOL) handleTouchMovedEvent:touches {
|
||||
BOOL shouldSendPacket = false;
|
||||
BOOL updated = false;
|
||||
BOOL buttonTouch = false;
|
||||
float rsMaxX = RS_CENTER_X + STICK_OUTER_SIZE / 2;
|
||||
float rsMaxY = RS_CENTER_Y + STICK_OUTER_SIZE / 2;
|
||||
@ -354,10 +409,9 @@ static float L2_Y;
|
||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||
|
||||
leftStickX = 0x7FFE * xStickVal;
|
||||
leftStickY = 0x7FFE * -yStickVal;
|
||||
[_controllerSupport updateLeftStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _rsTouch) {
|
||||
if (xLoc > rsMaxX) xLoc = rsMaxX;
|
||||
if (xLoc < rsMinX) xLoc = rsMinX;
|
||||
@ -372,10 +426,9 @@ static float L2_Y;
|
||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||
|
||||
rightStickX = 0x7FFE * xStickVal;
|
||||
rightStickY = 0x7FFE * -yStickVal;
|
||||
[_controllerSupport updateRightStick:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _aTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _bTouch) {
|
||||
@ -406,167 +459,163 @@ static float L2_Y;
|
||||
buttonTouch = true;
|
||||
}
|
||||
}
|
||||
if (shouldSendPacket) {
|
||||
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
}
|
||||
return shouldSendPacket || buttonTouch;
|
||||
return updated || buttonTouch;
|
||||
}
|
||||
|
||||
- (BOOL)handleTouchDownEvent:touches {
|
||||
BOOL shouldSendPacket = false;
|
||||
BOOL updated = false;
|
||||
BOOL stickTouch = false;
|
||||
for (UITouch* touch in touches) {
|
||||
CGPoint touchLocation = [touch locationInView:_view];
|
||||
|
||||
if ([_aButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(A_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:A_FLAG];
|
||||
_aTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_bButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(B_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:B_FLAG];
|
||||
_bTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_xButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(X_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:X_FLAG];
|
||||
_xTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_yButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(Y_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:Y_FLAG];
|
||||
_yTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(UP_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:UP_FLAG];
|
||||
_upTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(DOWN_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:DOWN_FLAG];
|
||||
_downTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(LEFT_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:LEFT_FLAG];
|
||||
_leftTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(RIGHT_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:RIGHT_FLAG];
|
||||
_rightTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_startButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(PLAY_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:PLAY_FLAG];
|
||||
_startTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_selectButton.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(BACK_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:BACK_FLAG];
|
||||
_selectTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_l1Button.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(LB_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:LB_FLAG];
|
||||
_l1Touch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_r1Button.presentationLayer hitTest:touchLocation]) {
|
||||
UPDATE_BUTTON(RB_FLAG, 1);
|
||||
[_controllerSupport setButtonFlag:RB_FLAG];
|
||||
_r1Touch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_l2Button.presentationLayer hitTest:touchLocation]) {
|
||||
leftTrigger = 1 * 0xFF;
|
||||
[_controllerSupport updateLeftTrigger:0xFF];
|
||||
_l2Touch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_r2Button.presentationLayer hitTest:touchLocation]) {
|
||||
rightTrigger = 1 * 0xFF;
|
||||
[_controllerSupport updateRightTrigger:0xFF];
|
||||
_r2Touch = touch;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if ([_leftStick.presentationLayer hitTest:touchLocation]) {
|
||||
_lsTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
stickTouch = true;
|
||||
} else if ([_rightStick.presentationLayer hitTest:touchLocation]) {
|
||||
_rsTouch = touch;
|
||||
shouldSendPacket = true;
|
||||
stickTouch = true;
|
||||
}
|
||||
}
|
||||
if (shouldSendPacket) {
|
||||
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
}
|
||||
return shouldSendPacket;
|
||||
return updated || stickTouch;
|
||||
}
|
||||
|
||||
- (BOOL)handleTouchUpEvent:touches {
|
||||
BOOL shouldSendPacket = false;
|
||||
BOOL updated = false;
|
||||
for (UITouch* touch in touches) {
|
||||
if (touch == _aTouch) {
|
||||
UPDATE_BUTTON(A_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:A_FLAG];
|
||||
_aTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _bTouch) {
|
||||
UPDATE_BUTTON(B_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:B_FLAG];
|
||||
_bTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _xTouch) {
|
||||
UPDATE_BUTTON(X_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:X_FLAG];
|
||||
_xTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _yTouch) {
|
||||
UPDATE_BUTTON(Y_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:Y_FLAG];
|
||||
_yTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _upTouch) {
|
||||
UPDATE_BUTTON(UP_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:UP_FLAG];
|
||||
_upTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _downTouch) {
|
||||
UPDATE_BUTTON(DOWN_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:DOWN_FLAG];
|
||||
_downTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _leftTouch) {
|
||||
UPDATE_BUTTON(LEFT_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:LEFT_FLAG];
|
||||
_leftTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _rightTouch) {
|
||||
UPDATE_BUTTON(RIGHT_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:RIGHT_FLAG];
|
||||
_rightTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _startTouch) {
|
||||
UPDATE_BUTTON(PLAY_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:PLAY_FLAG];
|
||||
_startTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _selectTouch) {
|
||||
UPDATE_BUTTON(BACK_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:BACK_FLAG];
|
||||
_selectTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _l1Touch) {
|
||||
UPDATE_BUTTON(LB_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:LB_FLAG];
|
||||
_l1Touch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _r1Touch) {
|
||||
UPDATE_BUTTON(RB_FLAG, 0);
|
||||
[_controllerSupport clearButtonFlag:RB_FLAG];
|
||||
_r1Touch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _l2Touch) {
|
||||
leftTrigger = 0 * 0xFF;
|
||||
[_controllerSupport updateLeftTrigger:0];
|
||||
_l2Touch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
} else if (touch == _r2Touch) {
|
||||
rightTrigger = 0 * 0xFF;
|
||||
[_controllerSupport updateRightTrigger:0];
|
||||
_r2Touch = nil;
|
||||
shouldSendPacket = true;
|
||||
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);
|
||||
leftStickX = 0 * 0x7FFE;
|
||||
leftStickY = 0 * 0x7FFE;
|
||||
shouldSendPacket = true;
|
||||
[_controllerSupport updateLeftStick:0 y:0];
|
||||
updated = true;
|
||||
_lsTouch = nil;
|
||||
} 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);
|
||||
rightStickX = 0 * 0x7FFE;
|
||||
rightStickY = 0 * 0x7FFE;
|
||||
[_controllerSupport updateRightStick:0 y:0];
|
||||
_rsTouch = nil;
|
||||
shouldSendPacket = true;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (shouldSendPacket) {
|
||||
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
if (updated) {
|
||||
[_controllerSupport updateFinished];
|
||||
}
|
||||
return shouldSendPacket;
|
||||
return updated;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -7,9 +7,10 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "ControllerSupport.h"
|
||||
|
||||
@interface StreamView : UIView
|
||||
|
||||
- (void) setupOnScreenControls;
|
||||
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport;
|
||||
|
||||
@end
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <Limelight.h>
|
||||
#import "OnScreenControls.h"
|
||||
#import "DataManager.h"
|
||||
#import "ControllerSupport.h"
|
||||
|
||||
@implementation StreamView {
|
||||
CGPoint touchLocation;
|
||||
@ -17,12 +18,19 @@
|
||||
OnScreenControls* onScreenControls;
|
||||
}
|
||||
|
||||
- (void) setupOnScreenControls {
|
||||
onScreenControls = [[OnScreenControls alloc] initWithView:self];
|
||||
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport {
|
||||
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport];
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue];
|
||||
NSLog(@"Setting on-screen controls level: %d", (int)level);
|
||||
[onScreenControls setLevel:level];
|
||||
|
||||
if (level == OnScreenControlsLevelAuto) {
|
||||
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
|
||||
}
|
||||
else {
|
||||
NSLog(@"Setting manual on-screen controls level: %d", (int)level);
|
||||
[onScreenControls setLevel:level];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
|
@ -64,7 +64,7 @@
|
||||
[self.stageLabel setText:@"Waiting for first frame..."];
|
||||
[self.stageLabel sizeToFit];
|
||||
});
|
||||
[(StreamView*)self.view setupOnScreenControls];
|
||||
[(StreamView*)self.view setupOnScreenControls: _controllerSupport];
|
||||
}
|
||||
|
||||
- (void)connectionTerminated:(long)errorCode {
|
||||
|
@ -126,11 +126,12 @@
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="2" id="qSU-wh-tqA">
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="qSU-wh-tqA">
|
||||
<rect key="frame" x="16" y="265" width="209" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segments>
|
||||
<segment title="Off"/>
|
||||
<segment title="Auto"/>
|
||||
<segment title="Simple"/>
|
||||
<segment title="Full"/>
|
||||
</segments>
|
||||
|
@ -146,11 +146,12 @@
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="2" id="WGf-9d-eAm">
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="WGf-9d-eAm">
|
||||
<rect key="frame" x="16" y="246" width="200" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segments>
|
||||
<segment title="Off"/>
|
||||
<segment title="Auto"/>
|
||||
<segment title="Simple"/>
|
||||
<segment title="Full"/>
|
||||
</segments>
|
||||
|
Loading…
x
Reference in New Issue
Block a user