diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-07-20 09:28:22 +0300 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-07-21 09:37:52 +0300 |
commit | 8823eae328547991def3b13ee2919291d29a278b (patch) | |
tree | 7a9dbdf352b115531c05c43c306ff303d67602b5 /platform/iphone | |
parent | 292c952e3be9904d8aaaff1d3f7c569b2ffb658b (diff) |
Rename OSX to macOS and iPhoneOS to iOS.
Diffstat (limited to 'platform/iphone')
44 files changed, 0 insertions, 8044 deletions
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub deleted file mode 100644 index 5e10bf5646..0000000000 --- a/platform/iphone/SCsub +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -iphone_lib = [ - "godot_iphone.mm", - "os_iphone.mm", - "main.m", - "app_delegate.mm", - "view_controller.mm", - "ios.mm", - "vulkan_context_iphone.mm", - "display_server_iphone.mm", - "joypad_iphone.mm", - "godot_view.mm", - "tts_ios.mm", - "display_layer.mm", - "godot_app_delegate.m", - "godot_view_renderer.mm", - "godot_view_gesture_recognizer.mm", - "device_metrics.m", - "keyboard_input_view.mm", -] - -env_ios = env.Clone() -ios_lib = env_ios.add_library("iphone", iphone_lib) - -# (iOS) Enable module support -env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - - -def combine_libs(target=None, source=None, env=None): - lib_path = target[0].srcnode().abspath - if "osxcross" in env: - libtool = "$IPHONEPATH/usr/bin/${ios_triple}libtool" - else: - libtool = "$IPHONEPATH/usr/bin/libtool" - env.Execute( - libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) - ) - - -combine_command = env_ios.Command("#bin/libgodot" + env_ios["LIBSUFFIX"], [ios_lib] + env_ios["LIBS"], combine_libs) diff --git a/platform/iphone/api/api.cpp b/platform/iphone/api/api.cpp deleted file mode 100644 index f2e6fd7a7a..0000000000 --- a/platform/iphone/api/api.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* api.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "api.h" - -#if defined(IPHONE_ENABLED) - -void register_iphone_api() { - godot_ios_plugins_initialize(); -} - -void unregister_iphone_api() { - godot_ios_plugins_deinitialize(); -} - -#else - -void register_iphone_api() {} -void unregister_iphone_api() {} - -#endif diff --git a/platform/iphone/api/api.h b/platform/iphone/api/api.h deleted file mode 100644 index ece91a9f1a..0000000000 --- a/platform/iphone/api/api.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************/ -/* api.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef IPHONE_API_H -#define IPHONE_API_H - -#if defined(IPHONE_ENABLED) -extern void godot_ios_plugins_initialize(); -extern void godot_ios_plugins_deinitialize(); -#endif - -void register_iphone_api(); -void unregister_iphone_api(); - -#endif // IPHONE_API_H diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h deleted file mode 100644 index 0ec1dc071b..0000000000 --- a/platform/iphone/app_delegate.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* app_delegate.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -@class ViewController; - -// FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented again, -// so it can't be done with compilation time branching. -//#if defined(GLES3_ENABLED) -//@interface AppDelegate : NSObject <UIApplicationDelegate, GLViewDelegate> { -//#endif -//#if defined(VULKAN_ENABLED) -@interface AppDelegate : NSObject <UIApplicationDelegate> -//#endif - -@property(strong, nonatomic) UIWindow *window; -@property(strong, class, readonly, nonatomic) ViewController *viewController; - -@end diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm deleted file mode 100644 index c5c9b5a5f9..0000000000 --- a/platform/iphone/app_delegate.mm +++ /dev/null @@ -1,149 +0,0 @@ -/*************************************************************************/ -/* app_delegate.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "app_delegate.h" - -#include "core/config/project_settings.h" -#include "drivers/coreaudio/audio_driver_coreaudio.h" -#import "godot_view.h" -#include "main/main.h" -#include "os_iphone.h" -#import "view_controller.h" - -#import <AVFoundation/AVFoundation.h> -#import <AudioToolbox/AudioServices.h> - -#define kRenderingFrequency 60 - -extern int gargc; -extern char **gargv; - -extern int iphone_main(int, char **, String, String); -extern void iphone_finish(); - -@implementation AppDelegate - -static ViewController *mainViewController = nil; - -+ (ViewController *)viewController { - return mainViewController; -} - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // TODO: might be required to make an early return, so app wouldn't crash because of timeout. - // TODO: logo screen is not displayed while shaders are compiling - // DummyViewController(Splash/LoadingViewController) -> setup -> GodotViewController - - CGRect windowBounds = [[UIScreen mainScreen] bounds]; - - // Create a full-screen window - self.window = [[UIWindow alloc] initWithFrame:windowBounds]; - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - NSString *cacheDirectory = [paths objectAtIndex:0]; - - int err = iphone_main(gargc, gargv, String::utf8([documentsDirectory UTF8String]), String::utf8([cacheDirectory UTF8String])); - - if (err != 0) { - // bail, things did not go very well for us, should probably output a message on screen with our error code... - exit(0); - return NO; - } - - 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]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(onAudioInterruption:) - name:AVAudioSessionInterruptionNotification - object:[AVAudioSession sharedInstance]]; - - mainViewController = viewController; - - // prevent to stop music in another background app - [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; - - return YES; -} - -- (void)onAudioInterruption:(NSNotification *)notification { - if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) { - if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) { - NSLog(@"Audio interruption began"); - OSIPhone::get_singleton()->on_focus_out(); - } else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) { - NSLog(@"Audio interruption ended"); - OSIPhone::get_singleton()->on_focus_in(); - } - } -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - if (OS::get_singleton()->get_main_loop()) { - OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_MEMORY_WARNING); - } -} - -- (void)applicationWillTerminate:(UIApplication *)application { - iphone_finish(); -} - -// When application goes to background (e.g. user switches to another app or presses Home), -// then applicationWillResignActive -> applicationDidEnterBackground are called. -// When user opens the inactive app again, -// applicationWillEnterForeground -> applicationDidBecomeActive are called. - -// There are cases when applicationWillResignActive -> applicationDidBecomeActive -// sequence is called without the app going to background. For example, that happens -// 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)applicationWillResignActive:(UIApplication *)application { - OSIPhone::get_singleton()->on_focus_out(); -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - OSIPhone::get_singleton()->on_focus_in(); -} - -- (void)dealloc { - self.window = nil; -} - -@end diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py deleted file mode 100644 index 862f1fe50b..0000000000 --- a/platform/iphone/detect.py +++ /dev/null @@ -1,152 +0,0 @@ -import os -import sys -from methods import detect_darwin_sdk_path - - -def is_active(): - return True - - -def get_name(): - return "iOS" - - -def can_build(): - if sys.platform == "darwin" or ("OSXCROSS_IOS" in os.environ): - return True - - return False - - -def get_opts(): - from SCons.Variables import BoolVariable - - return [ - ( - "IPHONEPATH", - "Path to iPhone toolchain", - "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", - ), - ("IPHONESDK", "Path to the iPhone SDK", ""), - BoolVariable("ios_simulator", "Build for iOS Simulator", False), - BoolVariable("ios_exceptions", "Enable exceptions", False), - ("ios_triple", "Triple for ios toolchain", ""), - ] - - -def get_flags(): - return [ - ("tools", False), - ("use_volk", False), - ] - - -def configure(env): - ## Build type - - if env["target"].startswith("release"): - env.Append(CPPDEFINES=["NDEBUG", ("NS_BLOCK_ASSERTIONS", 1)]) - if env["optimize"] == "speed": # optimize for speed (default) - # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces - # when using `target=release_debug`. - opt = "-O3" if env["target"] == "release" else "-O2" - env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"]) - env.Append(LINKFLAGS=[opt]) - elif env["optimize"] == "size": # optimize for size - env.Append(CCFLAGS=["-Os", "-ftree-vectorize"]) - env.Append(LINKFLAGS=["-Os"]) - - elif env["target"] == "debug": - env.Append(CCFLAGS=["-gdwarf-2", "-O0"]) - env.Append(CPPDEFINES=["_DEBUG", ("DEBUG", 1)]) - - if env["use_lto"]: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) - - ## Architecture - env["bits"] = "64" - if env["arch"] != "x86_64": - env["arch"] = "arm64" - - ## Compiler configuration - - # Save this in environment for use by other modules - if "OSXCROSS_IOS" in os.environ: - env["osxcross"] = True - - env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] - - compiler_path = "$IPHONEPATH/usr/bin/${ios_triple}" - s_compiler_path = "$IPHONEPATH/Developer/usr/bin/" - - ccache_path = os.environ.get("CCACHE") - if ccache_path is None: - env["CC"] = compiler_path + "clang" - env["CXX"] = compiler_path + "clang++" - env["S_compiler"] = s_compiler_path + "gcc" - else: - # there aren't any ccache wrappers available for iOS, - # to enable caching we need to prepend the path to the ccache binary - env["CC"] = ccache_path + " " + compiler_path + "clang" - env["CXX"] = ccache_path + " " + compiler_path + "clang++" - env["S_compiler"] = ccache_path + " " + s_compiler_path + "gcc" - env["AR"] = compiler_path + "ar" - env["RANLIB"] = compiler_path + "ranlib" - - ## Compile flags - - if env["ios_simulator"]: - detect_darwin_sdk_path("iphonesimulator", env) - env.Append(ASFLAGS=["-mios-simulator-version-min=13.0"]) - env.Append(CCFLAGS=["-mios-simulator-version-min=13.0"]) - env.extra_suffix = ".simulator" + env.extra_suffix - else: - detect_darwin_sdk_path("iphone", env) - env.Append(ASFLAGS=["-miphoneos-version-min=11.0"]) - env.Append(CCFLAGS=["-miphoneos-version-min=11.0"]) - - if env["arch"] == "x86_64": - env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9" - env.Append( - CCFLAGS=( - "-fobjc-arc -arch x86_64" - " -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks" - " -fasm-blocks -isysroot $IPHONESDK" - ).split() - ) - env.Append(ASFLAGS=["-arch", "x86_64"]) - elif env["arch"] == "arm64": - env.Append( - CCFLAGS=( - "-fobjc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing" - " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits" - " -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies" - " -isysroot $IPHONESDK".split() - ) - ) - env.Append(ASFLAGS=["-arch", "arm64"]) - env.Append(CPPDEFINES=["NEED_LONG_INT"]) - - # Disable exceptions on non-tools (template) builds - if not env["tools"]: - if env["ios_exceptions"]: - env.Append(CCFLAGS=["-fexceptions"]) - else: - env.Append(CCFLAGS=["-fno-exceptions"]) - - # Temp fix for ABS/MAX/MIN macros in iPhone SDK blocking compilation - env.Append(CCFLAGS=["-Wno-ambiguous-macro"]) - - env.Prepend( - CPPPATH=[ - "$IPHONESDK/usr/include", - "$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers", - ] - ) - - env.Prepend(CPPPATH=["#platform/iphone"]) - env.Append(CPPDEFINES=["IPHONE_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) - - if env["vulkan"]: - env.Append(CPPDEFINES=["VULKAN_ENABLED"]) diff --git a/platform/iphone/device_metrics.h b/platform/iphone/device_metrics.h deleted file mode 100644 index b9fb9b2fd9..0000000000 --- a/platform/iphone/device_metrics.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************/ -/* device_metrics.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <Foundation/Foundation.h> - -@interface GodotDeviceMetrics : NSObject - -@property(nonatomic, class, readonly, strong) NSDictionary<NSArray *, NSNumber *> *dpiList; - -@end diff --git a/platform/iphone/device_metrics.m b/platform/iphone/device_metrics.m deleted file mode 100644 index ec4dd8130d..0000000000 --- a/platform/iphone/device_metrics.m +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************/ -/* device_metrics.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "device_metrics.h" - -@implementation GodotDeviceMetrics - -+ (NSDictionary *)dpiList { - return @{ - @[ - @"iPad1,1", - @"iPad2,1", - @"iPad2,2", - @"iPad2,3", - @"iPad2,4", - ] : @132, - @[ - @"iPhone1,1", - @"iPhone1,2", - @"iPhone2,1", - @"iPad2,5", - @"iPad2,6", - @"iPad2,7", - @"iPod1,1", - @"iPod2,1", - @"iPod3,1", - ] : @163, - @[ - @"iPad3,1", - @"iPad3,2", - @"iPad3,3", - @"iPad3,4", - @"iPad3,5", - @"iPad3,6", - @"iPad4,1", - @"iPad4,2", - @"iPad4,3", - @"iPad5,3", - @"iPad5,4", - @"iPad6,3", - @"iPad6,4", - @"iPad6,7", - @"iPad6,8", - @"iPad6,11", - @"iPad6,12", - @"iPad7,1", - @"iPad7,2", - @"iPad7,3", - @"iPad7,4", - @"iPad7,5", - @"iPad7,6", - @"iPad7,11", - @"iPad7,12", - @"iPad8,1", - @"iPad8,2", - @"iPad8,3", - @"iPad8,4", - @"iPad8,5", - @"iPad8,6", - @"iPad8,7", - @"iPad8,8", - @"iPad8,9", - @"iPad8,10", - @"iPad8,11", - @"iPad8,12", - @"iPad11,3", - @"iPad11,4", - ] : @264, - @[ - @"iPhone3,1", - @"iPhone3,2", - @"iPhone3,3", - @"iPhone4,1", - @"iPhone5,1", - @"iPhone5,2", - @"iPhone5,3", - @"iPhone5,4", - @"iPhone6,1", - @"iPhone6,2", - @"iPhone7,2", - @"iPhone8,1", - @"iPhone8,4", - @"iPhone9,1", - @"iPhone9,3", - @"iPhone10,1", - @"iPhone10,4", - @"iPhone11,8", - @"iPhone12,1", - @"iPhone12,8", - @"iPad4,4", - @"iPad4,5", - @"iPad4,6", - @"iPad4,7", - @"iPad4,8", - @"iPad4,9", - @"iPad5,1", - @"iPad5,2", - @"iPad11,1", - @"iPad11,2", - @"iPod4,1", - @"iPod5,1", - @"iPod7,1", - @"iPod9,1", - ] : @326, - @[ - @"iPhone7,1", - @"iPhone8,2", - @"iPhone9,2", - @"iPhone9,4", - @"iPhone10,2", - @"iPhone10,5", - ] : @401, - @[ - @"iPhone10,3", - @"iPhone10,6", - @"iPhone11,2", - @"iPhone11,4", - @"iPhone11,6", - @"iPhone12,3", - @"iPhone12,5", - ] : @458, - }; -} - -@end diff --git a/platform/iphone/display_layer.h b/platform/iphone/display_layer.h deleted file mode 100644 index a17c75dba1..0000000000 --- a/platform/iphone/display_layer.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* display_layer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <OpenGLES/EAGLDrawable.h> -#import <QuartzCore/QuartzCore.h> - -@protocol DisplayLayer <NSObject> - -- (void)renderDisplayLayer; -- (void)initializeDisplayLayer; -- (void)layoutDisplayLayer; - -@end - -// An ugly workaround for iOS simulator -#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR -#if defined(__IPHONE_13_0) -API_AVAILABLE(ios(13.0)) -@interface GodotMetalLayer : CAMetalLayer <DisplayLayer> -#else -@interface GodotMetalLayer : CALayer <DisplayLayer> -#endif -#else -@interface GodotMetalLayer : CAMetalLayer <DisplayLayer> -#endif -@end - -API_DEPRECATED("OpenGLES is deprecated", ios(2.0, 12.0)) -@interface GodotOpenGLLayer : CAEAGLLayer <DisplayLayer> - -@end diff --git a/platform/iphone/display_layer.mm b/platform/iphone/display_layer.mm deleted file mode 100644 index 92e81448ac..0000000000 --- a/platform/iphone/display_layer.mm +++ /dev/null @@ -1,173 +0,0 @@ -/*************************************************************************/ -/* display_layer.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "display_layer.h" - -#include "core/config/project_settings.h" -#include "core/os/keyboard.h" -#include "display_server_iphone.h" -#include "main/main.h" -#include "os_iphone.h" -#include "servers/audio_server.h" - -#import <AudioToolbox/AudioServices.h> -#import <GameController/GameController.h> -#import <OpenGLES/EAGL.h> -#import <OpenGLES/ES1/gl.h> -#import <OpenGLES/ES1/glext.h> -#import <QuartzCore/QuartzCore.h> -#import <UIKit/UIKit.h> - -@implementation GodotMetalLayer - -- (void)initializeDisplayLayer { -#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR - if (@available(iOS 13, *)) { - // Simulator supports Metal since iOS 13 - } else { - NSLog(@"iOS Simulator prior to iOS 13 does not support Metal rendering."); - } -#endif -} - -- (void)layoutDisplayLayer { -} - -- (void)renderDisplayLayer { -} - -@end - -@implementation GodotOpenGLLayer { - // The pixel dimensions of the backbuffer - GLint backingWidth; - GLint backingHeight; - - EAGLContext *context; - GLuint viewRenderbuffer, viewFramebuffer; - GLuint depthRenderbuffer; -} - -- (void)initializeDisplayLayer { - // Get our backing layer - - // Configure it so that it is opaque, does not retain the contents of the backbuffer when displayed, and uses RGBA8888 color. - self.opaque = YES; - self.drawableProperties = [NSDictionary - dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], - kEAGLDrawablePropertyRetainedBacking, - kEAGLColorFormatRGBA8, - kEAGLDrawablePropertyColorFormat, - nil]; - - // FIXME: Add Vulkan support via MoltenVK. Add fallback code back? - - // Create GL ES 2 context - if (GLOBAL_GET("rendering/driver/driver_name") == "opengl3") { - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - NSLog(@"Setting up an OpenGL ES 2.0 context."); - if (!context) { - NSLog(@"Failed to create OpenGL ES 2.0 context!"); - return; - } - } - - if (![EAGLContext setCurrentContext:context]) { - NSLog(@"Failed to set EAGLContext!"); - return; - } - if (![self createFramebuffer]) { - NSLog(@"Failed to create frame buffer!"); - return; - } -} - -- (void)layoutDisplayLayer { - [EAGLContext setCurrentContext:context]; - [self destroyFramebuffer]; - [self createFramebuffer]; -} - -- (void)renderDisplayLayer { - [EAGLContext setCurrentContext:context]; -} - -- (void)dealloc { - if ([EAGLContext currentContext] == context) { - [EAGLContext setCurrentContext:nil]; - } - - if (context) { - context = nil; - } -} - -- (BOOL)createFramebuffer { - glGenFramebuffersOES(1, &viewFramebuffer); - glGenRenderbuffersOES(1, &viewRenderbuffer); - - glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); - // This call associates the storage for the current render buffer with the EAGLDrawable (our CAself) - // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view). - [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self]; - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); - - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); - - // For this sample, we also need a depth buffer, so we'll create and attach one via another renderbuffer. - glGenRenderbuffersOES(1, &depthRenderbuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); - glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight); - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); - - if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return NO; - } - - return YES; -} - -// Clean up any buffers we have allocated. -- (void)destroyFramebuffer { - glDeleteFramebuffersOES(1, &viewFramebuffer); - viewFramebuffer = 0; - glDeleteRenderbuffersOES(1, &viewRenderbuffer); - viewRenderbuffer = 0; - - if (depthRenderbuffer) { - glDeleteRenderbuffersOES(1, &depthRenderbuffer); - depthRenderbuffer = 0; - } -} - -@end diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h deleted file mode 100644 index 7af222e3f8..0000000000 --- a/platform/iphone/display_server_iphone.h +++ /dev/null @@ -1,217 +0,0 @@ -/*************************************************************************/ -/* display_server_iphone.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef display_server_iphone_h -#define display_server_iphone_h - -#include "core/input/input.h" -#include "servers/display_server.h" - -#if defined(VULKAN_ENABLED) -#include "drivers/vulkan/rendering_device_vulkan.h" -#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" - -#include "vulkan_context_iphone.h" - -#import <QuartzCore/CAMetalLayer.h> -#ifdef USE_VOLK -#include <volk.h> -#else -#include <vulkan/vulkan.h> -#endif -#endif - -class DisplayServerIPhone : public DisplayServer { - GDCLASS(DisplayServerIPhone, DisplayServer) - - _THREAD_SAFE_CLASS_ - -#if defined(VULKAN_ENABLED) - VulkanContextIPhone *context_vulkan = nullptr; - RenderingDeviceVulkan *rendering_device_vulkan = nullptr; -#endif - - id tts = nullptr; - - DisplayServer::ScreenOrientation screen_orientation; - - ObjectID window_attached_instance_id; - - Callable window_event_callback; - Callable window_resize_callback; - Callable input_event_callback; - Callable input_text_callback; - - int virtual_keyboard_height = 0; - - void perform_event(const Ref<InputEvent> &p_event); - - DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); - ~DisplayServerIPhone(); - -public: - String rendering_driver; - - static DisplayServerIPhone *get_singleton(); - - static void register_iphone_driver(); - static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); - static Vector<String> get_rendering_drivers_func(); - - // MARK: - Events - - virtual void process_events() override; - - virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; - virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; - virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; - virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; - virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; - - static void _dispatch_input_events(const Ref<InputEvent> &p_event); - void send_input_event(const Ref<InputEvent> &p_event) const; - void send_input_text(const String &p_text) const; - void send_window_event(DisplayServer::WindowEvent p_event) const; - void _window_callback(const Callable &p_callable, const Variant &p_arg) const; - - // MARK: - Input - - // MARK: Touches - - void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click); - void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y); - void touches_cancelled(int p_idx); - - // MARK: Keyboard - - void key(Key p_key, bool p_pressed); - - // MARK: Motion - - void update_gravity(float p_x, float p_y, float p_z); - void update_accelerometer(float p_x, float p_y, float p_z); - void update_magnetometer(float p_x, float p_y, float p_z); - void update_gyroscope(float p_x, float p_y, float p_z); - - // MARK: - - - virtual bool has_feature(Feature p_feature) const override; - virtual String get_name() const override; - - virtual bool tts_is_speaking() const override; - virtual bool tts_is_paused() const override; - virtual Array tts_get_voices() const override; - - virtual void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.f, float p_rate = 1.f, int p_utterance_id = 0, bool p_interrupt = false) override; - virtual void tts_pause() override; - virtual void tts_resume() override; - virtual void tts_stop() override; - - virtual Rect2i get_display_safe_area() const override; - - virtual int get_screen_count() const override; - virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; - - virtual Vector<DisplayServer::WindowID> get_window_list() const override; - - virtual WindowID - get_window_at_screen_position(const Point2i &p_position) const override; - - virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; - virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override; - - virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override; - virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override; - - virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override; - virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override; - - virtual void window_set_transient(WindowID p_window, WindowID p_parent) override; - - virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; - virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; - virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override; - virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override; - virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override; - virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override; - virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override; - virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override; - - virtual float screen_get_max_scale() const override; - - virtual void screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) override; - virtual DisplayServer::ScreenOrientation screen_get_orientation(int p_screen) const override; - - virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override; - - virtual bool can_any_window_draw() const override; - - virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override; - virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; - - virtual bool screen_is_touchscreen(int p_screen) const override; - - virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override; - virtual void virtual_keyboard_hide() override; - - void virtual_keyboard_set_height(int height); - virtual int virtual_keyboard_get_height() const override; - - virtual void clipboard_set(const String &p_text) override; - virtual String clipboard_get() const override; - - virtual void screen_set_keep_on(bool p_enable) override; - virtual bool screen_is_kept_on() const override; - - void resize_window(CGSize size); -}; - -#endif /* display_server_iphone_h */ diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm deleted file mode 100644 index 28ffc9595e..0000000000 --- a/platform/iphone/display_server_iphone.mm +++ /dev/null @@ -1,655 +0,0 @@ -/*************************************************************************/ -/* display_server_iphone.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "display_server_iphone.h" - -#import "app_delegate.h" -#include "core/config/project_settings.h" -#include "core/io/file_access_pack.h" -#import "device_metrics.h" -#import "godot_view.h" -#include "ios.h" -#import "keyboard_input_view.h" -#include "os_iphone.h" -#include "tts_ios.h" -#import "view_controller.h" - -#import <Foundation/Foundation.h> -#import <sys/utsname.h> - -static const float kDisplayServerIPhoneAcceleration = 1; - -DisplayServerIPhone *DisplayServerIPhone::get_singleton() { - return (DisplayServerIPhone *)DisplayServer::get_singleton(); -} - -DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - rendering_driver = p_rendering_driver; - - // Init TTS - tts = [[TTS_IOS alloc] init]; - -#if defined(GLES3_ENABLED) - // FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented - // again, - // Note that we should be checking "opengl3" as the driver, might never enable this seeing OpenGL is deprecated on iOS - // We are hardcoding the rendering_driver to "vulkan" down below - - if (rendering_driver == "opengl_es") { - bool gl_initialization_error = false; - - // FIXME: Add Vulkan support via MoltenVK. Add fallback code back? - - if (RasterizerGLES3::is_viable() == OK) { - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); - } else { - gl_initialization_error = true; - } - - if (gl_initialization_error) { - OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.", "Unable to initialize video driver"); - // return ERR_UNAVAILABLE; - } - - // rendering_server = memnew(RenderingServerDefault); - // // FIXME: Reimplement threaded rendering - // if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - // rendering_server = memnew(RenderingServerWrapMT(rendering_server, - // false)); - // } - // rendering_server->init(); - // rendering_server->cursor_set_visible(false, 0); - - // reset this to what it should be, it will have been set to 0 after - // rendering_server->init() is called - // RasterizerStorageGLES3system_fbo = gl_view_base_fb; - } -#endif - -#if defined(VULKAN_ENABLED) - rendering_driver = "vulkan"; - - context_vulkan = nullptr; - rendering_device_vulkan = nullptr; - - if (rendering_driver == "vulkan") { - context_vulkan = memnew(VulkanContextIPhone); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = nullptr; - ERR_FAIL_MSG("Failed to initialize Vulkan context"); - } - - CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"vulkan"]; - - if (!layer) { - ERR_FAIL_MSG("Failed to create iOS rendering layer."); - } - - Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale(); - if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) { - memdelete(context_vulkan); - context_vulkan = nullptr; - ERR_FAIL_MSG("Failed to create Vulkan window."); - } - - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); - - RendererCompositorRD::make_current(); - } -#endif - - bool keep_screen_on = bool(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true)); - screen_set_keep_on(keep_screen_on); - - Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); - - r_error = OK; -} - -DisplayServerIPhone::~DisplayServerIPhone() { -#if defined(VULKAN_ENABLED) - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); - rendering_device_vulkan = nullptr; - } - - if (context_vulkan) { - context_vulkan->window_destroy(MAIN_WINDOW_ID); - memdelete(context_vulkan); - context_vulkan = nullptr; - } -#endif -} - -DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); -} - -Vector<String> DisplayServerIPhone::get_rendering_drivers_func() { - Vector<String> drivers; - -#if defined(VULKAN_ENABLED) - drivers.push_back("vulkan"); -#endif -#if defined(GLES3_ENABLED) - drivers.push_back("opengl_es"); -#endif - - return drivers; -} - -void DisplayServerIPhone::register_iphone_driver() { - register_create_function("iphone", create_func, get_rendering_drivers_func); -} - -// MARK: Events - -void DisplayServerIPhone::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { - window_resize_callback = p_callable; -} - -void DisplayServerIPhone::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { - window_event_callback = p_callable; -} -void DisplayServerIPhone::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { - input_event_callback = p_callable; -} - -void DisplayServerIPhone::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { - input_text_callback = p_callable; -} - -void DisplayServerIPhone::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { - // Probably not supported for iOS -} - -void DisplayServerIPhone::process_events() { - Input::get_singleton()->flush_buffered_events(); -} - -void DisplayServerIPhone::_dispatch_input_events(const Ref<InputEvent> &p_event) { - DisplayServerIPhone::get_singleton()->send_input_event(p_event); -} - -void DisplayServerIPhone::send_input_event(const Ref<InputEvent> &p_event) const { - _window_callback(input_event_callback, p_event); -} - -void DisplayServerIPhone::send_input_text(const String &p_text) const { - _window_callback(input_text_callback, p_text); -} - -void DisplayServerIPhone::send_window_event(DisplayServer::WindowEvent p_event) const { - _window_callback(window_event_callback, int(p_event)); -} - -void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Variant &p_arg) const { - if (!p_callable.is_null()) { - const Variant *argp = &p_arg; - Variant ret; - Callable::CallError ce; - p_callable.call((const Variant **)&argp, 1, ret, ce); - } -} - -// MARK: - Input - -// MARK: Touches - -void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) { - if (!GLOBAL_DEF("debug/disable_touch", false)) { - Ref<InputEventScreenTouch> ev; - ev.instantiate(); - - ev->set_index(p_idx); - ev->set_pressed(p_pressed); - ev->set_position(Vector2(p_x, p_y)); - perform_event(ev); - } -} - -void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) { - if (!GLOBAL_DEF("debug/disable_touch", false)) { - Ref<InputEventScreenDrag> ev; - ev.instantiate(); - ev->set_index(p_idx); - ev->set_position(Vector2(p_x, p_y)); - ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y)); - perform_event(ev); - } -} - -void DisplayServerIPhone::perform_event(const Ref<InputEvent> &p_event) { - Input::get_singleton()->parse_input_event(p_event); -} - -void DisplayServerIPhone::touches_cancelled(int p_idx) { - touch_press(p_idx, -1, -1, false, false); -} - -// MARK: Keyboard - -void DisplayServerIPhone::key(Key p_key, bool p_pressed) { - Ref<InputEventKey> ev; - ev.instantiate(); - ev->set_echo(false); - ev->set_pressed(p_pressed); - ev->set_keycode(p_key); - ev->set_physical_keycode(p_key); - ev->set_unicode((char32_t)p_key); - perform_event(ev); -} - -// MARK: Motion - -void DisplayServerIPhone::update_gravity(float p_x, float p_y, float p_z) { - Input::get_singleton()->set_gravity(Vector3(p_x, p_y, p_z)); -} - -void DisplayServerIPhone::update_accelerometer(float p_x, float p_y, float p_z) { - // Found out the Z should not be negated! Pass as is! - Vector3 v_accelerometer = Vector3( - p_x / kDisplayServerIPhoneAcceleration, - p_y / kDisplayServerIPhoneAcceleration, - p_z / kDisplayServerIPhoneAcceleration); - - Input::get_singleton()->set_accelerometer(v_accelerometer); -} - -void DisplayServerIPhone::update_magnetometer(float p_x, float p_y, float p_z) { - Input::get_singleton()->set_magnetometer(Vector3(p_x, p_y, p_z)); -} - -void DisplayServerIPhone::update_gyroscope(float p_x, float p_y, float p_z) { - Input::get_singleton()->set_gyroscope(Vector3(p_x, p_y, p_z)); -} - -// MARK: - - -bool DisplayServerIPhone::has_feature(Feature p_feature) const { - switch (p_feature) { - // case FEATURE_CURSOR_SHAPE: - // case FEATURE_CUSTOM_CURSOR_SHAPE: - // case FEATURE_GLOBAL_MENU: - // case FEATURE_HIDPI: - // case FEATURE_ICON: - // case FEATURE_IME: - // case FEATURE_MOUSE: - // case FEATURE_MOUSE_WARP: - // case FEATURE_NATIVE_DIALOG: - // case FEATURE_NATIVE_ICON: - // case FEATURE_WINDOW_TRANSPARENCY: - case FEATURE_CLIPBOARD: - case FEATURE_KEEP_SCREEN_ON: - case FEATURE_ORIENTATION: - case FEATURE_TOUCHSCREEN: - case FEATURE_VIRTUAL_KEYBOARD: - case FEATURE_TEXT_TO_SPEECH: - return true; - default: - return false; - } -} - -String DisplayServerIPhone::get_name() const { - return "iPhone"; -} - -bool DisplayServerIPhone::tts_is_speaking() const { - ERR_FAIL_COND_V(!tts, false); - return [tts isSpeaking]; -} - -bool DisplayServerIPhone::tts_is_paused() const { - ERR_FAIL_COND_V(!tts, false); - return [tts isPaused]; -} - -Array DisplayServerIPhone::tts_get_voices() const { - ERR_FAIL_COND_V(!tts, Array()); - return [tts getVoices]; -} - -void DisplayServerIPhone::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) { - ERR_FAIL_COND(!tts); - [tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt]; -} - -void DisplayServerIPhone::tts_pause() { - ERR_FAIL_COND(!tts); - [tts pauseSpeaking]; -} - -void DisplayServerIPhone::tts_resume() { - ERR_FAIL_COND(!tts); - [tts resumeSpeaking]; -} - -void DisplayServerIPhone::tts_stop() { - ERR_FAIL_COND(!tts); - [tts stopSpeaking]; -} - -Rect2i DisplayServerIPhone::get_display_safe_area() const { - if (@available(iOS 11, *)) { - UIEdgeInsets insets = UIEdgeInsetsZero; - UIView *view = AppDelegate.viewController.godotView; - if ([view respondsToSelector:@selector(safeAreaInsets)]) { - insets = [view safeAreaInsets]; - } - float scale = screen_get_scale(); - Size2i insets_position = Size2i(insets.left, insets.top) * scale; - Size2i insets_size = Size2i(insets.left + insets.right, insets.top + insets.bottom) * scale; - return Rect2i(screen_get_position() + insets_position, screen_get_size() - insets_size); - } else { - return Rect2i(screen_get_position(), screen_get_size()); - } -} - -int DisplayServerIPhone::get_screen_count() const { - return 1; -} - -Point2i DisplayServerIPhone::screen_get_position(int p_screen) const { - return Size2i(); -} - -Size2i DisplayServerIPhone::screen_get_size(int p_screen) const { - CALayer *layer = AppDelegate.viewController.godotView.renderingLayer; - - if (!layer) { - return Size2i(); - } - - return Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_scale(p_screen); -} - -Rect2i DisplayServerIPhone::screen_get_usable_rect(int p_screen) const { - return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); -} - -int DisplayServerIPhone::screen_get_dpi(int p_screen) const { - struct utsname systemInfo; - uname(&systemInfo); - - NSString *string = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; - - NSDictionary *iOSModelToDPI = [GodotDeviceMetrics dpiList]; - - for (NSArray *keyArray in iOSModelToDPI) { - if ([keyArray containsObject:string]) { - NSNumber *value = iOSModelToDPI[keyArray]; - return [value intValue]; - } - } - - // If device wasn't found in dictionary - // make a best guess from device metrics. - CGFloat scale = [UIScreen mainScreen].scale; - - UIUserInterfaceIdiom idiom = [UIDevice currentDevice].userInterfaceIdiom; - - switch (idiom) { - case UIUserInterfaceIdiomPad: - return scale == 2 ? 264 : 132; - case UIUserInterfaceIdiomPhone: { - if (scale == 3) { - CGFloat nativeScale = [UIScreen mainScreen].nativeScale; - return nativeScale == 3 ? 458 : 401; - } - - return 326; - } - default: - return 72; - } -} - -float DisplayServerIPhone::screen_get_refresh_rate(int p_screen) const { - return [UIScreen mainScreen].maximumFramesPerSecond; -} - -float DisplayServerIPhone::screen_get_scale(int p_screen) const { - return [UIScreen mainScreen].nativeScale; -} - -Vector<DisplayServer::WindowID> DisplayServerIPhone::get_window_list() const { - Vector<DisplayServer::WindowID> list; - list.push_back(MAIN_WINDOW_ID); - return list; -} - -DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const Point2i &p_position) const { - return MAIN_WINDOW_ID; -} - -int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { - ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); - switch (p_handle_type) { - case DISPLAY_HANDLE: { - return 0; // Not supported. - } - case WINDOW_HANDLE: { - return (int64_t)AppDelegate.viewController; - } - case WINDOW_VIEW: { - return (int64_t)AppDelegate.viewController.godotView; - } - default: { - return 0; - } - } -} - -void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { - window_attached_instance_id = p_instance; -} - -ObjectID DisplayServerIPhone::window_get_attached_instance_id(WindowID p_window) const { - return window_attached_instance_id; -} - -void DisplayServerIPhone::window_set_title(const String &p_title, WindowID p_window) { - // Probably not supported for iOS -} - -int DisplayServerIPhone::window_get_current_screen(WindowID p_window) const { - return SCREEN_OF_MAIN_WINDOW; -} - -void DisplayServerIPhone::window_set_current_screen(int p_screen, WindowID p_window) { - // Probably not supported for iOS -} - -Point2i DisplayServerIPhone::window_get_position(WindowID p_window) const { - return Point2i(); -} - -void DisplayServerIPhone::window_set_position(const Point2i &p_position, WindowID p_window) { - // Probably not supported for single window iOS app -} - -void DisplayServerIPhone::window_set_transient(WindowID p_window, WindowID p_parent) { - // Probably not supported for iOS -} - -void DisplayServerIPhone::window_set_max_size(const Size2i p_size, WindowID p_window) { - // Probably not supported for iOS -} - -Size2i DisplayServerIPhone::window_get_max_size(WindowID p_window) const { - return Size2i(); -} - -void DisplayServerIPhone::window_set_min_size(const Size2i p_size, WindowID p_window) { - // Probably not supported for iOS -} - -Size2i DisplayServerIPhone::window_get_min_size(WindowID p_window) const { - return Size2i(); -} - -void DisplayServerIPhone::window_set_size(const Size2i p_size, WindowID p_window) { - // Probably not supported for iOS -} - -Size2i DisplayServerIPhone::window_get_size(WindowID p_window) const { - CGRect screenBounds = [UIScreen mainScreen].bounds; - return Size2i(screenBounds.size.width, screenBounds.size.height) * screen_get_max_scale(); -} - -Size2i DisplayServerIPhone::window_get_real_size(WindowID p_window) const { - return window_get_size(p_window); -} - -void DisplayServerIPhone::window_set_mode(WindowMode p_mode, WindowID p_window) { - // Probably not supported for iOS -} - -DisplayServer::WindowMode DisplayServerIPhone::window_get_mode(WindowID p_window) const { - return WindowMode::WINDOW_MODE_FULLSCREEN; -} - -bool DisplayServerIPhone::window_is_maximize_allowed(WindowID p_window) const { - return false; -} - -void DisplayServerIPhone::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { - // Probably not supported for iOS -} - -bool DisplayServerIPhone::window_get_flag(WindowFlags p_flag, WindowID p_window) const { - return false; -} - -void DisplayServerIPhone::window_request_attention(WindowID p_window) { - // Probably not supported for iOS -} - -void DisplayServerIPhone::window_move_to_foreground(WindowID p_window) { - // Probably not supported for iOS -} - -float DisplayServerIPhone::screen_get_max_scale() const { - return screen_get_scale(SCREEN_OF_MAIN_WINDOW); -} - -void DisplayServerIPhone::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { - screen_orientation = p_orientation; -} - -DisplayServer::ScreenOrientation DisplayServerIPhone::screen_get_orientation(int p_screen) const { - return screen_orientation; -} - -bool DisplayServerIPhone::window_can_draw(WindowID p_window) const { - return true; -} - -bool DisplayServerIPhone::can_any_window_draw() const { - return true; -} - -bool DisplayServerIPhone::screen_is_touchscreen(int p_screen) const { - return true; -} - -void DisplayServerIPhone::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) { - NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()]; - - [AppDelegate.viewController.keyboardView - becomeFirstResponderWithString:existingString - multiline:p_multiline - cursorStart:p_cursor_start - cursorEnd:p_cursor_end]; -} - -void DisplayServerIPhone::virtual_keyboard_hide() { - [AppDelegate.viewController.keyboardView resignFirstResponder]; -} - -void DisplayServerIPhone::virtual_keyboard_set_height(int height) { - virtual_keyboard_height = height * screen_get_max_scale(); -} - -int DisplayServerIPhone::virtual_keyboard_get_height() const { - return virtual_keyboard_height; -} - -void DisplayServerIPhone::clipboard_set(const String &p_text) { - [UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8()]; -} - -String DisplayServerIPhone::clipboard_get() const { - NSString *text = [UIPasteboard generalPasteboard].string; - - return String::utf8([text UTF8String]); -} - -void DisplayServerIPhone::screen_set_keep_on(bool p_enable) { - [UIApplication sharedApplication].idleTimerDisabled = p_enable; -} - -bool DisplayServerIPhone::screen_is_kept_on() const { - return [UIApplication sharedApplication].idleTimerDisabled; -} - -void DisplayServerIPhone::resize_window(CGSize viewSize) { - Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale(); - -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - context_vulkan->window_resize(MAIN_WINDOW_ID, size.x, size.y); - } -#endif - - Variant resize_rect = Rect2i(Point2i(), size); - _window_callback(window_resize_callback, resize_rect); -} - -void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { - _THREAD_SAFE_METHOD_ -#if defined(VULKAN_ENABLED) - context_vulkan->set_vsync_mode(p_window, p_vsync_mode); -#endif -} - -DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const { - _THREAD_SAFE_METHOD_ -#if defined(VULKAN_ENABLED) - return context_vulkan->get_vsync_mode(p_window); -#else - return DisplayServer::VSYNC_ENABLED; -#endif -} diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp deleted file mode 100644 index 3b02e661c1..0000000000 --- a/platform/iphone/export/export.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* export.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "export.h" - -#include "export_plugin.h" - -void register_iphone_exporter() { - Ref<EditorExportPlatformIOS> platform; - platform.instantiate(); - - EditorExport::get_singleton()->add_export_platform(platform); -} diff --git a/platform/iphone/export/export.h b/platform/iphone/export/export.h deleted file mode 100644 index adb3c23957..0000000000 --- a/platform/iphone/export/export.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* export.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef IPHONE_EXPORT_H -#define IPHONE_EXPORT_H - -void register_iphone_exporter(); - -#endif // IPHONE_EXPORT_H diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp deleted file mode 100644 index 3b92bd19be..0000000000 --- a/platform/iphone/export/export_plugin.cpp +++ /dev/null @@ -1,1849 +0,0 @@ -/*************************************************************************/ -/* export_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "export_plugin.h" - -#include "editor/editor_node.h" - -void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); - // Vulkan and OpenGL ES 3.0 both mandate ETC2 support. - r_features->push_back("etc2"); - - Vector<String> architectures = _get_preset_architectures(p_preset); - for (int i = 0; i < architectures.size(); ++i) { - r_features->push_back(architectures[i]); - } -} - -Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() { - Vector<ExportArchitecture> archs; - archs.push_back(ExportArchitecture("arm64", true)); - return archs; -} - -struct LoadingScreenInfo { - const char *preset_key; - const char *export_name; - int width = 0; - int height = 0; - bool rotate = false; -}; - -static const LoadingScreenInfo loading_screen_infos[] = { - { PNAME("landscape_launch_screens/iphone_2436x1125"), "Default-Landscape-X.png", 2436, 1125, false }, - { PNAME("landscape_launch_screens/iphone_2208x1242"), "Default-Landscape-736h@3x.png", 2208, 1242, false }, - { PNAME("landscape_launch_screens/ipad_1024x768"), "Default-Landscape.png", 1024, 768, false }, - { PNAME("landscape_launch_screens/ipad_2048x1536"), "Default-Landscape@2x.png", 2048, 1536, false }, - - { PNAME("portrait_launch_screens/iphone_640x960"), "Default-480h@2x.png", 640, 960, true }, - { PNAME("portrait_launch_screens/iphone_640x1136"), "Default-568h@2x.png", 640, 1136, true }, - { PNAME("portrait_launch_screens/iphone_750x1334"), "Default-667h@2x.png", 750, 1334, true }, - { PNAME("portrait_launch_screens/iphone_1125x2436"), "Default-Portrait-X.png", 1125, 2436, true }, - { PNAME("portrait_launch_screens/ipad_768x1024"), "Default-Portrait.png", 768, 1024, true }, - { PNAME("portrait_launch_screens/ipad_1536x2048"), "Default-Portrait@2x.png", 1536, 2048, true }, - { PNAME("portrait_launch_screens/iphone_1242x2208"), "Default-Portrait-736h@3x.png", 1242, 2208, true } -}; - -void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); - - Vector<ExportArchitecture> architectures = _get_supported_architectures(); - for (int i = 0; i < architectures.size(); ++i) { - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), architectures[i].name)), architectures[i].is_default)); - } - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); - - Vector<PluginConfigIOS> found_plugins = get_plugins(); - for (int i = 0; i < found_plugins.size(); i++) { - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), found_plugins[i].name)), false)); - } - - HashSet<String> plist_keys; - - for (int i = 0; i < found_plugins.size(); i++) { - // Editable plugin plist values - PluginConfigIOS plugin = found_plugins[i]; - - for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) { - switch (E.value.type) { - case PluginConfigIOS::PlistItemType::STRING_INPUT: { - String preset_name = "plugins_plist/" + E.key; - if (!plist_keys.has(preset_name)) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), E.value.value)); - plist_keys.insert(preset_name); - } - } break; - default: - continue; - } - } - } - - plugins_changed.clear(); - plugins = found_plugins; - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad with Retina display - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad Pro - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with Retina display - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color())); - - for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), "")); - } -} - -void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug) { - static const String export_method_string[] = { - "app-store", - "development", - "ad-hoc", - "enterprise" - }; - static const String storyboard_image_scale_mode[] = { - "center", - "scaleAspectFit", - "scaleAspectFill", - "scaleToFill" - }; - String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug"); - String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release"); - bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer"); - bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution"); - String str; - String strnew; - str.parse_utf8((const char *)pfile.ptr(), pfile.size()); - Vector<String> lines = str.split("\n"); - for (int i = 0; i < lines.size(); i++) { - if (lines[i].find("$binary") != -1) { - strnew += lines[i].replace("$binary", p_config.binary_name) + "\n"; - } else if (lines[i].find("$modules_buildfile") != -1) { - strnew += lines[i].replace("$modules_buildfile", p_config.modules_buildfile) + "\n"; - } else if (lines[i].find("$modules_fileref") != -1) { - strnew += lines[i].replace("$modules_fileref", p_config.modules_fileref) + "\n"; - } else if (lines[i].find("$modules_buildphase") != -1) { - strnew += lines[i].replace("$modules_buildphase", p_config.modules_buildphase) + "\n"; - } else if (lines[i].find("$modules_buildgrp") != -1) { - strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n"; - } else if (lines[i].find("$name") != -1) { - strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; - } else if (lines[i].find("$bundle_identifier") != -1) { - strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n"; - } else if (lines[i].find("$short_version") != -1) { - strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n"; - } else if (lines[i].find("$version") != -1) { - strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n"; - } else if (lines[i].find("$signature") != -1) { - strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; - } else if (lines[i].find("$team_id") != -1) { - strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n"; - } else if (lines[i].find("$default_build_config") != -1) { - strnew += lines[i].replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n"; - } else if (lines[i].find("$export_method") != -1) { - int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release"); - strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n"; - } else if (lines[i].find("$provisioning_profile_uuid_release") != -1) { - strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n"; - } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) { - strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n"; - } else if (lines[i].find("$code_sign_style_debug") != -1) { - if (dbg_manual) { - strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n"; - } else { - strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n"; - } - } else if (lines[i].find("$code_sign_style_release") != -1) { - if (rel_manual) { - strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n"; - } else { - strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n"; - } - } else if (lines[i].find("$provisioning_profile_uuid") != -1) { - String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release"); - strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; - } else if (lines[i].find("$code_sign_identity_debug") != -1) { - strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n"; - } else if (lines[i].find("$code_sign_identity_release") != -1) { - strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n"; - } else if (lines[i].find("$additional_plist_content") != -1) { - strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n"; - } else if (lines[i].find("$godot_archs") != -1) { - strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n"; - } else if (lines[i].find("$linker_flags") != -1) { - strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; - } else if (lines[i].find("$targeted_device_family") != -1) { - String xcode_value; - switch ((int)p_preset->get("application/targeted_device_family")) { - case 0: // iPhone - xcode_value = "1"; - break; - case 1: // iPad - xcode_value = "2"; - break; - case 2: // iPhone & iPad - xcode_value = "1,2"; - break; - } - strnew += lines[i].replace("$targeted_device_family", xcode_value) + "\n"; - } else if (lines[i].find("$cpp_code") != -1) { - strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; - } else if (lines[i].find("$docs_in_place") != -1) { - strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n"; - } else if (lines[i].find("$docs_sharing") != -1) { - strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n"; - } else if (lines[i].find("$entitlements_push_notifications") != -1) { - bool is_on = p_preset->get("capabilities/push_notifications"); - strnew += lines[i].replace("$entitlements_push_notifications", is_on ? "<key>aps-environment</key><string>development</string>" : "") + "\n"; - } else if (lines[i].find("$required_device_capabilities") != -1) { - String capabilities; - - // I've removed armv7 as we can run on 64bit only devices - // Note that capabilities listed here are requirements for the app to be installed. - // They don't enable anything. - Vector<String> capabilities_list = p_config.capabilities; - - if ((bool)p_preset->get("capabilities/access_wifi") && !capabilities_list.has("wifi")) { - capabilities_list.push_back("wifi"); - } - - for (int idx = 0; idx < capabilities_list.size(); idx++) { - capabilities += "<string>" + capabilities_list[idx] + "</string>\n"; - } - - strnew += lines[i].replace("$required_device_capabilities", capabilities); - } else if (lines[i].find("$interface_orientations") != -1) { - String orientations; - const DisplayServer::ScreenOrientation screen_orientation = - DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))); - - switch (screen_orientation) { - case DisplayServer::SCREEN_LANDSCAPE: - orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n"; - break; - case DisplayServer::SCREEN_PORTRAIT: - orientations += "<string>UIInterfaceOrientationPortrait</string>\n"; - break; - case DisplayServer::SCREEN_REVERSE_LANDSCAPE: - orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n"; - break; - case DisplayServer::SCREEN_REVERSE_PORTRAIT: - orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n"; - break; - case DisplayServer::SCREEN_SENSOR_LANDSCAPE: - // Allow both landscape orientations depending on sensor direction. - orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n"; - orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n"; - break; - case DisplayServer::SCREEN_SENSOR_PORTRAIT: - // Allow both portrait orientations depending on sensor direction. - orientations += "<string>UIInterfaceOrientationPortrait</string>\n"; - orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n"; - break; - case DisplayServer::SCREEN_SENSOR: - // Allow all screen orientations depending on sensor direction. - orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n"; - orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n"; - orientations += "<string>UIInterfaceOrientationPortrait</string>\n"; - orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n"; - break; - } - - strnew += lines[i].replace("$interface_orientations", orientations); - } else if (lines[i].find("$camera_usage_description") != -1) { - String description = p_preset->get("privacy/camera_usage_description"); - strnew += lines[i].replace("$camera_usage_description", description) + "\n"; - } else if (lines[i].find("$microphone_usage_description") != -1) { - String description = p_preset->get("privacy/microphone_usage_description"); - strnew += lines[i].replace("$microphone_usage_description", description) + "\n"; - } else if (lines[i].find("$photolibrary_usage_description") != -1) { - String description = p_preset->get("privacy/photolibrary_usage_description"); - strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; - } else if (lines[i].find("$plist_launch_screen_name") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "<key>UILaunchStoryboardName</key>\n<string>Launch Screen</string>" : ""; - strnew += lines[i].replace("$plist_launch_screen_name", value) + "\n"; - } else if (lines[i].find("$pbx_launch_screen_file_reference") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"<group>\"; };" : ""; - strnew += lines[i].replace("$pbx_launch_screen_file_reference", value) + "\n"; - } else if (lines[i].find("$pbx_launch_screen_copy_files") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */," : ""; - strnew += lines[i].replace("$pbx_launch_screen_copy_files", value) + "\n"; - } else if (lines[i].find("$pbx_launch_screen_build_phase") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */," : ""; - strnew += lines[i].replace("$pbx_launch_screen_build_phase", value) + "\n"; - } else if (lines[i].find("$pbx_launch_screen_build_reference") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };" : ""; - strnew += lines[i].replace("$pbx_launch_screen_build_reference", value) + "\n"; - } else if (lines[i].find("$pbx_launch_image_usage_setting") != -1) { - bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); - String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; - strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; - } else if (lines[i].find("$launch_screen_image_mode") != -1) { - int image_scale_mode = p_preset->get("storyboard/image_scale_mode"); - String value; - - switch (image_scale_mode) { - case 0: { - String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - // If custom logo is not specified, Godot does not scale default one, so we should do the same. - value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; - } break; - default: { - value = storyboard_image_scale_mode[image_scale_mode - 1]; - } - } - - strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n"; - } else if (lines[i].find("$launch_screen_background_color") != -1) { - bool use_custom = p_preset->get("storyboard/use_custom_bg_color"); - Color color = use_custom ? p_preset->get("storyboard/custom_bg_color") : ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); - const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; - - Dictionary value_dictionary; - value_dictionary["red"] = color.r; - value_dictionary["green"] = color.g; - value_dictionary["blue"] = color.b; - value_dictionary["alpha"] = color.a; - String value = value_format.format(value_dictionary, "$_"); - - strnew += lines[i].replace("$launch_screen_background_color", value) + "\n"; - } else if (lines[i].find("$pbx_locale_file_reference") != -1) { - String locale_files; - Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); - if (translations.size() > 0) { - int index = 0; - for (const String &E : translations) { - Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };"; - } - index++; - } - } - strnew += lines[i].replace("$pbx_locale_file_reference", locale_files); - } else if (lines[i].find("$pbx_locale_build_reference") != -1) { - String locale_files; - Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); - if (translations.size() > 0) { - int index = 0; - for (const String &E : translations) { - Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,"; - } - index++; - } - } - strnew += lines[i].replace("$pbx_locale_build_reference", locale_files); - } else { - strnew += lines[i] + "\n"; - } - } - - // !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero... - // should apply the same fix in our OSX export. - CharString cs = strnew.utf8(); - pfile.resize(cs.size() - 1); - for (int i = 0; i < cs.size() - 1; i++) { - pfile.write[i] = cs[i]; - } -} - -String EditorExportPlatformIOS::_get_additional_plist_content() { - Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - String result; - for (int i = 0; i < export_plugins.size(); ++i) { - result += export_plugins[i]->get_ios_plist_content(); - } - return result; -} - -String EditorExportPlatformIOS::_get_linker_flags() { - Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - String result; - for (int i = 0; i < export_plugins.size(); ++i) { - String flags = export_plugins[i]->get_ios_linker_flags(); - if (flags.length() == 0) { - continue; - } - if (result.length() > 0) { - result += ' '; - } - result += flags; - } - // the flags will be enclosed in quotes, so need to escape them - return result.replace("\"", "\\\""); -} - -String EditorExportPlatformIOS::_get_cpp_code() { - Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - String result; - for (int i = 0; i < export_plugins.size(); ++i) { - result += export_plugins[i]->get_ios_cpp_code(); - } - return result; -} - -void EditorExportPlatformIOS::_blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p_src, bool p_rot) { - ERR_FAIL_COND(p_dst.is_null()); - ERR_FAIL_COND(p_src.is_null()); - - int sw = p_rot ? p_src->get_height() : p_src->get_width(); - int sh = p_rot ? p_src->get_width() : p_src->get_height(); - - int x_pos = (p_dst->get_width() - sw) / 2; - int y_pos = (p_dst->get_height() - sh) / 2; - - int xs = (x_pos >= 0) ? 0 : -x_pos; - int ys = (y_pos >= 0) ? 0 : -y_pos; - - if (sw + x_pos > p_dst->get_width()) { - sw = p_dst->get_width() - x_pos; - } - if (sh + y_pos > p_dst->get_height()) { - sh = p_dst->get_height() - y_pos; - } - - for (int y = ys; y < sh; y++) { - for (int x = xs; x < sw; x++) { - Color sc = p_rot ? p_src->get_pixel(p_src->get_width() - y - 1, x) : p_src->get_pixel(x, y); - Color dc = p_dst->get_pixel(x_pos + x, y_pos + y); - dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r); - dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); - dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); - dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); - p_dst->set_pixel(x_pos + x, y_pos + y, dc); - } - } -} - -struct IconInfo { - const char *preset_key; - const char *idiom; - const char *export_name; - const char *actual_size_side; - const char *scale; - const char *unscaled_size; -}; - -static const IconInfo icon_infos[] = { - // Home screen on iPhone - { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60" }, - { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40" }, - { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60" }, - - // Home screen on iPad - { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76" }, - { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76" }, - { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5" }, - - // App Store - { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024" }, - - // Spotlight - { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40" }, - { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40" }, - { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40" } -}; - -Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) { - String json_description = "{\"images\":["; - String sizes; - - Ref<DirAccess> da = DirAccess::open(p_iconset_dir); - ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'."); - - for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) { - IconInfo info = icon_infos[i]; - int side_size = String(info.actual_size_side).to_int(); - String icon_path = p_preset->get(info.preset_key); - if (icon_path.length() == 0) { - // Resize main app icon - icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); - Ref<Image> img = memnew(Image); - Error err = ImageLoader::load_image(icon_path, img); - if (err != OK) { - ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'."); - return ERR_UNCONFIGURED; - } - img->resize(side_size, side_size); - err = img->save_png(p_iconset_dir + info.export_name); - if (err) { - String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'."); - ERR_PRINT(err_str.utf8().get_data()); - return err; - } - } else { - // Load custom icon and resize if required - Ref<Image> img = memnew(Image); - Error err = ImageLoader::load_image(icon_path, img); - if (err != OK) { - ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'."); - return ERR_UNCONFIGURED; - } - if (img->get_width() != side_size || img->get_height() != side_size) { - WARN_PRINT("Icon (" + String(info.preset_key) + "): '" + icon_path + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(side_size) + "x" + String::num_int64(side_size) + "."); - img->resize(side_size, side_size); - err = img->save_png(p_iconset_dir + info.export_name); - } else { - err = da->copy(icon_path, p_iconset_dir + info.export_name); - } - - if (err) { - String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'."); - ERR_PRINT(err_str.utf8().get_data()); - return err; - } - } - sizes += String(info.actual_size_side) + "\n"; - if (i > 0) { - json_description += ","; - } - json_description += String("{"); - json_description += String("\"idiom\":") + "\"" + info.idiom + "\","; - json_description += String("\"size\":") + "\"" + info.unscaled_size + "\","; - json_description += String("\"scale\":") + "\"" + info.scale + "\","; - json_description += String("\"filename\":") + "\"" + info.export_name + "\""; - json_description += String("}"); - } - json_description += "]}"; - - Ref<FileAccess> json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE); - ERR_FAIL_COND_V(json_file.is_null(), ERR_CANT_CREATE); - CharString json_utf8 = json_description.utf8(); - json_file->store_buffer((const uint8_t *)json_utf8.get_data(), json_utf8.length()); - - Ref<FileAccess> sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE); - ERR_FAIL_COND_V(sizes_file.is_null(), ERR_CANT_CREATE); - CharString sizes_utf8 = sizes.utf8(); - sizes_file->store_buffer((const uint8_t *)sizes_utf8.get_data(), sizes_utf8.length()); - - return OK; -} - -Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) { - const String custom_launch_image_2x = p_preset->get("storyboard/custom_image@2x"); - const String custom_launch_image_3x = p_preset->get("storyboard/custom_image@3x"); - - if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) { - Ref<Image> image; - String image_path = p_dest_dir.plus_file("splash@2x.png"); - image.instantiate(); - Error err = image->load(custom_launch_image_2x); - - if (err) { - image.unref(); - return err; - } - - if (image->save_png(image_path) != OK) { - return ERR_FILE_CANT_WRITE; - } - - image.unref(); - image_path = p_dest_dir.plus_file("splash@3x.png"); - image.instantiate(); - err = image->load(custom_launch_image_3x); - - if (err) { - image.unref(); - return err; - } - - if (image->save_png(image_path) != OK) { - return ERR_FILE_CANT_WRITE; - } - } else { - Ref<Image> splash; - - const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - - if (!splash_path.is_empty()) { - splash.instantiate(); - const Error err = splash->load(splash_path); - if (err) { - splash.unref(); - } - } - - if (splash.is_null()) { - splash = Ref<Image>(memnew(Image(boot_splash_png))); - } - - // Using same image for both @2x and @3x - // because Godot's own boot logo uses single image for all resolutions. - // Also not using @1x image, because devices using this image variant - // are not supported by iOS 9, which is minimal target. - const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); - const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); - - if (splash->save_png(splash_png_path_2x) != OK) { - return ERR_FILE_CANT_WRITE; - } - - if (splash->save_png(splash_png_path_3x) != OK) { - return ERR_FILE_CANT_WRITE; - } - } - - return OK; -} - -Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) { - Ref<DirAccess> da = DirAccess::open(p_dest_dir); - ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'."); - - for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) { - LoadingScreenInfo info = loading_screen_infos[i]; - String loading_screen_file = p_preset->get(info.preset_key); - - Color boot_bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); - String boot_logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - bool boot_logo_scale = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - - if (loading_screen_file.size() > 0) { - // Load custom loading screens, and resize if required. - Ref<Image> img = memnew(Image); - Error err = ImageLoader::load_image(loading_screen_file, img); - if (err != OK) { - ERR_PRINT("Invalid loading screen (" + String(info.preset_key) + "): '" + loading_screen_file + "'."); - return ERR_UNCONFIGURED; - } - if (img->get_width() != info.width || img->get_height() != info.height) { - WARN_PRINT("Loading screen (" + String(info.preset_key) + "): '" + loading_screen_file + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(info.width) + "x" + String::num_int64(info.height) + "."); - float aspect_ratio = (float)img->get_width() / (float)img->get_height(); - if (boot_logo_scale) { - if (info.height * aspect_ratio <= info.width) { - img->resize(info.height * aspect_ratio, info.height); - } else { - img->resize(info.width, info.width / aspect_ratio); - } - } - Ref<Image> new_img = memnew(Image); - new_img->create(info.width, info.height, false, Image::FORMAT_RGBA8); - new_img->fill(boot_bg_color); - _blend_and_rotate(new_img, img, false); - err = new_img->save_png(p_dest_dir + info.export_name); - } else { - err = da->copy(loading_screen_file, p_dest_dir + info.export_name); - } - if (err) { - String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'."; - ERR_PRINT(err_str.utf8().get_data()); - return err; - } - } else { - // Generate loading screen from the splash screen - Ref<Image> img = memnew(Image); - img->create(info.width, info.height, false, Image::FORMAT_RGBA8); - img->fill(boot_bg_color); - - Ref<Image> img_bs; - - if (boot_logo_path.length() > 0) { - img_bs = Ref<Image>(memnew(Image)); - ImageLoader::load_image(boot_logo_path, img_bs); - } - if (!img_bs.is_valid()) { - img_bs = Ref<Image>(memnew(Image(boot_splash_png))); - } - if (img_bs.is_valid()) { - float aspect_ratio = (float)img_bs->get_width() / (float)img_bs->get_height(); - if (info.rotate) { - if (boot_logo_scale) { - if (info.width * aspect_ratio <= info.height) { - img_bs->resize(info.width * aspect_ratio, info.width); - } else { - img_bs->resize(info.height, info.height / aspect_ratio); - } - } - } else { - if (boot_logo_scale) { - if (info.height * aspect_ratio <= info.width) { - img_bs->resize(info.height * aspect_ratio, info.height); - } else { - img_bs->resize(info.width, info.width / aspect_ratio); - } - } - } - _blend_and_rotate(img, img_bs, info.rotate); - } - Error err = img->save_png(p_dest_dir + info.export_name); - if (err) { - String err_str = String("Failed to export loading screen (") + info.preset_key + ") from splash screen."; - WARN_PRINT(err_str.utf8().get_data()); - } - } - } - - return OK; -} - -Error EditorExportPlatformIOS::_walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata) { - Vector<String> dirs; - String current_dir = p_da->get_current_dir(); - p_da->list_dir_begin(); - String path = p_da->get_next(); - while (!path.is_empty()) { - if (p_da->current_is_dir()) { - if (path != "." && path != "..") { - dirs.push_back(path); - } - } else { - Error err = p_handler(current_dir.plus_file(path), p_userdata); - if (err) { - p_da->list_dir_end(); - return err; - } - } - path = p_da->get_next(); - } - p_da->list_dir_end(); - - for (int i = 0; i < dirs.size(); ++i) { - String dir = dirs[i]; - p_da->change_dir(dir); - Error err = _walk_dir_recursive(p_da, p_handler, p_userdata); - p_da->change_dir(".."); - if (err) { - return err; - } - } - - return OK; -} - -struct CodesignData { - const Ref<EditorExportPreset> &preset; - bool debug = false; - - CodesignData(const Ref<EditorExportPreset> &p_preset, bool p_debug) : - preset(p_preset), - debug(p_debug) { - } -}; - -Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { - if (p_file.ends_with(".dylib")) { - CodesignData *data = static_cast<CodesignData *>(p_userdata); - print_line(String("Signing ") + p_file); - - String sign_id; - if (data->debug) { - sign_id = data->preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : data->preset->get("application/code_sign_identity_debug"); - } else { - sign_id = data->preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : data->preset->get("application/code_sign_identity_release"); - } - - List<String> codesign_args; - codesign_args.push_back("-f"); - codesign_args.push_back("-s"); - codesign_args.push_back(sign_id); - codesign_args.push_back(p_file); - String str; - Error err = OS::get_singleton()->execute("codesign", codesign_args, &str, nullptr, true); - print_verbose("codesign (" + p_file + "):\n" + str); - - return err; - } - return OK; -} - -struct PbxId { -private: - static char _hex_char(uint8_t four_bits) { - if (four_bits < 10) { - return ('0' + four_bits); - } - return 'A' + (four_bits - 10); - } - - static String _hex_pad(uint32_t num) { - Vector<char> ret; - ret.resize(sizeof(num) * 2); - for (uint64_t i = 0; i < sizeof(num) * 2; ++i) { - uint8_t four_bits = (num >> (sizeof(num) * 8 - (i + 1) * 4)) & 0xF; - ret.write[i] = _hex_char(four_bits); - } - return String::utf8(ret.ptr(), ret.size()); - } - -public: - uint32_t high_bits; - uint32_t mid_bits; - uint32_t low_bits; - - String str() const { - return _hex_pad(high_bits) + _hex_pad(mid_bits) + _hex_pad(low_bits); - } - - PbxId &operator++() { - low_bits++; - if (!low_bits) { - mid_bits++; - if (!mid_bits) { - high_bits++; - } - } - - return *this; - } -}; - -struct ExportLibsData { - Vector<String> lib_paths; - String dest_dir; -}; - -void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) { - // that is just a random number, we just need Godot IDs not to clash with - // existing IDs in the project. - PbxId current_id = { 0x58938401, 0, 0 }; - String pbx_files; - String pbx_frameworks_build; - String pbx_frameworks_refs; - String pbx_resources_build; - String pbx_resources_refs; - String pbx_embeded_frameworks; - - const String file_info_format = String("$build_id = {isa = PBXBuildFile; fileRef = $ref_id; };\n") + - "$ref_id = {isa = PBXFileReference; lastKnownFileType = $file_type; name = \"$name\"; path = \"$file_path\"; sourceTree = \"<group>\"; };\n"; - - for (int i = 0; i < p_additional_assets.size(); ++i) { - String additional_asset_info_format = file_info_format; - - String build_id = (++current_id).str(); - String ref_id = (++current_id).str(); - String framework_id = ""; - - const IOSExportAsset &asset = p_additional_assets[i]; - - String type; - if (asset.exported_path.ends_with(".framework")) { - if (asset.should_embed) { - additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n"; - framework_id = (++current_id).str(); - pbx_embeded_frameworks += framework_id + ",\n"; - } - - type = "wrapper.framework"; - } else if (asset.exported_path.ends_with(".xcframework")) { - if (asset.should_embed) { - additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n"; - framework_id = (++current_id).str(); - pbx_embeded_frameworks += framework_id + ",\n"; - } - - type = "wrapper.xcframework"; - } else if (asset.exported_path.ends_with(".dylib")) { - type = "compiled.mach-o.dylib"; - } else if (asset.exported_path.ends_with(".a")) { - type = "archive.ar"; - } else { - type = "file"; - } - - String &pbx_build = asset.is_framework ? pbx_frameworks_build : pbx_resources_build; - String &pbx_refs = asset.is_framework ? pbx_frameworks_refs : pbx_resources_refs; - - if (pbx_build.length() > 0) { - pbx_build += ",\n"; - pbx_refs += ",\n"; - } - pbx_build += build_id; - pbx_refs += ref_id; - - Dictionary format_dict; - format_dict["build_id"] = build_id; - format_dict["ref_id"] = ref_id; - format_dict["name"] = asset.exported_path.get_file(); - format_dict["file_path"] = asset.exported_path; - format_dict["file_type"] = type; - if (framework_id.length() > 0) { - format_dict["framework_id"] = framework_id; - } - pbx_files += additional_asset_info_format.format(format_dict, "$_"); - } - - // Note, frameworks like gamekit are always included in our project.pbxprof file - // even if turned off in capabilities. - - String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size()); - str = str.replace("$additional_pbx_files", pbx_files); - str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build); - str = str.replace("$additional_pbx_frameworks_refs", pbx_frameworks_refs); - str = str.replace("$additional_pbx_resources_build", pbx_resources_build); - str = str.replace("$additional_pbx_resources_refs", pbx_resources_refs); - str = str.replace("$pbx_embeded_frameworks", pbx_embeded_frameworks); - - CharString cs = str.utf8(); - p_project_data.resize(cs.size() - 1); - for (int i = 0; i < cs.size() - 1; i++) { - p_project_data.write[i] = cs[i]; - } -} - -Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { - String binary_name = p_out_dir.get_file().get_basename(); - - Ref<DirAccess> da = DirAccess::create_for_path(p_asset); - if (da.is_null()) { - ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + "."); - } - bool file_exists = da->file_exists(p_asset); - bool dir_exists = da->dir_exists(p_asset); - if (!file_exists && !dir_exists) { - return ERR_FILE_NOT_FOUND; - } - - String base_dir = p_asset.get_base_dir().replace("res://", ""); - String destination_dir; - String destination; - String asset_path; - - bool create_framework = false; - - if (p_is_framework && p_asset.ends_with(".dylib")) { - // For iOS we need to turn .dylib into .framework - // to be able to send application to AppStore - asset_path = String("dylibs").plus_file(base_dir); - - String file_name; - - if (!p_custom_file_name) { - file_name = p_asset.get_basename().get_file(); - } else { - file_name = *p_custom_file_name; - } - - String framework_name = file_name + ".framework"; - - asset_path = asset_path.plus_file(framework_name); - destination_dir = p_out_dir.plus_file(asset_path); - destination = destination_dir.plus_file(file_name); - create_framework = true; - } else if (p_is_framework && (p_asset.ends_with(".framework") || p_asset.ends_with(".xcframework"))) { - asset_path = String("dylibs").plus_file(base_dir); - - String file_name; - - if (!p_custom_file_name) { - file_name = p_asset.get_file(); - } else { - file_name = *p_custom_file_name; - } - - asset_path = asset_path.plus_file(file_name); - destination_dir = p_out_dir.plus_file(asset_path); - destination = destination_dir; - } else { - asset_path = base_dir; - - String file_name; - - if (!p_custom_file_name) { - file_name = p_asset.get_file(); - } else { - file_name = *p_custom_file_name; - } - - destination_dir = p_out_dir.plus_file(asset_path); - asset_path = asset_path.plus_file(file_name); - destination = p_out_dir.plus_file(asset_path); - } - - Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); - - if (!filesystem_da->dir_exists(destination_dir)) { - Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); - if (make_dir_err) { - return make_dir_err; - } - } - - Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); - if (err) { - return err; - } - IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed }; - r_exported_assets.push_back(exported_asset); - - if (create_framework) { - String file_name; - - if (!p_custom_file_name) { - file_name = p_asset.get_basename().get_file(); - } else { - file_name = *p_custom_file_name; - } - - String framework_name = file_name + ".framework"; - - // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib - { - List<String> install_name_args; - install_name_args.push_back("-id"); - install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name)); - install_name_args.push_back(destination); - - OS::get_singleton()->execute("install_name_tool", install_name_args); - } - - // Creating Info.plist - { - String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n" - "<dict>\n" - "<key>CFBundleShortVersionString</key>\n" - "<string>1.0</string>\n" - "<key>CFBundleIdentifier</key>\n" - "<string>com.gdnative.framework.$name</string>\n" - "<key>CFBundleName</key>\n" - "<string>$name</string>\n" - "<key>CFBundleExecutable</key>\n" - "<string>$name</string>\n" - "<key>DTPlatformName</key>\n" - "<string>iphoneos</string>\n" - "<key>CFBundleInfoDictionaryVersion</key>\n" - "<string>6.0</string>\n" - "<key>CFBundleVersion</key>\n" - "<string>1</string>\n" - "<key>CFBundlePackageType</key>\n" - "<string>FMWK</string>\n" - "<key>MinimumOSVersion</key>\n" - "<string>10.0</string>\n" - "</dict>\n" - "</plist>"; - - String info_plist = info_plist_format.replace("$name", file_name); - - Ref<FileAccess> f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE); - if (f.is_valid()) { - f->store_string(info_plist); - } - } - } - - return OK; -} - -Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) { - for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) { - String asset = p_assets[f_idx]; - if (!asset.begins_with("res://")) { - // either SDK-builtin or already a part of the export template - IOSExportAsset exported_asset = { asset, p_is_framework, p_should_embed }; - r_exported_assets.push_back(exported_asset); - } else { - Error err = _copy_asset(p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets); - ERR_FAIL_COND_V(err, err); - } - } - - return OK; -} - -Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) { - Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - for (int i = 0; i < export_plugins.size(); i++) { - Vector<String> linked_frameworks = export_plugins[i]->get_ios_frameworks(); - Error err = _export_additional_assets(p_out_dir, linked_frameworks, true, false, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - Vector<String> embedded_frameworks = export_plugins[i]->get_ios_embedded_frameworks(); - err = _export_additional_assets(p_out_dir, embedded_frameworks, true, true, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - Vector<String> project_static_libs = export_plugins[i]->get_ios_project_static_libs(); - for (int j = 0; j < project_static_libs.size(); j++) { - project_static_libs.write[j] = project_static_libs[j].get_file(); // Only the file name as it's copied to the project - } - err = _export_additional_assets(p_out_dir, project_static_libs, true, false, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - Vector<String> ios_bundle_files = export_plugins[i]->get_ios_bundle_files(); - err = _export_additional_assets(p_out_dir, ios_bundle_files, false, false, r_exported_assets); - ERR_FAIL_COND_V(err, err); - } - - Vector<String> library_paths; - for (int i = 0; i < p_libraries.size(); ++i) { - library_paths.push_back(p_libraries[i].path); - } - Error err = _export_additional_assets(p_out_dir, library_paths, true, true, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - return OK; -} - -Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) { - Vector<ExportArchitecture> all_archs = _get_supported_architectures(); - Vector<String> enabled_archs; - for (int i = 0; i < all_archs.size(); ++i) { - bool is_enabled = p_preset->get("architectures/" + all_archs[i].name); - if (is_enabled) { - enabled_archs.push_back(all_archs[i].name); - } - } - return enabled_archs; -} - -Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug) { - String plugin_definition_cpp_code; - String plugin_initialization_cpp_code; - String plugin_deinitialization_cpp_code; - - Vector<String> plugin_linked_dependencies; - Vector<String> plugin_embedded_dependencies; - Vector<String> plugin_files; - - Vector<PluginConfigIOS> enabled_plugins = get_enabled_plugins(p_preset); - - Vector<String> added_linked_dependenciy_names; - Vector<String> added_embedded_dependenciy_names; - HashMap<String, String> plist_values; - - HashSet<String> plugin_linker_flags; - - Error err; - - for (int i = 0; i < enabled_plugins.size(); i++) { - PluginConfigIOS plugin = enabled_plugins[i]; - - // Export plugin binary. - String plugin_main_binary = PluginConfigIOS::get_plugin_main_binary(plugin, p_debug); - String plugin_binary_result_file = plugin.binary.get_file(); - // We shouldn't embed .xcframework that contains static libraries. - // Static libraries are not embedded anyway. - err = _copy_asset(dest_dir, plugin_main_binary, &plugin_binary_result_file, true, false, r_exported_assets); - - ERR_FAIL_COND_V(err, err); - - // Adding dependencies. - // Use separate container for names to check for duplicates. - for (int j = 0; j < plugin.linked_dependencies.size(); j++) { - String dependency = plugin.linked_dependencies[j]; - String name = dependency.get_file(); - - if (added_linked_dependenciy_names.has(name)) { - continue; - } - - added_linked_dependenciy_names.push_back(name); - plugin_linked_dependencies.push_back(dependency); - } - - for (int j = 0; j < plugin.system_dependencies.size(); j++) { - String dependency = plugin.system_dependencies[j]; - String name = dependency.get_file(); - - if (added_linked_dependenciy_names.has(name)) { - continue; - } - - added_linked_dependenciy_names.push_back(name); - plugin_linked_dependencies.push_back(dependency); - } - - for (int j = 0; j < plugin.embedded_dependencies.size(); j++) { - String dependency = plugin.embedded_dependencies[j]; - String name = dependency.get_file(); - - if (added_embedded_dependenciy_names.has(name)) { - continue; - } - - added_embedded_dependenciy_names.push_back(name); - plugin_embedded_dependencies.push_back(dependency); - } - - plugin_files.append_array(plugin.files_to_copy); - - // Capabilities - // Also checking for duplicates. - for (int j = 0; j < plugin.capabilities.size(); j++) { - String capability = plugin.capabilities[j]; - - if (p_config_data.capabilities.has(capability)) { - continue; - } - - p_config_data.capabilities.push_back(capability); - } - - // Linker flags - // Checking duplicates - for (int j = 0; j < plugin.linker_flags.size(); j++) { - String linker_flag = plugin.linker_flags[j]; - plugin_linker_flags.insert(linker_flag); - } - - // Plist - // Using hash map container to remove duplicates - - for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) { - String key = E.key; - const PluginConfigIOS::PlistItem &item = E.value; - - String value; - - switch (item.type) { - case PluginConfigIOS::PlistItemType::STRING_INPUT: { - String preset_name = "plugins_plist/" + key; - String input_value = p_preset->get(preset_name); - value = "<string>" + input_value + "</string>"; - } break; - default: - value = item.value; - break; - } - - if (key.is_empty() || value.is_empty()) { - continue; - } - - String plist_key = "<key>" + key + "</key>"; - - plist_values[plist_key] = value; - } - - // CPP Code - String definition_comment = "// Plugin: " + plugin.name + "\n"; - String initialization_method = plugin.initialization_method + "();\n"; - String deinitialization_method = plugin.deinitialization_method + "();\n"; - - plugin_definition_cpp_code += definition_comment + - "extern void " + initialization_method + - "extern void " + deinitialization_method + "\n"; - - plugin_initialization_cpp_code += "\t" + initialization_method; - plugin_deinitialization_cpp_code += "\t" + deinitialization_method; - } - - // Updating `Info.plist` - { - for (const KeyValue<String, String> &E : plist_values) { - String key = E.key; - String value = E.value; - - if (key.is_empty() || value.is_empty()) { - continue; - } - - p_config_data.plist_content += key + value + "\n"; - } - } - - // Export files - { - // Export linked plugin dependency - err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - // Export embedded plugin dependency - err = _export_additional_assets(dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets); - ERR_FAIL_COND_V(err, err); - - // Export plugin files - err = _export_additional_assets(dest_dir, plugin_files, false, false, r_exported_assets); - ERR_FAIL_COND_V(err, err); - } - - // Update CPP - { - Dictionary plugin_format; - plugin_format["definition"] = plugin_definition_cpp_code; - plugin_format["initialization"] = plugin_initialization_cpp_code; - plugin_format["deinitialization"] = plugin_deinitialization_cpp_code; - - String plugin_cpp_code = "\n// Godot Plugins\n" - "void godot_ios_plugins_initialize();\n" - "void godot_ios_plugins_deinitialize();\n" - "// Exported Plugins\n\n" - "$definition" - "// Use Plugins\n" - "void godot_ios_plugins_initialize() {\n" - "$initialization" - "}\n\n" - "void godot_ios_plugins_deinitialize() {\n" - "$deinitialization" - "}\n"; - - p_config_data.cpp_code += plugin_cpp_code.format(plugin_format, "$_"); - } - - // Update Linker Flag Values - { - String result_linker_flags = " "; - for (const String &E : plugin_linker_flags) { - const String &flag = E; - - if (flag.length() == 0) { - continue; - } - - if (result_linker_flags.length() > 0) { - result_linker_flags += ' '; - } - - result_linker_flags += flag; - } - result_linker_flags = result_linker_flags.replace("\"", "\\\""); - p_config_data.linker_flags += result_linker_flags; - } - - return OK; -} - -Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { - ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - - String src_pkg_name; - String dest_dir = p_path.get_base_dir() + "/"; - String binary_name = p_path.get_file().get_basename(); - - EditorProgress ep("export", "Exporting for iOS", 5, true); - - String team_id = p_preset->get("application/app_store_team_id"); - ERR_FAIL_COND_V_MSG(team_id.length() == 0, ERR_CANT_OPEN, "App Store Team ID not specified - cannot configure the project."); - - if (p_debug) { - src_pkg_name = p_preset->get("custom_template/debug"); - } else { - src_pkg_name = p_preset->get("custom_template/release"); - } - - if (src_pkg_name.is_empty()) { - String err; - src_pkg_name = find_export_template("iphone.zip", &err); - if (src_pkg_name.is_empty()) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found.")); - return ERR_FILE_NOT_FOUND; - } - } - - if (!DirAccess::exists(dest_dir)) { - return ERR_FILE_BAD_PATH; - } - - { - Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (da.is_valid()) { - String current_dir = da->get_current_dir(); - - // remove leftovers from last export so they don't interfere - // in case some files are no longer needed - if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) { - da->erase_contents_recursive(); - } - if (da->change_dir(dest_dir + binary_name) == OK) { - da->erase_contents_recursive(); - } - - da->change_dir(current_dir); - - if (!da->dir_exists(dest_dir + binary_name)) { - Error err = da->make_dir(dest_dir + binary_name); - if (err) { - return err; - } - } - } - } - - if (ep.step("Making .pck", 0)) { - return ERR_SKIP; - } - String pack_path = dest_dir + binary_name + ".pck"; - Vector<SharedObject> libraries; - Error err = save_pack(p_preset, p_debug, pack_path, &libraries); - if (err) { - return err; - } - - if (ep.step("Extracting and configuring Xcode project", 1)) { - return ERR_SKIP; - } - - String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".xcframework"; - - print_line("Static framework: " + library_to_use); - String pkg_name; - if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { - pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name")); - } else { - pkg_name = "Unnamed"; - } - - bool found_library = false; - - const String project_file = "godot_ios.xcodeproj/project.pbxproj"; - HashSet<String> files_to_parse; - files_to_parse.insert("godot_ios/godot_ios-Info.plist"); - files_to_parse.insert(project_file); - files_to_parse.insert("godot_ios/export_options.plist"); - files_to_parse.insert("godot_ios/dummy.cpp"); - files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata"); - files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme"); - files_to_parse.insert("godot_ios/godot_ios.entitlements"); - files_to_parse.insert("godot_ios/Launch Screen.storyboard"); - - IOSConfigData config_data = { - pkg_name, - binary_name, - _get_additional_plist_content(), - String(" ").join(_get_preset_architectures(p_preset)), - _get_linker_flags(), - _get_cpp_code(), - "", - "", - "", - "", - Vector<String>() - }; - - Vector<IOSExportAsset> assets; - - Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir); - ERR_FAIL_COND_V(tmp_app_path.is_null(), ERR_CANT_CREATE); - - print_line("Unzipping..."); - Ref<FileAccess> io_fa; - zlib_filefunc_def io = zipio_create_io(&io_fa); - unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io); - if (!src_pkg_zip) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Could not open export template (not a zip file?): \"%s\".", src_pkg_name)); - return ERR_CANT_OPEN; - } - - err = _export_ios_plugins(p_preset, config_data, dest_dir + binary_name, assets, p_debug); - ERR_FAIL_COND_V(err, err); - - //export rest of the files - int ret = unzGoToFirstFile(src_pkg_zip); - Vector<uint8_t> project_file_data; - while (ret == UNZ_OK) { -#if defined(OSX_ENABLED) || defined(X11_ENABLED) - bool is_execute = false; -#endif - - //get filename - unz_file_info info; - char fname[16384]; - ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0); - if (ret != UNZ_OK) { - break; - } - - String file = String::utf8(fname); - - print_line("READ: " + file); - Vector<uint8_t> data; - data.resize(info.uncompressed_size); - - //read - unzOpenCurrentFile(src_pkg_zip); - unzReadCurrentFile(src_pkg_zip, data.ptrw(), data.size()); - unzCloseCurrentFile(src_pkg_zip); - - //write - - file = file.replace_first("iphone/", ""); - - if (files_to_parse.has(file)) { - _fix_config_file(p_preset, data, config_data, p_debug); - } else if (file.begins_with("libgodot.iphone")) { - if (!file.begins_with(library_to_use) || file.ends_with(String("/empty"))) { - ret = unzGoToNextFile(src_pkg_zip); - continue; //ignore! - } - found_library = true; -#if defined(OSX_ENABLED) || defined(X11_ENABLED) - is_execute = true; -#endif - file = file.replace(library_to_use, binary_name + ".xcframework"); - } - - if (file == project_file) { - project_file_data = data; - } - - ///@TODO need to parse logo files - - if (data.size() > 0) { - file = file.replace("godot_ios", binary_name); - - print_line("ADDING: " + file + " size: " + itos(data.size())); - - /* write it into our folder structure */ - file = dest_dir + file; - - /* make sure this folder exists */ - String dir_name = file.get_base_dir(); - if (!tmp_app_path->dir_exists(dir_name)) { - print_line("Creating " + dir_name); - Error dir_err = tmp_app_path->make_dir_recursive(dir_name); - if (dir_err) { - ERR_PRINT("Can't create '" + dir_name + "'."); - unzClose(src_pkg_zip); - return ERR_CANT_CREATE; - } - } - - /* write the file */ - { - Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE); - if (f.is_null()) { - ERR_PRINT("Can't write '" + file + "'."); - unzClose(src_pkg_zip); - return ERR_CANT_CREATE; - }; - f->store_buffer(data.ptr(), data.size()); - } - -#if defined(OSX_ENABLED) || defined(X11_ENABLED) - if (is_execute) { - // we need execute rights on this file - chmod(file.utf8().get_data(), 0755); - } -#endif - } - - ret = unzGoToNextFile(src_pkg_zip); - } - - /* we're done with our source zip */ - unzClose(src_pkg_zip); - - if (!found_library) { - ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive."); - return ERR_FILE_NOT_FOUND; - } - - Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized"); - Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized"); - Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized"); - Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized"); - - Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); - if (translations.size() > 0) { - { - String fname = dest_dir + binary_name + "/en.lproj"; - tmp_app_path->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - f->store_line("/* Localized versions of Info.plist keys */"); - f->store_line(""); - f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";"); - f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";"); - f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";"); - f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";"); - } - - for (const String &E : translations) { - Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - String fname = dest_dir + binary_name + "/" + lang + ".lproj"; - tmp_app_path->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - f->store_line("/* Localized versions of Info.plist keys */"); - f->store_line(""); - if (appnames.has(lang)) { - f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); - } - if (camera_usage_descriptions.has(lang)) { - f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); - } - if (microphone_usage_descriptions.has(lang)) { - f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); - } - if (photolibrary_usage_descriptions.has(lang)) { - f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";"); - } - } - } - } - - // Copy project static libs to the project - Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - for (int i = 0; i < export_plugins.size(); i++) { - Vector<String> project_static_libs = export_plugins[i]->get_ios_project_static_libs(); - for (int j = 0; j < project_static_libs.size(); j++) { - const String &static_lib_path = project_static_libs[j]; - String dest_lib_file_path = dest_dir + static_lib_path.get_file(); - Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path); - if (lib_copy_err != OK) { - ERR_PRINT("Can't copy '" + static_lib_path + "'."); - return lib_copy_err; - } - } - } - - String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/"; - err = OK; - if (!tmp_app_path->dir_exists(iconset_dir)) { - err = tmp_app_path->make_dir_recursive(iconset_dir); - } - if (err) { - return err; - } - - err = _export_icons(p_preset, iconset_dir); - if (err) { - return err; - } - - { - bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard"); - - String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"; - String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/"; - - Ref<DirAccess> launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - if (launch_screen_da.is_null()) { - return ERR_CANT_CREATE; - } - - if (use_storyboard) { - print_line("Using Launch Storyboard"); - - if (launch_screen_da->change_dir(launch_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(launch_image_path); - } - - err = _export_loading_screen_file(p_preset, splash_image_path); - } else { - print_line("Using Launch Images"); - - const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard"; - - launch_screen_da->remove(launch_screen_path); - - if (launch_screen_da->change_dir(splash_image_path) == OK) { - launch_screen_da->erase_contents_recursive(); - launch_screen_da->remove(splash_image_path); - } - - err = _export_loading_screen_images(p_preset, launch_image_path); - } - } - - if (err) { - return err; - } - - print_line("Exporting additional assets"); - _export_additional_assets(dest_dir + binary_name, libraries, assets); - _add_assets_to_project(p_preset, project_file_data, assets); - String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj"; - { - Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE); - if (f.is_null()) { - ERR_PRINT("Can't write '" + project_file_name + "'."); - return ERR_CANT_CREATE; - }; - f->store_buffer(project_file_data.ptr(), project_file_data.size()); - } - -#ifdef OSX_ENABLED - { - if (ep.step("Code-signing dylibs", 2)) { - return ERR_SKIP; - } - Ref<DirAccess> dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs"); - ERR_FAIL_COND_V(dylibs_dir.is_null(), ERR_CANT_OPEN); - CodesignData codesign_data(p_preset, p_debug); - err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); - ERR_FAIL_COND_V(err, err); - } - - if (ep.step("Making .xcarchive", 3)) { - return ERR_SKIP; - } - String archive_path = p_path.get_basename() + ".xcarchive"; - List<String> archive_args; - archive_args.push_back("-project"); - archive_args.push_back(dest_dir + binary_name + ".xcodeproj"); - archive_args.push_back("-scheme"); - archive_args.push_back(binary_name); - archive_args.push_back("-sdk"); - archive_args.push_back("iphoneos"); - archive_args.push_back("-configuration"); - archive_args.push_back(p_debug ? "Debug" : "Release"); - archive_args.push_back("-destination"); - archive_args.push_back("generic/platform=iOS"); - archive_args.push_back("archive"); - archive_args.push_back("-allowProvisioningUpdates"); - archive_args.push_back("-archivePath"); - archive_args.push_back(archive_path); - String archive_str; - err = OS::get_singleton()->execute("xcodebuild", archive_args, &archive_str, nullptr, true); - ERR_FAIL_COND_V(err, err); - print_line("xcodebuild (.xcarchive):\n" + archive_str); - - if (ep.step("Making .ipa", 4)) { - return ERR_SKIP; - } - List<String> export_args; - export_args.push_back("-exportArchive"); - export_args.push_back("-archivePath"); - export_args.push_back(archive_path); - export_args.push_back("-exportOptionsPlist"); - export_args.push_back(dest_dir + binary_name + "/export_options.plist"); - export_args.push_back("-allowProvisioningUpdates"); - export_args.push_back("-exportPath"); - export_args.push_back(dest_dir); - String export_str; - err = OS::get_singleton()->execute("xcodebuild", export_args, &export_str, nullptr, true); - ERR_FAIL_COND_V(err, err); - print_line("xcodebuild (.ipa):\n" + export_str); -#else - print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package."); -#endif - - return OK; -} - -bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { - String err; - bool valid = false; - - // Look for export templates (first official, and if defined custom templates). - - bool dvalid = exists_export_template("iphone.zip", &err); - bool rvalid = dvalid; // Both in the same ZIP. - - if (p_preset->get("custom_template/debug") != "") { - dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); - if (!dvalid) { - err += TTR("Custom debug template not found.") + "\n"; - } - } - if (p_preset->get("custom_template/release") != "") { - rvalid = FileAccess::exists(p_preset->get("custom_template/release")); - if (!rvalid) { - err += TTR("Custom release template not found.") + "\n"; - } - } - - valid = dvalid || rvalid; - r_missing_templates = !valid; - - // Validate the rest of the configuration. - - String team_id = p_preset->get("application/app_store_team_id"); - if (team_id.length() == 0) { - err += TTR("App Store Team ID not specified - cannot configure the project.") + "\n"; - valid = false; - } - - String identifier = p_preset->get("application/bundle_identifier"); - String pn_err; - if (!is_package_name_valid(identifier, &pn_err)) { - err += TTR("Invalid Identifier:") + " " + pn_err + "\n"; - valid = false; - } - - const String etc_error = test_etc2(); - if (!etc_error.is_empty()) { - valid = false; - err += etc_error; - } - - if (!err.is_empty()) { - r_error = err; - } - - return valid; -} - -EditorExportPlatformIOS::EditorExportPlatformIOS() { - logo = ImageTexture::create_from_image(memnew(Image(_iphone_logo))); - plugins_changed.set(); - check_for_changes_thread.start(_check_for_changes_poll_thread, this); -} - -EditorExportPlatformIOS::~EditorExportPlatformIOS() { - quit_request.set(); - check_for_changes_thread.wait_to_finish(); -} diff --git a/platform/iphone/export/export_plugin.h b/platform/iphone/export/export_plugin.h deleted file mode 100644 index 1db7418e3f..0000000000 --- a/platform/iphone/export/export_plugin.h +++ /dev/null @@ -1,293 +0,0 @@ -/*************************************************************************/ -/* export_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef IPHONE_EXPORT_PLUGIN_H -#define IPHONE_EXPORT_PLUGIN_H - -#include "core/config/project_settings.h" -#include "core/io/file_access.h" -#include "core/io/image_loader.h" -#include "core/io/marshalls.h" -#include "core/io/resource_saver.h" -#include "core/io/zip_io.h" -#include "core/os/os.h" -#include "core/templates/safe_refcount.h" -#include "core/version.h" -#include "editor/editor_export.h" -#include "editor/editor_settings.h" -#include "main/splash.gen.h" -#include "platform/iphone/logo.gen.h" -#include "string.h" - -#include "godot_plugin_config.h" - -#include <sys/stat.h> - -class EditorExportPlatformIOS : public EditorExportPlatform { - GDCLASS(EditorExportPlatformIOS, EditorExportPlatform); - - Ref<ImageTexture> logo; - - // Plugins - SafeFlag plugins_changed; - Thread check_for_changes_thread; - SafeFlag quit_request; - Mutex plugins_lock; - Vector<PluginConfigIOS> plugins; - - typedef Error (*FileHandler)(String p_file, void *p_userdata); - static Error _walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata); - static Error _codesign(String p_file, void *p_userdata); - void _blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p_src, bool p_rot); - - struct IOSConfigData { - String pkg_name; - String binary_name; - String plist_content; - String architectures; - String linker_flags; - String cpp_code; - String modules_buildfile; - String modules_fileref; - String modules_buildphase; - String modules_buildgrp; - Vector<String> capabilities; - }; - struct ExportArchitecture { - String name; - bool is_default = false; - - ExportArchitecture() {} - - ExportArchitecture(String p_name, bool p_is_default) { - name = p_name; - is_default = p_is_default; - } - }; - - struct IOSExportAsset { - String exported_path; - bool is_framework = false; // framework is anything linked to the binary, otherwise it's a resource - bool should_embed = false; - }; - - String _get_additional_plist_content(); - String _get_linker_flags(); - String _get_cpp_code(); - void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug); - Error _export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir); - Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir); - Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir); - - Vector<ExportArchitecture> _get_supported_architectures(); - Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset); - - void _add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets); - Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); - Error _copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets); - Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets); - Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug); - - bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const { - String pname = p_package; - - if (pname.length() == 0) { - if (r_error) { - *r_error = TTR("Identifier is missing."); - } - return false; - } - - for (int i = 0; i < pname.length(); i++) { - char32_t c = pname[i]; - if (!(is_ascii_alphanumeric_char(c) || c == '-' || c == '.')) { - if (r_error) { - *r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c)); - } - return false; - } - } - - return true; - } - - static void _check_for_changes_poll_thread(void *ud) { - EditorExportPlatformIOS *ea = static_cast<EditorExportPlatformIOS *>(ud); - - while (!ea->quit_request.is_set()) { - // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed.is_set()) { - MutexLock lock(ea->plugins_lock); - - Vector<PluginConfigIOS> loaded_plugins = get_plugins(); - - if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed.set(); - } else { - for (int i = 0; i < ea->plugins.size(); i++) { - if (ea->plugins[i].name != loaded_plugins[i].name || ea->plugins[i].last_updated != loaded_plugins[i].last_updated) { - ea->plugins_changed.set(); - break; - } - } - } - } - - uint64_t wait = 3000000; - uint64_t time = OS::get_singleton()->get_ticks_usec(); - while (OS::get_singleton()->get_ticks_usec() - time < wait) { - OS::get_singleton()->delay_usec(300000); - - if (ea->quit_request.is_set()) { - break; - } - } - } - } - -protected: - virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override; - virtual void get_export_options(List<ExportOption> *r_options) override; - -public: - virtual String get_name() const override { return "iOS"; } - virtual String get_os_name() const override { return "iOS"; } - virtual Ref<Texture2D> get_logo() const override { return logo; } - - virtual bool should_update_export_options() override { - bool export_options_changed = plugins_changed.is_set(); - if (export_options_changed) { - // don't clear unless we're reporting true, to avoid race - plugins_changed.clear(); - } - return export_options_changed; - } - - virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override { - List<String> list; - list.push_back("ipa"); - return list; - } - virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; - - virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; - - virtual void get_platform_features(List<String> *r_features) override { - r_features->push_back("mobile"); - r_features->push_back("ios"); - } - - virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override { - } - - EditorExportPlatformIOS(); - ~EditorExportPlatformIOS(); - - /// List the gdip files in the directory specified by the p_path parameter. - static Vector<String> list_plugin_config_files(const String &p_path, bool p_check_directories) { - Vector<String> dir_files; - Ref<DirAccess> da = DirAccess::open(p_path); - if (da.is_valid()) { - da->list_dir_begin(); - while (true) { - String file = da->get_next(); - if (file.is_empty()) { - break; - } - - if (file == "." || file == "..") { - continue; - } - - if (da->current_is_hidden()) { - continue; - } - - if (da->current_is_dir()) { - if (p_check_directories) { - Vector<String> directory_files = list_plugin_config_files(p_path.plus_file(file), false); - for (int i = 0; i < directory_files.size(); ++i) { - dir_files.push_back(file.plus_file(directory_files[i])); - } - } - - continue; - } - - if (file.ends_with(PluginConfigIOS::PLUGIN_CONFIG_EXT)) { - dir_files.push_back(file); - } - } - da->list_dir_end(); - } - - return dir_files; - } - - static Vector<PluginConfigIOS> get_plugins() { - Vector<PluginConfigIOS> loaded_plugins; - - String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins"); - - if (DirAccess::exists(plugins_dir)) { - Vector<String> plugins_filenames = list_plugin_config_files(plugins_dir, true); - - if (!plugins_filenames.is_empty()) { - Ref<ConfigFile> config_file = memnew(ConfigFile); - for (int i = 0; i < plugins_filenames.size(); i++) { - PluginConfigIOS config = PluginConfigIOS::load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); - if (config.valid_config) { - loaded_plugins.push_back(config); - } else { - print_error("Invalid plugin config file " + plugins_filenames[i]); - } - } - } - } - - return loaded_plugins; - } - - static Vector<PluginConfigIOS> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) { - Vector<PluginConfigIOS> enabled_plugins; - Vector<PluginConfigIOS> all_plugins = get_plugins(); - for (int i = 0; i < all_plugins.size(); i++) { - PluginConfigIOS plugin = all_plugins[i]; - bool enabled = p_presets->get("plugins/" + plugin.name); - if (enabled) { - enabled_plugins.push_back(plugin); - } - } - - return enabled_plugins; - } -}; - -#endif diff --git a/platform/iphone/export/godot_plugin_config.cpp b/platform/iphone/export/godot_plugin_config.cpp deleted file mode 100644 index 9118b95337..0000000000 --- a/platform/iphone/export/godot_plugin_config.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/*************************************************************************/ -/* godot_plugin_config.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "godot_plugin_config.h" - -#include "core/config/project_settings.h" -#include "core/io/dir_access.h" -#include "core/io/file_access.h" - -String PluginConfigIOS::resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { - String absolute_path; - - if (dependency_path.is_empty()) { - return absolute_path; - } - - if (dependency_path.is_absolute_path()) { - return dependency_path; - } - - String res_path = ProjectSettings::get_singleton()->globalize_path("res://"); - absolute_path = plugin_config_dir.plus_file(dependency_path); - - return absolute_path.replace(res_path, "res://"); -} - -String PluginConfigIOS::resolve_system_dependency_path(String dependency_path) { - String absolute_path; - - if (dependency_path.is_empty()) { - return absolute_path; - } - - if (dependency_path.is_absolute_path()) { - return dependency_path; - } - - String system_path = "/System/Library/Frameworks"; - - return system_path.plus_file(dependency_path); -} - -Vector<String> PluginConfigIOS::resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths) { - Vector<String> paths; - - for (int i = 0; i < p_paths.size(); i++) { - String path = resolve_local_dependency_path(plugin_config_dir, p_paths[i]); - - if (path.is_empty()) { - continue; - } - - paths.push_back(path); - } - - return paths; -} - -Vector<String> PluginConfigIOS::resolve_system_dependencies(Vector<String> p_paths) { - Vector<String> paths; - - for (int i = 0; i < p_paths.size(); i++) { - String path = resolve_system_dependency_path(p_paths[i]); - - if (path.is_empty()) { - continue; - } - - paths.push_back(path); - } - - return paths; -} - -bool PluginConfigIOS::validate_plugin(PluginConfigIOS &plugin_config) { - bool valid_name = !plugin_config.name.is_empty(); - bool valid_binary_name = !plugin_config.binary.is_empty(); - bool valid_initialize = !plugin_config.initialization_method.is_empty(); - bool valid_deinitialize = !plugin_config.deinitialization_method.is_empty(); - - bool fields_value = valid_name && valid_binary_name && valid_initialize && valid_deinitialize; - - if (!fields_value) { - return false; - } - - String plugin_extension = plugin_config.binary.get_extension().to_lower(); - - if ((plugin_extension == "a" && FileAccess::exists(plugin_config.binary)) || - (plugin_extension == "xcframework" && DirAccess::exists(plugin_config.binary))) { - plugin_config.valid_config = true; - plugin_config.supports_targets = false; - } else { - String file_path = plugin_config.binary.get_base_dir(); - String file_name = plugin_config.binary.get_basename().get_file(); - String file_extension = plugin_config.binary.get_extension(); - String release_file_name = file_path.plus_file(file_name + ".release." + file_extension); - String debug_file_name = file_path.plus_file(file_name + ".debug." + file_extension); - - if ((plugin_extension == "a" && FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) || - (plugin_extension == "xcframework" && DirAccess::exists(release_file_name) && DirAccess::exists(debug_file_name))) { - plugin_config.valid_config = true; - plugin_config.supports_targets = true; - } - } - - return plugin_config.valid_config; -} - -String PluginConfigIOS::get_plugin_main_binary(PluginConfigIOS &plugin_config, bool p_debug) { - if (!plugin_config.supports_targets) { - return plugin_config.binary; - } - - String plugin_binary_dir = plugin_config.binary.get_base_dir(); - String plugin_name_prefix = plugin_config.binary.get_basename().get_file(); - String plugin_extension = plugin_config.binary.get_extension(); - String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + "." + plugin_extension; - - return plugin_binary_dir.plus_file(plugin_file); -} - -uint64_t PluginConfigIOS::get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path) { - uint64_t last_updated = FileAccess::get_modified_time(config_path); - - if (!plugin_config.supports_targets) { - last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary)); - } else { - String file_path = plugin_config.binary.get_base_dir(); - String file_name = plugin_config.binary.get_basename().get_file(); - String plugin_extension = plugin_config.binary.get_extension(); - String release_file_name = file_path.plus_file(file_name + ".release." + plugin_extension); - String debug_file_name = file_path.plus_file(file_name + ".debug." + plugin_extension); - - last_updated = MAX(last_updated, FileAccess::get_modified_time(release_file_name)); - last_updated = MAX(last_updated, FileAccess::get_modified_time(debug_file_name)); - } - - return last_updated; -} - -PluginConfigIOS PluginConfigIOS::load_plugin_config(Ref<ConfigFile> config_file, const String &path) { - PluginConfigIOS plugin_config = {}; - - if (!config_file.is_valid()) { - return plugin_config; - } - - config_file->clear(); - - Error err = config_file->load(path); - - if (err != OK) { - return plugin_config; - } - - String config_base_dir = path.get_base_dir(); - - plugin_config.name = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_NAME_KEY, String()); - plugin_config.initialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_INITIALIZE_KEY, String()); - plugin_config.deinitialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_DEINITIALIZE_KEY, String()); - - String binary_path = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_BINARY_KEY, String()); - plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path); - - if (config_file->has_section(PluginConfigIOS::DEPENDENCIES_SECTION)) { - Vector<String> linked_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKED_KEY, Vector<String>()); - Vector<String> embedded_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_EMBEDDED_KEY, Vector<String>()); - Vector<String> system_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_SYSTEM_KEY, Vector<String>()); - Vector<String> files = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_FILES_KEY, Vector<String>()); - - plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies); - plugin_config.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies); - plugin_config.system_dependencies = resolve_system_dependencies(system_dependencies); - - plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files); - - plugin_config.capabilities = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_CAPABILITIES_KEY, Vector<String>()); - - plugin_config.linker_flags = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKER_FLAGS, Vector<String>()); - } - - if (config_file->has_section(PluginConfigIOS::PLIST_SECTION)) { - List<String> keys; - config_file->get_section_keys(PluginConfigIOS::PLIST_SECTION, &keys); - - for (int i = 0; i < keys.size(); i++) { - Vector<String> key_components = keys[i].split(":"); - - String key_value = ""; - PluginConfigIOS::PlistItemType key_type = PluginConfigIOS::PlistItemType::UNKNOWN; - - if (key_components.size() == 1) { - key_value = key_components[0]; - key_type = PluginConfigIOS::PlistItemType::STRING; - } else if (key_components.size() == 2) { - key_value = key_components[0]; - - if (key_components[1].to_lower() == "string") { - key_type = PluginConfigIOS::PlistItemType::STRING; - } else if (key_components[1].to_lower() == "integer") { - key_type = PluginConfigIOS::PlistItemType::INTEGER; - } else if (key_components[1].to_lower() == "boolean") { - key_type = PluginConfigIOS::PlistItemType::BOOLEAN; - } else if (key_components[1].to_lower() == "raw") { - key_type = PluginConfigIOS::PlistItemType::RAW; - } else if (key_components[1].to_lower() == "string_input") { - key_type = PluginConfigIOS::PlistItemType::STRING_INPUT; - } - } - - if (key_value.is_empty() || key_type == PluginConfigIOS::PlistItemType::UNKNOWN) { - continue; - } - - String value; - - switch (key_type) { - case PluginConfigIOS::PlistItemType::STRING: { - String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String()); - value = "<string>" + raw_value + "</string>"; - } break; - case PluginConfigIOS::PlistItemType::INTEGER: { - int raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], 0); - Dictionary value_dictionary; - String value_format = "<integer>$value</integer>"; - value_dictionary["value"] = raw_value; - value = value_format.format(value_dictionary, "$_"); - } break; - case PluginConfigIOS::PlistItemType::BOOLEAN: - if (config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], false)) { - value = "<true/>"; - } else { - value = "<false/>"; - } - break; - case PluginConfigIOS::PlistItemType::RAW: { - String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String()); - value = raw_value; - } break; - case PluginConfigIOS::PlistItemType::STRING_INPUT: { - String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String()); - value = raw_value; - } break; - default: - continue; - } - - plugin_config.plist[key_value] = PluginConfigIOS::PlistItem{ key_type, value }; - } - } - - if (validate_plugin(plugin_config)) { - plugin_config.last_updated = get_plugin_modification_time(plugin_config, path); - } - - return plugin_config; -} diff --git a/platform/iphone/export/godot_plugin_config.h b/platform/iphone/export/godot_plugin_config.h deleted file mode 100644 index 9ef8aa8c6d..0000000000 --- a/platform/iphone/export/godot_plugin_config.h +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************/ -/* godot_plugin_config.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef IPHONE_GODOT_PLUGIN_CONFIG_H -#define IPHONE_GODOT_PLUGIN_CONFIG_H - -#include "core/error/error_list.h" -#include "core/io/config_file.h" -#include "core/string/ustring.h" - -/* - The `config` section and fields are required and defined as follow: -- **name**: name of the plugin -- **binary**: path to static `.a` library - -The `dependencies` and fields are optional. -- **linked**: dependencies that should only be linked. -- **embedded**: dependencies that should be linked and embedded into application. -- **system**: system dependencies that should be linked. -- **capabilities**: capabilities that would be used for `UIRequiredDeviceCapabilities` options in Info.plist file. -- **files**: files that would be copied into application - -The `plist` section are optional. -- **key**: key and value that would be added in Info.plist file. - */ - -struct PluginConfigIOS { - inline static const char *PLUGIN_CONFIG_EXT = ".gdip"; - - inline static const char *CONFIG_SECTION = "config"; - inline static const char *CONFIG_NAME_KEY = "name"; - inline static const char *CONFIG_BINARY_KEY = "binary"; - inline static const char *CONFIG_INITIALIZE_KEY = "initialization"; - inline static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization"; - - inline static const char *DEPENDENCIES_SECTION = "dependencies"; - inline static const char *DEPENDENCIES_LINKED_KEY = "linked"; - inline static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded"; - inline static const char *DEPENDENCIES_SYSTEM_KEY = "system"; - inline static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities"; - inline static const char *DEPENDENCIES_FILES_KEY = "files"; - inline static const char *DEPENDENCIES_LINKER_FLAGS = "linker_flags"; - - inline static const char *PLIST_SECTION = "plist"; - - enum PlistItemType { - UNKNOWN, - STRING, - INTEGER, - BOOLEAN, - RAW, - STRING_INPUT, - }; - - struct PlistItem { - PlistItemType type; - String value; - }; - - // Set to true when the config file is properly loaded. - bool valid_config = false; - bool supports_targets = false; - // Unix timestamp of last change to this plugin. - uint64_t last_updated = 0; - - // Required config section - String name; - String binary; - String initialization_method; - String deinitialization_method; - - // Optional dependencies section - Vector<String> linked_dependencies; - Vector<String> embedded_dependencies; - Vector<String> system_dependencies; - - Vector<String> files_to_copy; - Vector<String> capabilities; - - Vector<String> linker_flags; - - // Optional plist section - // String value is default value. - // Currently supports `string`, `boolean`, `integer`, `raw`, `string_input` types - // <name>:<type> = <value> - HashMap<String, PlistItem> plist; - - static String resolve_local_dependency_path(String plugin_config_dir, String dependency_path); - - static String resolve_system_dependency_path(String dependency_path); - - static Vector<String> resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths); - - static Vector<String> resolve_system_dependencies(Vector<String> p_paths); - - static bool validate_plugin(PluginConfigIOS &plugin_config); - - static String get_plugin_main_binary(PluginConfigIOS &plugin_config, bool p_debug); - - static uint64_t get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path); - - static PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, const String &path); -}; - -#endif // GODOT_PLUGIN_CONFIG_H diff --git a/platform/iphone/godot_app_delegate.h b/platform/iphone/godot_app_delegate.h deleted file mode 100644 index 703a906bda..0000000000 --- a/platform/iphone/godot_app_delegate.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************/ -/* godot_app_delegate.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -typedef NSObject<UIApplicationDelegate> ApplicationDelegateService; - -@interface GodotApplicalitionDelegate : NSObject <UIApplicationDelegate> - -@property(class, readonly, strong) NSArray<ApplicationDelegateService *> *services; - -+ (void)addService:(ApplicationDelegateService *)service; - -@end diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m deleted file mode 100644 index 84347f9a30..0000000000 --- a/platform/iphone/godot_app_delegate.m +++ /dev/null @@ -1,467 +0,0 @@ -/*************************************************************************/ -/* godot_app_delegate.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_app_delegate.h" - -#import "app_delegate.h" - -@interface GodotApplicalitionDelegate () - -@end - -@implementation GodotApplicalitionDelegate - -static NSMutableArray<ApplicationDelegateService *> *services = nil; - -+ (NSArray<ApplicationDelegateService *> *)services { - return services; -} - -+ (void)load { - services = [NSMutableArray new]; - [services addObject:[AppDelegate new]]; -} - -+ (void)addService:(ApplicationDelegateService *)service { - if (!services || !service) { - return; - } - [services addObject:service]; -} - -// UIApplicationDelegate documentation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate - -// MARK: Window - -- (UIWindow *)window { - UIWindow *result = nil; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - UIWindow *value = [service window]; - - if (value) { - result = value; - } - } - - return result; -} - -// MARK: Initializing - -- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application willFinishLaunchingWithOptions:launchOptions]) { - result = YES; - } - } - - return result; -} - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application didFinishLaunchingWithOptions:launchOptions]) { - result = YES; - } - } - - return result; -} - -/* Can be handled by Info.plist. Not yet supported by Godot. - -// MARK: Scene - -- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {} - -- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {} - -*/ - -// MARK: Life-Cycle - -- (void)applicationDidBecomeActive:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationDidBecomeActive:application]; - } -} - -- (void)applicationWillResignActive:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationWillResignActive:application]; - } -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationDidEnterBackground:application]; - } -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationWillEnterForeground:application]; - } -} - -- (void)applicationWillTerminate:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationWillTerminate:application]; - } -} - -// MARK: Environment Changes - -- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationProtectedDataDidBecomeAvailable:application]; - } -} - -- (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationProtectedDataWillBecomeUnavailable:application]; - } -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationDidReceiveMemoryWarning:application]; - } -} - -- (void)applicationSignificantTimeChange:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationSignificantTimeChange:application]; - } -} - -// MARK: App State Restoration - -- (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application shouldSaveSecureApplicationState:coder]) { - result = YES; - } - } - - return result; -} - -- (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application shouldRestoreSecureApplicationState:coder]) { - result = YES; - } - } - - return result; -} - -- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - UIViewController *controller = [service application:application viewControllerWithRestorationIdentifierPath:identifierComponents coder:coder]; - - if (controller) { - return controller; - } - } - - return nil; -} - -- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application willEncodeRestorableStateWithCoder:coder]; - } -} - -- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didDecodeRestorableStateWithCoder:coder]; - } -} - -// MARK: Download Data in Background - -- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler]; - } - - completionHandler(); -} - -// MARK: Remote Notification - -// Moved to the iOS Plugin - -// MARK: User Activity and Handling Quick Actions - -- (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application willContinueUserActivityWithType:userActivityType]) { - result = YES; - } - } - - return result; -} - -- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application continueUserActivity:userActivity restorationHandler:restorationHandler]) { - result = YES; - } - } - - return result; -} - -- (void)application:(UIApplication *)application didUpdateUserActivity:(NSUserActivity *)userActivity { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didUpdateUserActivity:userActivity]; - } -} - -- (void)application:(UIApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didFailToContinueUserActivityWithType:userActivityType error:error]; - } -} - -- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application performActionForShortcutItem:shortcutItem completionHandler:completionHandler]; - } -} - -// MARK: WatchKit - -- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application handleWatchKitExtensionRequest:userInfo reply:reply]; - } -} - -// MARK: HealthKit - -- (void)applicationShouldRequestHealthAuthorization:(UIApplication *)application { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service applicationShouldRequestHealthAuthorization:application]; - } -} - -// MARK: Opening an URL - -- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:app openURL:url options:options]) { - return YES; - } - } - - return NO; -} - -// MARK: Disallowing Specified App Extension Types - -- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(UIApplicationExtensionPointIdentifier)extensionPointIdentifier { - BOOL result = NO; - - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - if ([service application:application shouldAllowExtensionPointIdentifier:extensionPointIdentifier]) { - result = YES; - } - } - - return result; -} - -// MARK: SiriKit - -- (id)application:(UIApplication *)application handlerForIntent:(INIntent *)intent API_AVAILABLE(ios(14.0)) { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - id result = [service application:application handlerForIntent:intent]; - - if (result) { - return result; - } - } - - return nil; -} - -// MARK: CloudKit - -- (void)application:(UIApplication *)application userDidAcceptCloudKitShareWithMetadata:(CKShareMetadata *)cloudKitShareMetadata { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application userDidAcceptCloudKitShareWithMetadata:cloudKitShareMetadata]; - } -} - -/* Handled By Info.plist file for now - -// MARK: Interface Geometry - -- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {} - -*/ - -@end diff --git a/platform/iphone/godot_iphone.mm b/platform/iphone/godot_iphone.mm deleted file mode 100644 index 59fdfa9dcd..0000000000 --- a/platform/iphone/godot_iphone.mm +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************/ -/* godot_iphone.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "core/string/ustring.h" -#include "main/main.h" -#include "os_iphone.h" - -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -static OSIPhone *os = nullptr; - -int add_path(int, char **); -int add_cmdline(int, char **); -int iphone_main(int, char **, String); - -int add_path(int p_argc, char **p_args) { - NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"]; - if (!str) { - return p_argc; - } - - p_args[p_argc++] = (char *)"--path"; - p_args[p_argc++] = (char *)[str cStringUsingEncoding:NSUTF8StringEncoding]; - p_args[p_argc] = nullptr; - - return p_argc; -} - -int add_cmdline(int p_argc, char **p_args) { - NSArray *arr = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_cmdline"]; - if (!arr) { - return p_argc; - } - - for (NSUInteger i = 0; i < [arr count]; i++) { - NSString *str = [arr objectAtIndex:i]; - if (!str) { - continue; - } - p_args[p_argc++] = (char *)[str cStringUsingEncoding:NSUTF8StringEncoding]; - } - - p_args[p_argc] = nullptr; - - return p_argc; -} - -int iphone_main(int argc, char **argv, String data_dir, String cache_dir) { - size_t len = strlen(argv[0]); - - while (len--) { - if (argv[0][len] == '/') { - break; - } - } - - if (len >= 0) { - char path[512]; - memcpy(path, argv[0], len > sizeof(path) ? sizeof(path) : len); - path[len] = 0; - printf("Path: %s\n", path); - chdir(path); - } - - printf("godot_iphone %s\n", argv[0]); - char cwd[512]; - getcwd(cwd, sizeof(cwd)); - printf("cwd %s\n", cwd); - os = new OSIPhone(data_dir, cache_dir); - - // We must override main when testing is enabled - TEST_MAIN_OVERRIDE - - char *fargv[64]; - for (int i = 0; i < argc; i++) { - fargv[i] = argv[i]; - } - fargv[argc] = nullptr; - argc = add_path(argc, fargv); - argc = add_cmdline(argc, fargv); - - printf("os created\n"); - - Error err = Main::setup(fargv[0], argc - 1, &fargv[1], false); - printf("setup %i\n", err); - - if (err == ERR_HELP) { // Returned by --help and --version, so success. - return 0; - } else if (err != OK) { - return 255; - } - - os->initialize_modules(); - - return 0; -} - -void iphone_finish() { - printf("iphone_finish\n"); - Main::cleanup(); - delete os; -} diff --git a/platform/iphone/godot_view.h b/platform/iphone/godot_view.h deleted file mode 100644 index fcb97fa63a..0000000000 --- a/platform/iphone/godot_view.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************/ -/* godot_view.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -class String; - -@class GodotView; -@protocol DisplayLayer; -@protocol GodotViewRendererProtocol; - -@protocol GodotViewDelegate - -- (BOOL)godotViewFinishedSetup:(GodotView *)view; - -@end - -@interface GodotView : UIView - -@property(assign, nonatomic) id<GodotViewRendererProtocol> renderer; -@property(assign, nonatomic) id<GodotViewDelegate> delegate; - -@property(assign, readonly, nonatomic) BOOL isActive; - -@property(assign, nonatomic) BOOL useCADisplayLink; -@property(strong, readonly, nonatomic) CALayer<DisplayLayer> *renderingLayer; -@property(assign, readonly, nonatomic) BOOL canRender; - -@property(assign, nonatomic) NSTimeInterval renderingInterval; - -- (CALayer<DisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName; -- (void)stopRendering; -- (void)startRendering; - -- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; - -@end diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm deleted file mode 100644 index e48dd2e507..0000000000 --- a/platform/iphone/godot_view.mm +++ /dev/null @@ -1,481 +0,0 @@ -/*************************************************************************/ -/* godot_view.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_view.h" - -#include "core/os/keyboard.h" -#include "core/string/ustring.h" -#import "display_layer.h" -#include "display_server_iphone.h" -#import "godot_view_gesture_recognizer.h" -#import "godot_view_renderer.h" - -#import <CoreMotion/CoreMotion.h> - -static const int max_touches = 8; -static const float earth_gravity = 9.80665; - -@interface GodotView () { - UITouch *godot_touches[max_touches]; -} - -@property(assign, nonatomic) BOOL isActive; - -// CADisplayLink available on 3.1+ synchronizes the animation timer & drawing with the refresh rate of the display, only supports animation intervals of 1/60 1/30 & 1/15 -@property(strong, nonatomic) CADisplayLink *displayLink; - -// An animation timer that, when animation is started, will periodically call -drawView at the given rate. -// Only used if CADisplayLink is not -@property(strong, nonatomic) NSTimer *animationTimer; - -@property(strong, nonatomic) CALayer<DisplayLayer> *renderingLayer; - -@property(strong, nonatomic) CMMotionManager *motionManager; - -@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer; - -@end - -@implementation GodotView - -- (CALayer<DisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName { - if (self.renderingLayer) { - return self.renderingLayer; - } - - CALayer<DisplayLayer> *layer; - - if ([driverName isEqualToString:@"vulkan"]) { - layer = [GodotMetalLayer layer]; - } else if ([driverName isEqualToString:@"opengl_es"]) { - if (@available(iOS 13, *)) { - NSLog(@"OpenGL ES is deprecated on iOS 13"); - } -#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR - return nil; -#else - layer = [GodotOpenGLLayer layer]; -#endif - } else { - return nil; - } - - layer.frame = self.bounds; - layer.contentsScale = self.contentScaleFactor; - - [self.layer addSublayer:layer]; - self.renderingLayer = layer; - - [layer initializeDisplayLayer]; - - return self.renderingLayer; -} - -- (instancetype)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)dealloc { - [self stopRendering]; - - self.renderer = nil; - self.delegate = nil; - - if (self.renderingLayer) { - [self.renderingLayer removeFromSuperlayer]; - self.renderingLayer = nil; - } - - if (self.motionManager) { - [self.motionManager stopDeviceMotionUpdates]; - self.motionManager = nil; - } - - if (self.displayLink) { - [self.displayLink invalidate]; - self.displayLink = nil; - } - - if (self.animationTimer) { - [self.animationTimer invalidate]; - self.animationTimer = nil; - } - - if (self.delayGestureRecognizer) { - self.delayGestureRecognizer = nil; - } -} - -- (void)godot_commonInit { - self.contentScaleFactor = [UIScreen mainScreen].nativeScale; - - [self initTouches]; - - self.multipleTouchEnabled = YES; - - // Configure and start accelerometer - if (!self.motionManager) { - self.motionManager = [[CMMotionManager alloc] init]; - if (self.motionManager.deviceMotionAvailable) { - self.motionManager.deviceMotionUpdateInterval = 1.0 / 70.0; - [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical]; - } else { - self.motionManager = nil; - } - } - - // Initialize delay gesture recognizer - GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init]; - self.delayGestureRecognizer = gestureRecognizer; - [self addGestureRecognizer:self.delayGestureRecognizer]; -} - -- (void)stopRendering { - if (!self.isActive) { - return; - } - - self.isActive = NO; - - printf("******** stop animation!\n"); - - if (self.useCADisplayLink) { - [self.displayLink invalidate]; - self.displayLink = nil; - } else { - [self.animationTimer invalidate]; - self.animationTimer = nil; - } - - [self clearTouches]; -} - -- (void)startRendering { - if (self.isActive) { - return; - } - - self.isActive = YES; - - printf("start animation!\n"); - - if (self.useCADisplayLink) { - self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView)]; - - // Approximate frame rate - // assumes device refreshes at 60 fps - int displayFPS = (NSInteger)(1.0 / self.renderingInterval); - - self.displayLink.preferredFramesPerSecond = displayFPS; - - // Setup DisplayLink in main thread - [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - } else { - self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:self.renderingInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; - } -} - -- (void)drawView { - if (!self.isActive) { - printf("draw view not active!\n"); - return; - } - - if (self.useCADisplayLink) { - // Pause the CADisplayLink to avoid recursion - [self.displayLink setPaused:YES]; - - // Process all input events - while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource) { - // Continue. - } - - // We are good to go, resume the CADisplayLink - [self.displayLink setPaused:NO]; - } - - [self.renderingLayer renderDisplayLayer]; - - if (!self.renderer) { - return; - } - - if ([self.renderer setupView:self]) { - return; - } - - if (self.delegate) { - BOOL delegateFinishedSetup = [self.delegate godotViewFinishedSetup:self]; - - if (!delegateFinishedSetup) { - return; - } - } - - [self handleMotion]; - [self.renderer renderOnView:self]; -} - -- (BOOL)canRender { - if (self.useCADisplayLink) { - return self.displayLink != nil; - } else { - return self.animationTimer != nil; - } -} - -- (void)setRenderingInterval:(NSTimeInterval)renderingInterval { - _renderingInterval = renderingInterval; - - if (self.canRender) { - [self stopRendering]; - [self startRendering]; - } -} - -- (void)layoutSubviews { - if (self.renderingLayer) { - self.renderingLayer.frame = self.bounds; - [self.renderingLayer layoutDisplayLayer]; - - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->resize_window(self.bounds.size); - } - } - - [super layoutSubviews]; -} - -// MARK: - Input - -// MARK: Touches - -- (void)initTouches { - for (int i = 0; i < max_touches; i++) { - godot_touches[i] = nullptr; - } -} - -- (int)getTouchIDForTouch:(UITouch *)p_touch { - int first = -1; - for (int i = 0; i < max_touches; i++) { - if (first == -1 && godot_touches[i] == nullptr) { - first = i; - continue; - } - if (godot_touches[i] == p_touch) { - return i; - } - } - - if (first != -1) { - godot_touches[first] = p_touch; - return first; - } - - return -1; -} - -- (int)removeTouch:(UITouch *)p_touch { - int remaining = 0; - for (int i = 0; i < max_touches; i++) { - if (godot_touches[i] == nullptr) { - continue; - } - if (godot_touches[i] == p_touch) { - godot_touches[i] = nullptr; - } else { - ++remaining; - } - } - return remaining; -} - -- (void)clearTouches { - for (int i = 0; i < max_touches; i++) { - godot_touches[i] = nullptr; - } -} - -- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touchesSet containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); - } - } -} - -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - CGPoint prev_point = [touch previousLocationInView:self]; - DisplayServerIPhone::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor); - } - } -} - -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - [self removeTouch:touch]; - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIPhone::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); - } - } -} - -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - DisplayServerIPhone::get_singleton()->touches_cancelled(tid); - } - } - [self clearTouches]; -} - -// MARK: Motion - -- (void)handleMotion { - if (!self.motionManager) { - return; - } - - // Just using polling approach for now, we can set this up so it sends - // data to us in intervals, might be better. See Apple reference pages - // for more details: - // https://developer.apple.com/reference/coremotion/cmmotionmanager?language=objc - - // Apple splits our accelerometer date into a gravity and user movement - // component. We add them back together. - CMAcceleration gravity = self.motionManager.deviceMotion.gravity; - CMAcceleration acceleration = self.motionManager.deviceMotion.userAcceleration; - - // To be consistent with Android we convert the unit of measurement from g (Earth's gravity) - // to m/s^2. - gravity.x *= earth_gravity; - gravity.y *= earth_gravity; - gravity.z *= earth_gravity; - acceleration.x *= earth_gravity; - acceleration.y *= earth_gravity; - acceleration.z *= earth_gravity; - - ///@TODO We don't seem to be getting data here, is my device broken or - /// is this code incorrect? - CMMagneticField magnetic = self.motionManager.deviceMotion.magneticField.field; - - ///@TODO we can access rotationRate as a CMRotationRate variable - ///(processed date) or CMGyroData (raw data), have to see what works - /// best - CMRotationRate rotation = self.motionManager.deviceMotion.rotationRate; - - // Adjust for screen orientation. - // [[UIDevice currentDevice] orientation] changes even if we've fixed - // our orientation which is not a good thing when you're trying to get - // your user to move the screen in all directions and want consistent - // output - - ///@TODO Using [[UIApplication sharedApplication] statusBarOrientation] - /// is a bit of a hack. Godot obviously knows the orientation so maybe - /// we - // can use that instead? (note that left and right seem swapped) - - UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown; - - if (@available(iOS 13, *)) { - interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; -#endif - } - - switch (interfaceOrientation) { - case UIInterfaceOrientationLandscapeLeft: { - DisplayServerIPhone::get_singleton()->update_gravity(-gravity.y, gravity.x, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.y + gravity.y), (acceleration.x + gravity.x), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.y, magnetic.x, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.y, rotation.x, rotation.z); - } break; - case UIInterfaceOrientationLandscapeRight: { - DisplayServerIPhone::get_singleton()->update_gravity(gravity.y, -gravity.x, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer((acceleration.y + gravity.y), -(acceleration.x + gravity.x), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.y, -magnetic.x, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.y, -rotation.x, rotation.z); - } break; - case UIInterfaceOrientationPortraitUpsideDown: { - DisplayServerIPhone::get_singleton()->update_gravity(-gravity.x, gravity.y, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(-(acceleration.x + gravity.x), (acceleration.y + gravity.y), acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(-magnetic.x, magnetic.y, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(-rotation.x, rotation.y, rotation.z); - } break; - default: { // assume portrait - DisplayServerIPhone::get_singleton()->update_gravity(gravity.x, gravity.y, gravity.z); - DisplayServerIPhone::get_singleton()->update_accelerometer(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z); - DisplayServerIPhone::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z); - DisplayServerIPhone::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z); - } break; - } -} - -@end diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/iphone/godot_view_gesture_recognizer.h deleted file mode 100644 index 9fd8a6b222..0000000000 --- a/platform/iphone/godot_view_gesture_recognizer.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************/ -/* godot_view_gesture_recognizer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -// GLViewGestureRecognizer allows iOS gestures to work correctly by -// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer. -// It catches all gestures incoming to UIView and delays them for 150ms -// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer) -// If touch cancellation or end message is fired it fires delayed -// begin touch immediately as well as last touch signal - -#import <UIKit/UIKit.h> - -@interface GodotViewGestureRecognizer : UIGestureRecognizer - -@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval; - -- (instancetype)init; - -@end diff --git a/platform/iphone/godot_view_gesture_recognizer.mm b/platform/iphone/godot_view_gesture_recognizer.mm deleted file mode 100644 index 49a92add5e..0000000000 --- a/platform/iphone/godot_view_gesture_recognizer.mm +++ /dev/null @@ -1,186 +0,0 @@ -/*************************************************************************/ -/* godot_view_gesture_recognizer.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_view_gesture_recognizer.h" - -#import "godot_view.h" - -#include "core/config/project_settings.h" - -// Minimum distance for touches to move to fire -// a delay timer before scheduled time. -// Should be the low enough to not cause issues with dragging -// but big enough to allow click to work. -const CGFloat kGLGestureMovementDistance = 0.5; - -@interface GodotViewGestureRecognizer () - -@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval; - -@end - -@interface GodotViewGestureRecognizer () - -// Timer used to delay begin touch message. -// Should work as simple emulation of UIDelayedAction -@property(strong, nonatomic) NSTimer *delayTimer; - -// Delayed touch parameters -@property(strong, nonatomic) NSSet *delayedTouches; -@property(strong, nonatomic) UIEvent *delayedEvent; - -@end - -@implementation GodotViewGestureRecognizer - -- (GodotView *)godotView { - return (GodotView *)self.view; -} - -- (instancetype)init { - self = [super init]; - - self.cancelsTouchesInView = YES; - self.delaysTouchesBegan = YES; - self.delaysTouchesEnded = YES; - self.requiresExclusiveTouchType = NO; - - self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay"); - - return self; -} - -- (void)dealloc { - if (self.delayTimer) { - [self.delayTimer invalidate]; - self.delayTimer = nil; - } - - if (self.delayedTouches) { - self.delayedTouches = nil; - } - - if (self.delayedEvent) { - self.delayedEvent = nil; - } -} - -- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event { - [self.delayTimer fire]; - - self.delayedTouches = touches; - self.delayedEvent = event; - - self.delayTimer = [NSTimer - scheduledTimerWithTimeInterval:self.delayTimeInterval - target:self - selector:@selector(fireDelayedTouches:) - userInfo:nil - repeats:NO]; -} - -- (void)fireDelayedTouches:(id)timer { - [self.delayTimer invalidate]; - self.delayTimer = nil; - - if (self.delayedTouches) { - [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent]; - } - - self.delayedTouches = nil; - self.delayedEvent = nil; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan]; - [self delayTouches:cleared andEvent:event]; - - [super touchesBegan:touches withEvent:event]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved]; - - if (self.delayTimer) { - // We should check if movement was significant enough to fire an event - // for dragging to work correctly. - for (UITouch *touch in cleared) { - CGPoint from = [touch locationInView:self.godotView]; - CGPoint to = [touch previousLocationInView:self.godotView]; - CGFloat xDistance = from.x - to.x; - CGFloat yDistance = from.y - to.y; - - CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance); - - // Early exit, since one of touches has moved enough to fire a drag event. - if (distance > kGLGestureMovementDistance) { - [self.delayTimer fire]; - [self.godotView godotTouchesMoved:cleared withEvent:event]; - return; - } - } - - return; - } - - [self.godotView godotTouchesMoved:cleared withEvent:event]; - - [super touchesMoved:touches withEvent:event]; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded]; - [self.godotView godotTouchesEnded:cleared withEvent:event]; - - [super touchesEnded:touches withEvent:event]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - [self.godotView godotTouchesCancelled:touches withEvent:event]; - - [super touchesCancelled:touches withEvent:event]; -} - -- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave { - NSMutableSet *cleared = [touches mutableCopy]; - - for (UITouch *touch in touches) { - if (touch.view != self.view || touch.phase != phaseToSave) { - [cleared removeObject:touch]; - } - } - - return cleared; -} - -@end diff --git a/platform/iphone/godot_view_renderer.h b/platform/iphone/godot_view_renderer.h deleted file mode 100644 index b3ee23ae4f..0000000000 --- a/platform/iphone/godot_view_renderer.h +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************/ -/* godot_view_renderer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -@protocol GodotViewRendererProtocol <NSObject> - -@property(assign, readonly, nonatomic) BOOL hasFinishedSetup; - -- (BOOL)setupView:(UIView *)view; -- (void)renderOnView:(UIView *)view; - -@end - -@interface GodotViewRenderer : NSObject <GodotViewRendererProtocol> - -@end diff --git a/platform/iphone/godot_view_renderer.mm b/platform/iphone/godot_view_renderer.mm deleted file mode 100644 index 32477ae41c..0000000000 --- a/platform/iphone/godot_view_renderer.mm +++ /dev/null @@ -1,118 +0,0 @@ -/*************************************************************************/ -/* godot_view_renderer.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_view_renderer.h" - -#include "core/config/project_settings.h" -#include "core/os/keyboard.h" -#import "display_server_iphone.h" -#include "main/main.h" -#include "os_iphone.h" -#include "servers/audio_server.h" - -#import <AudioToolbox/AudioServices.h> -#import <CoreMotion/CoreMotion.h> -#import <GameController/GameController.h> -#import <QuartzCore/QuartzCore.h> -#import <UIKit/UIKit.h> - -@interface GodotViewRenderer () - -@property(assign, nonatomic) BOOL hasFinishedProjectDataSetup; -@property(assign, nonatomic) BOOL hasStartedMain; -@property(assign, nonatomic) BOOL hasFinishedSetup; - -@end - -@implementation GodotViewRenderer - -- (BOOL)setupView:(UIView *)view { - if (self.hasFinishedSetup) { - return NO; - } - - if (!OS::get_singleton()) { - exit(0); - } - - if (!self.hasFinishedProjectDataSetup) { - [self setupProjectData]; - return YES; - } - - if (!self.hasStartedMain) { - self.hasStartedMain = YES; - OSIPhone::get_singleton()->start(); - return YES; - } - - self.hasFinishedSetup = YES; - - return NO; -} - -- (void)setupProjectData { - self.hasFinishedProjectDataSetup = YES; - - Main::setup2(); - - // this might be necessary before here - NSDictionary *dict = [[NSBundle mainBundle] infoDictionary]; - for (NSString *key in dict) { - NSObject *value = [dict objectForKey:key]; - String ukey = String::utf8([key UTF8String]); - - // we need a NSObject to Variant conversor - - if ([value isKindOfClass:[NSString class]]) { - NSString *str = (NSString *)value; - String uval = String::utf8([str UTF8String]); - - ProjectSettings::get_singleton()->set("Info.plist/" + ukey, uval); - - } else if ([value isKindOfClass:[NSNumber class]]) { - NSNumber *n = (NSNumber *)value; - double dval = [n doubleValue]; - - ProjectSettings::get_singleton()->set("Info.plist/" + ukey, dval); - } - // do stuff - } -} - -- (void)renderOnView:(UIView *)view { - if (!OSIPhone::get_singleton()) { - return; - } - - OSIPhone::get_singleton()->iterate(); -} - -@end diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h deleted file mode 100644 index 0607d7b395..0000000000 --- a/platform/iphone/ios.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************/ -/* ios.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef IOS_H -#define IOS_H - -#include "core/object/class_db.h" -#import <CoreHaptics/CoreHaptics.h> - -class iOS : public Object { - GDCLASS(iOS, Object); - - static void _bind_methods(); - -private: - CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr; - - CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13)); - void start_haptic_engine(); - void stop_haptic_engine(); - -public: - static void alert(const char *p_alert, const char *p_title); - - bool supports_haptic_engine(); - void vibrate_haptic_engine(float p_duration_seconds); - - String get_model() const; - String get_rate_url(int p_app_id) const; - - iOS(); -}; - -#endif diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm deleted file mode 100644 index 79baae028a..0000000000 --- a/platform/iphone/ios.mm +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* ios.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "ios.h" - -#import "app_delegate.h" -#import "view_controller.h" - -#import <CoreHaptics/CoreHaptics.h> -#import <UIKit/UIKit.h> -#include <sys/sysctl.h> - -void iOS::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url); - ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine); - ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine); - ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine); -}; - -bool iOS::supports_haptic_engine() { - if (@available(iOS 13, *)) { - id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware]; - return capabilities.supportsHaptics; - } - - return false; -} - -CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) { - if (haptic_engine == nullptr) { - NSError *error = nullptr; - haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error]; - - if (!error) { - [haptic_engine setAutoShutdownEnabled:true]; - } else { - haptic_engine = nullptr; - NSLog(@"Could not initialize haptic engine: %@", error); - } - } - - return haptic_engine; -} - -void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) { - if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy... - if (supports_haptic_engine()) { - CHHapticEngine *haptic_engine = get_haptic_engine_instance(); - if (haptic_engine) { - NSDictionary *hapticDict = @{ - CHHapticPatternKeyPattern : @[ - @{CHHapticPatternKeyEvent : @{ - CHHapticPatternKeyEventType : CHHapticEventTypeHapticContinuous, - CHHapticPatternKeyTime : @(CHHapticTimeImmediate), - CHHapticPatternKeyEventDuration : @(p_duration_seconds) - }, - }, - ], - }; - - NSError *error; - CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error]; - - [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error]; - - NSLog(@"Could not vibrate using haptic engine: %@", error); - } - - return; - } - } - - NSLog(@"Haptic engine is not supported in this version of iOS"); -} - -void iOS::start_haptic_engine() { - if (@available(iOS 13, *)) { - if (supports_haptic_engine()) { - CHHapticEngine *haptic_engine = get_haptic_engine_instance(); - if (haptic_engine) { - [haptic_engine startWithCompletionHandler:^(NSError *returnedError) { - if (returnedError) { - NSLog(@"Could not start haptic engine: %@", returnedError); - } - }]; - } - - return; - } - } - - NSLog(@"Haptic engine is not supported in this version of iOS"); -} - -void iOS::stop_haptic_engine() { - if (@available(iOS 13, *)) { - if (supports_haptic_engine()) { - CHHapticEngine *haptic_engine = get_haptic_engine_instance(); - if (haptic_engine) { - [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) { - if (returnedError) { - NSLog(@"Could not stop haptic engine: %@", returnedError); - } - }]; - } - - return; - } - } - - NSLog(@"Haptic engine is not supported in this version of iOS"); -} - -void iOS::alert(const char *p_alert, const char *p_title) { - NSString *title = [NSString stringWithUTF8String:p_title]; - NSString *message = [NSString stringWithUTF8String:p_alert]; - - UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *button = [UIAlertAction actionWithTitle:@"OK" - style:UIAlertActionStyleCancel - handler:^(id){ - }]; - - [alert addAction:button]; - - [AppDelegate.viewController presentViewController:alert animated:YES completion:nil]; -} - -String iOS::get_model() const { - // [[UIDevice currentDevice] model] only returns "iPad" or "iPhone". - size_t size; - sysctlbyname("hw.machine", nullptr, &size, nullptr, 0); - char *model = (char *)malloc(size); - if (model == nullptr) { - return ""; - } - sysctlbyname("hw.machine", model, &size, nullptr, 0); - NSString *platform = [NSString stringWithCString:model encoding:NSUTF8StringEncoding]; - free(model); - const char *str = [platform UTF8String]; - return String::utf8(str != nullptr ? str : ""); -} - -String iOS::get_rate_url(int p_app_id) const { - String app_url_path = "itms-apps://itunes.apple.com/app/idAPP_ID"; - - String ret = app_url_path.replace("APP_ID", String::num(p_app_id)); - - printf("returning rate url %s\n", ret.utf8().get_data()); - return ret; -} - -iOS::iOS() {} diff --git a/platform/iphone/joypad_iphone.h b/platform/iphone/joypad_iphone.h deleted file mode 100644 index 37e272a2c9..0000000000 --- a/platform/iphone/joypad_iphone.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* joypad_iphone.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <GameController/GameController.h> - -@interface JoypadIPhoneObserver : NSObject - -- (void)startObserving; -- (void)startProcessing; -- (void)finishObserving; - -@end - -class JoypadIPhone { -private: - JoypadIPhoneObserver *observer; - -public: - JoypadIPhone(); - ~JoypadIPhone(); - - void start_processing(); -}; diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm deleted file mode 100644 index 9c2feeaaca..0000000000 --- a/platform/iphone/joypad_iphone.mm +++ /dev/null @@ -1,344 +0,0 @@ -/*************************************************************************/ -/* joypad_iphone.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "joypad_iphone.h" - -#include "core/config/project_settings.h" -#include "drivers/coreaudio/audio_driver_coreaudio.h" -#include "main/main.h" - -#import "godot_view.h" - -#include "os_iphone.h" - -JoypadIPhone::JoypadIPhone() { - observer = [[JoypadIPhoneObserver alloc] init]; - [observer startObserving]; -} - -JoypadIPhone::~JoypadIPhone() { - if (observer) { - [observer finishObserving]; - observer = nil; - } -} - -void JoypadIPhone::start_processing() { - if (observer) { - [observer startProcessing]; - } -} - -@interface JoypadIPhoneObserver () - -@property(assign, nonatomic) BOOL isObserving; -@property(assign, nonatomic) BOOL isProcessing; -@property(strong, nonatomic) NSMutableDictionary *connectedJoypads; -@property(strong, nonatomic) NSMutableArray *joypadsQueue; - -@end - -@implementation JoypadIPhoneObserver - -- (instancetype)init { - self = [super init]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.isObserving = NO; - self.isProcessing = NO; -} - -- (void)startProcessing { - self.isProcessing = YES; - - for (GCController *controller in self.joypadsQueue) { - [self addiOSJoypad:controller]; - } - - [self.joypadsQueue removeAllObjects]; -} - -- (void)startObserving { - if (self.isObserving) { - return; - } - - self.isObserving = YES; - - self.connectedJoypads = [NSMutableDictionary dictionary]; - self.joypadsQueue = [NSMutableArray array]; - - // get told when controllers connect, this will be called right away for - // already connected controllers - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(controllerWasConnected:) - name:GCControllerDidConnectNotification - object:nil]; - - // get told when controllers disconnect - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(controllerWasDisconnected:) - name:GCControllerDidDisconnectNotification - object:nil]; -} - -- (void)finishObserving { - if (self.isObserving) { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - } - - self.isObserving = NO; - self.isProcessing = NO; - - self.connectedJoypads = nil; - self.joypadsQueue = nil; -} - -- (void)dealloc { - [self finishObserving]; -} - -- (int)getJoyIdForController:(GCController *)controller { - NSArray *keys = [self.connectedJoypads allKeysForObject:controller]; - - for (NSNumber *key in keys) { - int joy_id = [key intValue]; - return joy_id; - } - - return -1; -} - -- (void)addiOSJoypad:(GCController *)controller { - // get a new id for our controller - int joy_id = Input::get_singleton()->get_unused_joy_id(); - - if (joy_id == -1) { - printf("Couldn't retrieve new joy id\n"); - return; - } - - // assign our player index - if (controller.playerIndex == GCControllerPlayerIndexUnset) { - controller.playerIndex = [self getFreePlayerIndex]; - } - - // tell Godot about our new controller - Input::get_singleton()->joy_connection_changed(joy_id, true, String::utf8([controller.vendorName UTF8String])); - - // add it to our dictionary, this will retain our controllers - [self.connectedJoypads setObject:controller forKey:[NSNumber numberWithInt:joy_id]]; - - // set our input handler - [self setControllerInputHandler:controller]; -} - -- (void)controllerWasConnected:(NSNotification *)notification { - // get our controller - GCController *controller = (GCController *)notification.object; - - if (!controller) { - printf("Couldn't retrieve new controller\n"); - return; - } - - if ([[self.connectedJoypads allKeysForObject:controller] count] > 0) { - printf("Controller is already registered\n"); - } else if (!self.isProcessing) { - [self.joypadsQueue addObject:controller]; - } else { - [self addiOSJoypad:controller]; - } -} - -- (void)controllerWasDisconnected:(NSNotification *)notification { - // find our joystick, there should be only one in our dictionary - GCController *controller = (GCController *)notification.object; - - if (!controller) { - return; - } - - NSArray *keys = [self.connectedJoypads allKeysForObject:controller]; - for (NSNumber *key in keys) { - // tell Godot this joystick is no longer there - int joy_id = [key intValue]; - Input::get_singleton()->joy_connection_changed(joy_id, false, ""); - - // and remove it from our dictionary - [self.connectedJoypads removeObjectForKey:key]; - } -} - -- (GCControllerPlayerIndex)getFreePlayerIndex { - bool have_player_1 = false; - bool have_player_2 = false; - bool have_player_3 = false; - bool have_player_4 = false; - - if (self.connectedJoypads == nil) { - NSArray *keys = [self.connectedJoypads allKeys]; - for (NSNumber *key in keys) { - GCController *controller = [self.connectedJoypads objectForKey:key]; - if (controller.playerIndex == GCControllerPlayerIndex1) { - have_player_1 = true; - } else if (controller.playerIndex == GCControllerPlayerIndex2) { - have_player_2 = true; - } else if (controller.playerIndex == GCControllerPlayerIndex3) { - have_player_3 = true; - } else if (controller.playerIndex == GCControllerPlayerIndex4) { - have_player_4 = true; - } - } - } - - if (!have_player_1) { - return GCControllerPlayerIndex1; - } else if (!have_player_2) { - return GCControllerPlayerIndex2; - } else if (!have_player_3) { - return GCControllerPlayerIndex3; - } else if (!have_player_4) { - return GCControllerPlayerIndex4; - } else { - return GCControllerPlayerIndexUnset; - } -} - -- (void)setControllerInputHandler:(GCController *)controller { - // Hook in the callback handler for the correct gamepad profile. - // This is a bit of a weird design choice on Apples part. - // You need to select the most capable gamepad profile for the - // gamepad attached. - if (controller.extendedGamepad != nil) { - // The extended gamepad profile has all the input you could possibly find on - // a gamepad but will only be active if your gamepad actually has all of - // these... - _weakify(self); - _weakify(controller); - - controller.extendedGamepad.valueChangedHandler = ^(GCExtendedGamepad *gamepad, GCControllerElement *element) { - _strongify(self); - _strongify(controller); - - int joy_id = [self getJoyIdForController:controller]; - - if (element == gamepad.buttonA) { - Input::get_singleton()->joy_button(joy_id, JoyButton::A, - gamepad.buttonA.isPressed); - } else if (element == gamepad.buttonB) { - Input::get_singleton()->joy_button(joy_id, JoyButton::B, - gamepad.buttonB.isPressed); - } else if (element == gamepad.buttonX) { - Input::get_singleton()->joy_button(joy_id, JoyButton::X, - gamepad.buttonX.isPressed); - } else if (element == gamepad.buttonY) { - Input::get_singleton()->joy_button(joy_id, JoyButton::Y, - gamepad.buttonY.isPressed); - } else if (element == gamepad.leftShoulder) { - Input::get_singleton()->joy_button(joy_id, JoyButton::LEFT_SHOULDER, - gamepad.leftShoulder.isPressed); - } else if (element == gamepad.rightShoulder) { - Input::get_singleton()->joy_button(joy_id, JoyButton::RIGHT_SHOULDER, - gamepad.rightShoulder.isPressed); - } else if (element == gamepad.dpad) { - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_UP, - gamepad.dpad.up.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_DOWN, - gamepad.dpad.down.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_LEFT, - gamepad.dpad.left.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT, - gamepad.dpad.right.isPressed); - } - - if (element == gamepad.leftThumbstick) { - float value = gamepad.leftThumbstick.xAxis.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_X, value); - value = -gamepad.leftThumbstick.yAxis.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_Y, value); - } else if (element == gamepad.rightThumbstick) { - float value = gamepad.rightThumbstick.xAxis.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_X, value); - value = -gamepad.rightThumbstick.yAxis.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_Y, value); - } else if (element == gamepad.leftTrigger) { - float value = gamepad.leftTrigger.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_LEFT, value); - } else if (element == gamepad.rightTrigger) { - float value = gamepad.rightTrigger.value; - Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value); - } - }; - } else if (controller.microGamepad != nil) { - // micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad - _weakify(self); - _weakify(controller); - - controller.microGamepad.valueChangedHandler = ^(GCMicroGamepad *gamepad, GCControllerElement *element) { - _strongify(self); - _strongify(controller); - - int joy_id = [self getJoyIdForController:controller]; - - if (element == gamepad.buttonA) { - Input::get_singleton()->joy_button(joy_id, JoyButton::A, - gamepad.buttonA.isPressed); - } else if (element == gamepad.buttonX) { - Input::get_singleton()->joy_button(joy_id, JoyButton::X, - gamepad.buttonX.isPressed); - } else if (element == gamepad.dpad) { - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_UP, - gamepad.dpad.up.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_DOWN, - gamepad.dpad.down.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_LEFT, gamepad.dpad.left.isPressed); - Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT, gamepad.dpad.right.isPressed); - } - }; - } - - ///@TODO need to add support for controller.motion which gives us access to - /// the orientation of the device (if supported) - - ///@TODO need to add support for controllerPausedHandler which should be a - /// toggle -} - -@end diff --git a/platform/iphone/keyboard_input_view.h b/platform/iphone/keyboard_input_view.h deleted file mode 100644 index 33fa5d571a..0000000000 --- a/platform/iphone/keyboard_input_view.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************/ -/* keyboard_input_view.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -@interface GodotKeyboardInputView : UITextView - -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; - -@end diff --git a/platform/iphone/keyboard_input_view.mm b/platform/iphone/keyboard_input_view.mm deleted file mode 100644 index f2a7b22483..0000000000 --- a/platform/iphone/keyboard_input_view.mm +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************/ -/* keyboard_input_view.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "keyboard_input_view.h" - -#include "core/os/keyboard.h" -#include "display_server_iphone.h" -#include "os_iphone.h" - -@interface GodotKeyboardInputView () <UITextViewDelegate> - -@property(nonatomic, copy) NSString *previousText; -@property(nonatomic, assign) NSRange previousSelectedRange; - -@end - -@implementation GodotKeyboardInputView - -- (instancetype)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer { - self = [super initWithFrame:frame textContainer:textContainer]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.hidden = YES; - self.delegate = self; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(observeTextChange:) - name:UITextViewTextDidChangeNotification - object:self]; -} - -- (void)dealloc { - self.delegate = nil; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -// MARK: Keyboard - -- (BOOL)canBecomeFirstResponder { - return YES; -} - -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end { - self.text = existingString; - self.previousText = existingString; - - NSInteger safeStartIndex = MAX(start, 0); - - NSRange textRange; - - // Either a simple cursor or a selection. - if (end > 0) { - textRange = NSMakeRange(safeStartIndex, end - start); - } else { - textRange = NSMakeRange(safeStartIndex, 0); - } - - self.selectedRange = textRange; - self.previousSelectedRange = textRange; - - return [self becomeFirstResponder]; -} - -- (BOOL)resignFirstResponder { - self.text = nil; - self.previousText = nil; - return [super resignFirstResponder]; -} - -// MARK: OS Messages - -- (void)deleteText:(NSInteger)charactersToDelete { - for (int i = 0; i < charactersToDelete; i++) { - DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, true); - DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, false); - } -} - -- (void)enterText:(NSString *)substring { - String characters; - characters.parse_utf8([substring UTF8String]); - - for (int i = 0; i < characters.size(); i++) { - int character = characters[i]; - - switch (character) { - case 10: - character = (int)Key::ENTER; - break; - case 8198: - character = (int)Key::SPACE; - break; - default: - break; - } - - DisplayServerIPhone::get_singleton()->key((Key)character, true); - DisplayServerIPhone::get_singleton()->key((Key)character, false); - } -} - -// MARK: Observer - -- (void)observeTextChange:(NSNotification *)notification { - if (notification.object != self) { - return; - } - - if (self.previousSelectedRange.length == 0) { - // We are deleting all text before cursor if no range was selected. - // This way any inserted or changed text will be updated. - NSString *substringToDelete = [self.previousText substringToIndex:self.previousSelectedRange.location]; - [self deleteText:substringToDelete.length]; - } else { - // If text was previously selected - // we are sending only one `backspace`. - // It will remove all text from text input. - [self deleteText:1]; - } - - NSString *substringToEnter; - - if (self.selectedRange.length == 0) { - // If previous cursor had a selection - // we have to calculate an inserted text. - if (self.previousSelectedRange.length != 0) { - NSInteger rangeEnd = self.selectedRange.location + self.selectedRange.length; - NSInteger rangeStart = MIN(self.previousSelectedRange.location, self.selectedRange.location); - NSInteger rangeLength = MAX(0, rangeEnd - rangeStart); - - NSRange calculatedRange; - - if (rangeLength >= 0) { - calculatedRange = NSMakeRange(rangeStart, rangeLength); - } else { - calculatedRange = NSMakeRange(rangeStart, 0); - } - - substringToEnter = [self.text substringWithRange:calculatedRange]; - } else { - substringToEnter = [self.text substringToIndex:self.selectedRange.location]; - } - } else { - substringToEnter = [self.text substringWithRange:self.selectedRange]; - } - - [self enterText:substringToEnter]; - - self.previousText = self.text; - self.previousSelectedRange = self.selectedRange; -} - -@end diff --git a/platform/iphone/logo.png b/platform/iphone/logo.png Binary files differdeleted file mode 100644 index 966d8aa70a..0000000000 --- a/platform/iphone/logo.png +++ /dev/null diff --git a/platform/iphone/main.m b/platform/iphone/main.m deleted file mode 100644 index acfa7ab731..0000000000 --- a/platform/iphone/main.m +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* main.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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_app_delegate.h" - -#import <UIKit/UIKit.h> -#include <stdio.h> - -int gargc; -char **gargv; - -int main(int argc, char *argv[]) { -#if defined(VULKAN_ENABLED) - //MoltenVK - enable full component swizzling support - setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); -#endif - - printf("*********** main.m\n"); - gargc = argc; - gargv = argv; - - printf("running app main\n"); - @autoreleasepool { - NSString *className = NSStringFromClass([GodotApplicalitionDelegate class]); - UIApplicationMain(argc, argv, nil, className); - } - printf("main done\n"); - return 0; -} diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h deleted file mode 100644 index d03403bbb4..0000000000 --- a/platform/iphone/os_iphone.h +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************/ -/* os_iphone.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifdef IPHONE_ENABLED - -#ifndef OS_IPHONE_H -#define OS_IPHONE_H - -#include "drivers/coreaudio/audio_driver_coreaudio.h" -#include "drivers/unix/os_unix.h" -#include "ios.h" -#include "joypad_iphone.h" -#include "servers/audio_server.h" -#include "servers/rendering/renderer_compositor.h" - -#if defined(VULKAN_ENABLED) -#include "drivers/vulkan/rendering_device_vulkan.h" -#include "platform/iphone/vulkan_context_iphone.h" -#endif - -class OSIPhone : public OS_Unix { -private: - static HashMap<String, void *> dynamic_symbol_lookup_table; - friend void register_dynamic_symbol(char *name, void *address); - - AudioDriverCoreAudio audio_driver; - - iOS *ios = nullptr; - - JoypadIPhone *joypad_iphone = nullptr; - - MainLoop *main_loop = nullptr; - - virtual void initialize_core() override; - virtual void initialize() override; - - virtual void initialize_joypads() override { - } - - virtual void set_main_loop(MainLoop *p_main_loop) override; - virtual MainLoop *get_main_loop() const override; - - virtual void delete_main_loop() override; - - virtual void finalize() override; - - String user_data_dir; - String cache_dir; - - bool is_focused = false; - - void deinitialize_modules(); - -public: - static OSIPhone *get_singleton(); - - OSIPhone(String p_data_dir, String p_cache_dir); - ~OSIPhone(); - - void initialize_modules(); - - bool iterate(); - - void start(); - - virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; - - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override; - virtual Error close_dynamic_library(void *p_library_handle) override; - virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override; - - virtual String get_name() const override; - virtual String get_model_name() const override; - - virtual Error shell_open(String p_uri) override; - - void set_user_data_dir(String p_dir); - virtual String get_user_data_dir() const override; - - virtual String get_cache_path() const override; - - virtual String get_locale() const override; - - virtual String get_unique_id() const override; - virtual String get_processor_name() const override; - - virtual void vibrate_handheld(int p_duration_ms = 500) override; - - virtual bool _check_internal_feature_support(const String &p_feature) override; - - void on_focus_out(); - void on_focus_in(); -}; - -#endif // OS_IPHONE_H - -#endif // IPHONE_ENABLED diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm deleted file mode 100644 index 95b06b728e..0000000000 --- a/platform/iphone/os_iphone.mm +++ /dev/null @@ -1,346 +0,0 @@ -/*************************************************************************/ -/* os_iphone.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifdef IPHONE_ENABLED - -#include "os_iphone.h" - -#import "app_delegate.h" -#include "core/config/project_settings.h" -#include "core/io/dir_access.h" -#include "core/io/file_access.h" -#include "core/io/file_access_pack.h" -#include "display_server_iphone.h" -#include "drivers/unix/syslog_logger.h" -#import "godot_view.h" -#include "main/main.h" -#import "view_controller.h" - -#import <AudioToolbox/AudioServices.h> -#import <UIKit/UIKit.h> -#import <dlfcn.h> -#include <sys/sysctl.h> - -#if defined(VULKAN_ENABLED) -#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" -#import <QuartzCore/CAMetalLayer.h> -#ifdef USE_VOLK -#include <volk.h> -#else -#include <vulkan/vulkan.h> -#endif -#endif - -// Initialization order between compilation units is not guaranteed, -// so we use this as a hack to ensure certain code is called before -// everything else, but after all units are initialized. -typedef void (*init_callback)(); -static init_callback *ios_init_callbacks = nullptr; -static int ios_init_callbacks_count = 0; -static int ios_init_callbacks_capacity = 0; -HashMap<String, void *> OSIPhone::dynamic_symbol_lookup_table; - -void add_ios_init_callback(init_callback cb) { - if (ios_init_callbacks_count == ios_init_callbacks_capacity) { - void *new_ptr = realloc(ios_init_callbacks, sizeof(cb) * 32); - if (new_ptr) { - ios_init_callbacks = (init_callback *)(new_ptr); - ios_init_callbacks_capacity += 32; - } - } - if (ios_init_callbacks_capacity > ios_init_callbacks_count) { - ios_init_callbacks[ios_init_callbacks_count] = cb; - ++ios_init_callbacks_count; - } -} - -void register_dynamic_symbol(char *name, void *address) { - OSIPhone::dynamic_symbol_lookup_table[String(name)] = address; -} - -OSIPhone *OSIPhone::get_singleton() { - return (OSIPhone *)OS::get_singleton(); -} - -OSIPhone::OSIPhone(String p_data_dir, String p_cache_dir) { - for (int i = 0; i < ios_init_callbacks_count; ++i) { - ios_init_callbacks[i](); - } - free(ios_init_callbacks); - ios_init_callbacks = nullptr; - ios_init_callbacks_count = 0; - ios_init_callbacks_capacity = 0; - - main_loop = nullptr; - - // can't call set_data_dir from here, since it requires DirAccess - // which is initialized in initialize_core - user_data_dir = p_data_dir; - cache_dir = p_cache_dir; - - Vector<Logger *> loggers; - loggers.push_back(memnew(SyslogLogger)); -#ifdef DEBUG_ENABLED - // it seems iOS app's stdout/stderr is only obtainable if you launch it from - // Xcode - loggers.push_back(memnew(StdLogger)); -#endif - _set_logger(memnew(CompositeLogger(loggers))); - - AudioDriverManager::add_driver(&audio_driver); - - DisplayServerIPhone::register_iphone_driver(); -} - -OSIPhone::~OSIPhone() {} - -void OSIPhone::alert(const String &p_alert, const String &p_title) { - const CharString utf8_alert = p_alert.utf8(); - const CharString utf8_title = p_title.utf8(); - iOS::alert(utf8_alert.get_data(), utf8_title.get_data()); -} - -void OSIPhone::initialize_core() { - OS_Unix::initialize_core(); - - set_user_data_dir(user_data_dir); -} - -void OSIPhone::initialize() { - initialize_core(); -} - -void OSIPhone::initialize_modules() { - ios = memnew(iOS); - Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios)); - - joypad_iphone = memnew(JoypadIPhone); -} - -void OSIPhone::deinitialize_modules() { - if (joypad_iphone) { - memdelete(joypad_iphone); - } - - if (ios) { - memdelete(ios); - } -} - -void OSIPhone::set_main_loop(MainLoop *p_main_loop) { - main_loop = p_main_loop; - - if (main_loop) { - main_loop->initialize(); - } -} - -MainLoop *OSIPhone::get_main_loop() const { - return main_loop; -} - -void OSIPhone::delete_main_loop() { - if (main_loop) { - main_loop->finalize(); - memdelete(main_loop); - } - - main_loop = nullptr; -} - -bool OSIPhone::iterate() { - if (!main_loop) { - return true; - } - - if (DisplayServer::get_singleton()) { - DisplayServer::get_singleton()->process_events(); - } - - return Main::iteration(); -} - -void OSIPhone::start() { - Main::start(); - - if (joypad_iphone) { - joypad_iphone->start_processing(); - } -} - -void OSIPhone::finalize() { - deinitialize_modules(); - - // Already gets called - //delete_main_loop(); -} - -// MARK: Dynamic Libraries - -Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { - if (p_path.length() == 0) { - p_library_handle = RTLD_SELF; - - if (r_resolved_path != nullptr) { - *r_resolved_path = p_path; - } - - return OK; - } - return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path); -} - -Error OSIPhone::close_dynamic_library(void *p_library_handle) { - if (p_library_handle == RTLD_SELF) { - return OK; - } - return OS_Unix::close_dynamic_library(p_library_handle); -} - -Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { - if (p_library_handle == RTLD_SELF) { - void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name); - if (ptr) { - p_symbol_handle = *ptr; - return OK; - } - } - return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional); -} - -String OSIPhone::get_name() const { - return "iOS"; -} - -String OSIPhone::get_model_name() const { - String model = ios->get_model(); - if (model != "") { - return model; - } - - return OS_Unix::get_model_name(); -} - -Error OSIPhone::shell_open(String p_uri) { - NSString *urlPath = [[NSString alloc] initWithUTF8String:p_uri.utf8().get_data()]; - NSURL *url = [NSURL URLWithString:urlPath]; - - if (![[UIApplication sharedApplication] canOpenURL:url]) { - return ERR_CANT_OPEN; - } - - printf("opening url %s\n", p_uri.utf8().get_data()); - - [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; - - return OK; -} - -void OSIPhone::set_user_data_dir(String p_dir) { - Ref<DirAccess> da = DirAccess::open(p_dir); - user_data_dir = da->get_current_dir(); - printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data()); -} - -String OSIPhone::get_user_data_dir() const { - return user_data_dir; -} - -String OSIPhone::get_cache_path() const { - return cache_dir; -} - -String OSIPhone::get_locale() const { - NSString *preferedLanguage = [NSLocale preferredLanguages].firstObject; - - if (preferedLanguage) { - return String::utf8([preferedLanguage UTF8String]).replace("-", "_"); - } - - NSString *localeIdentifier = [[NSLocale currentLocale] localeIdentifier]; - return String::utf8([localeIdentifier UTF8String]).replace("-", "_"); -} - -String OSIPhone::get_unique_id() const { - NSString *uuid = [UIDevice currentDevice].identifierForVendor.UUIDString; - return String::utf8([uuid UTF8String]); -} - -String OSIPhone::get_processor_name() const { - char buffer[256]; - size_t buffer_len = 256; - if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) { - return String::utf8(buffer, buffer_len); - } - ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string.")); -} - -void OSIPhone::vibrate_handheld(int p_duration_ms) { - if (ios->supports_haptic_engine()) { - ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f); - } else { - // iOS <13 does not support duration for vibration - AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); - } -} - -bool OSIPhone::_check_internal_feature_support(const String &p_feature) { - return p_feature == "mobile"; -} - -void OSIPhone::on_focus_out() { - if (is_focused) { - is_focused = false; - - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); - } - - [AppDelegate.viewController.godotView stopRendering]; - - audio_driver.stop(); - } -} - -void OSIPhone::on_focus_in() { - if (!is_focused) { - is_focused = true; - - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); - } - - [AppDelegate.viewController.godotView startRendering]; - - audio_driver.start(); - } -} - -#endif // IPHONE_ENABLED diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h deleted file mode 100644 index fed77d8932..0000000000 --- a/platform/iphone/platform_config.h +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************/ -/* platform_config.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include <alloca.h> - -#define OPENGL_INCLUDE_H <ES3/gl.h> - -#define PLATFORM_REFCOUNT - -#define PTHREAD_RENAME_SELF - -#define _weakify(var) __weak typeof(var) GDWeak_##var = var; -#define _strongify(var) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wshadow\"") \ - __strong typeof(var) var = GDWeak_##var; \ - _Pragma("clang diagnostic pop") diff --git a/platform/iphone/tts_ios.h b/platform/iphone/tts_ios.h deleted file mode 100644 index 064316b0b2..0000000000 --- a/platform/iphone/tts_ios.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************/ -/* tts_ios.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef TTS_IOS_H -#define TTS_IOS_H - -#if __has_include(<AVFAudio/AVSpeechSynthesis.h>) -#import <AVFAudio/AVSpeechSynthesis.h> -#else -#import <AVFoundation/AVFoundation.h> -#endif - -#include "core/string/ustring.h" -#include "core/templates/list.h" -#include "core/templates/rb_map.h" -#include "core/variant/array.h" -#include "servers/display_server.h" - -@interface TTS_IOS : NSObject <AVSpeechSynthesizerDelegate> { - bool speaking; - HashMap<id, int> ids; - - AVSpeechSynthesizer *av_synth; - List<DisplayServer::TTSUtterance> queue; -} - -- (void)pauseSpeaking; -- (void)resumeSpeaking; -- (void)stopSpeaking; -- (bool)isSpeaking; -- (bool)isPaused; -- (void)speak:(const String &)text voice:(const String &)voice volume:(int)volume pitch:(float)pitch rate:(float)rate utterance_id:(int)utterance_id interrupt:(bool)interrupt; -- (Array)getVoices; -@end - -#endif // TTS_IOS_H diff --git a/platform/iphone/tts_ios.mm b/platform/iphone/tts_ios.mm deleted file mode 100644 index a079d02add..0000000000 --- a/platform/iphone/tts_ios.mm +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************/ -/* tts_ios.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "tts_ios.h" - -@implementation TTS_IOS - -- (id)init { - self = [super init]; - self->speaking = false; - self->av_synth = [[AVSpeechSynthesizer alloc] init]; - [self->av_synth setDelegate:self]; - print_verbose("Text-to-Speech: AVSpeechSynthesizer initialized."); - return self; -} - -- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance { - NSString *string = [utterance speechString]; - - // Convert from UTF-16 to UTF-32 position. - int pos = 0; - for (NSUInteger i = 0; i < MIN(characterRange.location, string.length); i++) { - unichar c = [string characterAtIndex:i]; - if ((c & 0xfffffc00) == 0xd800) { - i++; - } - pos++; - } - - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_BOUNDARY, ids[utterance], pos); -} - -- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth didCancelSpeechUtterance:(AVSpeechUtterance *)utterance { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, ids[utterance]); - ids.erase(utterance); - speaking = false; - [self update]; -} - -- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth didFinishSpeechUtterance:(AVSpeechUtterance *)utterance { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, ids[utterance]); - ids.erase(utterance); - speaking = false; - [self update]; -} - -- (void)update { - if (!speaking && queue.size() > 0) { - DisplayServer::TTSUtterance &message = queue.front()->get(); - - AVSpeechUtterance *new_utterance = [[AVSpeechUtterance alloc] initWithString:[NSString stringWithUTF8String:message.text.utf8().get_data()]]; - [new_utterance setVoice:[AVSpeechSynthesisVoice voiceWithIdentifier:[NSString stringWithUTF8String:message.voice.utf8().get_data()]]]; - if (message.rate > 1.f) { - [new_utterance setRate:Math::range_lerp(message.rate, 1.f, 10.f, AVSpeechUtteranceDefaultSpeechRate, AVSpeechUtteranceMaximumSpeechRate)]; - } else if (message.rate < 1.f) { - [new_utterance setRate:Math::range_lerp(message.rate, 0.1f, 1.f, AVSpeechUtteranceMinimumSpeechRate, AVSpeechUtteranceDefaultSpeechRate)]; - } - [new_utterance setPitchMultiplier:message.pitch]; - [new_utterance setVolume:(Math::range_lerp(message.volume, 0.f, 100.f, 0.f, 1.f))]; - - ids[new_utterance] = message.id; - [av_synth speakUtterance:new_utterance]; - - queue.pop_front(); - - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_STARTED, message.id); - speaking = true; - } -} - -- (void)pauseSpeaking { - [av_synth pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate]; -} - -- (void)resumeSpeaking { - [av_synth continueSpeaking]; -} - -- (void)stopSpeaking { - for (DisplayServer::TTSUtterance &message : queue) { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, message.id); - } - queue.clear(); - [av_synth stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; - speaking = false; -} - -- (bool)isSpeaking { - return speaking || (queue.size() > 0); -} - -- (bool)isPaused { - return [av_synth isPaused]; -} - -- (void)speak:(const String &)text voice:(const String &)voice volume:(int)volume pitch:(float)pitch rate:(float)rate utterance_id:(int)utterance_id interrupt:(bool)interrupt { - if (interrupt) { - [self stopSpeaking]; - } - - if (text.is_empty()) { - DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, utterance_id); - return; - } - - DisplayServer::TTSUtterance message; - message.text = text; - message.voice = voice; - message.volume = CLAMP(volume, 0, 100); - message.pitch = CLAMP(pitch, 0.f, 2.f); - message.rate = CLAMP(rate, 0.1f, 10.f); - message.id = utterance_id; - queue.push_back(message); - - if ([self isPaused]) { - [self resumeSpeaking]; - } else { - [self update]; - } -} - -- (Array)getVoices { - Array list; - for (AVSpeechSynthesisVoice *voice in [AVSpeechSynthesisVoice speechVoices]) { - NSString *voiceIdentifierString = [voice identifier]; - NSString *voiceLocaleIdentifier = [voice language]; - NSString *voiceName = [voice name]; - Dictionary voice_d; - voice_d["name"] = String::utf8([voiceName UTF8String]); - voice_d["id"] = String::utf8([voiceIdentifierString UTF8String]); - voice_d["language"] = String::utf8([voiceLocaleIdentifier UTF8String]); - list.push_back(voice_d); - } - return list; -} - -@end diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h deleted file mode 100644 index c8b37a4d11..0000000000 --- a/platform/iphone/view_controller.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************/ -/* view_controller.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 <UIKit/UIKit.h> - -@class GodotView; -@class GodotNativeVideoView; -@class GodotKeyboardInputView; - -@interface ViewController : UIViewController - -@property(nonatomic, readonly, strong) GodotView *godotView; -@property(nonatomic, readonly, strong) GodotKeyboardInputView *keyboardView; - -@end diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm deleted file mode 100644 index 4f4ef4f046..0000000000 --- a/platform/iphone/view_controller.mm +++ /dev/null @@ -1,240 +0,0 @@ -/*************************************************************************/ -/* view_controller.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "view_controller.h" -#include "core/config/project_settings.h" -#include "display_server_iphone.h" -#import "godot_view.h" -#import "godot_view_renderer.h" -#import "keyboard_input_view.h" -#include "os_iphone.h" - -#import <AVFoundation/AVFoundation.h> -#import <GameController/GameController.h> - -@interface ViewController () <GodotViewDelegate> - -@property(strong, nonatomic) GodotViewRenderer *renderer; -@property(strong, nonatomic) GodotKeyboardInputView *keyboardView; - -@property(strong, nonatomic) UIView *godotLoadingOverlay; - -@end - -@implementation ViewController - -- (GodotView *)godotView { - return (GodotView *)self.view; -} - -- (void)loadView { - GodotView *view = [[GodotView alloc] init]; - GodotViewRenderer *renderer = [[GodotViewRenderer alloc] init]; - - self.renderer = renderer; - self.view = view; - - view.renderer = self.renderer; - view.delegate = self; -} - -- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - // Initialize view controller values. -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - printf("*********** did receive memory warning!\n"); -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - [self observeKeyboard]; - [self displayLoadingOverlay]; - - if (@available(iOS 11.0, *)) { - [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; - } -} - -- (void)observeKeyboard { - printf("******** setting up keyboard input view\n"); - self.keyboardView = [GodotKeyboardInputView new]; - [self.view addSubview:self.keyboardView]; - - printf("******** adding observer for keyboard show/hide\n"); - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardOnScreen:) - name:UIKeyboardDidShowNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardHidden:) - name:UIKeyboardDidHideNotification - object:nil]; -} - -- (void)displayLoadingOverlay { - NSBundle *bundle = [NSBundle mainBundle]; - NSString *storyboardName = @"Launch Screen"; - - if ([bundle pathForResource:storyboardName ofType:@"storyboardc"] == nil) { - return; - } - - UIStoryboard *launchStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:bundle]; - - UIViewController *controller = [launchStoryboard instantiateInitialViewController]; - self.godotLoadingOverlay = controller.view; - self.godotLoadingOverlay.frame = self.view.bounds; - self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - - [self.view addSubview:self.godotLoadingOverlay]; -} - -- (BOOL)godotViewFinishedSetup:(GodotView *)view { - [self.godotLoadingOverlay removeFromSuperview]; - self.godotLoadingOverlay = nil; - - return YES; -} - -- (void)dealloc { - self.keyboardView = nil; - - self.renderer = nil; - - if (self.godotLoadingOverlay) { - [self.godotLoadingOverlay removeFromSuperview]; - self.godotLoadingOverlay = nil; - } - - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -// MARK: Orientation - -- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { - return UIRectEdgeAll; -} - -- (BOOL)shouldAutorotate { - if (!DisplayServerIPhone::get_singleton()) { - return NO; - } - - switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { - case DisplayServer::SCREEN_SENSOR: - case DisplayServer::SCREEN_SENSOR_LANDSCAPE: - case DisplayServer::SCREEN_SENSOR_PORTRAIT: - return YES; - default: - return NO; - } -} - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations { - if (!DisplayServerIPhone::get_singleton()) { - return UIInterfaceOrientationMaskAll; - } - - switch (DisplayServerIPhone::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { - case DisplayServer::SCREEN_PORTRAIT: - return UIInterfaceOrientationMaskPortrait; - case DisplayServer::SCREEN_REVERSE_LANDSCAPE: - return UIInterfaceOrientationMaskLandscapeRight; - case DisplayServer::SCREEN_REVERSE_PORTRAIT: - return UIInterfaceOrientationMaskPortraitUpsideDown; - case DisplayServer::SCREEN_SENSOR_LANDSCAPE: - return UIInterfaceOrientationMaskLandscape; - case DisplayServer::SCREEN_SENSOR_PORTRAIT: - return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; - case DisplayServer::SCREEN_SENSOR: - return UIInterfaceOrientationMaskAll; - case DisplayServer::SCREEN_LANDSCAPE: - return UIInterfaceOrientationMaskLandscapeLeft; - } -} - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (BOOL)prefersHomeIndicatorAutoHidden { - if (GLOBAL_GET("display/window/ios/hide_home_indicator")) { - return YES; - } else { - return NO; - } -} - -// MARK: Keyboard - -- (void)keyboardOnScreen:(NSNotification *)notification { - NSDictionary *info = notification.userInfo; - NSValue *value = info[UIKeyboardFrameEndUserInfoKey]; - - CGRect rawFrame = [value CGRectValue]; - CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil]; - - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height); - } -} - -- (void)keyboardHidden:(NSNotification *)notification { - if (DisplayServerIPhone::get_singleton()) { - DisplayServerIPhone::get_singleton()->virtual_keyboard_set_height(0); - } -} - -@end diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/iphone/vulkan_context_iphone.h deleted file mode 100644 index 7576525755..0000000000 --- a/platform/iphone/vulkan_context_iphone.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* vulkan_context_iphone.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#ifndef VULKAN_CONTEXT_IPHONE_H -#define VULKAN_CONTEXT_IPHONE_H - -#include "drivers/vulkan/vulkan_context.h" - -#import <UIKit/UIKit.h> - -class VulkanContextIPhone : public VulkanContext { - virtual const char *_get_platform_surface_extension() const; - -public: - Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height); - - VulkanContextIPhone(); - ~VulkanContextIPhone(); -}; - -#endif // VULKAN_CONTEXT_IPHONE_H diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/iphone/vulkan_context_iphone.mm deleted file mode 100644 index 17cb0f6009..0000000000 --- a/platform/iphone/vulkan_context_iphone.mm +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************/ -/* vulkan_context_iphone.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -#include "vulkan_context_iphone.h" -#ifdef USE_VOLK -#include <volk.h> -#else -#include <vulkan/vulkan.h> -#endif - -const char *VulkanContextIPhone::_get_platform_surface_extension() const { - return VK_MVK_IOS_SURFACE_EXTENSION_NAME; -} - -Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) { - VkIOSSurfaceCreateInfoMVK createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.pView = (__bridge const void *)p_metal_layer; - - VkSurfaceKHR surface; - VkResult err = - vkCreateIOSSurfaceMVK(get_instance(), &createInfo, nullptr, &surface); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); - - return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height); -} - -VulkanContextIPhone::VulkanContextIPhone() {} - -VulkanContextIPhone::~VulkanContextIPhone() {} |