diff --git a/Natives/FileListViewController.m b/Natives/FileListViewController.m index b39e22bc..26f2c3a7 100644 --- a/Natives/FileListViewController.m +++ b/Natives/FileListViewController.m @@ -3,7 +3,7 @@ @interface FileListViewController () { } -@property(nonatomic, strong) NSMutableArray *fileList; +@property(nonatomic) NSMutableArray *fileList; @end diff --git a/Natives/LauncherNavigationController.m b/Natives/LauncherNavigationController.m index 614e0a10..62f3d088 100644 --- a/Natives/LauncherNavigationController.m +++ b/Natives/LauncherNavigationController.m @@ -72,6 +72,7 @@ int versionSelectedAt = 0; [self.toolbar addSubview:self.progressViewSub]; self.buttonInstall = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(self.buttonInstall); self.buttonInstall.enabled = NO; [self.buttonInstall setTitle:NSLocalizedString(@"Play", nil) forState:UIControlStateNormal]; self.buttonInstall.autoresizingMask = AUTORESIZE_MASKS; @@ -83,6 +84,7 @@ int versionSelectedAt = 0; [self.toolbar addSubview:self.buttonInstall]; UIButton *buttonCustomControls = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(buttonCustomControls); [buttonCustomControls setTitle:NSLocalizedString(@"launcher.menu.custom_controls", nil) forState:UIControlStateNormal]; buttonCustomControls.autoresizingMask = AUTORESIZE_MASKS; buttonCustomControls.frame = CGRectMake(0, self.toolbar.frame.size.height/2, splitWidth, self.toolbar.frame.size.height/2); @@ -90,6 +92,7 @@ int versionSelectedAt = 0; [self.toolbar addSubview:buttonCustomControls]; UIButton *buttonInstallJar = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(buttonInstallJar); [buttonInstallJar setTitle:NSLocalizedString(@"launcher.menu.install_jar", nil) forState:UIControlStateNormal]; buttonInstallJar.autoresizingMask = AUTORESIZE_MASKS; buttonInstallJar.frame = CGRectMake(splitWidth*2, self.toolbar.frame.size.height/2, splitWidth, self.toolbar.frame.size.height/2); diff --git a/Natives/LauncherPrefGameDirViewController.m b/Natives/LauncherPrefGameDirViewController.m index d40479b4..0488b036 100644 --- a/Natives/LauncherPrefGameDirViewController.m +++ b/Natives/LauncherPrefGameDirViewController.m @@ -5,7 +5,7 @@ #import "ios_uikit_bridge.h" @interface LauncherPrefGameDirViewController () -@property NSMutableArray *array; +@property(nonatomic) NSMutableArray *array; @end @implementation LauncherPrefGameDirViewController diff --git a/Natives/LauncherPreferencesViewController2.m b/Natives/LauncherPreferencesViewController2.m index 180046b2..cfbe2afd 100644 --- a/Natives/LauncherPreferencesViewController2.m +++ b/Natives/LauncherPreferencesViewController2.m @@ -12,9 +12,9 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *); @interface LauncherPreferencesViewController2() {} -@property NSArray* prefSections; -@property NSArray*>* prefContents; -@property BOOL prefDetailVisible; +@property(nonatomic) NSArray* prefSections; +@property(nonatomic) NSArray*>* prefContents; +@property(nonatomic) BOOL prefDetailVisible; @property CreateView typeButton, typeChildPane, typePickField, typeTextField, typeSlider, typeSwitch; @end diff --git a/Natives/LoginViewController.m b/Natives/LoginViewController.m index 90485ba9..f6ae631a 100644 --- a/Natives/LoginViewController.m +++ b/Natives/LoginViewController.m @@ -25,7 +25,7 @@ extern NSMutableDictionary *prefDict; #pragma mark - LoginViewController @interface LoginViewController () {} -@property ASWebAuthenticationSession *authVC; +@property(nonatomic) ASWebAuthenticationSession *authVC; @end @implementation LoginViewController @@ -38,11 +38,11 @@ extern NSMutableDictionary *prefDict; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(msaLoginCallback:) name:@"MSALoginCallback" object:nil]; - CGRect screenBounds = [[UIScreen mainScreen] bounds]; + CGRect screenBounds = UIScreen.mainScreen.bounds; - int width = (int) roundf(screenBounds.size.width); - int height = (int) roundf(screenBounds.size.height) - self.navigationController.navigationBar.frame.size.height; - int rawHeight = (int) roundf(screenBounds.size.height); + CGFloat width = screenBounds.size.width; + CGFloat height = screenBounds.size.height - self.navigationController.navigationBar.frame.size.height; + CGFloat rawHeight = screenBounds.size.height; UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; @@ -99,7 +99,8 @@ extern NSMutableDictionary *prefDict; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"login.menu.about", nil) style:UIBarButtonItemStyleDone target:self action:@selector(aboutLauncher)]; } - UIButton *button_faq = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + UIButton *button_faq = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(button_faq); [button_faq setTitle:NSLocalizedString(@"FAQ", @"Frequently asked questions") forState:UIControlStateNormal]; button_faq.frame = CGRectMake(widthSplit2 - (((width - widthSplit * 2.0) / 2) / 2), (height - 80.0), (width - widthSplit * 2.0) / 2, 40.0); if([date isEqualToString:@"06-29"] || [date isEqualToString:@"06-30"] || [date isEqualToString:@"07-01"]) { @@ -117,7 +118,8 @@ extern NSMutableDictionary *prefDict; } [scrollView addSubview:button_faq]; - UIButton *button_login = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + UIButton *button_login = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(button_login); [button_login setTitle:NSLocalizedString(@"Sign in", nil) forState:UIControlStateNormal]; button_login.frame = CGRectMake(button_faq.frame.origin.x - button_faq.frame.size.width - 20, (height - 80.0), (width - widthSplit * 2.0) / 2, 40.0); if([date isEqualToString:@"06-29"] || [date isEqualToString:@"06-30"] || [date isEqualToString:@"07-01"]) { @@ -147,7 +149,8 @@ extern NSMutableDictionary *prefDict; } [scrollView addSubview:button_login]; - UIButton *button_accounts = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + UIButton *button_accounts = [UIButton buttonWithType:UIButtonTypeSystem]; + setButtonPointerInteraction(button_accounts); [button_accounts setTitle:NSLocalizedString(@"Accounts", nil) forState:UIControlStateNormal]; button_accounts.frame = CGRectMake(button_faq.frame.origin.x + button_faq.frame.size.width + 20, (height - 80.0), (width - widthSplit * 2.0) / 2, 40.0); if([date isEqualToString:@"06-29"] || [date isEqualToString:@"06-30"] || [date isEqualToString:@"07-01"]) { diff --git a/Natives/SurfaceViewController.h b/Natives/SurfaceViewController.h index 2a919654..9282d58a 100644 --- a/Natives/SurfaceViewController.h +++ b/Natives/SurfaceViewController.h @@ -5,11 +5,12 @@ CGRect virtualMouseFrame; CGPoint lastVirtualMousePoint; - @interface SurfaceViewController : UIViewController -@property(nonatomic, strong) GameSurfaceView* surfaceView; +@property(nonatomic) GameSurfaceView* surfaceView; @property UIImageView* mousePointerView; -@property UIPanGestureRecognizer* scrollPanGesture; +@property(nonatomic) UIPanGestureRecognizer* scrollPanGesture; + +- (void)sendTouchPoint:(CGPoint)location withEvent:(int)event; @end diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 6affa896..2f923b6f 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -220,6 +220,12 @@ BOOL slideableHotbar; [self.navigationItem setHidesBackButton:YES animated:YES]; [self.navigationController setNavigationBarHidden:YES animated:YES]; + // Perform Gamepad joystick ticking, while alos controlling frame rate? + CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:ControllerInput.class selector:@selector(tick)]; + if (@available(iOS 15.0, *)) { + displayLink.preferredFrameRateRange = CAFrameRateRangeMake(60, 120, 120); + } + [displayLink addToRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes]; CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGFloat screenScale = [[UIScreen mainScreen] scale]; @@ -355,7 +361,7 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; self.mouseConnectCallback = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { NSLog(@"Input: Mouse connected!"); GCMouse* mouse = note.object; - [self registerMouseCallbacks: mouse]; + [self registerMouseCallbacks:mouse]; [self setNeedsUpdateOfPrefersPointerLocked]; }]; self.mouseDisconnectCallback = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { @@ -407,6 +413,7 @@ self.view.frame.size.width * 0.3 - 36.0 * 0.7, self.view.frame.size.height)]; [self updateJetsamControl]; [self updatePreferenceChanges]; [self executebtn_special_togglebtn:0]; + [self launchMinecraft]; } @@ -830,36 +837,34 @@ CGPoint lastCenterPoint; } - (void)surfaceOnHover:(UIHoverGestureRecognizer *)sender API_AVAILABLE(ios(13.0)) { - if (@available(iOS 13.0, *)) { - if (@available(iOS 14.0, *)) { - if (isGrabbing) return; - } - CGPoint point = [sender locationInView:self.rootView]; - // NSLog(@"Mouse move!!"); - // NSLog(@"Mouse pos = %f, %f", point.x, point.y); - switch (sender.state) { - case UIGestureRecognizerStateBegan: - [self sendTouchPoint:point withEvent:ACTION_DOWN]; - break; - case UIGestureRecognizerStateChanged: - [self sendTouchPoint:point withEvent:ACTION_MOVE]; - break; - case UIGestureRecognizerStateEnded: - case UIGestureRecognizerStateCancelled: - [self sendTouchPoint:point withEvent:ACTION_UP]; - break; - default: - // point = CGPointMake(-1, -1); - break; - } + if (@available(iOS 14.0, *)) { + if (isGrabbing) return; + } + CGPoint point = [sender locationInView:self.rootView]; + // NSLog(@"Mouse move!!"); + // NSLog(@"Mouse pos = %f, %f", point.x, point.y); + switch (sender.state) { + case UIGestureRecognizerStateBegan: + [self sendTouchPoint:point withEvent:ACTION_DOWN]; + break; + case UIGestureRecognizerStateChanged: + [self sendTouchPoint:point withEvent:ACTION_MOVE]; + break; + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + [self sendTouchPoint:point withEvent:ACTION_UP]; + break; + default: + // point = CGPointMake(-1, -1); + break; } } -(void)surfaceOnLongpress:(UILongPressGestureRecognizer *)sender { if (!slideableHotbar) { - CGFloat screenScale = [[UIScreen mainScreen] scale]; CGPoint location = [sender locationInView:self.rootView]; + CGFloat screenScale = UIScreen.mainScreen.scale; currentHotbarSlot = callback_SurfaceViewController_touchHotbar(location.x * screenScale, location.y * screenScale); } if (sender.state == UIGestureRecognizerStateBegan) { @@ -895,19 +900,16 @@ CallbackBridge_nativeSendKey(GLFW_KEY_Q, 0, 0, 0); sender.state == UIGestureRecognizerStateEnded) { CGPoint velocity = [sender velocityInView:self.rootView]; if (velocity.x != 0.0f || velocity.y != 0.0f) { - CallbackBridge_nativeSendScroll((CGFloat) (velocity.x/10.0), (CGFloat) (velocity.y/10.0)); + CallbackBridge_nativeSendScroll(velocity.x/100.0, velocity.y/100.0); } } } -// FIXME: incomplete - (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)) API_AVAILABLE(ios(13.4)) API_AVAILABLE(ios(13.4)){ - NSLog(@"regionForRequest called"); return nil; } - (UIPointerStyle *)pointerInteraction:(UIPointerInteraction *)interaction styleForRegion:(UIPointerRegion *)region API_AVAILABLE(ios(13.4)){ - NSLog(@"styleForRegion called"); return [UIPointerStyle hiddenPointerStyle]; } @@ -1111,7 +1113,7 @@ int touchesMovedCount; for (UITouch *touch in touches) { if (@available(iOS 14.0, *)) { // 13.4 - if (touch.type == UITouchTypeIndirectPointer) { + if (isGrabbing && touch.type == UITouchTypeIndirectPointer) { continue; // handle this in a different place } } diff --git a/Natives/input/ControllerInput.h b/Natives/input/ControllerInput.h index 14de3bc7..62d142b8 100644 --- a/Natives/input/ControllerInput.h +++ b/Natives/input/ControllerInput.h @@ -6,5 +6,6 @@ + (void)initKeycodeTable; + (void)registerControllerCallbacks:(GCController *)controller; + (void)unregisterControllerCallbacks:(GCController *)controller; ++ (void)tick; @end diff --git a/Natives/input/ControllerInput.m b/Natives/input/ControllerInput.m index ed0c8c06..43aec444 100644 --- a/Natives/input/ControllerInput.m +++ b/Natives/input/ControllerInput.m @@ -4,6 +4,10 @@ #include "../glfw_keycodes.h" +CFAbsoluteTime lastFrameTime; +CGFloat lastXValue; // lastHorizontalValue +CGFloat lastYValue; // lastVerticalValue + @implementation ControllerInput NSMutableDictionary *gameMap, *menuMap; @@ -166,34 +170,27 @@ BOOL leftShiftHeld; gamepad.leftThumbstick.valueChangedHandler = ^(GCControllerDirectionPad * _Nonnull dpad, float xValue, float yValue) { if (!isGrabbing) { - UIImageView *pointerView = [(id)currentWindow().rootViewController mousePointerView]; - virtualMouseFrame.origin.x += xValue; - virtualMouseFrame.origin.y += yValue; - pointerView.frame = virtualMouseFrame; + lastXValue = xValue; + lastYValue = yValue; } - CGFloat screenScale = UIScreen.mainScreen.scale; - callback_SurfaceViewController_onTouch(ACTION_MOVE_MOTION, - isGrabbing ? xValue : virtualMouseFrame.origin.x*screenScale, - isGrabbing ? yValue : virtualMouseFrame.origin.y*screenScale - ); }; gamepad.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad * _Nonnull dpad, float xValue, float yValue) { - if (!isGrabbing) { - return; + if (isGrabbing) { + lastXValue = xValue; + lastYValue = yValue; } - - dpad.up.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { - [self sendKeyEvent:GLFW_KEY_W pressed:pressed]; - }; - dpad.left.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { - [self sendKeyEvent:GLFW_KEY_A pressed:pressed]; - }; - dpad.down.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { - [self sendKeyEvent:GLFW_KEY_S pressed:pressed]; - }; - dpad.right.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { - [self sendKeyEvent:GLFW_KEY_D pressed:pressed]; - }; + }; + gamepad.rightThumbstick.up.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { + [self sendKeyEvent:GLFW_KEY_W pressed:pressed]; + }; + gamepad.rightThumbstick.left.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { + [self sendKeyEvent:GLFW_KEY_A pressed:pressed]; + }; + gamepad.rightThumbstick.down.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { + [self sendKeyEvent:GLFW_KEY_S pressed:pressed]; + }; + gamepad.rightThumbstick.right.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { + [self sendKeyEvent:GLFW_KEY_D pressed:pressed]; }; if (@available(iOS 12.1, *)) { gamepad.leftThumbstickButton.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) { @@ -205,6 +202,28 @@ BOOL leftShiftHeld; } } +/** + * Send the new mouse position, computing the delta + */ ++ (void)tick { + // There isn't a convenient way to get ns, use ms at this point + CGFloat frameTimeMilis = CACurrentMediaTime(); + // GameController automatically performs deadzone calculations + // so we just take the raw input + if (lastFrameTime != 0 && (lastXValue != 0 || lastYValue != 0)) { + CGFloat acceleration = MathUtils_dist(0, 0, lastXValue, lastYValue); // magnitude + CGFloat deltaX = lastXValue * acceleration * 18; + CGFloat deltaY = -lastYValue * acceleration * 18; + CGFloat deltaTimeScale = (frameTimeMilis - lastFrameTime) / 0.016666666; // Scale of 1 = 60Hz + deltaX *= deltaTimeScale; + deltaY *= deltaTimeScale; + + SurfaceViewController *vc = (id)(currentWindow().rootViewController); + [vc sendTouchPoint:CGPointMake(deltaX, deltaY) withEvent:ACTION_MOVE_MOTION]; + } + lastFrameTime = frameTimeMilis; +} + + (void)unregisterControllerCallbacks:(GCController *)controller { GCExtendedGamepad *gamepad = controller.extendedGamepad; gamepad.leftShoulder.pressedChangedHandler = nil; diff --git a/Natives/main.m b/Natives/main.m index 8c780267..7c2f8bfd 100644 --- a/Natives/main.m +++ b/Natives/main.m @@ -105,16 +105,19 @@ void init_logDeviceAndVer(char *argument) { const char *deviceSoftware = [[[UIDevice currentDevice] systemVersion] cStringUsingEncoding:NSUTF8StringEncoding]; // PojavLauncher version - regLog("[Pre-Init] PojavLauncher version: %s - branch %s commit %s", CONFIG_TYPE, CONFIG_BRANCH, CONFIG_COMMIT); + regLog("[Pre-Init] PojavLauncher version: %s, branch: %s, commit: %s", CONFIG_TYPE, CONFIG_BRANCH, CONFIG_COMMIT); setenv("POJAV_DETECTEDHW", deviceHardware, 1); setenv("POJAV_DETECTEDSW", deviceSoftware, 1); - if (getenv("POJAV_DETECTEDJB")) { - regLog("[Pre-Init] %s with iOS %s (Jailbroken)", deviceHardware, deviceSoftware); - } else { - regLog("[Pre-Init] %s with iOS %s (Unjailbroken)", deviceHardware, deviceSoftware); + NSString *tsPath = [NSString stringWithFormat:@"%s/../_TrollStore", getenv("BUNDLE_PATH")]; + const char *type = "Unjailbroken"; + if ([fm fileExistsAtPath:tsPath]) { + type = "TrollStore"; + } else if (getenv("POJAV_DETECTEDJB")) { + type = "Jailbroken"; } + regLog("[Pre-Init] %s with iOS %s (%s)", deviceHardware, deviceSoftware, type); NSString *jvmPath = [NSString stringWithFormat:@"%s/jvm", getenv("BUNDLE_PATH")]; if (![fm fileExistsAtPath:jvmPath]) { diff --git a/Natives/utils.h b/Natives/utils.h index d0da80b2..0731f768 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -94,6 +94,7 @@ CGFloat MathUtils_dist(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2); CGFloat MathUtils_map(CGFloat x, CGFloat in_min, CGFloat in_max, CGFloat out_min, CGFloat out_max); CGFloat dpToPx(CGFloat dp); CGFloat pxToDp(CGFloat px); +void setButtonPointerInteraction(UIButton *button); void setViewBackgroundColor(UIView* view); void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer); diff --git a/Natives/utils.m b/Natives/utils.m index a112ef57..5f1ecc01 100644 --- a/Natives/utils.m +++ b/Natives/utils.m @@ -75,6 +75,16 @@ CGFloat pxToDp(CGFloat px) { return px / screenScale; } +void setButtonPointerInteraction(UIButton *button) { + if(@available (iOS 13.4, *)) { + button.pointerInteractionEnabled = YES; + button.pointerStyleProvider = ^ UIPointerStyle* (UIButton* button, UIPointerEffect* proposedEffect, UIPointerShape* proposedShape) { + UITargetedPreview *preview = [[UITargetedPreview alloc] initWithView:button]; + return [UIPointerStyle styleWithEffect:[UIPointerHighlightEffect effectWithPreview:preview] shape:proposedShape]; + }; + } +} + void setViewBackgroundColor(UIView* view) { if(@available(iOS 13.0, *)) { view.backgroundColor = UIColor.systemBackgroundColor;