From 8ded1ca3b357cf7982df133bdb4f70dece7a9514 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 19 Sep 2024 21:02:59 +0300 Subject: [PATCH] Move the palette picker to its own class --- iOS/GBPalettePicker.h | 7 ++ iOS/GBPalettePicker.m | 132 +++++++++++++++++++++++++++++++++ iOS/GBSettingsViewController.h | 1 - iOS/GBSettingsViewController.m | 105 ++++---------------------- iOS/GBViewController.m | 3 +- 5 files changed, 155 insertions(+), 93 deletions(-) create mode 100644 iOS/GBPalettePicker.h create mode 100644 iOS/GBPalettePicker.m diff --git a/iOS/GBPalettePicker.h b/iOS/GBPalettePicker.h new file mode 100644 index 0000000..4b9cc93 --- /dev/null +++ b/iOS/GBPalettePicker.h @@ -0,0 +1,7 @@ +#import +#import + +@interface GBPalettePicker : UITableViewController ++ (const GB_palette_t *)paletteForTheme:(NSString *)theme; +@end + diff --git a/iOS/GBPalettePicker.m b/iOS/GBPalettePicker.m new file mode 100644 index 0000000..d518404 --- /dev/null +++ b/iOS/GBPalettePicker.m @@ -0,0 +1,132 @@ +#import "GBPalettePicker.h" + +@interface GBPalettePicker () +{ + NSArray * _cacheNames; +} + +@end + +@implementation GBPalettePicker + ++ (const GB_palette_t *)paletteForTheme:(NSString *)theme +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + if ([theme isEqualToString:@"Greyscale"]) { + return &GB_PALETTE_GREY; + } + if ([theme isEqualToString:@"Lime (Game Boy)"]) { + return &GB_PALETTE_DMG; + } + if ([theme isEqualToString:@"Olive (Pocket)"]) { + return &GB_PALETTE_MGB; + } + if ([theme isEqualToString:@"Teal (Light)"]) { + return &GB_PALETTE_GBL; + } + static GB_palette_t customPalette; + NSArray *colors = [defaults dictionaryForKey:@"GBThemes"][theme][@"Colors"]; + if (colors.count != 5) return &GB_PALETTE_DMG; + unsigned i = 0; + for (NSNumber *color in colors) { + uint32_t c = [color unsignedIntValue]; + customPalette.colors[i++] = (struct GB_color_s) {c, c >> 8, c >> 16}; + } + return &customPalette; +} + ++ (UIColor *)colorFromGBColor:(const struct GB_color_s *)color +{ + return [UIColor colorWithRed:color->r / 255.0 + green:color->g / 255.0 + blue:color->b / 255.0 + alpha:1.0]; +} + ++ (UIImage *)previewImageForTheme:(NSString *)theme +{ + const GB_palette_t *palette = [self paletteForTheme:theme]; + UIGraphicsBeginImageContextWithOptions((CGSize){29, 29}, false, [UIScreen mainScreen].scale); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 29, 29) cornerRadius:7]; + [[self colorFromGBColor:&palette->colors[4]] set]; + [path fill]; + + path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(4, 4, 9, 9) cornerRadius:2]; + [[self colorFromGBColor:&palette->colors[0]] set]; + [path fill]; + + path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(16, 4, 9, 9) cornerRadius:2]; + [[self colorFromGBColor:&palette->colors[1]] set]; + [path fill]; + + path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(4, 16, 9, 9) cornerRadius:2]; + [[self colorFromGBColor:&palette->colors[2]] set]; + [path fill]; + + path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(16, 16, 9, 9) cornerRadius:2]; + [[self colorFromGBColor:&palette->colors[3]] set]; + [path fill]; + + UIImage *ret = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return ret; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 2; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + if (section == 0) return 4; + return [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBThemes"].count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; + + NSString *name = nil; + if (indexPath.section == 0) { + name = @[ + @"Greyscale", + @"Lime (Game Boy)", + @"Olive (Pocket)", + @"Teal (Light)", + ][indexPath.row]; + } + else { + if (!_cacheNames) { + _cacheNames = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBThemes"].allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + } + name = _cacheNames[indexPath.row]; + } + + cell.textLabel.text = name; + if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] isEqual:name]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + } + + cell.imageView.image = [self.class previewImageForTheme:name]; + return cell; + +} + +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + + [[NSUserDefaults standardUserDefaults] setObject:[self.tableView cellForRowAtIndexPath:indexPath].textLabel.text + forKey:@"GBCurrentTheme"]; + [self.tableView reloadData]; + return nil; +} + + +- (NSString *)title +{ + return @"Monochrome Palette"; +} + +@end diff --git a/iOS/GBSettingsViewController.h b/iOS/GBSettingsViewController.h index 679c931..601161a 100644 --- a/iOS/GBSettingsViewController.h +++ b/iOS/GBSettingsViewController.h @@ -25,7 +25,6 @@ typedef enum { @interface GBSettingsViewController : UITableViewController + (UIViewController *)settingsViewControllerWithLeftButton:(UIBarButtonItem *)button; -+ (const GB_palette_t *)paletteForTheme:(NSString *)theme; + (GBButton)controller:(GCController *)controller convertUsageToButton:(GBControllerUsage)usage; + (GBTheme *)themeNamed:(NSString *)name; @end diff --git a/iOS/GBSettingsViewController.m b/iOS/GBSettingsViewController.m index c5b98af..ae5d9fd 100644 --- a/iOS/GBSettingsViewController.m +++ b/iOS/GBSettingsViewController.m @@ -2,6 +2,7 @@ #import "GBTemperatureSlider.h" #import "GBViewBase.h" #import "GBThemesViewController.h" +#import "GBPalettePicker.h" #import "GBHapticManager.h" #import "GCExtendedGamepad+AllElements.h" #import @@ -23,95 +24,6 @@ static NSString const *typeLightTemp = @"typeLightTemp"; NSArray *> *_themes; // For prewarming } -+ (const GB_palette_t *)paletteForTheme:(NSString *)theme -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - if ([theme isEqualToString:@"Greyscale"]) { - return &GB_PALETTE_GREY; - } - if ([theme isEqualToString:@"Lime (Game Boy)"]) { - return &GB_PALETTE_DMG; - } - if ([theme isEqualToString:@"Olive (Pocket)"]) { - return &GB_PALETTE_MGB; - } - if ([theme isEqualToString:@"Teal (Light)"]) { - return &GB_PALETTE_GBL; - } - static GB_palette_t customPalette; - NSArray *colors = [defaults dictionaryForKey:@"GBThemes"][theme][@"Colors"]; - if (colors.count != 5) return &GB_PALETTE_DMG; - unsigned i = 0; - for (NSNumber *color in colors) { - uint32_t c = [color unsignedIntValue]; - customPalette.colors[i++] = (struct GB_color_s) {c, c >> 8, c >> 16}; - } - return &customPalette; -} - -+ (UIColor *) colorFromGBColor:(const struct GB_color_s *)color -{ - return [UIColor colorWithRed:color->r / 255.0 - green:color->g / 255.0 - blue:color->b / 255.0 - alpha:1.0]; -} - -+ (UIImage *)previewImageForTheme:(NSString *)theme -{ - const GB_palette_t *palette = [self paletteForTheme:theme]; - UIGraphicsBeginImageContextWithOptions((CGSize){29, 29}, false, [UIScreen mainScreen].scale); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 29, 29) cornerRadius:7]; - [[self colorFromGBColor:&palette->colors[4]] set]; - [path fill]; - - path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(4, 4, 9, 9) cornerRadius:2]; - [[self colorFromGBColor:&palette->colors[0]] set]; - [path fill]; - - path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(16, 4, 9, 9) cornerRadius:2]; - [[self colorFromGBColor:&palette->colors[1]] set]; - [path fill]; - - path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(4, 16, 9, 9) cornerRadius:2]; - [[self colorFromGBColor:&palette->colors[2]] set]; - [path fill]; - - path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(16, 16, 9, 9) cornerRadius:2]; - [[self colorFromGBColor:&palette->colors[3]] set]; - [path fill]; - - UIImage *ret = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return ret; -} - -+ (NSArray *)paletteMenu -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSArray *themes = [@[ - @"Greyscale", - @"Lime (Game Boy)", - @"Olive (Pocket)", - @"Teal (Light)", - ] arrayByAddingObjectsFromArray:[[defaults dictionaryForKey:@"GBThemes"] allKeys]]; - NSMutableArray *themeItems = [NSMutableArray arrayWithCapacity:themes.count]; - for (NSString *theme in themes) { - [themeItems addObject: @{@"type": typeRadio, @"pref": @"GBCurrentTheme", - @"title": theme, @"value": theme, - @"image": [self previewImageForTheme:theme]}]; - } - return @[ - @{ - @"items": [themeItems subarrayWithRange:(NSRange){0, 4}] - }, - @{ - @"items": [themeItems subarrayWithRange:(NSRange){4, themeItems.count - 4}] - } - ]; -} - + (NSArray *)rootStructure { #define QUICK_SUBMENU(title, ...) @{@"type": typeOptionSubmenu, @"title": title, @"submenu": @[@{@"items": __VA_ARGS__}]} @@ -306,8 +218,16 @@ static NSString const *typeLightTemp = @"typeLightTemp"; @{ @"items": @[@{ @"title": @"Monochrome Palette", - @"type": typeOptionSubmenu, - @"submenu": [self paletteMenu] + @"type": typeBlock, + @"block": ^bool(GBSettingsViewController *controller) { + UITableViewStyle style = UITableViewStyleGrouped; + if (@available(iOS 13.0, *)) { + style = UITableViewStyleInsetGrouped; + } + [controller.navigationController pushViewController:[[GBPalettePicker alloc] initWithStyle:style] animated:true]; + return true; + }, + @"pref": @"GBCurrentTheme", }], @"footer": @"This palette will be used when emulating a monochrome model such as the original Game Boy." } @@ -791,6 +711,9 @@ static id ValueForItem(NSDictionary *item) } } } + else if (item[@"pref"]) { + cell.detailTextLabel.text = [[NSUserDefaults standardUserDefaults] stringForKey:item[@"pref"]]; + } } else if (item[@"type"] == typeRadio) { if ([ValueForItem(item) isEqual:item[@"value"]]) { diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 1b7a82a..cd73883 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -11,6 +11,7 @@ #import "GBOptionViewController.h" #import "GBAboutController.h" #import "GBSettingsViewController.h" +#import "GBPalettePicker.h" #import "GBStatesViewController.h" #import "GBCheckableAlertController.h" #import "GBPrinterFeedController.h" @@ -1294,7 +1295,7 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response - (void)updatePalette { memcpy(&_palette, - [GBSettingsViewController paletteForTheme:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"]], + [GBPalettePicker paletteForTheme:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"]], sizeof(_palette)); GB_set_palette(&_gb, &_palette); }