diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
index b88dfae5b28..f40afda55e0 100644
--- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
+++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
@@ -59,5 +59,19 @@
$additional_plist_content
$plist_launch_screen_name
CADisableMinimumFrameDurationOnPhone
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+
+
+
+
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 06095332fa1..0c12f0f0719 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -14,6 +14,7 @@ iphone_lib = [
"tts_ios.mm",
"display_layer.mm",
"godot_app_delegate.m",
+ "godot_scene_delegate.m",
"godot_view_renderer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h
index a211ce2a106..9191a19edfd 100644
--- a/platform/iphone/app_delegate.h
+++ b/platform/iphone/app_delegate.h
@@ -32,7 +32,9 @@
@class ViewController;
-@interface AppDelegate : NSObject
+@interface AppDelegate : NSObject
+
++ (AppDelegate *)getSingleton;
@property(strong, nonatomic) UIWindow *window;
@property(strong, class, readonly, nonatomic) ViewController *viewController;
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index 714846191d5..6fafefa7720 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -64,11 +64,37 @@ static ViewController *mainViewController = nil;
return mainViewController;
}
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- // Create a full-screen window
- CGRect windowBounds = [[UIScreen mainScreen] bounds];
- self.window = [[UIWindow alloc] initWithFrame:windowBounds];
+static AppDelegate *delegate_singleton = nil;
++ (AppDelegate *)getSingleton {
+ if (!delegate_singleton) {
+ delegate_singleton = [AppDelegate new];
+ }
+ return delegate_singleton;
+}
+
+- (void)createViewController {
+ ViewController *viewController = [[ViewController alloc] init];
+ viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO;
+ viewController.godotView.renderingInterval = 1.0 / kRenderingFrequency;
+
+ self.window.rootViewController = viewController;
+
+ // Show the window
+ [self.window makeKeyAndVisible];
+
+ mainViewController = viewController;
+}
+
+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ if ([scene isKindOfClass:[UIWindowScene class]]) {
+ UIWindowScene *window_scene = (UIWindowScene *)scene;
+ self.window = [[UIWindow alloc] initWithWindowScene:window_scene];
+ [self createViewController];
+ }
+}
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
@@ -83,18 +109,14 @@ static ViewController *mainViewController = nil;
return FALSE;
}
- // WARNING: We must *always* create the GodotView after we have constructed the
- // OS with iphone_main. This allows the GodotView to access project settings so
- // it can properly initialize the OpenGL context
-
- ViewController *viewController = [[ViewController alloc] init];
- viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO;
- viewController.godotView.renderingInterval = 1.0 / kRenderingFrequency;
-
- self.window.rootViewController = viewController;
-
- // Show the window
- [self.window makeKeyAndVisible];
+ if (@available(iOS 13, tvOS 13, *)) {
+ // NOP
+ } else {
+ // Create a full-screen window
+ CGRect windowBounds = [[UIScreen mainScreen] bounds];
+ self.window = [[UIWindow alloc] initWithFrame:windowBounds];
+ [self createViewController];
+ }
[[NSNotificationCenter defaultCenter]
addObserver:self
@@ -102,8 +124,6 @@ static ViewController *mainViewController = nil;
name:AVAudioSessionInterruptionNotification
object:[AVAudioSession sharedInstance]];
- mainViewController = viewController;
-
int sessionCategorySetting = GLOBAL_GET("audio/general/ios/session_category");
// Initialize with default Ambient category.
@@ -166,22 +186,42 @@ static ViewController *mainViewController = nil;
// if you open the app list without switching to another app or open/close the
// notification panel by swiping from the upper part of the screen.
+- (void)sceneDidDisconnect:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ OSIPhone::get_singleton()->on_focus_out();
+}
+
- (void)applicationWillResignActive:(UIApplication *)application {
OSIPhone::get_singleton()->on_focus_out();
}
+- (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ OSIPhone::get_singleton()->on_focus_out();
+}
+
- (void)applicationDidBecomeActive:(UIApplication *)application {
OSIPhone::get_singleton()->on_focus_in();
}
+- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ OSIPhone::get_singleton()->on_focus_in();
+}
+
- (void)applicationDidEnterBackground:(UIApplication *)application {
OSIPhone::get_singleton()->on_enter_background();
}
+- (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ OSIPhone::get_singleton()->on_enter_background();
+}
+
- (void)applicationWillEnterForeground:(UIApplication *)application {
OSIPhone::get_singleton()->on_exit_background();
}
+- (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0), visionos(1.0)) {
+ OSIPhone::get_singleton()->on_exit_background();
+}
+
- (void)dealloc {
self.window = nil;
}
diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m
index 74e8705bc3f..8b174ede807 100644
--- a/platform/iphone/godot_app_delegate.m
+++ b/platform/iphone/godot_app_delegate.m
@@ -31,6 +31,7 @@
#import "godot_app_delegate.h"
#import "app_delegate.h"
+#import "godot_scene_delegate.h"
@interface GodotApplicalitionDelegate ()
@@ -46,7 +47,7 @@ static NSMutableArray *services = nil;
+ (void)load {
services = [NSMutableArray new];
- [services addObject:[AppDelegate new]];
+ [services addObject:[AppDelegate getSingleton]];
}
+ (void)addService:(ApplicationDelegateService *)service {
@@ -63,15 +64,29 @@ static NSMutableArray *services = nil;
- (UIWindow *)window {
UIWindow *result = nil;
- for (ApplicationDelegateService *service in services) {
- if (![service respondsToSelector:_cmd]) {
- continue;
+ if (@available(iOS 13, tvOS 13, *)) {
+ for (SceneDelegateService *service in [SceneDelegate services]) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ UIWindow *value = [service window];
+
+ if (value) {
+ result = value;
+ }
}
+ } else {
+ for (ApplicationDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
- UIWindow *value = [service window];
+ UIWindow *value = [service window];
- if (value) {
- result = value;
+ if (value) {
+ result = value;
+ }
}
}
@@ -456,12 +471,15 @@ static NSMutableArray *services = nil;
}
}
-/* Handled By Info.plist file for now
-
// MARK: Interface Geometry
-- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {}
+- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ UISceneConfiguration *config = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
+ config.delegateClass = [SceneDelegate class];
+ return config;
+}
-*/
+- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions API_AVAILABLE(ios(13.0), tvos(13.0)) {
+}
@end
diff --git a/platform/iphone/godot_scene_delegate.h b/platform/iphone/godot_scene_delegate.h
new file mode 100644
index 00000000000..16f47ff01b3
--- /dev/null
+++ b/platform/iphone/godot_scene_delegate.h
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/* godot_scene_delegate.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#import
+
+typedef NSObject SceneDelegateService API_AVAILABLE(ios(13.0), tvos(13.0));
+
+API_AVAILABLE(ios(13.0), tvos(13.0))
+@interface SceneDelegate : NSObject
+
+@property(class, readonly, strong) NSArray *services;
+
++ (void)addService:(SceneDelegateService *)service;
+
+@end
diff --git a/platform/iphone/godot_scene_delegate.m b/platform/iphone/godot_scene_delegate.m
new file mode 100644
index 00000000000..8140256782b
--- /dev/null
+++ b/platform/iphone/godot_scene_delegate.m
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/* godot_scene_delegate.m */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#import "godot_scene_delegate.h"
+
+#import "app_delegate.h"
+
+@implementation SceneDelegate
+
+API_AVAILABLE(ios(13.0), tvos(13.0))
+static NSMutableArray *services = nil;
+
++ (NSArray *)services API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ return services;
+}
+
++ (void)load {
+ if (@available(iOS 13, tvOS 13, *)) {
+ services = [NSMutableArray new];
+ [services addObject:[AppDelegate getSingleton]];
+ }
+}
+
++ (void)addService:(SceneDelegateService *)service API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ if (!services || !service) {
+ return;
+ }
+ [services addObject:service];
+}
+
+// MARK: Scene
+
+- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service scene:scene willConnectToSession:session options:connectionOptions];
+ }
+}
+
+// MARK: Life-Cycle
+
+- (void)sceneDidDisconnect:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service sceneDidDisconnect:scene];
+ }
+}
+
+- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service sceneDidBecomeActive:scene];
+ }
+}
+
+- (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service sceneWillResignActive:scene];
+ }
+}
+
+- (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service sceneDidEnterBackground:scene];
+ }
+}
+
+- (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)) {
+ for (SceneDelegateService *service in services) {
+ if (![service respondsToSelector:_cmd]) {
+ continue;
+ }
+
+ [service sceneWillEnterForeground:scene];
+ }
+}
+
+@end