123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- //
- // Copyright © 2020 osy. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- #import "UIViewController+Extensions.h"
- #import "VMCursor.h"
- #import "VMScroll.h"
- #import "VMDisplayMetalViewController+Gamepad.h"
- #import "VMDisplayMetalViewController+Touch.h"
- #import "CSDisplayMetal.h"
- #import "UTMQemuConfiguration.h"
- #import "UTMQemuConfiguration+Constants.h"
- #import "UTMLogging.h"
- const CGFloat kThumbstickSpeedMultiplier = 1000; // in points per second
- @implementation VMDisplayMetalViewController(Gamepad)
- - (void)initGamepad {
- // notifications for controller (dis)connect
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerWasConnected:) name:GCControllerDidConnectNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerWasDisconnected:) name:GCControllerDidDisconnectNotification object:nil];
- for (GCController *controller in [GCController controllers]) {
- [self setupController:controller];
- }
- }
- #pragma mark - Gamepad connection
- - (void)controllerWasConnected:(NSNotification *)notification {
- // a controller was connected
- GCController *controller = (GCController *)notification.object;
- UTMLog(@"Controller connected: %@", controller.vendorName);
- [self setupController:controller];
- }
- - (void)controllerWasDisconnected:(NSNotification *)notification {
- // a controller was disconnected
- GCController *controller = (GCController *)notification.object;
- UTMLog(@"Controller disconnected: %@", controller.vendorName);
- }
- - (void)setupController:(GCController *)controller {
- GCExtendedGamepad *gamepad = controller.extendedGamepad;
- __weak typeof(self) _self = self;
- _controller = controller;
- UTMLog(@"active controller switched to: %@", controller.vendorName);
-
- gamepad.leftTrigger.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonTriggerLeft" pressed:pressed];
- };
-
- gamepad.rightTrigger.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonTriggerRight" pressed:pressed];
- };
-
- gamepad.leftShoulder.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonShoulderLeft" pressed:pressed];
- };
-
- gamepad.rightShoulder.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonShoulderRight" pressed:pressed];
- };
-
- gamepad.buttonA.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonA" pressed:pressed];
- };
-
- gamepad.buttonB.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonB" pressed:pressed];
- };
-
- gamepad.buttonX.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonX" pressed:pressed];
- };
-
- gamepad.buttonY.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonY" pressed:pressed];
- };
-
- gamepad.dpad.up.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonDpadUp" pressed:pressed];
- };
-
- gamepad.dpad.left.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonDpadLeft" pressed:pressed];
- };
-
- gamepad.dpad.down.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonDpadDown" pressed:pressed];
- };
-
- gamepad.dpad.right.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonDpadRight" pressed:pressed];
- };
-
- gamepad.leftThumbstick.valueChangedHandler = ^(GCControllerDirectionPad * _Nonnull dpad, float xValue, float yValue) {
- VMDisplayMetalViewController *s = _self;
- CGPoint velocity = CGPointMake(xValue * kThumbstickSpeedMultiplier, -yValue * kThumbstickSpeedMultiplier);
- [s->_scroll startMovement:CGPointZero];
- [s->_scroll updateMovement:CGPointMake(xValue, yValue)];
- [s->_scroll endMovementWithVelocity:velocity resistance:0];
- };
-
- gamepad.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad * _Nonnull dpad, float xValue, float yValue) {
- NSInteger speed = [_self integerForSetting:@"GCThumbstickRightSpeed"];
- VMDisplayMetalViewController *s = _self;
- CGPoint center = s->_cursor.center;
- CGPoint start = CGPointMake(xValue * speed, -yValue * speed);
- CGPoint velocity = CGPointMake(xValue * kThumbstickSpeedMultiplier, -yValue * kThumbstickSpeedMultiplier);
- [s->_cursor startMovement:center];
- [s->_cursor updateMovement:CGPointMake(center.x + start.x, center.y + start.y)];
- [s->_cursor endMovementWithVelocity:velocity resistance:0];
- };
-
- if (@available(iOS 13.0, *)) {
- gamepad.buttonMenu.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
- [_self gamepadButton:@"GCButtonMenu" pressed:pressed];
- };
- }
- }
- - (void)gamepadButton:(NSString *)identifier pressed:(BOOL)isPressed {
- NSInteger value = [self integerForSetting:identifier];
- UTMLog(@"GC button %@ (%ld) pressed:%d", identifier, value, isPressed);
- switch (value) {
- case 0:
- break;
- case -1:
- [self.vmInput sendMouseButton:kCSInputButtonLeft pressed:isPressed];
- _mouseLeftDown = isPressed;
- break;
- case -3:
- [self.vmInput sendMouseButton:kCSInputButtonRight pressed:isPressed];
- _mouseRightDown = isPressed;
- break;
- case -2:
- [self.vmInput sendMouseButton:kCSInputButtonMiddle pressed:isPressed];
- _mouseMiddleDown = isPressed;
- break;
- default:
- [self sendExtendedKey:isPressed ? kCSInputKeyPress : kCSInputKeyRelease code:(int)value];
- break;
- }
- }
- @end
|