From 2cb1acc61104634885d14f6b7f870573a2d4886a Mon Sep 17 00:00:00 2001 From: Diego Waxemberg Date: Mon, 29 Dec 2014 00:11:14 -0500 Subject: [PATCH] Added analog sticks to onscreen controls --- .../StickInner.imageset/Contents.json | 23 ++++ .../StickInner.imageset/stick_inner-1.png | Bin 0 -> 1104 bytes .../StickInner.imageset/stick_inner-2.png | Bin 0 -> 1104 bytes .../StickInner.imageset/stick_inner.png | Bin 0 -> 1104 bytes .../StickOuter.imageset/Contents.json | 23 ++++ .../StickOuter.imageset/stick_outer-1.png | Bin 0 -> 1678 bytes .../StickOuter.imageset/stick_outer-2.png | Bin 0 -> 1678 bytes .../StickOuter.imageset/stick_outer.png | Bin 0 -> 1678 bytes Limelight/Input/OnScreenControls.h | 2 + Limelight/Input/OnScreenControls.m | 121 ++++++++++++++++-- Limelight/Input/StreamView.m | 2 +- 11 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 Limelight/Images.xcassets/StickInner.imageset/Contents.json create mode 100644 Limelight/Images.xcassets/StickInner.imageset/stick_inner-1.png create mode 100644 Limelight/Images.xcassets/StickInner.imageset/stick_inner-2.png create mode 100644 Limelight/Images.xcassets/StickInner.imageset/stick_inner.png create mode 100644 Limelight/Images.xcassets/StickOuter.imageset/Contents.json create mode 100644 Limelight/Images.xcassets/StickOuter.imageset/stick_outer-1.png create mode 100644 Limelight/Images.xcassets/StickOuter.imageset/stick_outer-2.png create mode 100644 Limelight/Images.xcassets/StickOuter.imageset/stick_outer.png diff --git a/Limelight/Images.xcassets/StickInner.imageset/Contents.json b/Limelight/Images.xcassets/StickInner.imageset/Contents.json new file mode 100644 index 0000000..a9f35e7 --- /dev/null +++ b/Limelight/Images.xcassets/StickInner.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "stick_inner-1.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "stick_inner.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "stick_inner-2.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Limelight/Images.xcassets/StickInner.imageset/stick_inner-1.png b/Limelight/Images.xcassets/StickInner.imageset/stick_inner-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c09763aba5e458146fb9deb52b3081bde0727388 GIT binary patch literal 1104 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 YV{c?-a;OG>?f?J)07*qoM6N<$f)x_;)c^nh literal 0 HcmV?d00001 diff --git a/Limelight/Images.xcassets/StickOuter.imageset/stick_outer-2.png b/Limelight/Images.xcassets/StickOuter.imageset/stick_outer-2.png new file mode 100644 index 0000000000000000000000000000000000000000..5748edeaef21da1723a186abc4cf13c9ef17d5ee GIT binary patch literal 1678 zcmV;9266d`P)005u}1^@s6i_d2*000IYNkl5|eVvV>&8`BAz|>5}qFN=ix)2q{q%6hwshZ*$}9DTdgb&$qX;v-_>| zi4;6Gw?EJ9Ja(@r81Ke%xf~0N#iIVQTsf*E+5EiwU7O#_6J~72WHLE9J3BjV1U8$^ zZtAbMA*cm;-3V0XFr7|EtVjle+p=c2u^}ITvMevfTFP8mG2>%A9)FR=ltm3`-Fyo2 z;^JamTgR#VUszEiLl!JnE7u44Ac?zXg(D3d#9E{#y3Z^lZaNYd>o)YanNo?xM-736 zC&7fpecg~&5g`T=9)fEZB0-DiA+8pS*E!Ef(!1}Fs1M;CPaUjW5v&}SN*Se?N>LQz z8n@gbkB8O6Evr~PaT$mOYlzj$U~foO#idrH#AGz(aW|jOe+lw$qheg)a*c|w=B4J% z@nThkS-ND|3|n=%JH(fQ2(Pl~NjyJ4|7yJ2@U%mG4NsKwA|BQ|R$9boUW7uDBD5TA zZ1v;)JV1O&h%l+(M8uaueyyeC{<1li!(Sa($qR1f1I9 z^Fo^KTSUFk zp>xK6R7__xbh*!(E*H>dOsyB}=LRXafm#8iRftnk} z{eqesCi;a?aM}&xyG?-uN1%F!m@^-sRvTvj2deu(nh!wr&=Q@`pn8Cv?iWza2hw~B zs(}a(1k?f%=~U%mfLfO{5iqDm!bHHJ8VMsn&=w#qSfE9P0099)-U8%7fL<=p$l%zjon(`MIpd#@d=B?;s=YBCbG88I{Ok~ z;o(#9yfrBVn2!L(+dZoau%5)z_Jj~%UIKJHsR(eF_z+;00_-KiqUUB50V2Q+^ZERH zFag$o?7kM^D*{A-ZZG&+^AOYp%OBh&LIjwX0Q-oqcM!5mga|OJD7csS8Ua>5MTh|N z5TFn7d22@479j#mUx1#(=eHY1CL|N|G%<*?6z6-5D=sAhH8z(N(UK3UE%{u_3yOQn zCC4&B_gE%3@(VM+Gh3T~5UHY@i^(H5XKZZUoE~y`UNaf4C=_hXUaP z5CRcU4M2EN4XD(Bc~uugv;X5|HK4lxBOeF>dkQakVKu~&|NA&-On_hw2>S-<7#NVM zXdAd;7|{AnTLnlo3_~H>Dh?S$!!T&~OWPnR4MCF6Eqg)Upb5TGFV{uaL60B=4L)`S zBeU7;h6f12tshnpf>b`Rf-oeaor6;^`v!f2(1TUccVGqK*u7tG>&IRYf=0erK~Rr; zsg6MKsz(P`T=8(hTg|uYpkWmTPrJ}B2*)DZv?9cyYZ`*OUR*J#yIx!|1dn>@oQ5Ff zwmu1J8do{xraC5*$q7{wYQ3sM>V7OrUO|T#o+73}!vgs}^&z<+7KknvZA(bKm}GOI z8W~e5L41f1@)X~PJ7#dl#@TtFv!y{`LcoCtAz$$!Ld1s%0r72@?JU-g%d&i~=lymF z^1T*oyJ~G!G%y^rK)*W(@YPtFk#qD_mbl?B0@_|t!*N-CO*|> z(wK&HS6Fe$`$T9-eBybcYp04JI2l=S$sa{%OnmF?_IoKt$&CoDh)<$itX_vGnFCK) zJ@$t7g~wjcQW%#v-(kz*? z5F6p424x{i>L#-z02O<@NYgiB6;r$}1UG9havsZG(XtqwRbP=xNg!}>*U43}N3oKC zm$?$jChn?bkzHCxQ+t~Ga2iraQc@0Al~)hEh!KU+DP-#f;o{u_S)Y8$PY z=j2(G0000jbVXQnQ*UN;cVTj60AhJAVr*}3WMp|RV{&KQKGBibQ YV{c?-a;OG>?f?J)07*qoM6N<$f)x_;)c^nh literal 0 HcmV?d00001 diff --git a/Limelight/Images.xcassets/StickOuter.imageset/stick_outer.png b/Limelight/Images.xcassets/StickOuter.imageset/stick_outer.png new file mode 100644 index 0000000000000000000000000000000000000000..5748edeaef21da1723a186abc4cf13c9ef17d5ee GIT binary patch literal 1678 zcmV;9266d`P)005u}1^@s6i_d2*000IYNkl5|eVvV>&8`BAz|>5}qFN=ix)2q{q%6hwshZ*$}9DTdgb&$qX;v-_>| zi4;6Gw?EJ9Ja(@r81Ke%xf~0N#iIVQTsf*E+5EiwU7O#_6J~72WHLE9J3BjV1U8$^ zZtAbMA*cm;-3V0XFr7|EtVjle+p=c2u^}ITvMevfTFP8mG2>%A9)FR=ltm3`-Fyo2 z;^JamTgR#VUszEiLl!JnE7u44Ac?zXg(D3d#9E{#y3Z^lZaNYd>o)YanNo?xM-736 zC&7fpecg~&5g`T=9)fEZB0-DiA+8pS*E!Ef(!1}Fs1M;CPaUjW5v&}SN*Se?N>LQz z8n@gbkB8O6Evr~PaT$mOYlzj$U~foO#idrH#AGz(aW|jOe+lw$qheg)a*c|w=B4J% z@nThkS-ND|3|n=%JH(fQ2(Pl~NjyJ4|7yJ2@U%mG4NsKwA|BQ|R$9boUW7uDBD5TA zZ1v;)JV1O&h%l+(M8uaueyyeC{<1li!(Sa($qR1f1I9 z^Fo^KTSUFk zp>xK6R7__xbh*!(E*H>dOsyB}=LRXafm#8iRftnk} z{eqesCi;a?aM}&xyG?-uN1%F!m@^-sRvTvj2deu(nh!wr&=Q@`pn8Cv?iWza2hw~B zs(}a(1k?f%=~U%mfLfO{5iqDm!bHHJ8VMsn&=w#qSfE9P0099)-U8%7fL<=p$l%zjon(`MIpd#@d=B?;s=YBCbG88I{Ok~ z;o(#9yfrBVn2!L(+dZoau%5)z_Jj~%UIKJHsR(eF_z+;00_-KiqUUB50V2Q+^ZERH zFag$o?7kM^D*{A-ZZG&+^AOYp%OBh&LIjwX0Q-oqcM!5mga|OJD7csS8Ua>5MTh|N z5TFn7d22@479j#mUx1#(=eHY1CL|N|G%<*?6z6-5D=sAhH8z(N(UK3UE%{u_3yOQn zCC4&B_gE%3@(VM+Gh3T~5UHY@i^(H5XKZZUoE~y`UNaf4C=_hXUaP z5CRcU4M2EN4XD(Bc~uugv;X5|HK4lxBOeF>dkQakVKu~&|NA&-On_hw2>S-<7#NVM zXdAd;7|{AnTLnlo3_~H>Dh?S$!!T&~OWPnR4MCF6Eqg)Upb5TGFV{uaL60B=4L)`S zBeU7;h6f12tshnpf>b`Rf-oeaor6;^`v!f2(1TUccVGqK*u7tG>&IRYf=0erK~Rr; zsg6MKsz(P`T=8(hTg|uYpkWmTPrJ}B2*)DZv?9cyYZ`*OUR*J#yIx!|1dn>@oQ5Ff zwmu1J8do{xraC5*$q7{wYQ3sM>V7OrUO|T#o+73}!vgs}^&z<+7KknvZA(bKm}GOI z8W~e5L41f1@)X~PJ7#dl#@TtFv!y{`LcoCtAz$$!Ld1s%0r72@?JU-g%d&i~=lymF z^1T*oyJ~G!G%y^rK)*W(@YPtFk#qD_mbl?B0@_|t!*N-CO*|> z(wK&HS6Fe$`$T9-eBybcYp04JI2l=S$sa{%OnmF?_IoKt$&CoDh)<$itX_vGnFCK) zJ@$t7g~wjcQW%#v-(kz*? z5F6p424x{i>L#-z02O<@NYgiB6;r$}1UG9havsZG(XtqwRbP=xNg!}>*U43}N3oKC zm$?$jChn?bkzHCxQ+t~Ga2iraQc@0Al~)hEh!KU+DP-#f;o{u_S)Y8$PY z=j2(G0000jbVXQnQ*UN;cVTj60AhJAVr*}3WMp|RV{&KQKGBibQ YV{c?-a;OG>?f?J)07*qoM6N<$f)x_;)c^nh literal 0 HcmV?d00001 diff --git a/Limelight/Input/OnScreenControls.h b/Limelight/Input/OnScreenControls.h index f961868..f157e6c 100644 --- a/Limelight/Input/OnScreenControls.h +++ b/Limelight/Input/OnScreenControls.h @@ -13,4 +13,6 @@ - (id) initWithView:(UIView*)view; - (void) handleTouchDownEvent:(UIEvent*)event; - (void) handleTouchUpEvent:(UIEvent*) event; +- (void) handleTouchMovedEvent:(UIEvent*)event; + @end diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m index 8104d1b..a00cc74 100644 --- a/Limelight/Input/OnScreenControls.m +++ b/Limelight/Input/OnScreenControls.m @@ -13,8 +13,6 @@ (y) ? (buttonFlags | (x)) : (buttonFlags & ~(x))) @implementation OnScreenControls { - UIView* _view; - BOOL shouldDrawControls; CALayer* _aButton; CALayer* _bButton; CALayer* _xButton; @@ -23,11 +21,19 @@ 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; @@ -41,17 +47,30 @@ 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 * .75; + D_PAD_CENTER_Y = _view.frame.size.height * .5; BUTTON_CENTER_X = _view.frame.size.width * .85; - BUTTON_CENTER_Y = _view.frame.size.height * .75; + 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; } @@ -105,6 +124,73 @@ static float D_PAD_CENTER_Y; [_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]; @@ -125,21 +211,25 @@ static float D_PAD_CENTER_Y; 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); + 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; + leftStickX = gamepad.leftThumbstick.xAxis.value * 0x7FFE; + leftStickY = gamepad.leftThumbstick.yAxis.value * 0x7FFE; - rightStickX = gamepad.rightThumbstick.xAxis.value * 0x7FFE; - rightStickY = gamepad.rightThumbstick.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; - */ + 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. } @@ -169,6 +259,11 @@ static float D_PAD_CENTER_Y; } 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); diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 748ed98..a1dbb6d 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -29,7 +29,7 @@ } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - + [onScreenControls handleTouchMovedEvent:event]; if ([[event allTouches] count] == 1) { UITouch *touch = [[event allTouches] anyObject]; CGPoint currentLocation = [touch locationInView:self];