diff --git a/iOS/GBBackgroundView.h b/iOS/GBBackgroundView.h index 9659588..41ed47a 100644 --- a/iOS/GBBackgroundView.h +++ b/iOS/GBBackgroundView.h @@ -8,6 +8,7 @@ @property (readonly) GBView *gbView; @property (nonatomic) GBLayout *layout; @property (nonatomic) bool usesSwipePad; +@property (nonatomic) bool fullScreenMode; - (void)enterPreviewMode:(bool)showLabel; - (void)reloadThemeImages; diff --git a/iOS/GBBackgroundView.m b/iOS/GBBackgroundView.m index 8878717..57f4c84 100644 --- a/iOS/GBBackgroundView.m +++ b/iOS/GBBackgroundView.m @@ -91,6 +91,7 @@ static GB_key_mask_t angleToKeyMask(double angle) bool _inDynamicSpeedMode; bool _previewMode; + UIView *_fadeView; UIImageView *_dpadView; UIImageView *_dpadShadowView; UIImageView *_aButtonView; @@ -104,6 +105,7 @@ static GB_key_mask_t angleToKeyMask(double angle) NSTimer *_fadeTimer; GB_key_mask_t _lastMask; + bool _fullScreenMode; } - (void)reloadThemeImages @@ -142,11 +144,16 @@ static GB_key_mask_t angleToKeyMask(double angle) _dpadShadowView.hidden = true; _gbView = [[GBViewMetal alloc] initWithFrame:CGRectZero]; + _fadeView = [[UIView alloc] initWithFrame:self.frame]; + _fadeView.backgroundColor = [UIColor colorWithWhite:0 alpha:0]; + _fadeView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self addSubview:_dpadView]; [self addSubview:_aButtonView]; [self addSubview:_bButtonView]; [self addSubview:_startButtonView]; [self addSubview:_selectButtonView]; + [self addSubview:_fadeView]; [self addSubview:_gbView]; [_dpadView addSubview:_dpadShadowView]; @@ -183,6 +190,10 @@ static GB_key_mask_t angleToKeyMask(double angle) - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (_previewMode) return; + if (_fullScreenMode) { + self.fullScreenMode = false; + return; + } static const double dpadRadius = 75; CGPoint dpadLocation = _layout.dpadLocation; double factor = [UIScreen mainScreen].scale; @@ -460,7 +471,17 @@ static GB_key_mask_t angleToKeyMask(double angle) screenFrame.size.width /= [UIScreen mainScreen].scale; screenFrame.size.height /= [UIScreen mainScreen].scale; - _gbView.frame = screenFrame; + if (_fullScreenMode) { + CGRect fullScreenFrame = layout.fullScreenRect; + fullScreenFrame.origin.x /= [UIScreen mainScreen].scale; + fullScreenFrame.origin.y /= [UIScreen mainScreen].scale; + fullScreenFrame.size.width /= [UIScreen mainScreen].scale; + fullScreenFrame.size.height /= [UIScreen mainScreen].scale; + _gbView.frame = fullScreenFrame; + } + else { + _gbView.frame = screenFrame; + } screenFrame.origin.x += 8; screenFrame.origin.y += 8; @@ -579,4 +600,21 @@ static GB_key_mask_t angleToKeyMask(double angle) _previewMode = true; } +- (bool)fullScreenMode +{ + return _fullScreenMode; +} + +- (void)setFullScreenMode:(bool)fullScreenMode +{ + if (fullScreenMode == _fullScreenMode) return; + _fullScreenMode = fullScreenMode; + [UIView animateWithDuration:1.0/3 animations:^{ + // Animating alpha has some weird quirks for some reason + _fadeView.backgroundColor = [UIColor colorWithWhite:0 alpha:fullScreenMode]; + [self setLayout:_layout]; + }]; + [self.window.rootViewController setNeedsStatusBarAppearanceUpdate]; +} + @end diff --git a/iOS/GBHorizontalLayout.m b/iOS/GBHorizontalLayout.m index 66f7cb3..a06a8b5 100644 --- a/iOS/GBHorizontalLayout.m +++ b/iOS/GBHorizontalLayout.m @@ -14,6 +14,10 @@ screenRect.size.height = self.hasFractionalPixels? (resolution.height - self.homeBar) : floor((resolution.height - self.homeBar) / 144) * 144; screenRect.size.width = screenRect.size.height / 144 * 160; + screenRect.origin.x = (resolution.width - screenRect.size.width) / 2; + screenRect.origin.y = (resolution.height - self.homeBar - screenRect.size.height) / 2; + self.fullScreenRect = screenRect; + double horizontalMargin, verticalMargin; while (true) { horizontalMargin = (resolution.width - screenRect.size.width) / 2; diff --git a/iOS/GBLayout.h b/iOS/GBLayout.h index cda5741..1f0c2d1 100644 --- a/iOS/GBLayout.h +++ b/iOS/GBLayout.h @@ -7,6 +7,7 @@ @property (readonly) UIImage *background; @property (readonly) CGRect screenRect; +@property (readonly) CGRect fullScreenRect; @property (readonly) CGRect logoRect; @property (readonly) CGPoint dpadLocation; @property (readonly) CGPoint aLocation; @@ -23,6 +24,7 @@ @interface GBLayout() @property UIImage *background; @property CGRect screenRect; +@property CGRect fullScreenRect; @property CGPoint dpadLocation; @property CGPoint aLocation; @property CGPoint bLocation; diff --git a/iOS/GBSettingsViewController.m b/iOS/GBSettingsViewController.m index de75ee3..bc8b4b6 100644 --- a/iOS/GBSettingsViewController.m +++ b/iOS/GBSettingsViewController.m @@ -399,11 +399,17 @@ static NSString const *typeLightTemp = @"typeLightTemp"; ], @"footer": ^NSString *(){ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBSwipeState"]) { - return @"Swipe down on the Game Boy to save the state into state slot 1. Swipe up to load the state from state slot 1"; + return @"Swipe down on the Game Boy to save the state into state slot 1. Swipe up to load the state from state slot 1."; } return @" "; // This space is needed, otherwise UITableView spacing breaks }, }, + @{ + @"items": @[ + @{@"type": typeCheck, @"pref": @"GBControllersHideInterface", @"title": @"Hide UI While Using a Controller"}, + ], + @"footer": @"When enabled, the on-screen user interface will be hidden while a game controller is being used." + }, @{ @"header": @"Enable Rumble", @"items": @[ diff --git a/iOS/GBVerticalLayout.m b/iOS/GBVerticalLayout.m index 44797d4..fd7676b 100644 --- a/iOS/GBVerticalLayout.m +++ b/iOS/GBVerticalLayout.m @@ -14,6 +14,10 @@ screenRect.size.width = self.hasFractionalPixels? resolution.width : floor(resolution.width / 160) * 160; screenRect.size.height = screenRect.size.width / 160 * 144; + screenRect.origin.x = (resolution.width - screenRect.size.width) / 2; + screenRect.origin.y = (resolution.height - screenRect.size.height) / 2; + self.fullScreenRect = screenRect; + double screenBorderWidth = screenRect.size.width / 40; screenRect.origin.x = (resolution.width - screenRect.size.width) / 2; screenRect.origin.y = self.minY + screenBorderWidth * 2; diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 01bab76..eef58cc 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -336,6 +336,11 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) name:GCControllerDidConnectNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(controllerDisconnected:) + name:GCControllerDidDisconnectNotification + object:nil]; + for (NSString *name in @[UIScreenDidConnectNotification, UIScreenDidDisconnectNotification, UIScreenModeDidChangeNotification]) { @@ -381,6 +386,12 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) } } +- (void)controllerDisconnected:(NSNotification *)notification +{ + if (notification.object == _lastController) { + _backgroundView.fullScreenMode = false; + } +} - (void)setControllerHandlers { @@ -419,6 +430,10 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) - (void)controller:(GCController *)controller buttonChanged:(GCControllerButtonInput *)button usage:(GBControllerUsage)usage { [self updateLastController:controller]; + if (_running && button.value > 0.25 && + [[NSUserDefaults standardUserDefaults] boolForKey:@"GBControllersHideInterface"]) { + _backgroundView.fullScreenMode = true; + } GBButton gbButton = [GBSettingsViewController controller:controller convertUsageToButton:usage]; static const double analogThreshold = 0.0625; @@ -488,11 +503,20 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) - (void)controller:(GCController *)controller axisChanged:(GCControllerDirectionPad *)axis usage:(GBControllerUsage)usage { [self updateLastController:controller]; + bool left = axis.left.value > 0.5; + bool right = axis.right.value > 0.5; + bool up = axis.up.value > 0.5; + bool down = axis.down.value > 0.5; - GB_set_key_state(&_gb, GB_KEY_LEFT, axis.left.value > 0.5); - GB_set_key_state(&_gb, GB_KEY_RIGHT, axis.right.value > 0.5); - GB_set_key_state(&_gb, GB_KEY_UP, axis.up.value > 0.5); - GB_set_key_state(&_gb, GB_KEY_DOWN, axis.down.value > 0.5); + if (_running && (left || right || up || down ) && + [[NSUserDefaults standardUserDefaults] boolForKey:@"GBControllersHideInterface"]) { + _backgroundView.fullScreenMode = true; + } + + GB_set_key_state(&_gb, GB_KEY_LEFT, left); + GB_set_key_state(&_gb, GB_KEY_RIGHT, right); + GB_set_key_state(&_gb, GB_KEY_UP, up); + GB_set_key_state(&_gb, GB_KEY_DOWN, down); } - (void)controller:(GCController *)controller motionChanged:(GCMotion *)motion @@ -793,7 +817,8 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) _backgroundView.frame = [layout viewRectForOrientation:orientation]; _backgroundView.layout = layout; if (!self.presentedViewController) { - _window.backgroundColor = layout.theme.backgroundGradientBottom; + _window.backgroundColor = _backgroundView.fullScreenMode? [UIColor blackColor] : + layout.theme.backgroundGradientBottom; } } @@ -850,9 +875,9 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) - (UIStatusBarStyle)preferredStatusBarStyle { if (@available(iOS 13.0, *)) { - return _verticalLayout.theme.isDark? UIStatusBarStyleLightContent : UIStatusBarStyleDarkContent; + return (_verticalLayout.theme.isDark || _backgroundView.fullScreenMode)? UIStatusBarStyleLightContent : UIStatusBarStyleDarkContent; } - return _verticalLayout.theme.isDark? UIStatusBarStyleLightContent : UIStatusBarStyleDefault; + return (_verticalLayout.theme.isDark || _backgroundView.fullScreenMode)? UIStatusBarStyleLightContent : UIStatusBarStyleDefault; } diff --git a/iOS/main.m b/iOS/main.m index 612a8c7..7d1cb76 100644 --- a/iOS/main.m +++ b/iOS/main.m @@ -26,6 +26,7 @@ int main(int argc, char * argv[]) @"GBDynamicSpeed": @NO, @"GBInterfaceTheme": @"SameBoy", + @"GBControllersHideInterface": @YES, @"GBCurrentTheme": @"Lime (Game Boy)", // Default themes