Custom palette and editor
This commit is contained in:
parent
f237b1e9b9
commit
178860e715
@ -10,6 +10,7 @@
|
|||||||
#include "GBCheatWindowController.h"
|
#include "GBCheatWindowController.h"
|
||||||
#include "GBTerminalTextFieldCell.h"
|
#include "GBTerminalTextFieldCell.h"
|
||||||
#include "BigSurToolbar.h"
|
#include "BigSurToolbar.h"
|
||||||
|
#import "GBPaletteEditorController.h"
|
||||||
|
|
||||||
/* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */
|
/* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */
|
||||||
/* Todo: Split into category files! This is so messy!!! */
|
/* Todo: Split into category files! This is so messy!!! */
|
||||||
@ -256,23 +257,7 @@ static void infraredStateChanged(GB_gameboy_t *gb, bool on)
|
|||||||
|
|
||||||
- (void) updatePalette
|
- (void) updatePalette
|
||||||
{
|
{
|
||||||
switch ([[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"]) {
|
GB_set_palette(&gb, [GBPaletteEditorController userPalette]);
|
||||||
case 1:
|
|
||||||
GB_set_palette(&gb, &GB_PALETTE_DMG);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
GB_set_palette(&gb, &GB_PALETTE_MGB);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
GB_set_palette(&gb, &GB_PALETTE_GBL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
GB_set_palette(&gb, &GB_PALETTE_GREY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) updateBorderMode
|
- (void) updateBorderMode
|
||||||
|
9
Cocoa/GBHueSliderCell.h
Normal file
9
Cocoa/GBHueSliderCell.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface NSSlider (GBHueSlider)
|
||||||
|
-(NSColor *)colorValue;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface GBHueSliderCell : NSSliderCell
|
||||||
|
-(NSColor *)colorValue;
|
||||||
|
@end
|
113
Cocoa/GBHueSliderCell.m
Normal file
113
Cocoa/GBHueSliderCell.m
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#import "GBHueSliderCell.h"
|
||||||
|
|
||||||
|
@interface NSSliderCell(privateAPI)
|
||||||
|
- (double)_normalizedDoubleValue;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GBHueSliderCell
|
||||||
|
{
|
||||||
|
bool _drawingTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSColor *)colorValue
|
||||||
|
{
|
||||||
|
double hue = self.doubleValue / 360.0;
|
||||||
|
double r = 0, g = 0, b =0 ;
|
||||||
|
double t = fmod(hue * 6, 1);
|
||||||
|
switch ((int)(hue * 6) % 6) {
|
||||||
|
case 0:
|
||||||
|
r = 1;
|
||||||
|
g = t;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = 1 - t;
|
||||||
|
g = 1;
|
||||||
|
b = 0;
|
||||||
|
case 2:
|
||||||
|
g = 1;
|
||||||
|
b = t;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
g = 1 - t;
|
||||||
|
b = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
b = 1;
|
||||||
|
r = t;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
b = 1 - t;
|
||||||
|
r = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return [NSColor colorWithRed:r green:g blue:b alpha:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)drawKnob:(NSRect)knobRect
|
||||||
|
{
|
||||||
|
[super drawKnob:knobRect];
|
||||||
|
NSRect peekRect = knobRect;
|
||||||
|
peekRect.size.width /= 2;
|
||||||
|
peekRect.size.height /= 2;
|
||||||
|
peekRect.origin.x += peekRect.size.width / 2;
|
||||||
|
peekRect.origin.y += peekRect.size.height / 2;
|
||||||
|
NSColor *color = self.colorValue;
|
||||||
|
if (!self.enabled) {
|
||||||
|
color = [color colorWithAlphaComponent:0.5];
|
||||||
|
}
|
||||||
|
[color setFill];
|
||||||
|
NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect:peekRect];
|
||||||
|
[path fill];
|
||||||
|
[[NSColor colorWithWhite:0 alpha:0.25] setStroke];
|
||||||
|
[path setLineWidth:0.5];
|
||||||
|
[path stroke];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(double)_normalizedDoubleValue
|
||||||
|
{
|
||||||
|
if (_drawingTrack) return 0;
|
||||||
|
return [super _normalizedDoubleValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped
|
||||||
|
{
|
||||||
|
if (!self.enabled) {
|
||||||
|
[super drawBarInside:rect flipped:flipped];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_drawingTrack = true;
|
||||||
|
[super drawBarInside:rect flipped:flipped];
|
||||||
|
_drawingTrack = false;
|
||||||
|
|
||||||
|
NSGradient *gradient = [[NSGradient alloc] initWithColors:@[
|
||||||
|
[NSColor redColor],
|
||||||
|
[NSColor yellowColor],
|
||||||
|
[NSColor greenColor],
|
||||||
|
[NSColor cyanColor],
|
||||||
|
[NSColor blueColor],
|
||||||
|
[NSColor magentaColor],
|
||||||
|
[NSColor redColor],
|
||||||
|
]];
|
||||||
|
|
||||||
|
rect.origin.y += rect.size.height / 2 - 0.5;
|
||||||
|
rect.size.height = 1;
|
||||||
|
rect.size.width -= 2;
|
||||||
|
rect.origin.x += 1;
|
||||||
|
[[NSColor redColor] set];
|
||||||
|
NSRectFill(rect);
|
||||||
|
|
||||||
|
rect.size.width -= self.knobThickness + 2;
|
||||||
|
rect.origin.x += self.knobThickness / 2 - 1;
|
||||||
|
|
||||||
|
[gradient drawInRect:rect angle:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSSlider (GBHueSlider)
|
||||||
|
- (NSColor *)colorValue
|
||||||
|
{
|
||||||
|
return ((GBHueSliderCell *)self.cell).colorValue;
|
||||||
|
}
|
||||||
|
@end
|
18
Cocoa/GBPaletteEditorController.h
Normal file
18
Cocoa/GBPaletteEditorController.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#import <Core/gb.h>
|
||||||
|
|
||||||
|
@interface GBPaletteEditorController : NSObject<NSTableViewDataSource, NSTableViewDelegate>
|
||||||
|
@property (weak) IBOutlet NSColorWell *colorWell0;
|
||||||
|
@property (weak) IBOutlet NSColorWell *colorWell1;
|
||||||
|
@property (weak) IBOutlet NSColorWell *colorWell2;
|
||||||
|
@property (weak) IBOutlet NSColorWell *colorWell3;
|
||||||
|
@property (weak) IBOutlet NSColorWell *colorWell4;
|
||||||
|
@property (weak) IBOutlet NSButton *disableLCDColorCheckbox;
|
||||||
|
@property (weak) IBOutlet NSButton *manualModeCheckbox;
|
||||||
|
@property (weak) IBOutlet NSSlider *brightnessSlider;
|
||||||
|
@property (weak) IBOutlet NSSlider *hueSlider;
|
||||||
|
@property (weak) IBOutlet NSSlider *hueStrengthSlider;
|
||||||
|
@property (weak) IBOutlet NSTableView *themesList;
|
||||||
|
@property (weak) IBOutlet NSMenu *menu;
|
||||||
|
+ (const GB_palette_t *)userPalette;
|
||||||
|
@end
|
378
Cocoa/GBPaletteEditorController.m
Normal file
378
Cocoa/GBPaletteEditorController.m
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
#import "GBPaletteEditorController.h"
|
||||||
|
#import "GBHueSliderCell.h"
|
||||||
|
#import <Core/gb.h>
|
||||||
|
|
||||||
|
#define MAGIC 'SBPL'
|
||||||
|
|
||||||
|
typedef struct __attribute__ ((packed)) {
|
||||||
|
uint32_t magic;
|
||||||
|
bool manual:1;
|
||||||
|
bool disabled_lcd_color:1;
|
||||||
|
unsigned padding:6;
|
||||||
|
struct GB_color_s colors[5];
|
||||||
|
int32_t brightness_bias;
|
||||||
|
uint32_t hue_bias;
|
||||||
|
uint32_t hue_bias_strength;
|
||||||
|
} theme_t;
|
||||||
|
|
||||||
|
static double blend(double from, double to, double position)
|
||||||
|
{
|
||||||
|
return from * (1 - position) + to * position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation NSColor (GBColor)
|
||||||
|
|
||||||
|
- (struct GB_color_s)gbColor
|
||||||
|
{
|
||||||
|
NSColor *sRGB = [self colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
|
||||||
|
return (struct GB_color_s){round(sRGB.redComponent * 255), round(sRGB.greenComponent * 255), round(sRGB.blueComponent * 255)};
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint32_t)intValue
|
||||||
|
{
|
||||||
|
struct GB_color_s color = self.gbColor;
|
||||||
|
return (color.r << 0) | (color.g << 8) | (color.b << 16) | 0xFF000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GBPaletteEditorController
|
||||||
|
|
||||||
|
- (NSArray<NSColorWell *> *)colorWells
|
||||||
|
{
|
||||||
|
return @[_colorWell0, _colorWell1, _colorWell2, _colorWell3, _colorWell4];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateEnabledControls
|
||||||
|
{
|
||||||
|
if (self.manualModeCheckbox.state) {
|
||||||
|
_brightnessSlider.enabled = false;
|
||||||
|
_hueSlider.enabled = false;
|
||||||
|
_hueStrengthSlider.enabled = false;
|
||||||
|
_colorWell1.enabled = true;
|
||||||
|
_colorWell2.enabled = true;
|
||||||
|
_colorWell3.enabled = true;
|
||||||
|
if (!(_colorWell4.enabled = self.disableLCDColorCheckbox.state)) {
|
||||||
|
_colorWell4.color = _colorWell3.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_colorWell1.enabled = false;
|
||||||
|
_colorWell2.enabled = false;
|
||||||
|
_colorWell3.enabled = false;
|
||||||
|
_colorWell4.enabled = true;
|
||||||
|
_brightnessSlider.enabled = true;
|
||||||
|
_hueSlider.enabled = true;
|
||||||
|
_hueStrengthSlider.enabled = true;
|
||||||
|
[self updateAutoColors];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSColor *)autoColorAtPositon:(double)position
|
||||||
|
{
|
||||||
|
NSColor *first = [_colorWell0.color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
|
||||||
|
NSColor *second = [_colorWell4.color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
|
||||||
|
double brightness = 1 / pow(4, (_brightnessSlider.doubleValue - 128) / 128.0);
|
||||||
|
position = pow(position, brightness);
|
||||||
|
NSColor *hue = _hueSlider.colorValue;
|
||||||
|
double bias = _hueStrengthSlider.doubleValue / 256.0;
|
||||||
|
double red = 1 / pow(4, (hue.redComponent * 2 - 1) * bias);
|
||||||
|
double green = 1 / pow(4, (hue.greenComponent * 2 - 1) * bias);
|
||||||
|
double blue = 1 / pow(4, (hue.blueComponent * 2 - 1) * bias);
|
||||||
|
NSColor *ret = [NSColor colorWithRed:blend(first.redComponent, second.redComponent, pow(position, red))
|
||||||
|
green:blend(first.greenComponent, second.greenComponent, pow(position, green))
|
||||||
|
blue:blend(first.blueComponent, second.blueComponent, pow(position, blue))
|
||||||
|
alpha:1.0];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)updateAutoColors:(id)sender
|
||||||
|
{
|
||||||
|
if (!self.manualModeCheckbox.state) {
|
||||||
|
[self updateAutoColors];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self savePalette:sender];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateAutoColors
|
||||||
|
{
|
||||||
|
if (_disableLCDColorCheckbox.state) {
|
||||||
|
_colorWell1.color = [self autoColorAtPositon:8 / 25.0];
|
||||||
|
_colorWell2.color = [self autoColorAtPositon:16 / 25.0];
|
||||||
|
_colorWell3.color = [self autoColorAtPositon:24 / 25.0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_colorWell1.color = [self autoColorAtPositon:1 / 3.0];
|
||||||
|
_colorWell2.color = [self autoColorAtPositon:2 / 3.0];
|
||||||
|
_colorWell3.color = _colorWell4.color;
|
||||||
|
}
|
||||||
|
[self savePalette:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)disabledLCDColorCheckboxChanged:(id)sender
|
||||||
|
{
|
||||||
|
[self updateEnabledControls];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)manualModeChanged:(id)sender
|
||||||
|
{
|
||||||
|
[self updateEnabledControls];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)updateColor4:(id)sender
|
||||||
|
{
|
||||||
|
if (!self.disableLCDColorCheckbox.state) {
|
||||||
|
self.colorWell4.color = self.colorWell3.color;
|
||||||
|
}
|
||||||
|
[self savePalette:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
if (themes.count == 0) {
|
||||||
|
[defaults setObject:@"Untitled Palette" forKey:@"GBCurrentTheme"];
|
||||||
|
[self savePalette:nil];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return themes.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||||
|
{
|
||||||
|
NSString *oldName = [self tableView:tableView objectValueForTableColumn:tableColumn row:row];
|
||||||
|
if ([oldName isEqualToString:object]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @[] mutableCopy];
|
||||||
|
NSString *newName = object;
|
||||||
|
unsigned i = 2;
|
||||||
|
if (!newName.length) {
|
||||||
|
newName = @"Untitled Palette";
|
||||||
|
}
|
||||||
|
while (themes[newName]) {
|
||||||
|
newName = [NSString stringWithFormat:@"%@ %d", object, i];
|
||||||
|
}
|
||||||
|
themes[newName] = themes[oldName];
|
||||||
|
[themes removeObjectForKey:oldName];
|
||||||
|
if ([oldName isEqualToString:[defaults stringForKey:@"GBCurrentTheme"]]) {
|
||||||
|
[defaults setObject:newName forKey:@"GBCurrentTheme"];
|
||||||
|
}
|
||||||
|
[defaults setObject:themes forKey:@"GBThemes"];
|
||||||
|
[tableView reloadData];
|
||||||
|
[self awakeFromNib];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)deleteTheme:(id)sender
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSString *name = [defaults stringForKey:@"GBCurrentTheme"];
|
||||||
|
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @[] mutableCopy];
|
||||||
|
[themes removeObjectForKey:name];
|
||||||
|
[defaults setObject:themes forKey:@"GBThemes"];
|
||||||
|
[_themesList reloadData];
|
||||||
|
[self awakeFromNib];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tableViewSelectionDidChange:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
NSString *name = [self tableView:nil objectValueForTableColumn:nil row:_themesList.selectedRow];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:name forKey:@"GBCurrentTheme"];
|
||||||
|
[self loadPalette];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tableViewSelectionIsChanging:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
[self tableViewSelectionDidChange:notification];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)awakeFromNib
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
NSString *theme = [defaults stringForKey:@"GBCurrentTheme"];
|
||||||
|
if (theme && themes[theme]) {
|
||||||
|
unsigned index = [[themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] indexOfObject:theme];
|
||||||
|
[_themesList selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:false];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[_themesList selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:false];
|
||||||
|
}
|
||||||
|
[self tableViewSelectionDidChange:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)addTheme:(id)sender
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
NSString *newName = @"Untitled Palette";
|
||||||
|
unsigned i = 2;
|
||||||
|
while (themes[newName]) {
|
||||||
|
newName = [NSString stringWithFormat:@"Untitled Palette %d", i++];
|
||||||
|
}
|
||||||
|
[defaults setObject:newName forKey:@"GBCurrentTheme"];
|
||||||
|
[self savePalette:sender];
|
||||||
|
[_themesList reloadData];
|
||||||
|
[self awakeFromNib];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
return [themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)][row];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadPalette
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *theme = [defaults dictionaryForKey:@"GBThemes"][[defaults stringForKey:@"GBCurrentTheme"]];
|
||||||
|
NSArray *colors = theme[@"Colors"];
|
||||||
|
if (colors.count == 5) {
|
||||||
|
unsigned i = 0;
|
||||||
|
for (NSNumber *color in colors) {
|
||||||
|
uint32_t c = [color unsignedIntValue];
|
||||||
|
self.colorWells[i++].color = [NSColor colorWithRed:(c & 0xFF) / 255.0
|
||||||
|
green:((c >> 8) & 0xFF) / 255.0
|
||||||
|
blue:((c >> 16) & 0xFF) / 255.0
|
||||||
|
alpha:1.0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_disableLCDColorCheckbox.state = [theme[@"DisabledLCDColor"] boolValue];
|
||||||
|
_manualModeCheckbox.state = [theme[@"Manual"] boolValue];
|
||||||
|
_brightnessSlider.doubleValue = [theme[@"BrightnessBias"] doubleValue] * 128 + 128;
|
||||||
|
_hueSlider.doubleValue = [theme[@"HueBias"] doubleValue] * 360;
|
||||||
|
_hueStrengthSlider.doubleValue = [theme[@"HueBiasStrength"] doubleValue] * 256;
|
||||||
|
[self updateEnabledControls];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)savePalette:(id)sender
|
||||||
|
{
|
||||||
|
NSDictionary *theme = @{
|
||||||
|
@"Colors":
|
||||||
|
@[@(_colorWell0.color.intValue),
|
||||||
|
@(_colorWell1.color.intValue),
|
||||||
|
@(_colorWell2.color.intValue),
|
||||||
|
@(_colorWell3.color.intValue),
|
||||||
|
@(_colorWell4.color.intValue)],
|
||||||
|
@"DisabledLCDColor": _disableLCDColorCheckbox.state? @YES : @NO,
|
||||||
|
@"Manual": _manualModeCheckbox.state? @YES : @NO,
|
||||||
|
@"BrightnessBias": @((_brightnessSlider.doubleValue - 128) / 128.0),
|
||||||
|
@"HueBias": @(_hueSlider.doubleValue / 360.0),
|
||||||
|
@"HueBiasStrength": @(_hueStrengthSlider.doubleValue / 256.0)
|
||||||
|
};
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @[] mutableCopy];
|
||||||
|
themes[[defaults stringForKey:@"GBCurrentTheme"]] = theme;
|
||||||
|
[defaults setObject:themes forKey:@"GBThemes"];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (const GB_palette_t *)userPalette
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
switch ([defaults integerForKey:@"GBColorPalette"]) {
|
||||||
|
case 1: return &GB_PALETTE_DMG;
|
||||||
|
case 2: return &GB_PALETTE_MGB;
|
||||||
|
case 3: return &GB_PALETTE_GBL;
|
||||||
|
default: return &GB_PALETTE_GREY;
|
||||||
|
case -1: {
|
||||||
|
static GB_palette_t customPalette;
|
||||||
|
NSArray *colors = [defaults dictionaryForKey:@"GBThemes"][[defaults stringForKey:@"GBCurrentTheme"]][@"Colors"];
|
||||||
|
if (colors.count == 5) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)export:(id)sender
|
||||||
|
{
|
||||||
|
NSSavePanel *savePanel = [NSSavePanel savePanel];
|
||||||
|
[savePanel setAllowedFileTypes:@[@"sbp"]];
|
||||||
|
savePanel.nameFieldStringValue = [NSString stringWithFormat:@"%@.sbp", [[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"]];
|
||||||
|
if ([savePanel runModal] == NSModalResponseOK) {
|
||||||
|
theme_t theme = {0,};
|
||||||
|
theme.magic = MAGIC;
|
||||||
|
theme.manual = _manualModeCheckbox.state;
|
||||||
|
theme.disabled_lcd_color = _disableLCDColorCheckbox.state;
|
||||||
|
unsigned i = 0;
|
||||||
|
for (NSColorWell *well in self.colorWells) {
|
||||||
|
theme.colors[i++] = well.color.gbColor;
|
||||||
|
}
|
||||||
|
theme.brightness_bias = (_brightnessSlider.doubleValue - 128) * (0x40000000 / 128);
|
||||||
|
theme.hue_bias = round(_hueSlider.doubleValue * (0x80000000 / 360.0));
|
||||||
|
theme.hue_bias_strength = (_hueStrengthSlider.doubleValue) * (0x80000000 / 256);
|
||||||
|
size_t size = sizeof(theme);
|
||||||
|
if (theme.manual) {
|
||||||
|
size = theme.disabled_lcd_color? 5 + 5 * sizeof(theme.colors[0]) : 5 + 4 * sizeof(theme.colors[0]);
|
||||||
|
}
|
||||||
|
[[NSData dataWithBytes:&theme length:size] writeToURL:savePanel.URL atomically:false];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)import:(id)sender
|
||||||
|
{
|
||||||
|
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
||||||
|
[openPanel setAllowedFileTypes:@[@"sbp"]];
|
||||||
|
if ([openPanel runModal] == NSModalResponseOK) {
|
||||||
|
NSData *data = [NSData dataWithContentsOfURL:openPanel.URL];
|
||||||
|
theme_t theme = {0,};
|
||||||
|
memcpy(&theme, data.bytes, MIN(sizeof(theme), data.length));
|
||||||
|
if (theme.magic != MAGIC) {
|
||||||
|
NSBeep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_manualModeCheckbox.state = theme.manual;
|
||||||
|
_disableLCDColorCheckbox.state = theme.disabled_lcd_color;
|
||||||
|
unsigned i = 0;
|
||||||
|
for (NSColorWell *well in self.colorWells) {
|
||||||
|
well.color = [NSColor colorWithRed:theme.colors[i].r / 255.0
|
||||||
|
green:theme.colors[i].g / 255.0
|
||||||
|
blue:theme.colors[i].b / 255.0
|
||||||
|
alpha:1.0];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (!theme.disabled_lcd_color) {
|
||||||
|
_colorWell4.color = _colorWell3.color;
|
||||||
|
}
|
||||||
|
_brightnessSlider.doubleValue = theme.brightness_bias / (0x40000000 / 128.0) + 128;
|
||||||
|
_hueSlider.doubleValue = theme.hue_bias / (0x80000000 / 360.0);
|
||||||
|
_hueStrengthSlider.doubleValue = theme.hue_bias_strength / (0x80000000 / 256.0);
|
||||||
|
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
NSString *baseName = openPanel.URL.lastPathComponent.stringByDeletingPathExtension;
|
||||||
|
NSString *newName = baseName;
|
||||||
|
i = 2;
|
||||||
|
while (themes[newName]) {
|
||||||
|
newName = [NSString stringWithFormat:@"%@ %d", baseName, i++];
|
||||||
|
}
|
||||||
|
[defaults setObject:newName forKey:@"GBCurrentTheme"];
|
||||||
|
[self savePalette:sender];
|
||||||
|
[self awakeFromNib];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)done:(NSButton *)sender
|
||||||
|
{
|
||||||
|
[sender.window.sheetParent endSheet:sender.window];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
static id singleton = nil;
|
||||||
|
if (singleton) return singleton;
|
||||||
|
return (singleton = [super init]);
|
||||||
|
}
|
||||||
|
@end
|
@ -1,5 +1,6 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <JoyKit/JoyKit.h>
|
#import <JoyKit/JoyKit.h>
|
||||||
|
#import "GBPaletteEditorController.h"
|
||||||
|
|
||||||
@interface GBPreferencesWindow : NSWindow <NSTableViewDelegate, NSTableViewDataSource, JOYListener>
|
@interface GBPreferencesWindow : NSWindow <NSTableViewDelegate, NSTableViewDataSource, JOYListener>
|
||||||
@property (nonatomic, strong) IBOutlet NSTableView *controlsTableView;
|
@property (nonatomic, strong) IBOutlet NSTableView *controlsTableView;
|
||||||
@ -29,4 +30,6 @@
|
|||||||
@property (weak) IBOutlet NSSlider *volumeSlider;
|
@property (weak) IBOutlet NSSlider *volumeSlider;
|
||||||
@property (weak) IBOutlet NSButton *OSDCheckbox;
|
@property (weak) IBOutlet NSButton *OSDCheckbox;
|
||||||
@property (weak) IBOutlet NSButton *screenshotFilterCheckbox;
|
@property (weak) IBOutlet NSButton *screenshotFilterCheckbox;
|
||||||
|
@property (weak) IBOutlet GBPaletteEditorController *paletteEditorController;
|
||||||
|
@property (strong) IBOutlet NSWindow *paletteEditor;
|
||||||
@end
|
@end
|
||||||
|
@ -153,8 +153,14 @@
|
|||||||
- (void)setColorPalettePopupButton:(NSPopUpButton *)colorPalettePopupButton
|
- (void)setColorPalettePopupButton:(NSPopUpButton *)colorPalettePopupButton
|
||||||
{
|
{
|
||||||
_colorPalettePopupButton = colorPalettePopupButton;
|
_colorPalettePopupButton = colorPalettePopupButton;
|
||||||
|
[self updatePalettesMenu];
|
||||||
NSInteger mode = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"];
|
NSInteger mode = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"];
|
||||||
[_colorPalettePopupButton selectItemAtIndex:mode];
|
if (mode >= 0) {
|
||||||
|
[_colorPalettePopupButton selectItemWithTag:mode];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[_colorPalettePopupButton selectItemWithTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] ?: @""];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSPopUpButton *)colorPalettePopupButton
|
- (NSPopUpButton *)colorPalettePopupButton
|
||||||
@ -366,10 +372,51 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updatePalettesMenu
|
||||||
|
{
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||||||
|
NSMenu *menu = _colorPalettePopupButton.menu;
|
||||||
|
while (menu.itemArray.count != 4) {
|
||||||
|
[menu removeItemAtIndex:4];
|
||||||
|
}
|
||||||
|
[menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
for (NSString *name in [themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) {
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:name action:nil keyEquivalent:@""];
|
||||||
|
item.tag = -2;
|
||||||
|
[menu addItem:item];
|
||||||
|
}
|
||||||
|
if (themes) {
|
||||||
|
[menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
}
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Custom…" action:nil keyEquivalent:@""];
|
||||||
|
item.tag = -1;
|
||||||
|
[menu addItem:item];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)colorPaletteChanged:(id)sender
|
- (IBAction)colorPaletteChanged:(id)sender
|
||||||
{
|
{
|
||||||
[[NSUserDefaults standardUserDefaults] setObject:@([sender indexOfSelectedItem])
|
signed tag = [sender selectedItem].tag;
|
||||||
|
if (tag == -2) {
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:@(-1)
|
||||||
forKey:@"GBColorPalette"];
|
forKey:@"GBColorPalette"];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:[sender selectedItem].title
|
||||||
|
forKey:@"GBCurrentTheme"];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (tag == -1) {
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:@(-1)
|
||||||
|
forKey:@"GBColorPalette"];
|
||||||
|
[_paletteEditorController awakeFromNib];
|
||||||
|
[self beginSheet:_paletteEditor completionHandler:^(NSModalResponse returnCode) {
|
||||||
|
[self updatePalettesMenu];
|
||||||
|
[_colorPalettePopupButton selectItemWithTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] ?: @""];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:@([sender selectedItem].tag)
|
||||||
|
forKey:@"GBColorPalette"];
|
||||||
|
}
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,8 @@
|
|||||||
<outlet property="graphicsFilterPopupButton" destination="6pP-kK-EEC" id="LS7-HY-kHC"/>
|
<outlet property="graphicsFilterPopupButton" destination="6pP-kK-EEC" id="LS7-HY-kHC"/>
|
||||||
<outlet property="highpassFilterPopupButton" destination="T69-6N-dhT" id="0p6-4m-hb1"/>
|
<outlet property="highpassFilterPopupButton" destination="T69-6N-dhT" id="0p6-4m-hb1"/>
|
||||||
<outlet property="interferenceSlider" destination="FpE-5i-j5L" id="hfH-e8-7cx"/>
|
<outlet property="interferenceSlider" destination="FpE-5i-j5L" id="hfH-e8-7cx"/>
|
||||||
|
<outlet property="paletteEditor" destination="g32-xe-7al" id="WLk-Hh-h5v"/>
|
||||||
|
<outlet property="paletteEditorController" destination="Zxl-vm-6c9" id="uPS-zn-osL"/>
|
||||||
<outlet property="playerListButton" destination="gWx-7h-0xq" id="zo6-82-JId"/>
|
<outlet property="playerListButton" destination="gWx-7h-0xq" id="zo6-82-JId"/>
|
||||||
<outlet property="preferredJoypadButton" destination="0Az-0R-oNw" id="7JM-tw-BhK"/>
|
<outlet property="preferredJoypadButton" destination="0Az-0R-oNw" id="7JM-tw-BhK"/>
|
||||||
<outlet property="rewindPopupButton" destination="7fg-Ww-JjR" id="Ka2-TP-B1x"/>
|
<outlet property="rewindPopupButton" destination="7fg-Ww-JjR" id="Ka2-TP-B1x"/>
|
||||||
@ -257,9 +259,9 @@
|
|||||||
<menuItem title="Greyscale" state="on" id="Ajr-5r-iIk">
|
<menuItem title="Greyscale" state="on" id="Ajr-5r-iIk">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem title="Lime (Game Boy)" id="snU-ht-fQq"/>
|
<menuItem title="Lime (Game Boy)" tag="1" id="snU-ht-fQq"/>
|
||||||
<menuItem title="Olive (Pocket)" id="MQi-yt-nsT"/>
|
<menuItem title="Olive (Pocket)" tag="2" id="MQi-yt-nsT"/>
|
||||||
<menuItem title="Teal (Light)" id="xlg-6i-Fhl"/>
|
<menuItem title="Teal (Light)" tag="3" id="xlg-6i-Fhl"/>
|
||||||
</items>
|
</items>
|
||||||
</menu>
|
</menu>
|
||||||
</popUpButtonCell>
|
</popUpButtonCell>
|
||||||
@ -319,7 +321,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<point key="canvasLocation" x="-176" y="690.5"/>
|
<point key="canvasLocation" x="-501" y="236.5"/>
|
||||||
</customView>
|
</customView>
|
||||||
<customView id="ymk-46-SX7">
|
<customView id="ymk-46-SX7">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="375"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="375"/>
|
||||||
@ -579,7 +581,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</slider>
|
</slider>
|
||||||
</subviews>
|
</subviews>
|
||||||
<point key="canvasLocation" x="-825" y="455.5"/>
|
<point key="canvasLocation" x="-854" y="627"/>
|
||||||
</customView>
|
</customView>
|
||||||
<customView id="8TU-6J-NCg">
|
<customView id="8TU-6J-NCg">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="467"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="467"/>
|
||||||
@ -608,7 +610,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
<clipView key="contentView" focusRingType="none" ambiguous="YES" drawsBackground="NO" id="AMs-PO-nid">
|
<clipView key="contentView" focusRingType="none" ambiguous="YES" drawsBackground="NO" id="AMs-PO-nid">
|
||||||
<rect key="frame" x="1" y="1" width="255" height="209"/>
|
<rect key="frame" x="1" y="1" width="255" height="209"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="UDd-IJ-fxX">
|
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="UDd-IJ-fxX">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="255" height="209"/>
|
<rect key="frame" x="0.0" y="0.0" width="255" height="209"/>
|
||||||
@ -770,7 +772,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<point key="canvasLocation" x="-159" y="1161.5"/>
|
<point key="canvasLocation" x="-854" y="260"/>
|
||||||
</customView>
|
</customView>
|
||||||
<customView id="ffn-ie-9C3">
|
<customView id="ffn-ie-9C3">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="95"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="95"/>
|
||||||
@ -803,14 +805,262 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<point key="canvasLocation" x="-825" y="699.5"/>
|
<point key="canvasLocation" x="-854" y="808"/>
|
||||||
</customView>
|
</customView>
|
||||||
|
<window title="Palette Editor" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="g32-xe-7al">
|
||||||
|
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
|
||||||
|
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||||
|
<rect key="contentRect" x="283" y="305" width="467" height="341"/>
|
||||||
|
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||||
|
<view key="contentView" id="uMa-Yg-exg">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="467" height="341"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<scrollView focusRingType="none" fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DPL-nH-GVw">
|
||||||
|
<rect key="frame" x="-1" y="24" width="160" height="318"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
|
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="5Al-aC-tq8">
|
||||||
|
<rect key="frame" x="1" y="1" width="158" height="316"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<tableView focusRingType="none" verticalHuggingPriority="750" ambiguous="YES" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" id="ZVn-bk-duk">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="158" height="316"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<size key="intercellSpacing" width="3" height="2"/>
|
||||||
|
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<tableColumns>
|
||||||
|
<tableColumn width="155" minWidth="40" maxWidth="1000" id="qZn-U2-gsp">
|
||||||
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||||
|
<font key="font" metaFont="smallSystem"/>
|
||||||
|
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</tableHeaderCell>
|
||||||
|
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="K1k-hc-zcx">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||||
|
</tableColumn>
|
||||||
|
</tableColumns>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="Zxl-vm-6c9" id="Qpu-7V-i4Q"/>
|
||||||
|
<outlet property="delegate" destination="Zxl-vm-6c9" id="FoY-pT-glW"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
</subviews>
|
||||||
|
<nil key="backgroundColor"/>
|
||||||
|
</clipView>
|
||||||
|
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="zn7-g9-fNo">
|
||||||
|
<rect key="frame" x="1" y="274" width="158" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
</scroller>
|
||||||
|
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="fa0-wo-kQe">
|
||||||
|
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
</scroller>
|
||||||
|
</scrollView>
|
||||||
|
<colorWell focusRingType="none" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="odC-WD-uUp">
|
||||||
|
<rect key="frame" x="167" y="266" width="55" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<color key="color" red="0.03129877895116806" green="0.094370834529399872" blue="0.062739767134189606" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateAutoColors:" target="Zxl-vm-6c9" id="wmS-sP-YVR"/>
|
||||||
|
</connections>
|
||||||
|
</colorWell>
|
||||||
|
<colorWell focusRingType="none" fixedFrame="YES" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="mpV-pm-9ZF">
|
||||||
|
<rect key="frame" x="222" y="266" width="55" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<color key="color" red="0.22354039549827576" green="0.38156121969223022" blue="0.22349703311920166" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="savePalette:" target="Zxl-vm-6c9" id="Ejl-bb-Vd8"/>
|
||||||
|
</connections>
|
||||||
|
</colorWell>
|
||||||
|
<colorWell focusRingType="none" fixedFrame="YES" tag="2" translatesAutoresizingMaskIntoConstraints="NO" id="NEt-gu-zL7">
|
||||||
|
<rect key="frame" x="277" y="266" width="55" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<color key="color" red="0.51789730787277222" green="0.64901769161224365" blue="0.38817742466926575" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="savePalette:" target="Zxl-vm-6c9" id="lle-OO-YK2"/>
|
||||||
|
</connections>
|
||||||
|
</colorWell>
|
||||||
|
<colorWell focusRingType="none" fixedFrame="YES" tag="3" translatesAutoresizingMaskIntoConstraints="NO" id="fVn-3k-iuN">
|
||||||
|
<rect key="frame" x="332" y="266" width="55" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<color key="color" red="0.77688723802566528" green="0.87309378385543823" blue="0.54894673824310303" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateColor4:" target="Zxl-vm-6c9" id="riQ-Kc-wcG"/>
|
||||||
|
</connections>
|
||||||
|
</colorWell>
|
||||||
|
<colorWell focusRingType="none" fixedFrame="YES" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="min-mf-sjI">
|
||||||
|
<rect key="frame" x="392" y="266" width="55" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<color key="color" red="0.82731041736199085" green="0.92976116399242459" blue="0.58457564096374282" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateAutoColors:" target="Zxl-vm-6c9" id="Oo4-Dx-wvS"/>
|
||||||
|
</connections>
|
||||||
|
</colorWell>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZUa-QG-4ss">
|
||||||
|
<rect key="frame" x="167" y="243" width="282" height="18"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="check" title="Distinct disabled LCD color" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="cRR-vH-5R2">
|
||||||
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="disabledLCDColorCheckboxChanged:" target="Zxl-vm-6c9" id="geJ-mH-o6c"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l33-w0-rLw">
|
||||||
|
<rect key="frame" x="167" y="221" width="277" height="18"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="check" title="Manual mode" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Gvn-Rq-LU5">
|
||||||
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="manualModeChanged:" target="Zxl-vm-6c9" id="BAF-n1-CiQ"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XFt-AQ-h4m">
|
||||||
|
<rect key="frame" x="165" y="198" width="284" height="17"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" title="Brightness bias:" id="qhH-ls-JEl">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wam-CT-owm">
|
||||||
|
<rect key="frame" x="177" y="162" width="272" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<sliderCell key="cell" continuous="YES" enabled="NO" state="on" alignment="left" maxValue="256" doubleValue="128" tickMarkPosition="above" numberOfTickMarks="3" sliderType="linear" id="ktr-gF-oxu"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateAutoColors:" target="Zxl-vm-6c9" id="Onm-Bw-sJu"/>
|
||||||
|
</connections>
|
||||||
|
</slider>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Dc6-NT-jgZ">
|
||||||
|
<rect key="frame" x="167" y="139" width="282" height="17"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" title="Hue bias:" id="GzN-2h-xBT">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ImK-kc-EEn">
|
||||||
|
<rect key="frame" x="177" y="105" width="272" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<sliderCell key="cell" continuous="YES" enabled="NO" state="on" alignment="left" maxValue="360" tickMarkPosition="above" sliderType="linear" id="2dt-f1-0bV" customClass="GBHueSliderCell"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateAutoColors:" target="Zxl-vm-6c9" id="2OR-Nl-jrN"/>
|
||||||
|
</connections>
|
||||||
|
</slider>
|
||||||
|
<slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ij9-bn-1y8">
|
||||||
|
<rect key="frame" x="177" y="48" width="272" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<sliderCell key="cell" continuous="YES" enabled="NO" state="on" alignment="left" maxValue="256" tickMarkPosition="above" sliderType="linear" id="4WJ-yV-tms"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="updateAutoColors:" target="Zxl-vm-6c9" id="Hkn-HH-usp"/>
|
||||||
|
</connections>
|
||||||
|
</slider>
|
||||||
|
<box horizontalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="hcd-Iu-gEm">
|
||||||
|
<rect key="frame" x="387" y="266" width="5" height="55"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
</box>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="t0j-uz-CIi">
|
||||||
|
<rect key="frame" x="0.0" y="-1" width="32" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="61Q-ht-htH">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="addTheme:" target="Zxl-vm-6c9" id="lAZ-PU-7Rk"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Qv-3A-Fy9">
|
||||||
|
<rect key="frame" x="31" y="-1" width="32" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Qax-9H-bwb">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="deleteTheme:" target="Zxl-vm-6c9" id="nlR-Hp-4m9"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xtD-ub-MX7">
|
||||||
|
<rect key="frame" x="62" y="-1" width="49" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<buttonCell key="cell" type="smallSquare" title="Export" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="RBw-u5-zpv">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="smallSystem"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="export:" target="Zxl-vm-6c9" id="9Fg-bN-W6z"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2E2-qz-P8N">
|
||||||
|
<rect key="frame" x="110" y="-1" width="49" height="28"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<buttonCell key="cell" type="smallSquare" title="Import" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="u9o-6G-fwU">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="smallSystem"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="import:" target="Zxl-vm-6c9" id="OTl-HS-9Rt"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CZc-qZ-GLV">
|
||||||
|
<rect key="frame" x="167" y="82" width="277" height="17"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" title="Hue bias strength:" id="qLB-J6-2mT">
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tyc-KF-YTY">
|
||||||
|
<rect key="frame" x="372.5" y="19" width="75" height="23"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
|
<buttonCell key="cell" type="roundTextured" title="Close" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Vhg-3I-evG">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="done:" target="Zxl-vm-6c9" id="RKB-kM-yzA"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
</view>
|
||||||
|
<point key="canvasLocation" x="-62.5" y="222.5"/>
|
||||||
|
</window>
|
||||||
|
<customObject id="Zxl-vm-6c9" customClass="GBPaletteEditorController">
|
||||||
|
<connections>
|
||||||
|
<outlet property="brightnessSlider" destination="Wam-CT-owm" id="8KP-J6-bwn"/>
|
||||||
|
<outlet property="colorWell0" destination="odC-WD-uUp" id="Ant-NL-9jb"/>
|
||||||
|
<outlet property="colorWell1" destination="mpV-pm-9ZF" id="ckr-ci-OFC"/>
|
||||||
|
<outlet property="colorWell2" destination="NEt-gu-zL7" id="Bzt-Fx-qLu"/>
|
||||||
|
<outlet property="colorWell3" destination="fVn-3k-iuN" id="7hN-Y8-efH"/>
|
||||||
|
<outlet property="colorWell4" destination="min-mf-sjI" id="5No-1R-X59"/>
|
||||||
|
<outlet property="disableLCDColorCheckbox" destination="ZUa-QG-4ss" id="Cn6-Ba-XOm"/>
|
||||||
|
<outlet property="hueSlider" destination="ImK-kc-EEn" id="bzo-ON-2bZ"/>
|
||||||
|
<outlet property="hueStrengthSlider" destination="ij9-bn-1y8" id="lcn-4q-27B"/>
|
||||||
|
<outlet property="manualModeCheckbox" destination="l33-w0-rLw" id="NBU-1I-UzJ"/>
|
||||||
|
<outlet property="menu" destination="dHJ-3R-Ora" id="SWT-qM-tca"/>
|
||||||
|
<outlet property="themesList" destination="ZVn-bk-duk" id="S4b-vM-ioi"/>
|
||||||
|
</connections>
|
||||||
|
</customObject>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="AppIcon" width="128" height="128"/>
|
<image name="AppIcon" width="128" height="128"/>
|
||||||
<image name="CPU" width="32" height="32"/>
|
<image name="CPU" width="32" height="32"/>
|
||||||
<image name="Display" width="32" height="32"/>
|
<image name="Display" width="32" height="32"/>
|
||||||
<image name="Joypad" width="32" height="32"/>
|
<image name="Joypad" width="32" height="32"/>
|
||||||
|
<image name="NSAddTemplate" width="11" height="11"/>
|
||||||
|
<image name="NSRemoveTemplate" width="11" height="11"/>
|
||||||
<image name="Speaker" width="32" height="32"/>
|
<image name="Speaker" width="32" height="32"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
Loading…
Reference in New Issue
Block a user