git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

iOS/GBPaletteEditor.m

      1 #import "GBPaletteEditor.h"
      2 #import "GBColorWell.h"
      3 #import "GBSlider.h"
      4 #import "GBPalettePicker.h"
      5 
      6 static double blend(double from, double to, double position)
      7 {
      8     return from * (1 - position) + to * position;
      9 }
     10 
     11 @implementation GBPaletteEditor
     12 {
     13     bool _displayingManual;
     14     NSString *_paletteName;
     15     bool _isCurrent;
     16     
     17     UITableViewCell *_nameCell;
     18     UITextField *_nameField;
     19     
     20     UITableViewCell *_colorsCell;
     21     UIColorWell *_colorWells[5];
     22     
     23     UITableViewCell *_disabledLCDCell;
     24     UISwitch *_disabledLCDSwitch;
     25     
     26     UITableViewCell *_manualCell;
     27     UISwitch *_manualSwitch;
     28 
     29     UITableViewCell *_brightnessCell;
     30     GBSlider *_brightnessSlider;
     31     
     32     UITableViewCell *_hueCell;
     33     GBSlider *_hueSlider;
     34     
     35     UITableViewCell *_hueStrengthCell;
     36     UISlider *_hueStrengthSlider;
     37 }
     38 
     39 
     40 - (instancetype)initForPalette:(NSString *)name
     41 {
     42     self = [self initWithStyle:UITableViewStyleInsetGrouped];
     43     _paletteName = name;
     44     _isCurrent = [[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] isEqual:name];
     45     return self;
     46 }
     47 
     48 - (UITableViewCell *)sliderCellWithSlider:(UISlider *)slider
     49 {
     50     UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
     51     CGRect rect = cell.contentView.bounds;
     52     rect.size.width -= 24;
     53     rect.size.height -= 24;
     54     rect.origin.x += 12;
     55     rect.origin.y += 12;
     56     slider.frame = rect;
     57     slider.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
     58     [cell.contentView addSubview:slider];
     59     cell.selectionStyle = UITableViewCellSelectionStyleNone;
     60     [slider addTarget:self action:@selector(updateAutoColors) forControlEvents:UIControlEventValueChanged];
     61     return cell;
     62 }
     63 
     64 - (void)viewDidLoad
     65 {
     66     [super viewDidLoad];
     67     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     68     NSDictionary *theme = [defaults dictionaryForKey:@"GBThemes"][_paletteName];
     69     
     70     {
     71         _nameCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
     72         CGRect frame = _nameCell.contentView.bounds;
     73         frame.size.width -= - 32;
     74         frame.origin.x += 16;
     75         _nameField = [[UITextField alloc] initWithFrame:frame];
     76         _nameField.font = _nameCell.textLabel.font;
     77         _nameField.text = _paletteName;
     78         _nameField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
     79         [_nameCell.contentView addSubview:_nameField];
     80         _nameCell.selectionStyle = UITableViewCellSelectionStyleNone;
     81     }
     82     
     83     {
     84         static const unsigned wellSize = 36;
     85         _colorsCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
     86         CGRect frame = _nameCell.contentView.bounds;
     87         UIView *view = [[UIView alloc] initWithFrame:CGRectMake((frame.size.width - wellSize * 5) / 2,
     88                                                                 (frame.size.height - wellSize) / 2,
     89                                                                 wellSize * 5,
     90                                                                 wellSize)];
     91         NSArray *titles = @[
     92             @"Darkest Color",
     93             @"Dark Midtone",
     94             @"Light Midtone",
     95             @"Lightest Color",
     96             @"Display Off Color",
     97         ];
     98         for (unsigned i = 0; i < 5; i++) {
     99             _colorWells[i] = [[GBColorWell alloc] initWithFrame:CGRectMake(i * wellSize, 0, wellSize, wellSize)];
    100             _colorWells[i].supportsAlpha = false;
    101             _colorWells[i].title = titles[i];
    102             _colorWells[i].selectedColor = [UIColor colorWithRed:(([theme[@"Colors"][i] unsignedIntValue] >> 0) & 0xFF) / 255.0
    103                                                            green:(([theme[@"Colors"][i] unsignedIntValue] >> 8) & 0xFF) / 255.0
    104                                                             blue:(([theme[@"Colors"][i] unsignedIntValue] >> 16) & 0xFF) / 255.0
    105                                                            alpha:1.0];
    106             [_colorWells[i] addTarget:self action:@selector(updateToggles) forControlEvents:UIControlEventValueChanged];
    107 
    108             [view addSubview:_colorWells[i]];
    109         }
    110         view.autoresizingMask =
    111             UIViewAutoresizingFlexibleLeftMargin |
    112             UIViewAutoresizingFlexibleRightMargin |
    113             UIViewAutoresizingFlexibleTopMargin |
    114             UIViewAutoresizingFlexibleBottomMargin;
    115         [_colorsCell.contentView addSubview:view];
    116         _colorsCell.selectionStyle = UITableViewCellSelectionStyleNone;
    117     }
    118     
    119     {
    120         _disabledLCDCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    121         _disabledLCDSwitch = [[UISwitch alloc] init];
    122         _disabledLCDCell.accessoryView = _disabledLCDSwitch;
    123         if ([theme[@"DisabledLCDColor"] boolValue]) {
    124             _disabledLCDSwitch.on = true;
    125         }
    126                 
    127         [_disabledLCDSwitch addTarget:self action:@selector(updateToggles) forControlEvents:UIControlEventValueChanged];
    128         _disabledLCDCell.selectionStyle = UITableViewCellSelectionStyleNone;
    129         _disabledLCDCell.textLabel.text = @"Distinct Disabled LCD Color";
    130     }
    131     
    132     {
    133         _manualCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    134         _manualSwitch = [[UISwitch alloc] init];
    135         _manualCell.accessoryView = _manualSwitch;
    136         if ([theme[@"Manual"] boolValue]) {
    137             _manualSwitch.on = true;
    138         }
    139         
    140         [_manualSwitch addTarget:self action:@selector(updateToggles) forControlEvents:UIControlEventValueChanged];
    141         _manualCell.selectionStyle = UITableViewCellSelectionStyleNone;
    142         _manualCell.textLabel.text = @"Manual Mode";
    143     }
    144     
    145     {
    146         _brightnessSlider = [[GBSlider alloc] init];
    147         _brightnessSlider.minimumValue = -1;
    148         _brightnessSlider.maximumValue = 1;
    149         _brightnessSlider.continuous = true;
    150         _brightnessSlider.style = GBSliderStyleTicks;
    151         _brightnessSlider.value = [theme[@"BrightnessBias"] doubleValue];
    152         _brightnessCell = [self sliderCellWithSlider:_brightnessSlider];
    153     }
    154     
    155     {
    156         _hueSlider = [[GBSlider alloc] init];
    157         _hueSlider.minimumValue = 0;
    158         _hueSlider.maximumValue = 360;
    159         _hueSlider.continuous = true;
    160         _hueSlider.style = GBSliderStyleHue;
    161         _hueSlider.value = [theme[@"HueBias"] doubleValue] * 360;
    162         _hueCell = [self sliderCellWithSlider:_hueSlider];
    163     }
    164     
    165     {
    166         _hueStrengthSlider = [[UISlider alloc] init];
    167         _hueStrengthSlider.minimumValue = 0;
    168         _hueStrengthSlider.maximumValue = 1;
    169         _hueStrengthSlider.continuous = true;
    170         _hueStrengthSlider.value = [theme[@"HueBiasStrength"] doubleValue];
    171         _hueStrengthCell = [self sliderCellWithSlider:_hueStrengthSlider];
    172     }
    173     
    174     [self updateToggles];
    175     self.title = [NSString stringWithFormat:@"Editing %@", _paletteName];
    176 }
    177 
    178 - (UIColor *)autoColorAtPositon:(double)position
    179 {
    180 
    181     UIColor *first = _colorWells[0].selectedColor;
    182     UIColor *second = _colorWells[4].selectedColor;
    183     
    184     CGFloat firstRed, firstGreen, firstBlue;
    185     CGFloat secondRed, secondGreen, secondBlue;
    186     [first getRed:&firstRed green:&firstGreen blue:&firstBlue alpha:NULL];
    187     [second getRed:&secondRed green:&secondGreen blue:&secondBlue alpha:NULL];
    188 
    189     
    190     double brightness = 1 / pow(4, _brightnessSlider.value);
    191     position = pow(position, brightness);
    192     UIColor *hue = _hueSlider.thumbTintColor;
    193     double bias = _hueStrengthSlider.value;
    194     
    195     CGFloat red, green, blue;
    196     [hue getRed:&red green:&green blue:&blue alpha:NULL];
    197     red = 1 / pow(4, (red * 2 - 1) * bias);
    198     green = 1 / pow(4, (green * 2 - 1) * bias);
    199     blue = 1 / pow(4, (blue * 2 - 1) * bias);
    200     UIColor *ret = [UIColor colorWithRed:blend(firstRed, secondRed, pow(position, red))
    201                                    green:blend(firstGreen, secondGreen, pow(position, green))
    202                                     blue:blend(firstBlue, secondBlue, pow(position, blue))
    203                                    alpha:1.0];
    204     return ret;
    205 }
    206 
    207 - (void)updateAutoColors
    208 {
    209     if (_disabledLCDSwitch.on) {
    210         _colorWells[1].selectedColor = [self autoColorAtPositon:8 / 25.0];
    211         _colorWells[2].selectedColor = [self autoColorAtPositon:16 / 25.0];
    212         _colorWells[3].selectedColor = [self autoColorAtPositon:24 / 25.0];
    213     }
    214     else {
    215         _colorWells[1].selectedColor = [self autoColorAtPositon:1 / 3.0];
    216         _colorWells[2].selectedColor = [self autoColorAtPositon:2 / 3.0];
    217         _colorWells[3].selectedColor = _colorWells[4].selectedColor;
    218     }
    219     [self save];
    220 }
    221 - (void)updateToggles
    222 {
    223     if (_manualSwitch.on) {
    224         _colorWells[1].enabled = true;
    225         _colorWells[2].enabled = true;
    226         _colorWells[3].enabled = true;
    227         if (!(_colorWells[4].enabled = _disabledLCDSwitch.on)) {
    228             _colorWells[4].selectedColor = _colorWells[3].selectedColor;
    229         }
    230         if (!_displayingManual) {
    231             [self.tableView deleteSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]
    232                           withRowAnimation:UITableViewRowAnimationFade];
    233         }
    234         [self save];
    235     }
    236     else {
    237         _colorWells[1].enabled = false;
    238         _colorWells[2].enabled = false;
    239         _colorWells[3].enabled = false;
    240         _colorWells[4].enabled = true;
    241         if (_displayingManual) {
    242             [self.tableView insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]
    243                           withRowAnimation:UITableViewRowAnimationFade];
    244         }
    245         [self updateAutoColors];
    246     }
    247 }
    248 
    249 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    250 {
    251     _displayingManual = _manualSwitch.on;
    252     return  _displayingManual? 2 : 5;
    253 }
    254 
    255 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    256 {
    257     switch (section) {
    258         case 0: return 1; // Name
    259         case 1: return 3; // Colors
    260         case 2: return 1; // Brightness Bias
    261         case 3: return 2; // Hue Bias
    262         default: return 0;
    263     };
    264 }
    265 
    266 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    267 {
    268     switch (section) {
    269         case 0: return @"Palette Name";
    270         case 2: return @"Brightness Bias";
    271         case 3: return @"Hue Bias";
    272     }
    273     return nil;
    274 }
    275 
    276 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    277 {
    278     switch (indexPath.section) {
    279         case 0: return _nameCell;
    280         case 1: {
    281             switch (indexPath.row) {
    282                 case 0: return _colorsCell;
    283                 case 1: return _disabledLCDCell;
    284                 case 2: return _manualCell;
    285             }
    286             return nil;
    287         }
    288         case 2: return _brightnessCell;
    289         case 3: return indexPath.row == 0? _hueCell : _hueStrengthCell;
    290     }
    291     return [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    292 }
    293 
    294 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    295 {
    296     if (indexPath.section == 2) return 63;
    297     return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    298 }
    299 
    300 - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
    301 {
    302     return nil;
    303 }
    304 
    305 - (NSNumber *)encodeWell:(unsigned)index
    306 {
    307     CGFloat r, g, b;
    308     [_colorWells[index].selectedColor getRed:&r green:&g blue:&b alpha:NULL];
    309     return @((((unsigned)round(r * 255) <<  0) |
    310               ((unsigned)round(g * 255) <<  8) |
    311               ((unsigned)round(b * 255) << 16) |
    312               0xFF000000));
    313 }
    314 
    315 - (void)save
    316 {
    317     NSMutableDictionary *themes = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBThemes"].mutableCopy;
    318     [themes removeObjectForKey:_paletteName];
    319     if (![_paletteName isEqual:_nameField.text]) {
    320         _paletteName = [GBPalettePicker makeUnique:_nameField.text];
    321     }
    322     
    323     themes[_paletteName] = @{
    324         @"BrightnessBias": @(_brightnessSlider.value),
    325         @"Colors": @[[self encodeWell:0],
    326                      [self encodeWell:1],
    327                      [self encodeWell:2],
    328                      [self encodeWell:3],
    329                      [self encodeWell:4]],
    330         @"DisabledLCDColor": _disabledLCDSwitch.on? @YES : @NO,
    331         @"HueBias": @(_hueSlider.value / 360.0),
    332         @"HueBiasStrength": @(_hueStrengthSlider.value),
    333         @"Manual": _manualSwitch.on? @YES : @NO,
    334     };
    335     
    336     [[NSUserDefaults standardUserDefaults] setObject:themes forKey:@"GBThemes"];
    337     if (_isCurrent) {
    338         [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"GBCurrentTheme"]; // Force a reload
    339         [[NSUserDefaults standardUserDefaults] setObject:_paletteName forKey:@"GBCurrentTheme"];
    340     }
    341 }
    342 - (void)viewWillDisappear:(BOOL)animated
    343 {
    344     [super viewWillDisappear:animated];
    345     [self save];
    346 }
    347 
    348 @end

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.