SplashScreen.mm
6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#include "SplashScreen.h"
#include "UnityViewControllerBase.h"
#include "OrientationSupport.h"
#include "Unity/ObjCRuntime.h"
#include "UI/UnityView.h"
#include <cstring>
#include "Unity/UnitySharedDecls.h"
#include <utility>
static SplashScreen* _splash = nil;
static SplashScreenController* _controller = nil;
@implementation SplashScreen
{
UIImageView* m_ImageView;
UIView* m_XibView;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame: frame];
return self;
}
- (void)createUI
{
NSString* launchScreen = [[NSBundle mainBundle].infoDictionary[@"UILaunchStoryboardName"] stringByDeletingPathExtension];
const bool hasXIB = [[NSBundle mainBundle] pathForResource: launchScreen ofType: @"nib"] != nil;
if (hasXIB)
{
self->m_XibView = [[[NSBundle mainBundle] loadNibNamed: launchScreen owner: nil options: nil] objectAtIndex: 0];
[self addSubview: self->m_XibView];
}
else
{
#if !PLATFORM_TVOS
NSAssert(NO, @"no storyboard/xib was provided.");
#endif
// we still support launch images on tvos, but unlike iOS there are only two options and no orientations
UIImage* launchImage = nil;
if ([UIScreen mainScreen].scale > 1.0)
launchImage = [UIImage imageNamed: @"LaunchImage@2x"];
if (!launchImage)
launchImage = [UIImage imageNamed: @"LaunchImage@"];
self->m_ImageView = [[UIImageView alloc] initWithImage: launchImage];
[self addSubview: self->m_ImageView];
}
}
- (void)updateOrientation:(ScreenOrientation)orient withSupportedOrientations:(const OrientationMask&)supportedOrientations
{
CGFloat scale = UnityScreenScaleFactor([UIScreen mainScreen]);
UnityReportResizeView(self.bounds.size.width * scale, self.bounds.size.height * scale, orient);
ReportSafeAreaChangeForView(self);
// for iOS only xib/storyboard are supported, for tvOS (launch images are supported) no orientation takes place at all
}
- (void)layoutSubviews
{
if (self->m_XibView)
self->m_XibView.frame = self.bounds;
else if (self->m_ImageView)
self->m_ImageView.frame = self.bounds;
}
+ (SplashScreen*)Instance
{
return _splash;
}
- (void)freeSubviews
{
m_ImageView = nil;
m_XibView = nil;
}
@end
@implementation SplashScreenController
{
OrientationMask _supportedOrientations;
}
- (id)init
{
self = [super init];
if (self)
{
self->_supportedOrientations = { false, false, false, false };
}
return self;
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
ScreenOrientation curOrient = UIViewControllerOrientation(self);
ScreenOrientation newOrient = OrientationAfterTransform(curOrient, [coordinator targetTransform]);
[_splash updateOrientation: newOrient withSupportedOrientations: self->_supportedOrientations];
[super viewWillTransitionToSize: size withTransitionCoordinator: coordinator];
}
- (void)create:(UIWindow*)window
{
NSArray* supportedOrientation = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"UISupportedInterfaceOrientations"];
// splash will be shown way before unity is inited so we need to override autorotation handling with values read from info.plist
self->_supportedOrientations.portrait = [supportedOrientation containsObject: @"UIInterfaceOrientationPortrait"];
self->_supportedOrientations.portraitUpsideDown = [supportedOrientation containsObject: @"UIInterfaceOrientationPortraitUpsideDown"];
self->_supportedOrientations.landscapeLeft = [supportedOrientation containsObject: @"UIInterfaceOrientationLandscapeRight"];
self->_supportedOrientations.landscapeRight = [supportedOrientation containsObject: @"UIInterfaceOrientationLandscapeLeft"];
// special handling of devices/ios that do not support upside down orientation
if (!UnityDeviceSupportsUpsideDown())
{
self->_supportedOrientations.portraitUpsideDown = false;
OrientationMask om = self->_supportedOrientations;
const bool anySupported = om.portrait || om.landscapeLeft || om.landscapeRight;
if (!anySupported)
{
self->_supportedOrientations.portrait = true;
printf_console("This device does not support UpsideDown orientation, so we switched to Portrait.\n");
}
}
_splash = [[SplashScreen alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
_splash.contentScaleFactor = UnityScreenScaleFactor([UIScreen mainScreen]);
_splash.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_splash.autoresizesSubviews = YES;
[_splash createUI];
window.rootViewController = self;
self.view = _splash;
[window addSubview: _splash];
[window bringSubviewToFront: _splash];
ScreenOrientation orient = UIViewControllerOrientation(self);
[_splash updateOrientation: orient withSupportedOrientations: self->_supportedOrientations];
OrientView([SplashScreenController Instance], _splash, orient);
}
#if PLATFORM_IOS
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
NSUInteger ret = 0;
if (self->_supportedOrientations.portrait)
ret |= (1 << UIInterfaceOrientationPortrait);
if (self->_supportedOrientations.portraitUpsideDown)
ret |= (1 << UIInterfaceOrientationPortraitUpsideDown);
if (self->_supportedOrientations.landscapeLeft)
ret |= (1 << UIInterfaceOrientationLandscapeRight);
if (self->_supportedOrientations.landscapeRight)
ret |= (1 << UIInterfaceOrientationLandscapeLeft);
return ret;
}
#endif
+ (SplashScreenController*)Instance
{
return _controller;
}
@end
void ShowSplashScreen(UIWindow* window)
{
NSString* launchScreen = [[NSBundle mainBundle].infoDictionary[@"UILaunchStoryboardName"] stringByDeletingPathExtension];
#if PLATFORM_IOS
// since launch images are no longer supported on ios we MUST have UILaunchStoryboardName filled
assert(launchScreen != nil && @"UILaunchStoryboardName key is missing from info.plist");
#endif
const bool hasStoryboard = launchScreen != nil && [[NSBundle mainBundle] pathForResource: launchScreen ofType: @"storyboardc"] != nil;
if (hasStoryboard)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName: launchScreen bundle: [NSBundle mainBundle]];
_controller = [storyboard instantiateInitialViewController];
window.rootViewController = _controller;
}
else
{
_controller = [[SplashScreenController alloc] init];
[_controller create: window];
}
[window makeKeyAndVisible];
}
void HideSplashScreen()
{
if (_splash)
{
[_splash removeFromSuperview];
[_splash freeSubviews];
}
_splash = nil;
_controller = nil;
}