mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2025-07-27 06:32:59 +00:00
289 lines
12 KiB
Objective-C
289 lines
12 KiB
Objective-C
//
|
|
// OnScreenControls.m
|
|
// Limelight
|
|
//
|
|
// Created by Diego Waxemberg on 12/28/14.
|
|
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
|
//
|
|
|
|
#import "OnScreenControls.h"
|
|
#include "Limelight.h"
|
|
|
|
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
|
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
|
|
|
@implementation OnScreenControls {
|
|
CALayer* _aButton;
|
|
CALayer* _bButton;
|
|
CALayer* _xButton;
|
|
CALayer* _yButton;
|
|
CALayer* _upButton;
|
|
CALayer* _downButton;
|
|
CALayer* _leftButton;
|
|
CALayer* _rightButton;
|
|
CALayer* _leftStick;
|
|
CALayer* _rightStick;
|
|
|
|
short buttonFlags;
|
|
short leftStickX, leftStickY;
|
|
short rightStickX, rightStickY;
|
|
char leftTrigger, rightTrigger;
|
|
|
|
UITouch* lsTouch;
|
|
UITouch* rsTouch;
|
|
|
|
UIView* _view;
|
|
BOOL shouldDrawControls;
|
|
}
|
|
|
|
static const float BUTTON_SIZE = 50;
|
|
static const float BUTTON_DIST = 20;
|
|
static float BUTTON_CENTER_X;
|
|
static float BUTTON_CENTER_Y;
|
|
|
|
static const float D_PAD_SHORT = 50;
|
|
static const float D_PAD_LONG = 65;
|
|
static const float D_PAD_DIST = 15;
|
|
static float D_PAD_CENTER_X;
|
|
static float D_PAD_CENTER_Y;
|
|
|
|
static const float STICK_INNER_SIZE = 80;
|
|
static const float STICK_OUTER_SIZE = 120;
|
|
static float LS_CENTER_X;
|
|
static float LS_CENTER_Y;
|
|
static float RS_CENTER_X;
|
|
static float RS_CENTER_Y;
|
|
|
|
- (id) initWithView:(UIView*)view {
|
|
self = [self init];
|
|
_view = view;
|
|
shouldDrawControls = YES;
|
|
|
|
D_PAD_CENTER_X = _view.frame.size.width * .15;
|
|
D_PAD_CENTER_Y = _view.frame.size.height * .5;
|
|
BUTTON_CENTER_X = _view.frame.size.width * .85;
|
|
BUTTON_CENTER_Y = _view.frame.size.height * .5;
|
|
|
|
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;
|
|
|
|
[self drawButtons];
|
|
[self drawSticks];
|
|
return self;
|
|
}
|
|
|
|
- (void) drawButtons {
|
|
// create A button
|
|
_aButton = [CALayer layer];
|
|
_aButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_SIZE / 2, BUTTON_CENTER_Y + BUTTON_DIST, BUTTON_SIZE, BUTTON_SIZE);
|
|
_aButton.contents = (id) [UIImage imageNamed:@"AButton"].CGImage;
|
|
[_view.layer addSublayer:_aButton];
|
|
|
|
// create B button
|
|
_bButton = [CALayer layer];
|
|
_bButton.frame = CGRectMake(BUTTON_CENTER_X + BUTTON_DIST, BUTTON_CENTER_Y - BUTTON_SIZE / 2, BUTTON_SIZE, BUTTON_SIZE);
|
|
_bButton.contents = (id) [UIImage imageNamed:@"BButton"].CGImage;
|
|
[_view.layer addSublayer:_bButton];
|
|
|
|
// create X Button
|
|
_xButton = [CALayer layer];
|
|
_xButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_DIST - BUTTON_SIZE, BUTTON_CENTER_Y - BUTTON_SIZE / 2, BUTTON_SIZE, BUTTON_SIZE);
|
|
_xButton.contents = (id) [UIImage imageNamed:@"XButton"].CGImage;
|
|
[_view.layer addSublayer:_xButton];
|
|
|
|
// create Y Button
|
|
_yButton = [CALayer layer];
|
|
_yButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_SIZE / 2, BUTTON_CENTER_Y - BUTTON_DIST - BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE);
|
|
_yButton.contents = (id) [UIImage imageNamed:@"YButton"].CGImage;
|
|
[_view.layer addSublayer:_yButton];
|
|
|
|
// create Down button
|
|
_downButton = [CALayer layer];
|
|
_downButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_SHORT / 2, D_PAD_CENTER_Y + D_PAD_DIST, D_PAD_SHORT, D_PAD_LONG);
|
|
_downButton.contents = (id) [UIImage imageNamed:@"DownButton"].CGImage;
|
|
[_view.layer addSublayer:_downButton];
|
|
|
|
// create Right button
|
|
_rightButton = [CALayer layer];
|
|
_rightButton.frame = CGRectMake(D_PAD_CENTER_X + D_PAD_DIST, D_PAD_CENTER_Y - D_PAD_SHORT / 2, D_PAD_LONG, D_PAD_SHORT);
|
|
_rightButton.contents = (id) [UIImage imageNamed:@"RightButton"].CGImage;
|
|
[_view.layer addSublayer:_rightButton];
|
|
|
|
// create Up button
|
|
_upButton = [CALayer layer];
|
|
_upButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_SHORT / 2, D_PAD_CENTER_Y - D_PAD_DIST - D_PAD_LONG, D_PAD_SHORT, D_PAD_LONG);
|
|
_upButton.contents = (id) [UIImage imageNamed:@"UpButton"].CGImage;
|
|
[_view.layer addSublayer:_upButton];
|
|
|
|
// create Left button
|
|
_leftButton = [CALayer layer];
|
|
_leftButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_DIST - D_PAD_LONG, D_PAD_CENTER_Y - D_PAD_SHORT / 2, D_PAD_LONG, D_PAD_SHORT);
|
|
_leftButton.contents = (id) [UIImage imageNamed:@"LeftButton"].CGImage;
|
|
[_view.layer addSublayer:_leftButton];
|
|
}
|
|
|
|
- (void) drawSticks {
|
|
// create left analog stick
|
|
CALayer* leftStickBackground = [CALayer layer];
|
|
leftStickBackground.frame = CGRectMake(LS_CENTER_X - STICK_OUTER_SIZE / 2, LS_CENTER_Y - STICK_OUTER_SIZE / 2, STICK_OUTER_SIZE, STICK_OUTER_SIZE);
|
|
leftStickBackground.contents = (id) [UIImage imageNamed:@"StickOuter"].CGImage;
|
|
[_view.layer addSublayer:leftStickBackground];
|
|
|
|
_leftStick = [CALayer layer];
|
|
_leftStick.frame = CGRectMake(LS_CENTER_X - STICK_INNER_SIZE / 2, LS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
|
_leftStick.contents = (id) [UIImage imageNamed:@"StickInner"].CGImage;
|
|
[_view.layer addSublayer:_leftStick];
|
|
|
|
// create right analog stick
|
|
CALayer* rightStickBackground = [CALayer layer];
|
|
rightStickBackground.frame = CGRectMake(RS_CENTER_X - STICK_OUTER_SIZE / 2, RS_CENTER_Y - STICK_OUTER_SIZE / 2, STICK_OUTER_SIZE, STICK_OUTER_SIZE);
|
|
rightStickBackground.contents = (id) [UIImage imageNamed:@"StickOuter"].CGImage;
|
|
[_view.layer addSublayer:rightStickBackground];
|
|
|
|
_rightStick = [CALayer layer];
|
|
_rightStick.frame = CGRectMake(RS_CENTER_X - STICK_INNER_SIZE / 2, RS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
|
_rightStick.contents = (id) [UIImage imageNamed:@"StickInner"].CGImage;
|
|
[_view.layer addSublayer:_rightStick];
|
|
}
|
|
|
|
- (void) handleTouchMovedEvent:(UIEvent*)event {
|
|
float rsMaxX = RS_CENTER_X + STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float rsMaxY = RS_CENTER_Y + STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float rsMinX = RS_CENTER_X - STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float rsMinY = RS_CENTER_Y - STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float lsMaxX = LS_CENTER_X + STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float lsMaxY = LS_CENTER_Y + STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float lsMinX = LS_CENTER_X - STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
float lsMinY = LS_CENTER_Y - STICK_OUTER_SIZE / 2 - STICK_INNER_SIZE / 2;
|
|
|
|
for (UITouch* touch in [event allTouches]) {
|
|
CGPoint touchLocation = [touch locationInView:_view];
|
|
float xLoc = touchLocation.x - STICK_INNER_SIZE / 2;
|
|
float yLoc = touchLocation.y - STICK_INNER_SIZE / 2;
|
|
if (touch == lsTouch) {
|
|
if (xLoc > lsMaxX) xLoc = lsMaxX;
|
|
if (xLoc < lsMinX) xLoc = lsMinX;
|
|
if (yLoc > lsMaxY) yLoc = lsMaxY;
|
|
if (yLoc < lsMinY) yLoc = lsMinY;
|
|
|
|
_leftStick.frame = CGRectMake(xLoc, yLoc, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
|
|
|
leftStickX = 0x7FFF * (xLoc - LS_CENTER_X) / (lsMaxX - LS_CENTER_X);
|
|
leftStickY = 0x7FFF * (yLoc - LS_CENTER_Y) / (lsMaxY - LS_CENTER_Y);
|
|
NSLog(@"Left Stick: x: %d y: %d", leftStickX, leftStickY);
|
|
|
|
} else if (touch == rsTouch) {
|
|
if (xLoc > rsMaxX) xLoc = rsMaxX;
|
|
if (xLoc < rsMinX) xLoc = rsMinX;
|
|
if (yLoc > rsMaxY) yLoc = rsMaxY;
|
|
if (yLoc < rsMinY) yLoc = rsMinY;
|
|
|
|
_rightStick.frame = CGRectMake(xLoc, yLoc, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
|
|
|
rightStickX = 0x7FFF * (xLoc - RS_CENTER_X) / (rsMaxX - RS_CENTER_X);
|
|
rightStickY = 0x7FFF * (yLoc - RS_CENTER_Y) / (rsMaxY - RS_CENTER_Y);
|
|
NSLog(@"Right Stick: x: %d y: %d", rightStickX, rightStickY);
|
|
}
|
|
}
|
|
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
|
}
|
|
|
|
- (void)handleTouchDownEvent:(UIEvent*)event {
|
|
for (UITouch* touch in [event allTouches]) {
|
|
CGPoint touchLocation = [touch locationInView:_view];
|
|
|
|
if ([_aButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(A_FLAG, 1);
|
|
} else if ([_bButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(B_FLAG, 1);
|
|
} else if ([_xButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(X_FLAG, 1);
|
|
} else if ([_yButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(Y_FLAG, 1);
|
|
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(UP_FLAG, 1);
|
|
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(DOWN_FLAG, 1);
|
|
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(LEFT_FLAG, 1);
|
|
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(RIGHT_FLAG, 1);
|
|
} else if ([_leftStick.presentationLayer hitTest:touchLocation]) {
|
|
lsTouch = touch;
|
|
} else if ([_rightStick.presentationLayer hitTest:touchLocation]) {
|
|
rsTouch = touch;
|
|
}
|
|
/*
|
|
|
|
UPDATE_BUTTON(LB_FLAG, gamepad.leftShoulder.pressed);
|
|
UPDATE_BUTTON(RB_FLAG, gamepad.rightShoulder.pressed);
|
|
|
|
leftStickX = gamepad.leftThumbstick.xAxis.value * 0x7FFE;
|
|
leftStickY = gamepad.leftThumbstick.yAxis.value * 0x7FFE;
|
|
|
|
rightStickX = gamepad.rightThumbstick.xAxis.value * 0x7FFE;
|
|
rightStickY = gamepad.rightThumbstick.yAxis.value * 0x7FFE;
|
|
|
|
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.
|
|
}
|
|
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
|
}
|
|
|
|
- (void)handleTouchUpEvent:(UIEvent*)event {
|
|
|
|
for (UITouch* touch in [event allTouches]) {
|
|
CGPoint touchLocation = [touch locationInView:_view];
|
|
|
|
if ([_aButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(A_FLAG, 0);
|
|
} else if ([_bButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(B_FLAG, 0);
|
|
} else if ([_xButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(X_FLAG, 0);
|
|
} else if ([_yButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(Y_FLAG, 0);
|
|
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(UP_FLAG, 0);
|
|
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(DOWN_FLAG, 0);
|
|
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(LEFT_FLAG, 0);
|
|
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
|
UPDATE_BUTTON(RIGHT_FLAG, 0);
|
|
}
|
|
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);
|
|
} 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);
|
|
}
|
|
/*
|
|
UPDATE_BUTTON(LB_FLAG, gamepad.leftShoulder.pressed);
|
|
UPDATE_BUTTON(RB_FLAG, gamepad.rightShoulder.pressed);
|
|
|
|
leftStickX = gamepad.leftThumbstick.xAxis.value * 0x7FFE;
|
|
leftStickY = gamepad.leftThumbstick.yAxis.value * 0x7FFE;
|
|
|
|
rightStickX = gamepad.rightThumbstick.xAxis.value * 0x7FFE;
|
|
rightStickY = gamepad.rightThumbstick.yAxis.value * 0x7FFE;
|
|
|
|
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.
|
|
}
|
|
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger,
|
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
|
}
|
|
|
|
|
|
@end
|