mirror of https://github.com/LIJI32/SameBoy.git
Automatic layout generation
This commit is contained in:
parent
d9bf739f52
commit
0441967332
2
Makefile
2
Makefile
|
@ -186,7 +186,7 @@ endif
|
||||||
CFLAGS += -arch arm64 -miphoneos-version-min=11.0 -isysroot $(SYSROOT)
|
CFLAGS += -arch arm64 -miphoneos-version-min=11.0 -isysroot $(SYSROOT)
|
||||||
LDFLAGS += -arch arm64
|
LDFLAGS += -arch arm64
|
||||||
OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT)
|
OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT)
|
||||||
LDFLAGS += -framework UIKit -framework Metal -framework MetalKit -framework AVFoundation -miphoneos-version-min=11.0 -isysroot $(SYSROOT)
|
LDFLAGS += -lobjc -framework UIKit -framework Foundation -framework CoreGraphics -framework Metal -framework MetalKit -framework AVFoundation -miphoneos-version-min=11.0 -isysroot $(SYSROOT)
|
||||||
CODESIGN := codesign -fs -
|
CODESIGN := codesign -fs -
|
||||||
else
|
else
|
||||||
ifeq ($(PLATFORM),Darwin)
|
ifeq ($(PLATFORM),Darwin)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import "GBLayout.h"
|
||||||
|
|
||||||
|
@interface GBHorizontalLayout : GBLayout
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,112 @@
|
||||||
|
#define GBLayoutInternal
|
||||||
|
#import "GBHorizontalLayout.h"
|
||||||
|
|
||||||
|
@implementation GBHorizontalLayout
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (!self) return nil;
|
||||||
|
|
||||||
|
CGSize resolution = {self.resolution.height - self.cutout, self.resolution.width};
|
||||||
|
|
||||||
|
CGRect screenRect = {0,};
|
||||||
|
screenRect.size.height = self.hasFractionalPixels? resolution.height : floor(resolution.height / 144) * 144;
|
||||||
|
screenRect.size.width = screenRect.size.height / 144 * 160;
|
||||||
|
|
||||||
|
double horizontalMargin, verticalMargin;
|
||||||
|
while (true) {
|
||||||
|
horizontalMargin = (resolution.width - screenRect.size.width) / 2;
|
||||||
|
verticalMargin = (resolution.height - screenRect.size.height) / 2;
|
||||||
|
if (horizontalMargin / self.factor < 170) {
|
||||||
|
if (self.hasFractionalPixels) {
|
||||||
|
screenRect.size.width = resolution.width - 170 * self.factor * 2;
|
||||||
|
screenRect.size.height = screenRect.size.width / 160 * 144;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
screenRect.size.width -= 160;
|
||||||
|
screenRect.size.height -= 144;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double screenBorderWidth = screenRect.size.width / 40;
|
||||||
|
|
||||||
|
screenRect.origin.x = (resolution.width - screenRect.size.width) / 2;
|
||||||
|
bool drawSameBoyLogo = false;
|
||||||
|
if (verticalMargin * 2 > screenBorderWidth * 7) {
|
||||||
|
drawSameBoyLogo = true;
|
||||||
|
screenRect.origin.y = (resolution.height - screenRect.size.height - screenBorderWidth * 5) / 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
screenRect.origin.y = (resolution.height - screenRect.size.height) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.screenRect = screenRect;
|
||||||
|
|
||||||
|
self.dpadLocation = (CGPoint){
|
||||||
|
round((screenRect.origin.x - screenBorderWidth) / 2),
|
||||||
|
round(resolution.height * 3 / 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
double wingWidth = (resolution.width - screenRect.size.width) / 2 - screenBorderWidth * 5;
|
||||||
|
double buttonRadius = 36 * self.factor;
|
||||||
|
CGSize buttonsDelta = [self buttonDeltaForMaxHorizontalDistance:wingWidth - buttonRadius * 2];
|
||||||
|
CGPoint buttonsCenter = {
|
||||||
|
resolution.width - self.dpadLocation.x,
|
||||||
|
self.dpadLocation.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.aLocation = (CGPoint) {
|
||||||
|
round(buttonsCenter.x + buttonsDelta.width / 2),
|
||||||
|
round(buttonsCenter.y - buttonsDelta.height / 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.bLocation = (CGPoint) {
|
||||||
|
round(buttonsCenter.x - buttonsDelta.width / 2),
|
||||||
|
round(buttonsCenter.y + buttonsDelta.height / 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.selectLocation = (CGPoint){
|
||||||
|
self.dpadLocation.x,
|
||||||
|
MIN(round(resolution.height * 3 / 4), self.dpadLocation.y + 180 * self.factor)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.startLocation = (CGPoint){
|
||||||
|
buttonsCenter.x,
|
||||||
|
self.selectLocation.y
|
||||||
|
};
|
||||||
|
|
||||||
|
resolution.width += self.cutout * 2;
|
||||||
|
self.screenRect = (CGRect){{self.screenRect.origin.x + self.cutout, self.screenRect.origin.y}, self.screenRect.size};
|
||||||
|
self.dpadLocation = (CGPoint){self.dpadLocation.x + self.cutout, self.dpadLocation.y};
|
||||||
|
self.aLocation = (CGPoint){self.aLocation.x + self.cutout, self.aLocation.y};
|
||||||
|
self.bLocation = (CGPoint){self.bLocation.x + self.cutout, self.bLocation.y};
|
||||||
|
self.startLocation = (CGPoint){self.startLocation.x + self.cutout, self.startLocation.y};
|
||||||
|
self.selectLocation = (CGPoint){self.selectLocation.x + self.cutout, self.selectLocation.y};
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(resolution, true, 1);
|
||||||
|
[self drawBackground];
|
||||||
|
[self drawScreenBezels];
|
||||||
|
if (drawSameBoyLogo) {
|
||||||
|
double bezelBottom = screenRect.origin.y + screenRect.size.height + screenBorderWidth;
|
||||||
|
double freeSpace = resolution.height - bezelBottom;
|
||||||
|
[self drawLogoInVerticalRange:(NSRange){bezelBottom + screenBorderWidth * 2, freeSpace - screenBorderWidth * 4}];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self drawLabels];
|
||||||
|
|
||||||
|
self.background = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)viewRectForOrientation:(UIInterfaceOrientation)orientation
|
||||||
|
{
|
||||||
|
if (orientation == UIInterfaceOrientationLandscapeLeft) {
|
||||||
|
return CGRectMake(-(signed)self.cutout / (signed)self.factor, 0, self.background.size.width / self.factor, self.background.size.height / self.factor);
|
||||||
|
}
|
||||||
|
return CGRectMake(0, 0, self.background.size.width / self.factor, self.background.size.height / self.factor);
|
||||||
|
}
|
||||||
|
@end
|
|
@ -0,0 +1,40 @@
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface GBLayout : NSObject
|
||||||
|
@property (readonly) UIImage *background;
|
||||||
|
@property (readonly) CGRect screenRect;
|
||||||
|
@property (readonly) CGPoint dpadLocation;
|
||||||
|
@property (readonly) CGPoint aLocation;
|
||||||
|
@property (readonly) CGPoint bLocation;
|
||||||
|
@property (readonly) CGPoint startLocation;
|
||||||
|
@property (readonly) CGPoint selectLocation;
|
||||||
|
- (CGRect)viewRectForOrientation:(UIInterfaceOrientation)orientation;
|
||||||
|
@end
|
||||||
|
|
||||||
|
#ifdef GBLayoutInternal
|
||||||
|
|
||||||
|
@interface GBLayout()
|
||||||
|
@property UIImage *background;
|
||||||
|
@property CGRect screenRect;
|
||||||
|
@property CGPoint dpadLocation;
|
||||||
|
@property CGPoint aLocation;
|
||||||
|
@property CGPoint bLocation;
|
||||||
|
@property CGPoint startLocation;
|
||||||
|
@property CGPoint selectLocation;
|
||||||
|
@property (readonly) CGSize resolution;
|
||||||
|
@property (readonly) unsigned factor;
|
||||||
|
@property (readonly) unsigned minY;
|
||||||
|
@property (readonly) unsigned cutout;
|
||||||
|
@property (readonly) bool hasFractionalPixels;
|
||||||
|
|
||||||
|
@property (readonly) UIColor *brandColor;
|
||||||
|
|
||||||
|
- (void)drawBackground;
|
||||||
|
- (void)drawScreenBezels;
|
||||||
|
- (void)drawLogoInVerticalRange:(NSRange)range;
|
||||||
|
- (void)drawLabels;
|
||||||
|
|
||||||
|
- (CGSize)buttonDeltaForMaxHorizontalDistance:(double)distance;
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,166 @@
|
||||||
|
#define GBLayoutInternal
|
||||||
|
#import "GBLayout.h"
|
||||||
|
|
||||||
|
@interface UIApplication()
|
||||||
|
- (double)statusBarHeightForOrientation:(UIInterfaceOrientation)orientation ignoreHidden:(bool)ignoreHidden;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GBLayout
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (!self) return nil;
|
||||||
|
_factor = [UIScreen mainScreen].scale;
|
||||||
|
_resolution = [UIScreen mainScreen].bounds.size;
|
||||||
|
_resolution.width *= _factor;
|
||||||
|
_resolution.height *= _factor;
|
||||||
|
if (_resolution.width > _resolution.height) {
|
||||||
|
_resolution = (CGSize){_resolution.height, _resolution.width};
|
||||||
|
}
|
||||||
|
_minY = [[UIApplication sharedApplication] statusBarHeightForOrientation:UIInterfaceOrientationPortrait
|
||||||
|
ignoreHidden:true] * _factor;
|
||||||
|
_cutout = _minY <= 24 * _factor? 0 : _minY;
|
||||||
|
|
||||||
|
// The Plus series will scale things lossily anyway, so no need to bother with integer scale things
|
||||||
|
// This also "catches" zoomed display modes
|
||||||
|
_hasFractionalPixels = _factor != [UIScreen mainScreen].nativeScale;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)viewRectForOrientation:(UIInterfaceOrientation)orientation
|
||||||
|
{
|
||||||
|
return CGRectMake(0, 0, self.background.size.width / self.factor, self.background.size.height / self.factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIColor *)brandColor
|
||||||
|
{
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
static UIColor *ret = nil;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
ret = [UIColor colorWithRed:0 / 255.0 green:70 / 255.0 blue:141 / 255.0 alpha:1.0];
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawBackground
|
||||||
|
{
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
CGColorRef top = [UIColor colorWithRed:192 / 255.0 green:195 / 255.0 blue:199 / 255.0 alpha:1.0].CGColor;
|
||||||
|
CGColorRef bottom = [UIColor colorWithRed:174 / 255.0 green:176 / 255.0 blue:180 / 255.0 alpha:1.0].CGColor;
|
||||||
|
CGColorRef colors[] = {top, bottom};
|
||||||
|
CFArrayRef colorsArray = CFArrayCreate(NULL, (const void **)colors, 2, &kCFTypeArrayCallBacks);
|
||||||
|
|
||||||
|
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, colorsArray, NULL);
|
||||||
|
CGContextDrawLinearGradient(context,
|
||||||
|
gradient,
|
||||||
|
(CGPoint){0, 0},
|
||||||
|
(CGPoint){0, CGBitmapContextGetHeight(context)},
|
||||||
|
0);
|
||||||
|
|
||||||
|
CFRelease(gradient);
|
||||||
|
CFRelease(colorsArray);
|
||||||
|
CFRelease(colorspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawScreenBezels
|
||||||
|
{
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
CGColorRef top = [UIColor colorWithWhite:53 / 255.0 alpha:1.0].CGColor;
|
||||||
|
CGColorRef bottom = [UIColor colorWithWhite:45 / 255.0 alpha:1.0].CGColor;
|
||||||
|
CGColorRef colors[] = {top, bottom};
|
||||||
|
CFArrayRef colorsArray = CFArrayCreate(NULL, (const void **)colors, 2, &kCFTypeArrayCallBacks);
|
||||||
|
|
||||||
|
double borderWidth = self.screenRect.size.width / 40;
|
||||||
|
CGRect bezelRect = self.screenRect;
|
||||||
|
bezelRect.origin.x -= borderWidth;
|
||||||
|
bezelRect.origin.y -= borderWidth;
|
||||||
|
bezelRect.size.width += borderWidth * 2;
|
||||||
|
bezelRect.size.height += borderWidth * 2;
|
||||||
|
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:bezelRect cornerRadius:borderWidth];
|
||||||
|
CGContextSaveGState(context);
|
||||||
|
CGContextSetShadowWithColor(context, (CGSize){0,}, borderWidth / 2, [UIColor colorWithWhite:0 alpha:1.0].CGColor);
|
||||||
|
[[UIColor colorWithWhite:0 alpha:0.25] setFill];
|
||||||
|
[path fill];
|
||||||
|
[path addClip];
|
||||||
|
|
||||||
|
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, colorsArray, NULL);
|
||||||
|
CGContextDrawLinearGradient(context,
|
||||||
|
gradient,
|
||||||
|
bezelRect.origin,
|
||||||
|
(CGPoint){bezelRect.origin.x, bezelRect.origin.y + bezelRect.size.height},
|
||||||
|
0);
|
||||||
|
|
||||||
|
CGContextRestoreGState(context);
|
||||||
|
|
||||||
|
CGContextSaveGState(context);
|
||||||
|
CGContextSetShadowWithColor(context, (CGSize){0,}, borderWidth / 2, [UIColor colorWithWhite:0 alpha:0.25].CGColor);
|
||||||
|
|
||||||
|
[[UIColor blackColor] setFill];
|
||||||
|
UIRectFill(self.screenRect);
|
||||||
|
CGContextRestoreGState(context);
|
||||||
|
|
||||||
|
CFRelease(gradient);
|
||||||
|
CFRelease(colorsArray);
|
||||||
|
CFRelease(colorspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawLogoInVerticalRange:(NSRange)range
|
||||||
|
{
|
||||||
|
UIFont *font = [UIFont fontWithName:@"AvenirNext-BoldItalic" size:range.length * 4 / 3];
|
||||||
|
|
||||||
|
CGRect rect = CGRectMake(0,
|
||||||
|
range.location - range.length / 3,
|
||||||
|
CGBitmapContextGetWidth(UIGraphicsGetCurrentContext()), range.length * 2);
|
||||||
|
NSMutableParagraphStyle *style = [NSParagraphStyle defaultParagraphStyle].mutableCopy;
|
||||||
|
style.alignment = NSTextAlignmentCenter;
|
||||||
|
[@"SAMEBOY" drawInRect:rect
|
||||||
|
withAttributes:@{
|
||||||
|
NSFontAttributeName: font,
|
||||||
|
NSForegroundColorAttributeName:self.brandColor,
|
||||||
|
NSParagraphStyleAttributeName: style,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawRotatedLabel:(NSString *)label withFont:(UIFont *)font origin:(CGPoint)origin distance:(double)distance
|
||||||
|
{
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
|
||||||
|
CGContextSaveGState(context);
|
||||||
|
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(origin.x, origin.y));
|
||||||
|
CGContextConcatCTM(context, CGAffineTransformMakeRotation(-M_PI / 6));
|
||||||
|
|
||||||
|
NSMutableParagraphStyle *style = [NSParagraphStyle defaultParagraphStyle].mutableCopy;
|
||||||
|
style.alignment = NSTextAlignmentCenter;
|
||||||
|
|
||||||
|
[label drawInRect:CGRectMake(-256, distance, 512, 256)
|
||||||
|
withAttributes:@{
|
||||||
|
NSFontAttributeName: font,
|
||||||
|
NSForegroundColorAttributeName:self.brandColor,
|
||||||
|
NSParagraphStyleAttributeName: style,
|
||||||
|
}];
|
||||||
|
CGContextRestoreGState(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawLabels
|
||||||
|
{
|
||||||
|
|
||||||
|
UIFont *labelFont = [UIFont fontWithName:@"AvenirNext-Bold" size:24 * _factor];
|
||||||
|
UIFont *smallLabelFont = [UIFont fontWithName:@"AvenirNext-DemiBold" size:20 * _factor];
|
||||||
|
|
||||||
|
[self drawRotatedLabel:@"A" withFont:labelFont origin:self.aLocation distance:40 * self.factor];
|
||||||
|
[self drawRotatedLabel:@"B" withFont:labelFont origin:self.bLocation distance:40 * self.factor];
|
||||||
|
[self drawRotatedLabel:@"SELECT" withFont:smallLabelFont origin:self.selectLocation distance:24 * self.factor];
|
||||||
|
[self drawRotatedLabel:@"START" withFont:smallLabelFont origin:self.startLocation distance:24 * self.factor];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)buttonDeltaForMaxHorizontalDistance:(double)maxDistance
|
||||||
|
{
|
||||||
|
CGSize buttonsDelta = {90 * self.factor, 45 * self.factor};
|
||||||
|
if (buttonsDelta.width <= maxDistance) {
|
||||||
|
return buttonsDelta;
|
||||||
|
}
|
||||||
|
return (CGSize){maxDistance, floor(sqrt(100 * 100 * self.factor * self.factor - maxDistance * maxDistance))};
|
||||||
|
}
|
||||||
|
@end
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import "GBLayout.h"
|
||||||
|
|
||||||
|
@interface GBVerticalLayout : GBLayout
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,76 @@
|
||||||
|
#define GBLayoutInternal
|
||||||
|
#import "GBVerticalLayout.h"
|
||||||
|
|
||||||
|
@implementation GBVerticalLayout
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (!self) return nil;
|
||||||
|
|
||||||
|
CGSize resolution = self.resolution;
|
||||||
|
|
||||||
|
CGRect screenRect = {0,};
|
||||||
|
screenRect.size.width = self.hasFractionalPixels? resolution.width : floor(resolution.width / 160) * 160;
|
||||||
|
screenRect.size.height = screenRect.size.width / 160 * 144;
|
||||||
|
|
||||||
|
double screenBorderWidth = screenRect.size.width / 40;
|
||||||
|
screenRect.origin.x = (resolution.width - screenRect.size.width) / 2;
|
||||||
|
screenRect.origin.y = self.minY + screenBorderWidth * 2;
|
||||||
|
self.screenRect = screenRect;
|
||||||
|
|
||||||
|
double controlAreaStart = screenRect.origin.y + screenRect.size.height + screenBorderWidth * 2;
|
||||||
|
|
||||||
|
self.selectLocation = (CGPoint){
|
||||||
|
MIN(resolution.width / 4, 120 * self.factor),
|
||||||
|
MIN(resolution.height - 80 * self.factor, (resolution.height - controlAreaStart) * 0.75 + controlAreaStart)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.startLocation = (CGPoint){
|
||||||
|
resolution.width - self.selectLocation.x,
|
||||||
|
self.selectLocation.y
|
||||||
|
};
|
||||||
|
|
||||||
|
double buttonRadius = 36 * self.factor;
|
||||||
|
CGSize buttonsDelta = [self buttonDeltaForMaxHorizontalDistance:resolution.width / 2 - buttonRadius * 2 - screenBorderWidth * 2];
|
||||||
|
|
||||||
|
self.dpadLocation = (CGPoint) {
|
||||||
|
self.selectLocation.x,
|
||||||
|
self.selectLocation.y - 140 * self.factor
|
||||||
|
};
|
||||||
|
|
||||||
|
CGPoint buttonsCenter = {
|
||||||
|
resolution.width - self.dpadLocation.x,
|
||||||
|
self.dpadLocation.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.aLocation = (CGPoint) {
|
||||||
|
round(buttonsCenter.x + buttonsDelta.width / 2),
|
||||||
|
round(buttonsCenter.y - buttonsDelta.height / 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.bLocation = (CGPoint) {
|
||||||
|
round(buttonsCenter.x - buttonsDelta.width / 2),
|
||||||
|
round(buttonsCenter.y + buttonsDelta.height / 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
double controlsTop = self.dpadLocation.y - 80 * self.factor;
|
||||||
|
double middleSpace = self.bLocation.x - buttonRadius - (self.dpadLocation.x + 80 * self.factor);
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(resolution, true, 1);
|
||||||
|
[self drawBackground];
|
||||||
|
[self drawScreenBezels];
|
||||||
|
|
||||||
|
if (controlsTop - controlAreaStart > 24 * self.factor + screenBorderWidth * 2 ||
|
||||||
|
middleSpace > 160 * self.factor) {
|
||||||
|
[self drawLogoInVerticalRange:(NSRange){controlAreaStart + screenBorderWidth, 24 * self.factor}];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self drawLabels];
|
||||||
|
|
||||||
|
self.background = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface GBViewController : UIViewController <UIApplicationDelegate>
|
||||||
|
@property (nullable, nonatomic, strong) UIWindow *window;
|
||||||
|
@end
|
|
@ -0,0 +1,92 @@
|
||||||
|
#import "GBViewController.h"
|
||||||
|
#import "GBHorizontalLayout.h"
|
||||||
|
#import "GBVerticalLayout.h"
|
||||||
|
|
||||||
|
static void positionView(UIImageView *view, CGPoint position)
|
||||||
|
{
|
||||||
|
double center = view.image.size.width / 2 * [UIScreen mainScreen].scale;
|
||||||
|
view.frame = (CGRect){
|
||||||
|
{
|
||||||
|
round(position.x - center) / [UIScreen mainScreen].scale,
|
||||||
|
round(position.y - center) / [UIScreen mainScreen].scale
|
||||||
|
},
|
||||||
|
view.image.size
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation GBViewController
|
||||||
|
{
|
||||||
|
GBLayout *_currentLayout;
|
||||||
|
GBHorizontalLayout *_horizontalLayout;
|
||||||
|
GBVerticalLayout *_verticalLayout;
|
||||||
|
UIImageView *_backgroundView;
|
||||||
|
UIImageView *_dpadView;
|
||||||
|
UIImageView *_aButtonView;
|
||||||
|
UIImageView *_bButtonView;
|
||||||
|
UIImageView *_startButtonView;
|
||||||
|
UIImageView *_selectButtonView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
|
{
|
||||||
|
_window = [[UIWindow alloc] init];
|
||||||
|
_window.rootViewController = self;
|
||||||
|
[_window makeKeyAndVisible];
|
||||||
|
_horizontalLayout = [[GBHorizontalLayout alloc] init];
|
||||||
|
_verticalLayout = [[GBVerticalLayout alloc] init];
|
||||||
|
|
||||||
|
_backgroundView = [[UIImageView alloc] initWithImage:nil];
|
||||||
|
[_window addSubview:_backgroundView];
|
||||||
|
|
||||||
|
_dpadView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dpad"]];
|
||||||
|
_aButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
|
||||||
|
_bButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
|
||||||
|
_startButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
|
||||||
|
_selectButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
|
||||||
|
|
||||||
|
[_backgroundView addSubview:_dpadView];
|
||||||
|
[_backgroundView addSubview:_aButtonView];
|
||||||
|
[_backgroundView addSubview:_bButtonView];
|
||||||
|
[_backgroundView addSubview:_startButtonView];
|
||||||
|
[_backgroundView addSubview:_selectButtonView];
|
||||||
|
|
||||||
|
[self orientationChange];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(orientationChange)
|
||||||
|
name:UIApplicationDidChangeStatusBarOrientationNotification
|
||||||
|
object:nil];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)orientationChange
|
||||||
|
{
|
||||||
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||||
|
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
||||||
|
_currentLayout = _verticalLayout;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_currentLayout = _horizontalLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
_backgroundView.image = _currentLayout.background;
|
||||||
|
_backgroundView.frame = [_currentLayout viewRectForOrientation:[UIApplication sharedApplication].statusBarOrientation];
|
||||||
|
|
||||||
|
positionView(_dpadView, _currentLayout.dpadLocation);
|
||||||
|
positionView(_aButtonView, _currentLayout.aLocation);
|
||||||
|
positionView(_bButtonView, _currentLayout.bLocation);
|
||||||
|
positionView(_startButtonView, _currentLayout.startLocation);
|
||||||
|
positionView(_selectButtonView, _currentLayout.selectLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)prefersHomeIndicatorAutoHidden
|
||||||
|
{
|
||||||
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||||
|
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
|
@ -1,6 +1,7 @@
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "GBViewController.h"
|
||||||
|
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
return UIApplicationMain(argc, argv, nil, nil);
|
return UIApplicationMain(argc, argv, nil, NSStringFromClass([GBViewController class]));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue