From 22ad95cbfee7bdc39226867e90d74d6ceb23f748 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 27 May 2022 18:32:55 +0200 Subject: [PATCH] ios: diagonal DPad buttons. Pan between buttons. Help tip for menu Add diagonal DPad buttons Allow switching virtual button without lifting finger. Display help tip on first startup about pausing/opening menu. --- .../emulator/PadViewController.mm | 117 +++++++++----- .../emulator/PadViewController.xib | 151 ++++++------------ .../apple/emulator-ios/emulator/ios_gamepad.h | 29 +++- 3 files changed, 156 insertions(+), 141 deletions(-) diff --git a/shell/apple/emulator-ios/emulator/PadViewController.mm b/shell/apple/emulator-ios/emulator/PadViewController.mm index f0a7c7def..6fb7a8c0f 100644 --- a/shell/apple/emulator-ios/emulator/PadViewController.mm +++ b/shell/apple/emulator-ios/emulator/PadViewController.mm @@ -27,6 +27,7 @@ UITouch *joyTouch; CGPoint joyBias; std::shared_ptr virtualGamepad; + NSMutableDictionary *touchToButton; } @end @@ -38,10 +39,23 @@ [super viewDidLoad]; virtualGamepad = std::make_shared(); GamepadDevice::Register(virtualGamepad); + touchToButton = [[NSMutableDictionary alloc] init]; } - (void)showController:(UIView *)parentView { + if (!cfgLoadBool("help", "PauseGameTip", false)) + { + UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Help Tip" + message:@"To pause the game, press Up+Down or Left+Right on the virtual DPad." + preferredStyle:UIAlertControllerStyleAlert]; + [self presentViewController:alert animated:YES completion:nil]; + UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + cfgSaveBool("help", "PauseGameTip", true); + }]; + [alert addAction:defaultAction]; + } [parentView addSubview:self.view]; } @@ -55,16 +69,6 @@ return self.view.window != nil; } -- (IBAction)keycodeDown:(id)sender -{ - virtualGamepad->gamepad_btn_input((u32)((UIButton *)sender).tag, true); -} - -- (IBAction)keycodeUp:(id)sender -{ - virtualGamepad->gamepad_btn_input((u32)((UIButton *)sender).tag, false); -} - - (void)resetTouch { joyTouch = nil; @@ -76,29 +80,42 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; { - if (joyTouch == nil) { - for (UITouch *touch in touches) { - CGPoint loc = [touch locationInView:[self joystickBackground]]; + for (UITouch *touch in touches) { + if (joyTouch == nil) { + CGPoint loc = [touch locationInView:self.joystickBackground]; if ([self.joystickBackground pointInside:loc withEvent:event]) { joyTouch = touch; joyBias = loc; virtualGamepad->gamepad_axis_input(IOS_AXIS_LX, 0); virtualGamepad->gamepad_axis_input(IOS_AXIS_LY, 0); - break; + continue; } } + CGPoint point = [touch locationInView:self.view]; + UIView *touchedView = [self.view hitTest:point withEvent:nil]; + NSValue *key = [NSValue valueWithPointer:(const void *)touch]; + if (touchedView.tag != 0 && touchToButton[key] == nil) { + touchToButton[key] = touchedView; + // button down + virtualGamepad->gamepad_btn_input((u32)touchedView.tag, true); + } } [super touchesBegan:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; { - if (joyTouch != nil) { - for (UITouch *touch in touches) { - if (touch == joyTouch) { - [self resetTouch]; - break; - } + for (UITouch *touch in touches) { + if (touch == joyTouch) { + [self resetTouch]; + continue; + } + NSValue *key = [NSValue valueWithPointer:(const void *)touch]; + UIView *button = touchToButton[key]; + if (button != nil) { + [touchToButton removeObjectForKey:key]; + // button up + virtualGamepad->gamepad_btn_input((u32)button.tag, false); } } [super touchesEnded:touches withEvent:event]; @@ -106,20 +123,35 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; { - if (joyTouch != nil) { - for (UITouch *touch in touches) { - if (touch == joyTouch) { - CGPoint pos = [touch locationInView:[self joystickBackground]]; - pos.x -= joyBias.x; - pos.y -= joyBias.y; - pos.x = std::max(std::min(25.0, pos.x), -25.0); - pos.y = std::max(std::min(25.0, pos.y), -25.0); - self.joyXConstraint.constant = pos.x; - self.joyYConstraint.constant = pos.y; - virtualGamepad->gamepad_axis_input(IOS_AXIS_LX, (s8)std::round(pos.x * 32767.0 / 25.0)); - virtualGamepad->gamepad_axis_input(IOS_AXIS_LY, (s8)std::round(pos.y * 32767.0 / 25.0)); - break; - } + for (UITouch *touch in touches) { + if (touch == joyTouch) { + CGPoint pos = [touch locationInView:[self joystickBackground]]; + pos.x -= joyBias.x; + pos.y -= joyBias.y; + pos.x = std::max(std::min(25.0, pos.x), -25.0); + pos.y = std::max(std::min(25.0, pos.y), -25.0); + self.joyXConstraint.constant = pos.x; + self.joyYConstraint.constant = pos.y; + virtualGamepad->gamepad_axis_input(IOS_AXIS_LX, (s8)std::round(pos.x * 32767.0 / 25.0)); + virtualGamepad->gamepad_axis_input(IOS_AXIS_LY, (s8)std::round(pos.y * 32767.0 / 25.0)); + continue; + } + CGPoint point = [touch locationInView:self.view]; + UIView *touchedView = [self.view hitTest:point withEvent:nil]; + NSValue *key = [NSValue valueWithPointer:(const void *)touch]; + UIView *button = touchToButton[key]; + if (button != nil && touchedView.tag != button.tag) { + // button up + virtualGamepad->gamepad_btn_input((u32)button.tag, false); + touchToButton[key] = touchedView; + // button down + virtualGamepad->gamepad_btn_input((u32)touchedView.tag, true); + } + else if (button == nil && touchedView.tag != 0) + { + touchToButton[key] = touchedView; + // button down + virtualGamepad->gamepad_btn_input((u32)touchedView.tag, true); } } [super touchesMoved:touches withEvent:event]; @@ -127,12 +159,17 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; { - if (joyTouch != nil) { - for (UITouch *touch in touches) { - if (touch == joyTouch) { - [self resetTouch]; - break; - } + for (UITouch *touch in touches) { + if (touch == joyTouch) { + [self resetTouch]; + continue; + } + NSValue *key = [NSValue valueWithPointer:(const void *)touch]; + UIView *button = touchToButton[key]; + if (button != nil) { + [touchToButton removeObjectForKey:key]; + // button up + virtualGamepad->gamepad_btn_input((u32)button.tag, false); } } [super touchesCancelled:touches withEvent:event]; diff --git a/shell/apple/emulator-ios/emulator/PadViewController.xib b/shell/apple/emulator-ios/emulator/PadViewController.xib index 62da8aae8..7987867e9 100644 --- a/shell/apple/emulator-ios/emulator/PadViewController.xib +++ b/shell/apple/emulator-ios/emulator/PadViewController.xib @@ -21,16 +21,9 @@ - + @@ -38,16 +31,9 @@ - + @@ -65,62 +51,43 @@ - - - - + @@ -128,62 +95,34 @@ - - - - + @@ -191,20 +130,13 @@ - + @@ -212,25 +144,37 @@ + + + + + + + + + + + + @@ -238,11 +182,17 @@ + + + + + + @@ -250,6 +200,7 @@ + @@ -257,7 +208,7 @@ - + diff --git a/shell/apple/emulator-ios/emulator/ios_gamepad.h b/shell/apple/emulator-ios/emulator/ios_gamepad.h index ebe8633d2..688c7b4b3 100644 --- a/shell/apple/emulator-ios/emulator/ios_gamepad.h +++ b/shell/apple/emulator-ios/emulator/ios_gamepad.h @@ -50,7 +50,13 @@ enum IOSButton { IOS_BTN_PADDLE4, IOS_BTN_TOUCHPAD, - IOS_BTN_MAX + IOS_BTN_MAX, + + IOS_BTN_UP_RIGHT = 10, + IOS_BTN_UP_LEFT, + IOS_BTN_DOWN_LEFT, + IOS_BTN_DOWN_RIGHT, + }; enum IOSAxis { IOS_AXIS_L1 = 1, @@ -555,6 +561,27 @@ public: if (code == IOS_BTN_Y) code = IOS_BTN_X; // btn3 } + switch (code) + { + case IOS_BTN_UP_RIGHT: + GamepadDevice::gamepad_btn_input(IOS_BTN_UP, pressed); + code = IOS_BTN_RIGHT; + break; + case IOS_BTN_DOWN_RIGHT: + GamepadDevice::gamepad_btn_input(IOS_BTN_DOWN, pressed); + code = IOS_BTN_RIGHT; + break; + case IOS_BTN_DOWN_LEFT: + GamepadDevice::gamepad_btn_input(IOS_BTN_DOWN, pressed); + code = IOS_BTN_LEFT; + break; + case IOS_BTN_UP_LEFT: + GamepadDevice::gamepad_btn_input(IOS_BTN_UP, pressed); + code = IOS_BTN_LEFT; + break; + default: + break; + } return GamepadDevice::gamepad_btn_input(code, pressed); }