1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-10 13:00:37 +00:00

Merge pull request #105628 from rsanchezsaez/apple/ios-visionos-4.5

Native visionOS platform support
This commit is contained in:
Rémi Verschelde
2025-05-20 23:09:07 +02:00
committed by GitHub
141 changed files with 8711 additions and 5428 deletions

View File

@@ -647,7 +647,11 @@ if env["scu_build"]:
# are actually handled to change compile options, etc. # are actually handled to change compile options, etc.
detect.configure(env) detect.configure(env)
print(f'Building for platform "{env["platform"]}", architecture "{env["arch"]}", target "{env["target"]}".') platform_string = env["platform"]
if env.get("simulator"):
platform_string += " (simulator)"
print(f'Building for platform "{platform_string}", architecture "{env["arch"]}", target "{env["target"]}".')
if env.dev_build: if env.dev_build:
print_info("Developer build, with debug optimization level and debug symbols (unless overridden).") print_info("Developer build, with debug optimization level and debug symbols (unless overridden).")

View File

@@ -48,7 +48,7 @@ def make_default_controller_mappings(target, source, env):
"Windows": "WINDOWS", "Windows": "WINDOWS",
"Mac OS X": "MACOS", "Mac OS X": "MACOS",
"Android": "ANDROID", "Android": "ANDROID",
"iOS": "IOS", "iOS": "APPLE_EMBEDDED",
"Web": "WEB", "Web": "WEB",
} }

View File

@@ -585,7 +585,7 @@ bool OS::has_feature(const String &p_feature) {
} }
#endif #endif
#if defined(IOS_SIMULATOR) #if defined(IOS_SIMULATOR) || defined(VISIONOS_SIMULATOR)
if (p_feature == "simulator") { if (p_feature == "simulator") {
return true; return true;
} }

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorExportPlatformAppleEmbedded" inherits="EditorExportPlatform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Base class for the Apple embedded platform exporters (iOS and visionOS).
</brief_description>
<description>
The base class for Apple embedded platform exporters. These include iOS and visionOS, but not macOS. See the classes inheriting from this one for more details.
</description>
<tutorials>
<link title="Exporting for iOS">$DOCS_URL/tutorials/export/exporting_for_ios.html</link>
<link title="iOS plugins documentation index">$DOCS_URL/tutorials/platform/ios/index.html</link>
</tutorials>
</class>

View File

@@ -4,7 +4,7 @@
Base class for the desktop platform exporter (Windows and Linux/BSD). Base class for the desktop platform exporter (Windows and Linux/BSD).
</brief_description> </brief_description>
<description> <description>
The base class for the desktop platform exporters. These include Windows and Linux/BSD, but not macOS. See the classes inheriting this one for more details. The base class for the desktop platform exporters. These include Windows and Linux/BSD, but not macOS. See the classes inheriting from this one for more details.
</description> </description>
<tutorials> <tutorials>
<link title="Exporting for Windows">$DOCS_URL/tutorials/export/exporting_for_windows.html</link> <link title="Exporting for Windows">$DOCS_URL/tutorials/export/exporting_for_windows.html</link>

View File

@@ -251,6 +251,57 @@
If no modifications are needed, then an empty [PackedByteArray] should be returned. If no modifications are needed, then an empty [PackedByteArray] should be returned.
</description> </description>
</method> </method>
<method name="add_apple_embedded_platform_bundle_file">
<return type="void" />
<param index="0" name="path" type="String" />
<description>
Adds an Apple embedded platform bundle file from the given [param path] to the exported project.
</description>
</method>
<method name="add_apple_embedded_platform_cpp_code">
<return type="void" />
<param index="0" name="code" type="String" />
<description>
Adds C++ code to the Apple embedded platform export. The final code is created from the code appended by each active export plugin.
</description>
</method>
<method name="add_apple_embedded_platform_embedded_framework">
<return type="void" />
<param index="0" name="path" type="String" />
<description>
Adds a dynamic library (*.dylib, *.framework) to the Linking Phase in the Apple embedded platform's Xcode project and embeds it into the resulting binary.
[b]Note:[/b] For static libraries (*.a), this works in the same way as [method add_apple_embedded_platform_framework].
[b]Note:[/b] This method should not be used for System libraries as they are already present on the device.
</description>
</method>
<method name="add_apple_embedded_platform_framework">
<return type="void" />
<param index="0" name="path" type="String" />
<description>
Adds a static library (*.a) or a dynamic library (*.dylib, *.framework) to the Linking Phase to the Apple embedded platform's Xcode project.
</description>
</method>
<method name="add_apple_embedded_platform_linker_flags">
<return type="void" />
<param index="0" name="flags" type="String" />
<description>
Adds linker flags for the Apple embedded platform export.
</description>
</method>
<method name="add_apple_embedded_platform_plist_content">
<return type="void" />
<param index="0" name="plist_content" type="String" />
<description>
Adds additional fields to the Apple embedded platform's project Info.plist file.
</description>
</method>
<method name="add_apple_embedded_platform_project_static_lib">
<return type="void" />
<param index="0" name="path" type="String" />
<description>
Adds a static library from the given [param path] to the Apple embedded platform project.
</description>
</method>
<method name="add_file"> <method name="add_file">
<return type="void" /> <return type="void" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
@@ -262,55 +313,55 @@
[param file] will not be imported, so consider using [method _customize_resource] to remap imported resources. [param file] will not be imported, so consider using [method _customize_resource] to remap imported resources.
</description> </description>
</method> </method>
<method name="add_ios_bundle_file"> <method name="add_ios_bundle_file" deprecated="Use [method add_apple_embedded_platform_bundle_file] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
<description> <description>
Adds an iOS bundle file from the given [param path] to the exported project. Adds an iOS bundle file from the given [param path] to the exported project.
</description> </description>
</method> </method>
<method name="add_ios_cpp_code"> <method name="add_ios_cpp_code" deprecated="Use [method add_apple_embedded_platform_cpp_code] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="code" type="String" /> <param index="0" name="code" type="String" />
<description> <description>
Adds a C++ code to the iOS export. The final code is created from the code appended by each active export plugin. Adds C++ code to the iOS export. The final code is created from the code appended by each active export plugin.
</description> </description>
</method> </method>
<method name="add_ios_embedded_framework"> <method name="add_ios_embedded_framework" deprecated="Use [method add_apple_embedded_platform_embedded_framework] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
<description> <description>
Adds a dynamic library (*.dylib, *.framework) to Linking Phase in iOS's Xcode project and embeds it into resulting binary. Adds a dynamic library (*.dylib, *.framework) to Linking Phase in iOS's Xcode project and embeds it into resulting binary.
[b]Note:[/b] For static libraries (*.a) works in same way as [method add_ios_framework]. [b]Note:[/b] For static libraries (*.a), this works the in same way as [method add_apple_embedded_platform_framework].
[b]Note:[/b] This method should not be used for System libraries as they are already present on the device. [b]Note:[/b] This method should not be used for System libraries as they are already present on the device.
</description> </description>
</method> </method>
<method name="add_ios_framework"> <method name="add_ios_framework" deprecated="Use [method add_apple_embedded_platform_framework] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
<description> <description>
Adds a static library (*.a) or dynamic library (*.dylib, *.framework) to Linking Phase in iOS's Xcode project. Adds a static library (*.a) or a dynamic library (*.dylib, *.framework) to the Linking Phase to the iOS Xcode project.
</description> </description>
</method> </method>
<method name="add_ios_linker_flags"> <method name="add_ios_linker_flags" deprecated="Use [method add_apple_embedded_platform_linker_flags] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="flags" type="String" /> <param index="0" name="flags" type="String" />
<description> <description>
Adds linker flags for the iOS export. Adds linker flags for the iOS export.
</description> </description>
</method> </method>
<method name="add_ios_plist_content"> <method name="add_ios_plist_content" deprecated="Use [method add_apple_embedded_platform_plist_content] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="plist_content" type="String" /> <param index="0" name="plist_content" type="String" />
<description> <description>
Adds content for iOS Property List files. Adds additional fields to the iOS project Info.plist file.
</description> </description>
</method> </method>
<method name="add_ios_project_static_lib"> <method name="add_ios_project_static_lib" deprecated="Use [method add_apple_embedded_platform_project_static_lib] instead.">
<return type="void" /> <return type="void" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
<description> <description>
Adds a static lib from the given [param path] to the iOS project. Adds a static library from the given [param path] to the iOS project.
</description> </description>
</method> </method>
<method name="add_macos_plugin_file"> <method name="add_macos_plugin_file">

View File

@@ -900,6 +900,9 @@
<member name="display/display_server/driver.macos" type="String" setter="" getter=""> <member name="display/display_server/driver.macos" type="String" setter="" getter="">
MacOS override for [member display/display_server/driver]. MacOS override for [member display/display_server/driver].
</member> </member>
<member name="display/display_server/driver.visionos" type="String" setter="" getter="">
visionOS override for [member display/display_server/driver].
</member>
<member name="display/display_server/driver.windows" type="String" setter="" getter=""> <member name="display/display_server/driver.windows" type="String" setter="" getter="">
Windows override for [member display/display_server/driver]. Windows override for [member display/display_server/driver].
</member> </member>
@@ -3163,6 +3166,11 @@
- [code]metal[/code] (default), Metal from native drivers, only supported on Apple Silicon Macs. On Intel Macs, it will automatically fall back to [code]vulkan[/code] as Metal support is not implemented. - [code]metal[/code] (default), Metal from native drivers, only supported on Apple Silicon Macs. On Intel Macs, it will automatically fall back to [code]vulkan[/code] as Metal support is not implemented.
- [code]vulkan[/code], Vulkan over Metal via MoltenVK, supported on both Apple Silicon and Intel Macs. - [code]vulkan[/code], Vulkan over Metal via MoltenVK, supported on both Apple Silicon and Intel Macs.
</member> </member>
<member name="rendering/rendering_device/driver.visionos" type="String" setter="" getter="" default="&quot;metal&quot;">
visionOS override for [member rendering/rendering_device/driver].
Only one option is supported:
- [code]metal[/code] (default), Metal from native drivers.
</member>
<member name="rendering/rendering_device/driver.windows" type="String" setter="" getter="" default="&quot;vulkan&quot;"> <member name="rendering/rendering_device/driver.windows" type="String" setter="" getter="" default="&quot;vulkan&quot;">
Windows override for [member rendering/rendering_device/driver]. Windows override for [member rendering/rendering_device/driver].
Two options are supported: Two options are supported:

View File

@@ -14,8 +14,6 @@ SConscript("windows/SCsub")
# Sounds drivers # Sounds drivers
SConscript("alsa/SCsub") SConscript("alsa/SCsub")
if env["platform"] == "ios" or env["platform"] == "macos":
SConscript("coreaudio/SCsub")
SConscript("pulseaudio/SCsub") SConscript("pulseaudio/SCsub")
if env["platform"] == "windows": if env["platform"] == "windows":
SConscript("wasapi/SCsub") SConscript("wasapi/SCsub")
@@ -28,8 +26,11 @@ if env["xaudio2"]:
SConscript("xaudio2/SCsub") SConscript("xaudio2/SCsub")
# Shared Apple platform drivers # Shared Apple platform drivers
if env["platform"] in ["macos", "ios"]: if env["platform"] in ["macos", "ios", "visionos"]:
SConscript("apple/SCsub") SConscript("apple/SCsub")
SConscript("coreaudio/SCsub")
if env["platform"] in ["ios", "visionos"]:
SConscript("apple_embedded/SCsub")
# Accessibility # Accessibility
if env["accesskit"] and env["platform"] in ["macos", "windows", "linuxbsd"]: if env["accesskit"] and env["platform"] in ["macos", "windows", "linuxbsd"]:
@@ -37,7 +38,7 @@ if env["accesskit"] and env["platform"] in ["macos", "windows", "linuxbsd"]:
# Midi drivers # Midi drivers
SConscript("alsamidi/SCsub") SConscript("alsamidi/SCsub")
if env["platform"] in ["macos", "ios"]: if env["platform"] in ["macos"]:
SConscript("coremidi/SCsub") SConscript("coremidi/SCsub")
SConscript("winmidi/SCsub") SConscript("winmidi/SCsub")

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
env_apple_embedded = env.Clone()
# Enable module support
env_apple_embedded.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
# Use bundled Vulkan headers
vulkan_dir = "#thirdparty/vulkan"
env_apple_embedded.Prepend(CPPPATH=[vulkan_dir, vulkan_dir + "/include"])
# Driver source files
env_apple_embedded.add_source_files(env.drivers_sources, "*.mm")

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* app_delegate.h */ /* app_delegate_service.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -32,18 +32,11 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@class ViewController; @class GDTViewController;
// FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented again, @interface GDTAppDelegateService : NSObject <UIApplicationDelegate>
// 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, nonatomic) UIWindow *window;
@property(strong, class, readonly, nonatomic) ViewController *viewController; @property(strong, class, readonly, nonatomic) GDTViewController *viewController;
@end @end

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* app_delegate.mm */ /* app_delegate_service.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "app_delegate.h" #import "app_delegate_service.h"
#import "godot_view.h" #import "godot_view_apple_embedded.h"
#import "os_ios.h" #import "os_apple_embedded.h"
#import "view_controller.h" #import "view_controller.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
@@ -46,10 +46,10 @@
extern int gargc; extern int gargc;
extern char **gargv; extern char **gargv;
extern int ios_main(int, char **); extern int apple_embedded_main(int, char **);
extern void ios_finish(); extern void apple_embedded_finish();
@implementation AppDelegate @implementation GDTAppDelegateService
enum { enum {
SESSION_CATEGORY_AMBIENT, SESSION_CATEGORY_AMBIENT,
@@ -60,9 +60,9 @@ enum {
SESSION_CATEGORY_SOLO_AMBIENT SESSION_CATEGORY_SOLO_AMBIENT
}; };
static ViewController *mainViewController = nil; static GDTViewController *mainViewController = nil;
+ (ViewController *)viewController { + (GDTViewController *)viewController {
return mainViewController; return mainViewController;
} }
@@ -71,12 +71,15 @@ static ViewController *mainViewController = nil;
// TODO: logo screen is not displayed while shaders are compiling // TODO: logo screen is not displayed while shaders are compiling
// DummyViewController(Splash/LoadingViewController) -> setup -> GodotViewController // DummyViewController(Splash/LoadingViewController) -> setup -> GodotViewController
CGRect windowBounds = [[UIScreen mainScreen] bounds]; #if !defined(VISIONOS_ENABLED)
// Create a full-screen window // Create a full-screen window
CGRect windowBounds = [[UIScreen mainScreen] bounds];
self.window = [[UIWindow alloc] initWithFrame:windowBounds]; self.window = [[UIWindow alloc] initWithFrame:windowBounds];
#else
self.window = [[UIWindow alloc] init];
#endif
int err = ios_main(gargc, gargv); int err = apple_embedded_main(gargc, gargv);
if (err != 0) { if (err != 0) {
// bail, things did not go very well for us, should probably output a message on screen with our error code... // bail, things did not go very well for us, should probably output a message on screen with our error code...
@@ -84,7 +87,7 @@ static ViewController *mainViewController = nil;
return NO; return NO;
} }
ViewController *viewController = [[ViewController alloc] init]; GDTViewController *viewController = [[GDTViewController alloc] init];
viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO; viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO;
viewController.godotView.renderingInterval = 1.0 / kRenderingFrequency; viewController.godotView.renderingInterval = 1.0 / kRenderingFrequency;
@@ -135,10 +138,10 @@ static ViewController *mainViewController = nil;
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) { if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) { if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
NSLog(@"Audio interruption began"); NSLog(@"Audio interruption began");
OS_IOS::get_singleton()->on_focus_out(); OS_AppleEmbedded::get_singleton()->on_focus_out();
} else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) { } else if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]) {
NSLog(@"Audio interruption ended"); NSLog(@"Audio interruption ended");
OS_IOS::get_singleton()->on_focus_in(); OS_AppleEmbedded::get_singleton()->on_focus_in();
} }
} }
} }
@@ -150,7 +153,7 @@ static ViewController *mainViewController = nil;
} }
- (void)applicationWillTerminate:(UIApplication *)application { - (void)applicationWillTerminate:(UIApplication *)application {
ios_finish(); apple_embedded_finish();
} }
// When application goes to background (e.g. user switches to another app or presses Home), // When application goes to background (e.g. user switches to another app or presses Home),
@@ -164,19 +167,19 @@ static ViewController *mainViewController = nil;
// notification panel by swiping from the upper part of the screen. // notification panel by swiping from the upper part of the screen.
- (void)applicationWillResignActive:(UIApplication *)application { - (void)applicationWillResignActive:(UIApplication *)application {
OS_IOS::get_singleton()->on_focus_out(); OS_AppleEmbedded::get_singleton()->on_focus_out();
} }
- (void)applicationDidBecomeActive:(UIApplication *)application { - (void)applicationDidBecomeActive:(UIApplication *)application {
OS_IOS::get_singleton()->on_focus_in(); OS_AppleEmbedded::get_singleton()->on_focus_in();
} }
- (void)applicationDidEnterBackground:(UIApplication *)application { - (void)applicationDidEnterBackground:(UIApplication *)application {
OS_IOS::get_singleton()->on_enter_background(); OS_AppleEmbedded::get_singleton()->on_enter_background();
} }
- (void)applicationWillEnterForeground:(UIApplication *)application { - (void)applicationWillEnterForeground:(UIApplication *)application {
OS_IOS::get_singleton()->on_exit_background(); OS_AppleEmbedded::get_singleton()->on_exit_background();
} }
- (void)dealloc { - (void)dealloc {

View File

@@ -0,0 +1,59 @@
/**************************************************************************/
/* apple_embedded.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/object/class_db.h"
#import <CoreHaptics/CoreHaptics.h>
class AppleEmbedded : public Object {
GDCLASS(AppleEmbedded, 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, float p_amplitude);
String get_model() const;
String get_rate_url(int p_app_id) const;
AppleEmbedded();
};

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* ios.mm */ /* apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,23 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "ios.h" #import "apple_embedded.h"
#import "app_delegate.h" #import "app_delegate_service.h"
#import "view_controller.h" #import "view_controller.h"
#import <CoreHaptics/CoreHaptics.h> #import <CoreHaptics/CoreHaptics.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
void iOS::_bind_methods() { void AppleEmbedded::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url); ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &AppleEmbedded::get_rate_url);
ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine); ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &AppleEmbedded::supports_haptic_engine);
ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine); ClassDB::bind_method(D_METHOD("start_haptic_engine"), &AppleEmbedded::start_haptic_engine);
ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine); ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &AppleEmbedded::stop_haptic_engine);
} }
bool iOS::supports_haptic_engine() { bool AppleEmbedded::supports_haptic_engine() {
if (@available(iOS 13, *)) { if (@available(iOS 13, *)) {
id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware]; id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware];
return capabilities.supportsHaptics; return capabilities.supportsHaptics;
@@ -53,7 +53,7 @@ bool iOS::supports_haptic_engine() {
return false; return false;
} }
CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) { CHHapticEngine *AppleEmbedded::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
if (haptic_engine == nullptr) { if (haptic_engine == nullptr) {
NSError *error = nullptr; NSError *error = nullptr;
haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error]; haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error];
@@ -69,7 +69,7 @@ CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
return haptic_engine; return haptic_engine;
} }
void iOS::vibrate_haptic_engine(float p_duration_seconds, float p_amplitude) API_AVAILABLE(ios(13)) { void AppleEmbedded::vibrate_haptic_engine(float p_duration_seconds, float p_amplitude) API_AVAILABLE(ios(13)) {
if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy... if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy...
if (supports_haptic_engine()) { if (supports_haptic_engine()) {
CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance(); CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
@@ -117,10 +117,10 @@ void iOS::vibrate_haptic_engine(float p_duration_seconds, float p_amplitude) API
} }
} }
NSLog(@"Haptic engine is not supported in this version of iOS"); NSLog(@"Haptic engine is not supported");
} }
void iOS::start_haptic_engine() { void AppleEmbedded::start_haptic_engine() {
if (@available(iOS 13, *)) { if (@available(iOS 13, *)) {
if (supports_haptic_engine()) { if (supports_haptic_engine()) {
CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance(); CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
@@ -136,10 +136,10 @@ void iOS::start_haptic_engine() {
} }
} }
NSLog(@"Haptic engine is not supported in this version of iOS"); NSLog(@"Haptic engine is not supported");
} }
void iOS::stop_haptic_engine() { void AppleEmbedded::stop_haptic_engine() {
if (@available(iOS 13, *)) { if (@available(iOS 13, *)) {
if (supports_haptic_engine()) { if (supports_haptic_engine()) {
CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance(); CHHapticEngine *cur_haptic_engine = get_haptic_engine_instance();
@@ -155,10 +155,10 @@ void iOS::stop_haptic_engine() {
} }
} }
NSLog(@"Haptic engine is not supported in this version of iOS"); NSLog(@"Haptic engine is not supported");
} }
void iOS::alert(const char *p_alert, const char *p_title) { void AppleEmbedded::alert(const char *p_alert, const char *p_title) {
NSString *title = [NSString stringWithUTF8String:p_title]; NSString *title = [NSString stringWithUTF8String:p_title];
NSString *message = [NSString stringWithUTF8String:p_alert]; NSString *message = [NSString stringWithUTF8String:p_alert];
@@ -170,10 +170,10 @@ void iOS::alert(const char *p_alert, const char *p_title) {
[alert addAction:button]; [alert addAction:button];
[AppDelegate.viewController presentViewController:alert animated:YES completion:nil]; [GDTAppDelegateService.viewController presentViewController:alert animated:YES completion:nil];
} }
String iOS::get_model() const { String AppleEmbedded::get_model() const {
// [[UIDevice currentDevice] model] only returns "iPad" or "iPhone". // [[UIDevice currentDevice] model] only returns "iPad" or "iPhone".
size_t size; size_t size;
sysctlbyname("hw.machine", nullptr, &size, nullptr, 0); sysctlbyname("hw.machine", nullptr, &size, nullptr, 0);
@@ -188,7 +188,7 @@ String iOS::get_model() const {
return String::utf8(str != nullptr ? str : ""); return String::utf8(str != nullptr ? str : "");
} }
String iOS::get_rate_url(int p_app_id) const { String AppleEmbedded::get_rate_url(int p_app_id) const {
String app_url_path = "itms-apps://itunes.apple.com/app/idAPP_ID"; String app_url_path = "itms-apps://itunes.apple.com/app/idAPP_ID";
String ret = app_url_path.replace("APP_ID", String::num_int64(p_app_id)); String ret = app_url_path.replace("APP_ID", String::num_int64(p_app_id));
@@ -197,4 +197,4 @@ String iOS::get_rate_url(int p_app_id) const {
return ret; return ret;
} }
iOS::iOS() {} AppleEmbedded::AppleEmbedded() {}

View File

@@ -0,0 +1,42 @@
/**************************************************************************/
/* display_layer_apple_embedded.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#import <QuartzCore/CAMetalLayer.h>
@protocol GDTDisplayLayer <NSObject>
- (void)startRenderDisplayLayer;
- (void)stopRenderDisplayLayer;
- (void)initializeDisplayLayer;
- (void)layoutDisplayLayer;
@end

View File

@@ -0,0 +1,233 @@
/**************************************************************************/
/* display_server_apple_embedded.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/input/input.h"
#include "servers/display_server.h"
#if defined(RD_ENABLED)
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#import "rendering_context_driver_vulkan_apple_embedded.h"
#include "drivers/vulkan/godot_vulkan.h"
#endif // VULKAN_ENABLED
#if defined(METAL_ENABLED)
#import "drivers/metal/rendering_context_driver_metal.h"
#endif // METAL_ENABLED
#endif // RD_ENABLED
#if defined(GLES3_ENABLED)
#include "drivers/gles3/rasterizer_gles3.h"
#endif // GLES3_ENABLED
#import <Foundation/Foundation.h>
#import <QuartzCore/CAMetalLayer.h>
class DisplayServerAppleEmbedded : public DisplayServer {
GDSOFTCLASS(DisplayServerAppleEmbedded, DisplayServer);
_THREAD_SAFE_CLASS_
#if defined(RD_ENABLED)
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif
NativeMenu *native_menu = nullptr;
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;
Callable system_theme_changed;
int virtual_keyboard_height = 0;
void perform_event(const Ref<InputEvent> &p_event);
void initialize_tts() const;
protected:
DisplayServerAppleEmbedded(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error);
~DisplayServerAppleEmbedded();
public:
String rendering_driver;
static DisplayServerAppleEmbedded *get_singleton();
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;
void emit_system_theme_changed();
// MARK: - Input
// MARK: Touches and Apple Pencil
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, float p_pressure, Vector2 p_tilt);
void touches_canceled(int p_idx);
// MARK: Keyboard
void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location);
bool is_keyboard_active() const;
// MARK: Motion
void update_gravity(const Vector3 &p_gravity);
void update_accelerometer(const Vector3 &p_accelerometer);
void update_magnetometer(const Vector3 &p_magnetometer);
void update_gyroscope(const Vector3 &p_gyroscope);
// MARK: -
virtual bool has_feature(Feature p_feature) const override;
virtual bool tts_is_speaking() const override;
virtual bool tts_is_paused() const override;
virtual TypedArray<Dictionary> 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 bool is_dark_mode_supported() const override;
virtual bool is_dark_mode() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
virtual Rect2i get_display_safe_area() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() 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 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 Point2i window_get_position_with_decorations(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_size_with_decorations(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 bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const 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 is_touchscreen_available() const override;
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, 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 bool has_hardware_keyboard() 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);
virtual void swap_buffers() override {}
};

View File

@@ -0,0 +1,794 @@
/**************************************************************************/
/* display_server_apple_embedded.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#import "display_server_apple_embedded.h"
#import "app_delegate_service.h"
#import "apple_embedded.h"
#import "godot_view_apple_embedded.h"
#import "key_mapping_apple_embedded.h"
#import "keyboard_input_view.h"
#import "os_apple_embedded.h"
#import "tts_apple_embedded.h"
#import "view_controller.h"
#include "core/config/project_settings.h"
#include "core/io/file_access_pack.h"
#import <GameController/GameController.h>
static const float kDisplayServerIOSAcceleration = 1.f;
DisplayServerAppleEmbedded *DisplayServerAppleEmbedded::get_singleton() {
return (DisplayServerAppleEmbedded *)DisplayServer::get_singleton();
}
DisplayServerAppleEmbedded::DisplayServerAppleEmbedded(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {
KeyMappingAppleEmbedded::initialize();
rendering_driver = p_rendering_driver;
// Init TTS
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
initialize_tts();
}
native_menu = memnew(NativeMenu);
bool has_made_render_compositor_current = false;
#if defined(RD_ENABLED)
rendering_context = nullptr;
rendering_device = nullptr;
CALayer *layer = nullptr;
union {
#ifdef VULKAN_ENABLED
RenderingContextDriverVulkanAppleEmbedded::WindowPlatformData vulkan;
#endif
#ifdef METAL_ENABLED
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wunguarded-availability")
// Eliminate "RenderingContextDriverMetal is only available on iOS 14.0 or newer".
RenderingContextDriverMetal::WindowPlatformData metal;
GODOT_CLANG_WARNING_POP
#endif
} wpd;
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
layer = [GDTAppDelegateService.viewController.godotView initializeRenderingForDriver:@"vulkan"];
if (!layer) {
ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer.");
}
wpd.vulkan.layer_ptr = (CAMetalLayer *const *)&layer;
rendering_context = memnew(RenderingContextDriverVulkanAppleEmbedded);
}
#endif
#ifdef METAL_ENABLED
if (rendering_driver == "metal") {
if (@available(iOS 14.0, *)) {
layer = [GDTAppDelegateService.viewController.godotView initializeRenderingForDriver:@"metal"];
wpd.metal.layer = (CAMetalLayer *)layer;
rendering_context = memnew(RenderingContextDriverMetal);
} else {
OS::get_singleton()->alert("Metal is only supported on iOS 14.0 and later.");
r_error = ERR_UNAVAILABLE;
return;
}
}
#endif
if (rendering_context) {
if (rendering_context->initialize() != OK) {
memdelete(rendering_context);
rendering_context = nullptr;
#if defined(GLES3_ENABLED)
bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
if (fallback_to_opengl3 && rendering_driver != "opengl3") {
WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
rendering_driver = "opengl3";
OS::get_singleton()->set_current_rendering_method("gl_compatibility");
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else
#endif
{
ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
r_error = ERR_UNAVAILABLE;
return;
}
}
}
if (rendering_context) {
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
rendering_context->window_set_size(MAIN_WINDOW_ID, size.width, size.height);
rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);
rendering_device = memnew(RenderingDevice);
if (rendering_device->initialize(rendering_context, MAIN_WINDOW_ID) != OK) {
rendering_device = nullptr;
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
has_made_render_compositor_current = true;
}
#endif
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
CALayer *layer = [GDTAppDelegateService.viewController.godotView initializeRenderingForDriver:@"opengl3"];
if (!layer) {
ERR_FAIL_MSG("Failed to create iOS OpenGLES rendering layer.");
}
RasterizerGLES3::make_current(false);
has_made_render_compositor_current = true;
}
#endif
ERR_FAIL_COND_MSG(!has_made_render_compositor_current, vformat("Failed to make RendererCompositor current for rendering driver %s", rendering_driver));
bool keep_screen_on = bool(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
screen_set_keep_on(keep_screen_on);
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
}
DisplayServerAppleEmbedded::~DisplayServerAppleEmbedded() {
if (native_menu) {
memdelete(native_menu);
native_menu = nullptr;
}
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->screen_free(MAIN_WINDOW_ID);
memdelete(rendering_device);
rendering_device = nullptr;
}
if (rendering_context) {
rendering_context->window_destroy(MAIN_WINDOW_ID);
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif
}
Vector<String> DisplayServerAppleEmbedded::get_rendering_drivers_func() {
Vector<String> drivers;
#if defined(VULKAN_ENABLED)
drivers.push_back("vulkan");
#endif
#if defined(METAL_ENABLED)
if (@available(ios 14.0, *)) {
drivers.push_back("metal");
}
#endif
#if defined(GLES3_ENABLED)
drivers.push_back("opengl3");
#endif
return drivers;
}
// MARK: Events
void DisplayServerAppleEmbedded::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
window_resize_callback = p_callable;
}
void DisplayServerAppleEmbedded::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
window_event_callback = p_callable;
}
void DisplayServerAppleEmbedded::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
input_event_callback = p_callable;
}
void DisplayServerAppleEmbedded::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
input_text_callback = p_callable;
}
void DisplayServerAppleEmbedded::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
// Probably not supported for iOS
}
void DisplayServerAppleEmbedded::process_events() {
Input::get_singleton()->flush_buffered_events();
}
void DisplayServerAppleEmbedded::_dispatch_input_events(const Ref<InputEvent> &p_event) {
DisplayServerAppleEmbedded::get_singleton()->send_input_event(p_event);
}
void DisplayServerAppleEmbedded::send_input_event(const Ref<InputEvent> &p_event) const {
_window_callback(input_event_callback, p_event);
}
void DisplayServerAppleEmbedded::send_input_text(const String &p_text) const {
_window_callback(input_text_callback, p_text);
}
void DisplayServerAppleEmbedded::send_window_event(DisplayServer::WindowEvent p_event) const {
_window_callback(window_event_callback, int(p_event));
}
void DisplayServerAppleEmbedded::_window_callback(const Callable &p_callable, const Variant &p_arg) const {
if (p_callable.is_valid()) {
p_callable.call(p_arg);
}
}
// MARK: - Input
// MARK: Touches
void DisplayServerAppleEmbedded::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
Ref<InputEventScreenTouch> ev;
ev.instantiate();
ev->set_index(p_idx);
ev->set_pressed(p_pressed);
ev->set_position(Vector2(p_x, p_y));
ev->set_double_tap(p_double_click);
perform_event(ev);
}
void DisplayServerAppleEmbedded::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt) {
Ref<InputEventScreenDrag> ev;
ev.instantiate();
ev->set_index(p_idx);
ev->set_pressure(p_pressure);
ev->set_tilt(p_tilt);
ev->set_position(Vector2(p_x, p_y));
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
ev->set_relative_screen_position(ev->get_relative());
perform_event(ev);
}
void DisplayServerAppleEmbedded::perform_event(const Ref<InputEvent> &p_event) {
Input::get_singleton()->parse_input_event(p_event);
}
void DisplayServerAppleEmbedded::touches_canceled(int p_idx) {
touch_press(p_idx, -1, -1, false, false);
}
// MARK: Keyboard
void DisplayServerAppleEmbedded::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
ev->set_keycode(fix_keycode(p_char, p_key));
if (@available(iOS 13.4, *)) {
if (p_key != Key::SHIFT) {
ev->set_shift_pressed(p_modifier & UIKeyModifierShift);
}
if (p_key != Key::CTRL) {
ev->set_ctrl_pressed(p_modifier & UIKeyModifierControl);
}
if (p_key != Key::ALT) {
ev->set_alt_pressed(p_modifier & UIKeyModifierAlternate);
}
if (p_key != Key::META) {
ev->set_meta_pressed(p_modifier & UIKeyModifierCommand);
}
}
ev->set_key_label(p_unshifted);
ev->set_physical_keycode(p_physical);
ev->set_unicode(fix_unicode(p_char));
ev->set_location(p_location);
perform_event(ev);
}
// MARK: Motion
void DisplayServerAppleEmbedded::update_gravity(const Vector3 &p_gravity) {
Input::get_singleton()->set_gravity(p_gravity);
}
void DisplayServerAppleEmbedded::update_accelerometer(const Vector3 &p_accelerometer) {
Input::get_singleton()->set_accelerometer(p_accelerometer / kDisplayServerIOSAcceleration);
}
void DisplayServerAppleEmbedded::update_magnetometer(const Vector3 &p_magnetometer) {
Input::get_singleton()->set_magnetometer(p_magnetometer);
}
void DisplayServerAppleEmbedded::update_gyroscope(const Vector3 &p_gyroscope) {
Input::get_singleton()->set_gyroscope(p_gyroscope);
}
// MARK: -
bool DisplayServerAppleEmbedded::has_feature(Feature p_feature) const {
switch (p_feature) {
#ifndef DISABLE_DEPRECATED
case FEATURE_GLOBAL_MENU: {
return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));
} break;
#endif
// case FEATURE_CURSOR_SHAPE:
// case FEATURE_CUSTOM_CURSOR_SHAPE:
// case FEATURE_HIDPI:
// case FEATURE_ICON:
// case FEATURE_IME:
// case FEATURE_MOUSE:
// case FEATURE_MOUSE_WARP:
// case FEATURE_NATIVE_DIALOG:
// case FEATURE_NATIVE_DIALOG_INPUT:
// case FEATURE_NATIVE_DIALOG_FILE:
// case FEATURE_NATIVE_DIALOG_FILE_EXTRA:
// case FEATURE_NATIVE_DIALOG_FILE_MIME:
// 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;
}
}
void DisplayServerAppleEmbedded::initialize_tts() const {
const_cast<DisplayServerAppleEmbedded *>(this)->tts = [[GDTTTS alloc] init];
}
bool DisplayServerAppleEmbedded::tts_is_speaking() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, false);
return [tts isSpeaking];
}
bool DisplayServerAppleEmbedded::tts_is_paused() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, false);
return [tts isPaused];
}
TypedArray<Dictionary> DisplayServerAppleEmbedded::tts_get_voices() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, TypedArray<Dictionary>());
return [tts getVoices];
}
void DisplayServerAppleEmbedded::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) {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(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 DisplayServerAppleEmbedded::tts_pause() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts pauseSpeaking];
}
void DisplayServerAppleEmbedded::tts_resume() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts resumeSpeaking];
}
void DisplayServerAppleEmbedded::tts_stop() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts stopSpeaking];
}
bool DisplayServerAppleEmbedded::is_dark_mode_supported() const {
if (@available(iOS 13.0, *)) {
return true;
} else {
return false;
}
}
bool DisplayServerAppleEmbedded::is_dark_mode() const {
if (@available(iOS 13.0, *)) {
return [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark;
} else {
return false;
}
}
void DisplayServerAppleEmbedded::set_system_theme_change_callback(const Callable &p_callable) {
system_theme_changed = p_callable;
}
void DisplayServerAppleEmbedded::emit_system_theme_changed() {
if (system_theme_changed.is_valid()) {
Variant ret;
Callable::CallError ce;
system_theme_changed.callp(nullptr, 0, ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
}
}
}
Rect2i DisplayServerAppleEmbedded::get_display_safe_area() const {
UIEdgeInsets insets = UIEdgeInsetsZero;
UIView *view = GDTAppDelegateService.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);
}
int DisplayServerAppleEmbedded::get_screen_count() const {
return 1;
}
int DisplayServerAppleEmbedded::get_primary_screen() const {
return 0;
}
Point2i DisplayServerAppleEmbedded::screen_get_position(int p_screen) const {
return Size2i();
}
Size2i DisplayServerAppleEmbedded::screen_get_size(int p_screen) const {
CALayer *layer = GDTAppDelegateService.viewController.godotView.renderingLayer;
if (!layer) {
return Size2i();
}
return Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_scale(p_screen);
}
Rect2i DisplayServerAppleEmbedded::screen_get_usable_rect(int p_screen) const {
return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
}
Vector<DisplayServer::WindowID> DisplayServerAppleEmbedded::get_window_list() const {
Vector<DisplayServer::WindowID> list;
list.push_back(MAIN_WINDOW_ID);
return list;
}
DisplayServer::WindowID DisplayServerAppleEmbedded::get_window_at_screen_position(const Point2i &p_position) const {
return MAIN_WINDOW_ID;
}
int64_t DisplayServerAppleEmbedded::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)GDTAppDelegateService.viewController;
}
case WINDOW_VIEW: {
return (int64_t)GDTAppDelegateService.viewController.godotView;
}
default: {
return 0;
}
}
}
void DisplayServerAppleEmbedded::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
window_attached_instance_id = p_instance;
}
ObjectID DisplayServerAppleEmbedded::window_get_attached_instance_id(WindowID p_window) const {
return window_attached_instance_id;
}
void DisplayServerAppleEmbedded::window_set_title(const String &p_title, WindowID p_window) {
// Probably not supported for iOS
}
int DisplayServerAppleEmbedded::window_get_current_screen(WindowID p_window) const {
return SCREEN_OF_MAIN_WINDOW;
}
void DisplayServerAppleEmbedded::window_set_current_screen(int p_screen, WindowID p_window) {
// Probably not supported for iOS
}
Point2i DisplayServerAppleEmbedded::window_get_position(WindowID p_window) const {
return Point2i();
}
Point2i DisplayServerAppleEmbedded::window_get_position_with_decorations(WindowID p_window) const {
return Point2i();
}
void DisplayServerAppleEmbedded::window_set_position(const Point2i &p_position, WindowID p_window) {
// Probably not supported for single window iOS app
}
void DisplayServerAppleEmbedded::window_set_transient(WindowID p_window, WindowID p_parent) {
// Probably not supported for iOS
}
void DisplayServerAppleEmbedded::window_set_max_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerAppleEmbedded::window_get_max_size(WindowID p_window) const {
return Size2i();
}
void DisplayServerAppleEmbedded::window_set_min_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerAppleEmbedded::window_get_min_size(WindowID p_window) const {
return Size2i();
}
void DisplayServerAppleEmbedded::window_set_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerAppleEmbedded::window_get_size(WindowID p_window) const {
id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
CGRect windowBounds = appDelegate.window.bounds;
return Size2i(windowBounds.size.width, windowBounds.size.height) * screen_get_max_scale();
}
Size2i DisplayServerAppleEmbedded::window_get_size_with_decorations(WindowID p_window) const {
return window_get_size(p_window);
}
void DisplayServerAppleEmbedded::window_set_mode(WindowMode p_mode, WindowID p_window) {
// Probably not supported for iOS
}
DisplayServer::WindowMode DisplayServerAppleEmbedded::window_get_mode(WindowID p_window) const {
return WindowMode::WINDOW_MODE_FULLSCREEN;
}
bool DisplayServerAppleEmbedded::window_is_maximize_allowed(WindowID p_window) const {
return false;
}
void DisplayServerAppleEmbedded::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
// Probably not supported for iOS
}
bool DisplayServerAppleEmbedded::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
return false;
}
void DisplayServerAppleEmbedded::window_request_attention(WindowID p_window) {
// Probably not supported for iOS
}
void DisplayServerAppleEmbedded::window_move_to_foreground(WindowID p_window) {
// Probably not supported for iOS
}
bool DisplayServerAppleEmbedded::window_is_focused(WindowID p_window) const {
return true;
}
float DisplayServerAppleEmbedded::screen_get_max_scale() const {
return screen_get_scale(SCREEN_OF_MAIN_WINDOW);
}
void DisplayServerAppleEmbedded::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {
screen_orientation = p_orientation;
if (@available(iOS 16.0, *)) {
[GDTAppDelegateService.viewController setNeedsUpdateOfSupportedInterfaceOrientations];
}
#if !defined(VISIONOS_ENABLED)
else {
[UIViewController attemptRotationToDeviceOrientation];
}
#endif
}
DisplayServer::ScreenOrientation DisplayServerAppleEmbedded::screen_get_orientation(int p_screen) const {
return screen_orientation;
}
bool DisplayServerAppleEmbedded::window_can_draw(WindowID p_window) const {
return true;
}
bool DisplayServerAppleEmbedded::can_any_window_draw() const {
return true;
}
bool DisplayServerAppleEmbedded::is_touchscreen_available() const {
return true;
}
_FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text, int p_pos) {
int limit = p_pos;
for (int i = 0; i < MIN(p_existing_text.length(), p_pos); i++) {
if (p_existing_text[i] > 0xffff) {
limit++;
}
}
return limit;
}
void DisplayServerAppleEmbedded::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()];
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
GDTAppDelegateService.viewController.keyboardView.textContentType = nil;
switch (p_type) {
case KEYBOARD_TYPE_DEFAULT: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
} break;
case KEYBOARD_TYPE_MULTILINE: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
} break;
case KEYBOARD_TYPE_NUMBER: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeNumberPad;
} break;
case KEYBOARD_TYPE_NUMBER_DECIMAL: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeDecimalPad;
} break;
case KEYBOARD_TYPE_PHONE: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypePhonePad;
GDTAppDelegateService.viewController.keyboardView.textContentType = UITextContentTypeTelephoneNumber;
} break;
case KEYBOARD_TYPE_EMAIL_ADDRESS: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeEmailAddress;
GDTAppDelegateService.viewController.keyboardView.textContentType = UITextContentTypeEmailAddress;
} break;
case KEYBOARD_TYPE_PASSWORD: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
GDTAppDelegateService.viewController.keyboardView.textContentType = UITextContentTypePassword;
} break;
case KEYBOARD_TYPE_URL: {
GDTAppDelegateService.viewController.keyboardView.keyboardType = UIKeyboardTypeWebSearch;
GDTAppDelegateService.viewController.keyboardView.textContentType = UITextContentTypeURL;
} break;
}
[GDTAppDelegateService.viewController.keyboardView
becomeFirstResponderWithString:existingString
cursorStart:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_start)
cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)];
}
bool DisplayServerAppleEmbedded::is_keyboard_active() const {
return [GDTAppDelegateService.viewController.keyboardView isFirstResponder];
}
void DisplayServerAppleEmbedded::virtual_keyboard_hide() {
[GDTAppDelegateService.viewController.keyboardView resignFirstResponder];
}
void DisplayServerAppleEmbedded::virtual_keyboard_set_height(int height) {
virtual_keyboard_height = height * screen_get_max_scale();
}
int DisplayServerAppleEmbedded::virtual_keyboard_get_height() const {
return virtual_keyboard_height;
}
bool DisplayServerAppleEmbedded::has_hardware_keyboard() const {
if (@available(iOS 14.0, *)) {
return [GCKeyboard coalescedKeyboard];
} else {
return false;
}
}
void DisplayServerAppleEmbedded::clipboard_set(const String &p_text) {
[UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8().get_data()];
}
String DisplayServerAppleEmbedded::clipboard_get() const {
NSString *text = [UIPasteboard generalPasteboard].string;
return String::utf8([text UTF8String]);
}
void DisplayServerAppleEmbedded::screen_set_keep_on(bool p_enable) {
[UIApplication sharedApplication].idleTimerDisabled = p_enable;
}
bool DisplayServerAppleEmbedded::screen_is_kept_on() const {
return [UIApplication sharedApplication].idleTimerDisabled;
}
void DisplayServerAppleEmbedded::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_size(MAIN_WINDOW_ID, size.x, size.y);
}
#endif
Variant resize_rect = Rect2i(Point2i(), size);
_window_callback(window_resize_callback, resize_rect);
}
void DisplayServerAppleEmbedded::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
DisplayServer::VSyncMode DisplayServerAppleEmbedded::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;
}

View File

@@ -32,12 +32,12 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
typedef NSObject<UIApplicationDelegate> ApplicationDelegateService; typedef NSObject<UIApplicationDelegate> GDTAppDelegateServiceProtocol;
@interface GodotApplicationDelegate : NSObject <UIApplicationDelegate> @interface GDTApplicationDelegate : NSObject <UIApplicationDelegate>
@property(class, readonly, strong) NSArray<ApplicationDelegateService *> *services; @property(class, readonly, strong) NSArray<GDTAppDelegateServiceProtocol *> *services;
+ (void)addService:(ApplicationDelegateService *)service; + (void)addService:(GDTAppDelegateServiceProtocol *)service;
@end @end

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_app_delegate.m */ /* godot_app_delegate.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -30,26 +30,22 @@
#import "godot_app_delegate.h" #import "godot_app_delegate.h"
#import "app_delegate.h" #import "app_delegate_service.h"
@interface GodotApplicationDelegate () @implementation GDTApplicationDelegate
@end static NSMutableArray<GDTAppDelegateServiceProtocol *> *services = nil;
@implementation GodotApplicationDelegate + (NSArray<GDTAppDelegateServiceProtocol *> *)services {
static NSMutableArray<ApplicationDelegateService *> *services = nil;
+ (NSArray<ApplicationDelegateService *> *)services {
return services; return services;
} }
+ (void)load { + (void)load {
services = [NSMutableArray new]; services = [NSMutableArray new];
[services addObject:[AppDelegate new]]; [services addObject:[GDTAppDelegateService new]];
} }
+ (void)addService:(ApplicationDelegateService *)service { + (void)addService:(GDTAppDelegateServiceProtocol *)service {
if (!services || !service) { if (!services || !service) {
return; return;
} }
@@ -63,7 +59,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (UIWindow *)window { - (UIWindow *)window {
UIWindow *result = nil; UIWindow *result = nil;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -83,7 +79,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions { - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -99,7 +95,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -125,7 +121,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: Life-Cycle // MARK: Life-Cycle
- (void)applicationDidBecomeActive:(UIApplication *)application { - (void)applicationDidBecomeActive:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -135,7 +131,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationWillResignActive:(UIApplication *)application { - (void)applicationWillResignActive:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -145,7 +141,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationDidEnterBackground:(UIApplication *)application { - (void)applicationDidEnterBackground:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -155,7 +151,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationWillEnterForeground:(UIApplication *)application { - (void)applicationWillEnterForeground:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -165,7 +161,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationWillTerminate:(UIApplication *)application { - (void)applicationWillTerminate:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -177,7 +173,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: Environment Changes // MARK: Environment Changes
- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application { - (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -187,7 +183,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application { - (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -197,7 +193,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -207,7 +203,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)applicationSignificantTimeChange:(UIApplication *)application { - (void)applicationSignificantTimeChange:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -221,7 +217,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) { - (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -237,7 +233,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) { - (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder API_AVAILABLE(ios(13.2)) {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -251,7 +247,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder { - (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -267,7 +263,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder { - (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -277,7 +273,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder { - (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -289,7 +285,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: Download Data in Background // MARK: Download Data in Background
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler { - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -309,7 +305,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType { - (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -325,7 +321,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler { - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -339,7 +335,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)application:(UIApplication *)application didUpdateUserActivity:(NSUserActivity *)userActivity { - (void)application:(UIApplication *)application didUpdateUserActivity:(NSUserActivity *)userActivity {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -349,7 +345,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)application:(UIApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error { - (void)application:(UIApplication *)application didFailToContinueUserActivityWithType:(NSString *)userActivityType error:(NSError *)error {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -359,7 +355,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
} }
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler { - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -371,7 +367,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: WatchKit // MARK: WatchKit
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply { - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -383,7 +379,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: HealthKit // MARK: HealthKit
- (void)applicationShouldRequestHealthAuthorization:(UIApplication *)application { - (void)applicationShouldRequestHealthAuthorization:(UIApplication *)application {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -395,7 +391,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: Opening an URL // MARK: Opening an URL
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -413,7 +409,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(UIApplicationExtensionPointIdentifier)extensionPointIdentifier { - (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(UIApplicationExtensionPointIdentifier)extensionPointIdentifier {
BOOL result = NO; BOOL result = NO;
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -429,7 +425,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: SiriKit // MARK: SiriKit
- (id)application:(UIApplication *)application handlerForIntent:(INIntent *)intent API_AVAILABLE(ios(14.0)) { - (id)application:(UIApplication *)application handlerForIntent:(INIntent *)intent API_AVAILABLE(ios(14.0)) {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }
@@ -447,7 +443,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
// MARK: CloudKit // MARK: CloudKit
- (void)application:(UIApplication *)application userDidAcceptCloudKitShareWithMetadata:(CKShareMetadata *)cloudKitShareMetadata { - (void)application:(UIApplication *)application userDidAcceptCloudKitShareWithMetadata:(CKShareMetadata *)cloudKitShareMetadata {
for (ApplicationDelegateService *service in services) { for (GDTAppDelegateServiceProtocol *service in services) {
if (![service respondsToSelector:_cmd]) { if (![service respondsToSelector:_cmd]) {
continue; continue;
} }

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_view.h */ /* godot_view_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -34,31 +34,39 @@
class String; class String;
@class GodotView; @class GDTView;
@protocol DisplayLayer; @protocol GDTDisplayLayer;
@protocol GodotViewRendererProtocol; @protocol GDTViewRendererProtocol;
@protocol GodotViewDelegate @protocol GDTViewDelegate
- (BOOL)godotViewFinishedSetup:(GodotView *)view; - (BOOL)godotViewFinishedSetup:(GDTView *)view;
@end @end
@interface GodotView : UIView @interface GDTView : UIView
@property(assign, nonatomic) id<GodotViewRendererProtocol> renderer; @property(assign, nonatomic) id<GDTViewRendererProtocol> renderer;
@property(assign, nonatomic) id<GodotViewDelegate> delegate; @property(assign, nonatomic) id<GDTViewDelegate> delegate;
@property(assign, readonly, nonatomic) BOOL isActive; @property(assign, readonly, nonatomic) BOOL isActive;
@property(assign, nonatomic) BOOL useCADisplayLink; @property(assign, nonatomic) BOOL useCADisplayLink;
@property(strong, readonly, nonatomic) CALayer<DisplayLayer> *renderingLayer; @property(strong, readonly, nonatomic) CALayer<GDTDisplayLayer> *renderingLayer;
@property(assign, readonly, nonatomic) BOOL canRender; @property(assign, readonly, nonatomic) BOOL canRender;
@property(assign, nonatomic) NSTimeInterval renderingInterval; @property(assign, nonatomic) NSTimeInterval renderingInterval;
- (CALayer<DisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName; // Can be extended by subclasses
- (void)godot_commonInit;
// Implemented in subclasses
- (CALayer<GDTDisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName;
- (void)stopRendering; - (void)stopRendering;
- (void)startRendering; - (void)startRendering;
@end @end
// Implemented in subclasses
extern GDTView *GDTViewCreate();

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_view.mm */ /* godot_view_apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "godot_view.h" #import "godot_view_apple_embedded.h"
#import "display_layer.h" #import "display_layer_apple_embedded.h"
#import "display_server_ios.h" #import "display_server_apple_embedded.h"
#import "godot_view_renderer.h" #import "godot_view_renderer.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
@@ -43,7 +43,7 @@
static const int max_touches = 32; static const int max_touches = 32;
static const float earth_gravity = 9.80665; static const float earth_gravity = 9.80665;
@interface GodotView () { @interface GDTView () {
UITouch *godot_touches[max_touches]; UITouch *godot_touches[max_touches];
} }
@@ -56,48 +56,17 @@ static const float earth_gravity = 9.80665;
// Only used if CADisplayLink is not // Only used if CADisplayLink is not
@property(strong, nonatomic) NSTimer *animationTimer; @property(strong, nonatomic) NSTimer *animationTimer;
@property(strong, nonatomic) CALayer<DisplayLayer> *renderingLayer; @property(strong, nonatomic) CALayer<GDTDisplayLayer> *renderingLayer;
@property(strong, nonatomic) CMMotionManager *motionManager; @property(strong, nonatomic) CMMotionManager *motionManager;
@end @end
@implementation GodotView @implementation GDTView
- (CALayer<DisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName { // Implemented in subclasses
if (self.renderingLayer) { - (CALayer<GDTDisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName {
return self.renderingLayer;
}
CALayer<DisplayLayer> *layer;
if ([driverName isEqualToString:@"vulkan"] || [driverName isEqualToString:@"metal"]) {
#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
if (@available(iOS 13, *)) {
layer = [GodotMetalLayer layer];
} else {
return nil; return nil;
}
#else
layer = [GodotMetalLayer layer];
#endif
} else if ([driverName isEqualToString:@"opengl3"]) {
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations") // OpenGL is deprecated in iOS 12.0.
layer = [GodotOpenGLLayer layer];
GODOT_CLANG_WARNING_POP
} 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 { - (instancetype)initWithCoder:(NSCoder *)coder {
@@ -148,7 +117,13 @@ static const float earth_gravity = 9.80665;
} }
- (void)godot_commonInit { - (void)godot_commonInit {
#if !defined(VISIONOS_ENABLED)
self.contentScaleFactor = [UIScreen mainScreen].scale; self.contentScaleFactor = [UIScreen mainScreen].scale;
#endif
if (@available(iOS 17.0, *)) {
[self registerForTraitChanges:@[ [UITraitUserInterfaceStyle class] ] withTarget:self action:@selector(traitCollectionDidChangeWithView:previousTraitCollection:)];
}
[self initTouches]; [self initTouches];
@@ -167,7 +142,7 @@ static const float earth_gravity = 9.80665;
} }
- (void)system_theme_changed { - (void)system_theme_changed {
DisplayServerIOS *ds = (DisplayServerIOS *)DisplayServer::get_singleton(); DisplayServerAppleEmbedded *ds = (DisplayServerAppleEmbedded *)DisplayServer::get_singleton();
if (ds) { if (ds) {
ds->emit_system_theme_changed(); ds->emit_system_theme_changed();
} }
@@ -175,8 +150,16 @@ static const float earth_gravity = 9.80665;
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
if (@available(iOS 13.0, *)) { if (@available(iOS 13.0, *)) {
#if !defined(VISIONOS_ENABLED)
[super traitCollectionDidChange:previousTraitCollection]; [super traitCollectionDidChange:previousTraitCollection];
#endif
[self traitCollectionDidChangeWithView:self
previousTraitCollection:previousTraitCollection];
}
}
- (void)traitCollectionDidChangeWithView:(UIView *)view previousTraitCollection:(UITraitCollection *)previousTraitCollection {
if (@available(iOS 13.0, *)) {
if ([UITraitCollection currentTraitCollection].userInterfaceStyle != previousTraitCollection.userInterfaceStyle) { if ([UITraitCollection currentTraitCollection].userInterfaceStyle != previousTraitCollection.userInterfaceStyle) {
[self system_theme_changed]; [self system_theme_changed];
} }
@@ -293,8 +276,8 @@ static const float earth_gravity = 9.80665;
self.renderingLayer.frame = self.bounds; self.renderingLayer.frame = self.bounds;
[self.renderingLayer layoutDisplayLayer]; [self.renderingLayer layoutDisplayLayer];
if (DisplayServerIOS::get_singleton()) { if (DisplayServerAppleEmbedded::get_singleton()) {
DisplayServerIOS::get_singleton()->resize_window(self.bounds.size); DisplayServerAppleEmbedded::get_singleton()->resize_window(self.bounds.size);
} }
} }
@@ -357,7 +340,7 @@ static const float earth_gravity = 9.80665;
int tid = [self getTouchIDForTouch:touch]; int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1); ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self]; CGPoint touchPoint = [touch locationInView:self];
DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); DisplayServerAppleEmbedded::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
} }
} }
@@ -369,7 +352,7 @@ static const float earth_gravity = 9.80665;
CGPoint prev_point = [touch previousLocationInView:self]; CGPoint prev_point = [touch previousLocationInView:self];
CGFloat alt = [touch altitudeAngle]; CGFloat alt = [touch altitudeAngle];
CGVector azim = [touch azimuthUnitVectorInView:self]; CGVector azim = [touch azimuthUnitVectorInView:self];
DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt)); DisplayServerAppleEmbedded::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
} }
} }
@@ -379,7 +362,7 @@ static const float earth_gravity = 9.80665;
ERR_FAIL_COND(tid == -1); ERR_FAIL_COND(tid == -1);
[self removeTouch:touch]; [self removeTouch:touch];
CGPoint touchPoint = [touch locationInView:self]; CGPoint touchPoint = [touch locationInView:self];
DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); DisplayServerAppleEmbedded::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
} }
} }
@@ -387,7 +370,7 @@ static const float earth_gravity = 9.80665;
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
int tid = [self getTouchIDForTouch:touch]; int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1); ERR_FAIL_COND(tid == -1);
DisplayServerIOS::get_singleton()->touches_canceled(tid); DisplayServerAppleEmbedded::get_singleton()->touches_canceled(tid);
} }
[self clearTouches]; [self clearTouches];
} }
@@ -440,6 +423,7 @@ static const float earth_gravity = 9.80665;
UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown; UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown;
#if !defined(VISIONOS_ENABLED)
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 140000 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 140000
interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
#else #else
@@ -451,31 +435,34 @@ static const float earth_gravity = 9.80665;
#endif #endif
} }
#endif #endif
#else
interfaceOrientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation;
#endif
switch (interfaceOrientation) { switch (interfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft: { case UIInterfaceOrientationLandscapeLeft: {
DisplayServerIOS::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), -Math::PI * 0.5));
} break; } break;
case UIInterfaceOrientationLandscapeRight: { case UIInterfaceOrientationLandscapeRight: {
DisplayServerIOS::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5));
DisplayServerIOS::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5)); DisplayServerAppleEmbedded::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), Math::PI * 0.5));
} break; } break;
case UIInterfaceOrientationPortraitUpsideDown: { case UIInterfaceOrientationPortraitUpsideDown: {
DisplayServerIOS::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), Math::PI)); DisplayServerAppleEmbedded::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z).rotated(Vector3(0, 0, 1), Math::PI));
DisplayServerIOS::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), Math::PI)); DisplayServerAppleEmbedded::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z).rotated(Vector3(0, 0, 1), Math::PI));
DisplayServerIOS::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), Math::PI)); DisplayServerAppleEmbedded::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z).rotated(Vector3(0, 0, 1), Math::PI));
DisplayServerIOS::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), Math::PI)); DisplayServerAppleEmbedded::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z).rotated(Vector3(0, 0, 1), Math::PI));
} break; } break;
default: { // assume portrait default: { // assume portrait
DisplayServerIOS::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z)); DisplayServerAppleEmbedded::get_singleton()->update_gravity(Vector3(gravity.x, gravity.y, gravity.z));
DisplayServerIOS::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z)); DisplayServerAppleEmbedded::get_singleton()->update_accelerometer(Vector3(acceleration.x + gravity.x, acceleration.y + gravity.y, acceleration.z + gravity.z));
DisplayServerIOS::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z)); DisplayServerAppleEmbedded::get_singleton()->update_magnetometer(Vector3(magnetic.x, magnetic.y, magnetic.z));
DisplayServerIOS::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z)); DisplayServerAppleEmbedded::get_singleton()->update_gyroscope(Vector3(rotation.x, rotation.y, rotation.z));
} break; } break;
} }
} }

View File

@@ -32,7 +32,7 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@protocol GodotViewRendererProtocol <NSObject> @protocol GDTViewRendererProtocol <NSObject>
@property(assign, readonly, nonatomic) BOOL hasFinishedSetup; @property(assign, readonly, nonatomic) BOOL hasFinishedSetup;
@@ -41,6 +41,6 @@
@end @end
@interface GodotViewRenderer : NSObject <GodotViewRendererProtocol> @interface GDTViewRenderer : NSObject <GDTViewRendererProtocol>
@end @end

View File

@@ -30,8 +30,8 @@
#import "godot_view_renderer.h" #import "godot_view_renderer.h"
#import "display_server_ios.h" #import "display_server_apple_embedded.h"
#import "os_ios.h" #import "os_apple_embedded.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
@@ -44,7 +44,7 @@
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@interface GodotViewRenderer () @interface GDTViewRenderer ()
@property(assign, nonatomic) BOOL hasFinishedProjectDataSetup; @property(assign, nonatomic) BOOL hasFinishedProjectDataSetup;
@property(assign, nonatomic) BOOL hasStartedMain; @property(assign, nonatomic) BOOL hasStartedMain;
@@ -52,7 +52,7 @@
@end @end
@implementation GodotViewRenderer @implementation GDTViewRenderer
- (BOOL)setupView:(UIView *)view { - (BOOL)setupView:(UIView *)view {
if (self.hasFinishedSetup) { if (self.hasFinishedSetup) {
@@ -70,7 +70,7 @@
if (!self.hasStartedMain) { if (!self.hasStartedMain) {
self.hasStartedMain = YES; self.hasStartedMain = YES;
OS_IOS::get_singleton()->start(); OS_AppleEmbedded::get_singleton()->start();
return YES; return YES;
} }
@@ -109,11 +109,11 @@
} }
- (void)renderOnView:(UIView *)view { - (void)renderOnView:(UIView *)view {
if (!OS_IOS::get_singleton()) { if (!OS_AppleEmbedded::get_singleton()) {
return; return;
} }
OS_IOS::get_singleton()->iterate(); OS_AppleEmbedded::get_singleton()->iterate();
} }
@end @end

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* key_mapping_ios.h */ /* key_mapping_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -34,8 +34,8 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
class KeyMappingIOS { class KeyMappingAppleEmbedded {
KeyMappingIOS() {} KeyMappingAppleEmbedded() {}
public: public:
static void initialize(); static void initialize();

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* key_mapping_ios.mm */ /* key_mapping_apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "key_mapping_ios.h" #import "key_mapping_apple_embedded.h"
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
@@ -40,7 +40,7 @@ struct HashMapHasherKeys {
HashMap<CFIndex, Key, HashMapHasherKeys> keyusage_map; HashMap<CFIndex, Key, HashMapHasherKeys> keyusage_map;
HashMap<CFIndex, KeyLocation, HashMapHasherKeys> location_map; HashMap<CFIndex, KeyLocation, HashMapHasherKeys> location_map;
void KeyMappingIOS::initialize() { void KeyMappingAppleEmbedded::initialize() {
if (@available(iOS 13.4, *)) { if (@available(iOS 13.4, *)) {
keyusage_map[UIKeyboardHIDUsageKeyboardA] = Key::A; keyusage_map[UIKeyboardHIDUsageKeyboardA] = Key::A;
keyusage_map[UIKeyboardHIDUsageKeyboardB] = Key::B; keyusage_map[UIKeyboardHIDUsageKeyboardB] = Key::B;
@@ -185,7 +185,7 @@ void KeyMappingIOS::initialize() {
} }
} }
Key KeyMappingIOS::remap_key(CFIndex p_keycode) { Key KeyMappingAppleEmbedded::remap_key(CFIndex p_keycode) {
if (@available(iOS 13.4, *)) { if (@available(iOS 13.4, *)) {
const Key *key = keyusage_map.getptr(p_keycode); const Key *key = keyusage_map.getptr(p_keycode);
if (key) { if (key) {
@@ -195,7 +195,7 @@ Key KeyMappingIOS::remap_key(CFIndex p_keycode) {
return Key::NONE; return Key::NONE;
} }
KeyLocation KeyMappingIOS::key_location(CFIndex p_keycode) { KeyLocation KeyMappingAppleEmbedded::key_location(CFIndex p_keycode) {
if (@available(iOS 13.4, *)) { if (@available(iOS 13.4, *)) {
const KeyLocation *location = location_map.getptr(p_keycode); const KeyLocation *location = location_map.getptr(p_keycode);
if (location) { if (location) {

View File

@@ -32,7 +32,7 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@interface GodotKeyboardInputView : UITextView @interface GDTKeyboardInputView : UITextView
- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; - (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end;

View File

@@ -30,19 +30,19 @@
#import "keyboard_input_view.h" #import "keyboard_input_view.h"
#import "display_server_ios.h" #import "display_server_apple_embedded.h"
#import "os_ios.h" #import "os_apple_embedded.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
@interface GodotKeyboardInputView () <UITextViewDelegate> @interface GDTKeyboardInputView () <UITextViewDelegate>
@property(nonatomic, copy) NSString *previousText; @property(nonatomic, copy) NSString *previousText;
@property(nonatomic, assign) NSRange previousSelectedRange; @property(nonatomic, assign) NSRange previousSelectedRange;
@end @end
@implementation GodotKeyboardInputView @implementation GDTKeyboardInputView
- (instancetype)initWithCoder:(NSCoder *)coder { - (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder]; self = [super initWithCoder:coder];
@@ -116,8 +116,8 @@
- (void)deleteText:(NSInteger)charactersToDelete { - (void)deleteText:(NSInteger)charactersToDelete {
for (int i = 0; i < charactersToDelete; i++) { for (int i = 0; i < charactersToDelete; i++) {
DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true, KeyLocation::UNSPECIFIED); DisplayServerAppleEmbedded::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true, KeyLocation::UNSPECIFIED);
DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false, KeyLocation::UNSPECIFIED); DisplayServerAppleEmbedded::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false, KeyLocation::UNSPECIFIED);
} }
} }
@@ -136,8 +136,8 @@
key = Key::SPACE; key = Key::SPACE;
} }
DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, true, KeyLocation::UNSPECIFIED); DisplayServerAppleEmbedded::get_singleton()->key(key, character, key, Key::NONE, 0, true, KeyLocation::UNSPECIFIED);
DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, false, KeyLocation::UNSPECIFIED); DisplayServerAppleEmbedded::get_singleton()->key(key, character, key, Key::NONE, 0, false, KeyLocation::UNSPECIFIED);
} }
} }

View File

@@ -0,0 +1,35 @@
/**************************************************************************/
/* main_utilities.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
void change_to_launch_dir(char **p_args);
int process_args(int p_argc, char **p_args, char **r_args);

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_ios.mm */ /* main_utilities.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,15 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "os_ios.h"
#include "core/string/ustring.h" #include "core/string/ustring.h"
#include "main/main.h"
#import <UIKit/UIKit.h>
#include <unistd.h> #include <unistd.h>
#include <cstdio> #include <cstdio>
static OS_IOS *os = nullptr; void change_to_launch_dir(char **p_args) {
size_t len = strlen(p_args[0]);
while (len--) {
if (p_args[0][len] == '/') {
break;
}
}
if (len >= 0) {
char path[512];
memcpy(path, p_args[0], len > sizeof(path) ? sizeof(path) : len);
path[len] = 0;
chdir(path);
}
}
int add_path(int p_argc, char **p_args) { int add_path(int p_argc, char **p_args) {
NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"]; NSString *str = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_path"];
@@ -70,50 +84,12 @@ int add_cmdline(int p_argc, char **p_args) {
return p_argc; return p_argc;
} }
int ios_main(int argc, char **argv) { int process_args(int p_argc, char **p_args, char **r_args) {
size_t len = strlen(argv[0]); for (int i = 0; i < p_argc; i++) {
r_args[i] = p_args[i];
while (len--) {
if (argv[0][len] == '/') {
break;
} }
} r_args[p_argc] = nullptr;
p_argc = add_path(p_argc, r_args);
if (len >= 0) { p_argc = add_cmdline(p_argc, r_args);
char path[512]; return p_argc;
memcpy(path, argv[0], len > sizeof(path) ? sizeof(path) : len);
path[len] = 0;
chdir(path);
}
os = new OS_IOS();
// 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);
Error err = Main::setup(fargv[0], argc - 1, &fargv[1], false);
if (err != OK) {
if (err == ERR_HELP) { // Returned by --help and --version, so success.
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
os->initialize_modules();
return os->get_exit_code();
}
void ios_finish() {
Main::cleanup();
delete os;
} }

View File

@@ -0,0 +1,137 @@
/**************************************************************************/
/* os_apple_embedded.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifdef APPLE_EMBEDDED_ENABLED
#import "apple_embedded.h"
#import "drivers/apple/joypad_apple.h"
#import "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
#include "servers/audio_server.h"
#include "servers/rendering/renderer_compositor.h"
#if defined(RD_ENABLED)
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#import "rendering_context_driver_vulkan_apple_embedded.h"
#endif
#endif
class OS_AppleEmbedded : public OS_Unix {
private:
static HashMap<String, void *> dynamic_symbol_lookup_table;
friend void register_dynamic_symbol(char *name, void *address);
AudioDriverCoreAudio audio_driver;
AppleEmbedded *apple_embedded = nullptr;
JoypadApple *joypad_apple = 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;
bool is_focused = false;
CGFloat _weight_to_ct(int p_weight) const;
CGFloat _stretch_to_ct(int p_stretch) const;
String _get_default_fontname(const String &p_font_name) const;
static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
void deinitialize_modules();
public:
static OS_AppleEmbedded *get_singleton();
OS_AppleEmbedded();
~OS_AppleEmbedded();
void initialize_modules();
bool iterate();
void start();
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
virtual Vector<String> get_system_fonts() const override;
virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = 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_distribution_name() const override;
virtual String get_version() const override;
virtual String get_model_name() const override;
virtual Error shell_open(const String &p_uri) override;
virtual String get_user_data_dir(const String &p_user_dir) const override;
virtual String get_cache_path() const override;
virtual String get_temp_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, float p_amplitude = -1.0) override;
virtual bool _check_internal_feature_support(const String &p_feature) override;
void on_focus_out();
void on_focus_in();
void on_enter_background();
void on_exit_background();
virtual Rect2 calculate_boot_screen_rect(const Size2 &p_window_size, const Size2 &p_imgrect_size) const override;
};
#endif // APPLE_EMBEDDED_ENABLED

View File

@@ -0,0 +1,717 @@
/**************************************************************************/
/* os_apple_embedded.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#import "os_apple_embedded.h"
#ifdef APPLE_EMBEDDED_ENABLED
#import "app_delegate_service.h"
#import "display_server_apple_embedded.h"
#import "godot_view_apple_embedded.h"
#import "terminal_logger_apple_embedded.h"
#import "view_controller.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 "drivers/unix/syslog_logger.h"
#include "main/main.h"
#import <AudioToolbox/AudioServices.h>
#import <CoreText/CoreText.h>
#import <UIKit/UIKit.h>
#import <dlfcn.h>
#include <sys/sysctl.h>
#if defined(RD_ENABLED)
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#import <QuartzCore/CAMetalLayer.h>
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/godot_vulkan.h"
#endif // VULKAN_ENABLED
#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 *apple_init_callbacks = nullptr;
static int apple_embedded_platform_init_callbacks_count = 0;
static int apple_embedded_platform_init_callbacks_capacity = 0;
HashMap<String, void *> OS_AppleEmbedded::dynamic_symbol_lookup_table;
void add_apple_embedded_platform_init_callback(init_callback cb) {
if (apple_embedded_platform_init_callbacks_count == apple_embedded_platform_init_callbacks_capacity) {
void *new_ptr = realloc(apple_init_callbacks, sizeof(cb) * (apple_embedded_platform_init_callbacks_capacity + 32));
if (new_ptr) {
apple_init_callbacks = (init_callback *)(new_ptr);
apple_embedded_platform_init_callbacks_capacity += 32;
} else {
ERR_FAIL_MSG("Unable to allocate memory for extension callbacks.");
}
}
apple_init_callbacks[apple_embedded_platform_init_callbacks_count++] = cb;
}
void register_dynamic_symbol(char *name, void *address) {
OS_AppleEmbedded::dynamic_symbol_lookup_table[String(name)] = address;
}
Rect2 fit_keep_aspect_centered(const Vector2 &p_container, const Vector2 &p_rect) {
real_t available_ratio = p_container.width / p_container.height;
real_t fit_ratio = p_rect.width / p_rect.height;
Rect2 result;
if (fit_ratio < available_ratio) {
// Fit height - we'll have horizontal gaps
result.size.height = p_container.height;
result.size.width = p_container.height * fit_ratio;
result.position.y = 0;
result.position.x = (p_container.width - result.size.width) * 0.5f;
} else {
// Fit width - we'll have vertical gaps
result.size.width = p_container.width;
result.size.height = p_container.width / fit_ratio;
result.position.x = 0;
result.position.y = (p_container.height - result.size.height) * 0.5f;
}
return result;
}
Rect2 fit_keep_aspect_covered(const Vector2 &p_container, const Vector2 &p_rect) {
real_t available_ratio = p_container.width / p_container.height;
real_t fit_ratio = p_rect.width / p_rect.height;
Rect2 result;
if (fit_ratio < available_ratio) {
// Need to scale up to fit width, and crop height
result.size.width = p_container.width;
result.size.height = p_container.width / fit_ratio;
result.position.x = 0;
result.position.y = (p_container.height - result.size.height) * 0.5f;
} else {
// Need to scale up to fit height, and crop width
result.size.width = p_container.height * fit_ratio;
result.size.height = p_container.height;
result.position.x = (p_container.width - result.size.width) * 0.5f;
result.position.y = 0;
}
return result;
}
OS_AppleEmbedded *OS_AppleEmbedded::get_singleton() {
return (OS_AppleEmbedded *)OS::get_singleton();
}
OS_AppleEmbedded::OS_AppleEmbedded() {
for (int i = 0; i < apple_embedded_platform_init_callbacks_count; ++i) {
apple_init_callbacks[i]();
}
free(apple_init_callbacks);
apple_init_callbacks = nullptr;
apple_embedded_platform_init_callbacks_count = 0;
apple_embedded_platform_init_callbacks_capacity = 0;
main_loop = nullptr;
Vector<Logger *> loggers;
loggers.push_back(memnew(TerminalLoggerAppleEmbedded));
_set_logger(memnew(CompositeLogger(loggers)));
AudioDriverManager::add_driver(&audio_driver);
}
OS_AppleEmbedded::~OS_AppleEmbedded() {}
void OS_AppleEmbedded::alert(const String &p_alert, const String &p_title) {
const CharString utf8_alert = p_alert.utf8();
const CharString utf8_title = p_title.utf8();
AppleEmbedded::alert(utf8_alert.get_data(), utf8_title.get_data());
}
void OS_AppleEmbedded::initialize_core() {
OS_Unix::initialize_core();
}
void OS_AppleEmbedded::initialize() {
initialize_core();
}
void OS_AppleEmbedded::initialize_joypads() {
joypad_apple = memnew(JoypadApple);
}
void OS_AppleEmbedded::initialize_modules() {
apple_embedded = memnew(AppleEmbedded);
Engine::get_singleton()->add_singleton(Engine::Singleton("AppleEmbedded", apple_embedded));
}
void OS_AppleEmbedded::deinitialize_modules() {
if (joypad_apple) {
memdelete(joypad_apple);
}
if (apple_embedded) {
memdelete(apple_embedded);
}
}
void OS_AppleEmbedded::set_main_loop(MainLoop *p_main_loop) {
main_loop = p_main_loop;
}
MainLoop *OS_AppleEmbedded::get_main_loop() const {
return main_loop;
}
void OS_AppleEmbedded::delete_main_loop() {
if (main_loop) {
main_loop->finalize();
memdelete(main_loop);
}
main_loop = nullptr;
}
bool OS_AppleEmbedded::iterate() {
if (!main_loop) {
return true;
}
if (DisplayServer::get_singleton()) {
DisplayServer::get_singleton()->process_events();
}
joypad_apple->process_joypads();
return Main::iteration();
}
void OS_AppleEmbedded::start() {
if (Main::start() == EXIT_SUCCESS) {
main_loop->initialize();
}
}
void OS_AppleEmbedded::finalize() {
deinitialize_modules();
// Already gets called
//delete_main_loop();
}
// MARK: Dynamic Libraries
_FORCE_INLINE_ String OS_AppleEmbedded::get_framework_executable(const String &p_path) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
// Read framework bundle to get executable name.
NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
NSBundle *bundle = [NSBundle bundleWithURL:url];
if (bundle) {
String exe_path = String::utf8([[bundle executablePath] UTF8String]);
if (da->file_exists(exe_path)) {
return exe_path;
}
}
// Try default executable name (invalid framework).
if (da->dir_exists(p_path) && da->file_exists(p_path.path_join(p_path.get_file().get_basename()))) {
return p_path.path_join(p_path.get_file().get_basename());
}
// Not a framework, try loading as .dylib.
return p_path;
}
Error OS_AppleEmbedded::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
if (p_path.length() == 0) {
// Static xcframework.
p_library_handle = RTLD_SELF;
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
*p_data->r_resolved_path = p_path;
}
return OK;
}
String path = get_framework_executable(p_path);
if (!FileAccess::exists(path)) {
// Load .dylib or framework from within the executable path.
path = get_framework_executable(get_executable_path().get_base_dir().path_join(p_path.get_file()));
}
if (!FileAccess::exists(path)) {
// Load .dylib converted to framework from within the executable path.
path = get_framework_executable(get_executable_path().get_base_dir().path_join(p_path.get_file().get_basename() + ".framework"));
}
if (!FileAccess::exists(path)) {
// Load .dylib or framework from a standard iOS location.
path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(p_path.get_file()));
}
if (!FileAccess::exists(path)) {
// Load .dylib converted to framework from a standard iOS location.
path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(p_path.get_file().get_basename() + ".framework"));
}
ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
*p_data->r_resolved_path = path;
}
return OK;
}
Error OS_AppleEmbedded::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 OS_AppleEmbedded::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 = OS_AppleEmbedded::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 OS_AppleEmbedded::get_distribution_name() const {
return get_name();
}
String OS_AppleEmbedded::get_version() const {
NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
}
String OS_AppleEmbedded::get_model_name() const {
String model = apple_embedded->get_model();
if (model != "") {
return model;
}
return OS_Unix::get_model_name();
}
Error OS_AppleEmbedded::shell_open(const 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;
}
print_verbose(vformat("Opening URL %s", p_uri));
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
return OK;
}
String OS_AppleEmbedded::get_user_data_dir(const String &p_user_dir) const {
static String ret;
if (ret.is_empty()) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if (paths && [paths count] >= 1) {
ret.append_utf8([[paths firstObject] UTF8String]);
}
}
return ret;
}
String OS_AppleEmbedded::get_cache_path() const {
static String ret;
if (ret.is_empty()) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if (paths && [paths count] >= 1) {
ret.append_utf8([[paths firstObject] UTF8String]);
}
}
return ret;
}
String OS_AppleEmbedded::get_temp_path() const {
static String ret;
if (ret.is_empty()) {
NSURL *url = [NSURL fileURLWithPath:NSTemporaryDirectory()
isDirectory:YES];
if (url) {
ret = String::utf8([url.path UTF8String]);
ret = ret.trim_prefix("file://");
}
}
return ret;
}
String OS_AppleEmbedded::get_locale() const {
NSString *preferredLanguage = [NSLocale preferredLanguages].firstObject;
if (preferredLanguage) {
return String::utf8([preferredLanguage UTF8String]).replace_char('-', '_');
}
NSString *localeIdentifier = [[NSLocale currentLocale] localeIdentifier];
return String::utf8([localeIdentifier UTF8String]).replace_char('-', '_');
}
String OS_AppleEmbedded::get_unique_id() const {
NSString *uuid = [UIDevice currentDevice].identifierForVendor.UUIDString;
return String::utf8([uuid UTF8String]);
}
String OS_AppleEmbedded::get_processor_name() const {
char buffer[256];
size_t buffer_len = 256;
if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, nullptr, 0) == 0) {
return String::utf8(buffer, buffer_len);
}
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
}
Vector<String> OS_AppleEmbedded::get_system_fonts() const {
HashSet<String> font_names;
CFArrayRef fonts = CTFontManagerCopyAvailableFontFamilyNames();
if (fonts) {
for (CFIndex i = 0; i < CFArrayGetCount(fonts); i++) {
CFStringRef cf_name = (CFStringRef)CFArrayGetValueAtIndex(fonts, i);
if (cf_name && (CFStringGetLength(cf_name) > 0) && (CFStringCompare(cf_name, CFSTR("LastResort"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && (CFStringGetCharacterAtIndex(cf_name, 0) != '.')) {
NSString *ns_name = (__bridge NSString *)cf_name;
font_names.insert(String::utf8([ns_name UTF8String]));
}
}
CFRelease(fonts);
}
Vector<String> ret;
for (const String &E : font_names) {
ret.push_back(E);
}
return ret;
}
String OS_AppleEmbedded::_get_default_fontname(const String &p_font_name) const {
String font_name = p_font_name;
if (font_name.to_lower() == "sans-serif") {
font_name = "Helvetica";
} else if (font_name.to_lower() == "serif") {
font_name = "Times";
} else if (font_name.to_lower() == "monospace") {
font_name = "Courier";
} else if (font_name.to_lower() == "fantasy") {
font_name = "Papyrus";
} else if (font_name.to_lower() == "cursive") {
font_name = "Apple Chancery";
};
return font_name;
}
CGFloat OS_AppleEmbedded::_weight_to_ct(int p_weight) const {
if (p_weight < 150) {
return -0.80;
} else if (p_weight < 250) {
return -0.60;
} else if (p_weight < 350) {
return -0.40;
} else if (p_weight < 450) {
return 0.0;
} else if (p_weight < 550) {
return 0.23;
} else if (p_weight < 650) {
return 0.30;
} else if (p_weight < 750) {
return 0.40;
} else if (p_weight < 850) {
return 0.56;
} else if (p_weight < 925) {
return 0.62;
} else {
return 1.00;
}
}
CGFloat OS_AppleEmbedded::_stretch_to_ct(int p_stretch) const {
if (p_stretch < 56) {
return -0.5;
} else if (p_stretch < 69) {
return -0.37;
} else if (p_stretch < 81) {
return -0.25;
} else if (p_stretch < 93) {
return -0.13;
} else if (p_stretch < 106) {
return 0.0;
} else if (p_stretch < 137) {
return 0.13;
} else if (p_stretch < 144) {
return 0.25;
} else if (p_stretch < 162) {
return 0.37;
} else {
return 0.5;
}
}
Vector<String> OS_AppleEmbedded::get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale, const String &p_script, int p_weight, int p_stretch, bool p_italic) const {
Vector<String> ret;
String font_name = _get_default_fontname(p_font_name);
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
CTFontSymbolicTraits traits = 0;
if (p_weight >= 700) {
traits |= kCTFontBoldTrait;
}
if (p_italic) {
traits |= kCTFontItalicTrait;
}
if (p_stretch < 100) {
traits |= kCTFontCondensedTrait;
} else if (p_stretch > 100) {
traits |= kCTFontExpandedTrait;
}
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
CGFloat weight = _weight_to_ct(p_weight);
CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
CGFloat stretch = _stretch_to_ct(p_stretch);
CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
if (font) {
CTFontRef family = CTFontCreateWithFontDescriptor(font, 0, nullptr);
if (family) {
CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, p_text.utf8().get_data(), kCFStringEncodingUTF8);
CFRange range = CFRangeMake(0, CFStringGetLength(string));
CTFontRef fallback_family = CTFontCreateForString(family, string, range);
if (fallback_family) {
CTFontDescriptorRef fallback_font = CTFontCopyFontDescriptor(fallback_family);
if (fallback_font) {
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fallback_font, kCTFontURLAttribute);
if (url) {
NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
ret.push_back(String::utf8([font_path UTF8String]));
CFRelease(url);
}
CFRelease(fallback_font);
}
CFRelease(fallback_family);
}
CFRelease(string);
CFRelease(family);
}
CFRelease(font);
}
CFRelease(attributes);
CFRelease(traits_dict);
CFRelease(sym_traits);
CFRelease(font_stretch);
CFRelease(font_weight);
CFRelease(name);
return ret;
}
String OS_AppleEmbedded::get_system_font_path(const String &p_font_name, int p_weight, int p_stretch, bool p_italic) const {
String ret;
String font_name = _get_default_fontname(p_font_name);
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name.utf8().get_data(), kCFStringEncodingUTF8);
CTFontSymbolicTraits traits = 0;
if (p_weight >= 700) {
traits |= kCTFontBoldTrait;
}
if (p_italic) {
traits |= kCTFontItalicTrait;
}
if (p_stretch < 100) {
traits |= kCTFontCondensedTrait;
} else if (p_stretch > 100) {
traits |= kCTFontExpandedTrait;
}
CFNumberRef sym_traits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &traits);
CFMutableDictionaryRef traits_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(traits_dict, kCTFontSymbolicTrait, sym_traits);
CGFloat weight = _weight_to_ct(p_weight);
CFNumberRef font_weight = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &weight);
CFDictionaryAddValue(traits_dict, kCTFontWeightTrait, font_weight);
CGFloat stretch = _stretch_to_ct(p_stretch);
CFNumberRef font_stretch = CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &stretch);
CFDictionaryAddValue(traits_dict, kCTFontWidthTrait, font_stretch);
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr);
CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, name);
CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits_dict);
CTFontDescriptorRef font = CTFontDescriptorCreateWithAttributes(attributes);
if (font) {
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(font, kCTFontURLAttribute);
if (url) {
NSString *font_path = [NSString stringWithString:[(__bridge NSURL *)url path]];
ret = String::utf8([font_path UTF8String]);
CFRelease(url);
}
CFRelease(font);
}
CFRelease(attributes);
CFRelease(traits_dict);
CFRelease(sym_traits);
CFRelease(font_stretch);
CFRelease(font_weight);
CFRelease(name);
return ret;
}
void OS_AppleEmbedded::vibrate_handheld(int p_duration_ms, float p_amplitude) {
if (apple_embedded->supports_haptic_engine()) {
if (p_amplitude > 0.0) {
p_amplitude = CLAMP(p_amplitude, 0.0, 1.0);
}
apple_embedded->vibrate_haptic_engine((float)p_duration_ms / 1000.f, p_amplitude);
} else {
// iOS <13 does not support duration for vibration
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
bool OS_AppleEmbedded::_check_internal_feature_support(const String &p_feature) {
if (p_feature == "system_fonts") {
return true;
}
if (p_feature == "mobile") {
return true;
}
return false;
}
void OS_AppleEmbedded::on_focus_out() {
if (is_focused) {
is_focused = false;
if (DisplayServerAppleEmbedded::get_singleton()) {
DisplayServerAppleEmbedded::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
}
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
}
[GDTAppDelegateService.viewController.godotView stopRendering];
audio_driver.stop();
}
}
void OS_AppleEmbedded::on_focus_in() {
if (!is_focused) {
is_focused = true;
if (DisplayServerAppleEmbedded::get_singleton()) {
DisplayServerAppleEmbedded::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN);
}
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
}
[GDTAppDelegateService.viewController.godotView startRendering];
audio_driver.start();
}
}
void OS_AppleEmbedded::on_enter_background() {
// Do not check for is_focused, because on_focus_out will always be fired first by applicationWillResignActive.
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED);
}
on_focus_out();
}
void OS_AppleEmbedded::on_exit_background() {
if (!is_focused) {
on_focus_in();
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED);
}
}
}
Rect2 OS_AppleEmbedded::calculate_boot_screen_rect(const Size2 &p_window_size, const Size2 &p_imgrect_size) const {
String scalemodestr = GLOBAL_GET("ios/launch_screen_image_mode");
if (scalemodestr == "scaleAspectFit") {
return fit_keep_aspect_centered(p_window_size, p_imgrect_size);
} else if (scalemodestr == "scaleAspectFill") {
return fit_keep_aspect_covered(p_window_size, p_imgrect_size);
} else if (scalemodestr == "scaleToFill") {
return Rect2(Point2(), p_window_size);
} else if (scalemodestr == "center") {
return OS_Unix::calculate_boot_screen_rect(p_window_size, p_imgrect_size);
} else {
WARN_PRINT(vformat("Boot screen scale mode mismatch between iOS and Godot: %s not supported", scalemodestr));
return OS_Unix::calculate_boot_screen_rect(p_window_size, p_imgrect_size);
}
}
#endif // APPLE_EMBEDDED_ENABLED

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* platform_config.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include <alloca.h>
#define PLATFORM_THREAD_OVERRIDE
#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")

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* rendering_context_driver_vulkan_ios.h */ /* rendering_context_driver_vulkan_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -36,7 +36,7 @@
#import <QuartzCore/CAMetalLayer.h> #import <QuartzCore/CAMetalLayer.h>
class RenderingContextDriverVulkanIOS : public RenderingContextDriverVulkan { class RenderingContextDriverVulkanAppleEmbedded : public RenderingContextDriverVulkan {
private: private:
virtual const char *_get_platform_surface_extension() const override final; virtual const char *_get_platform_surface_extension() const override final;
@@ -48,8 +48,8 @@ public:
CAMetalLayer *const *layer_ptr; CAMetalLayer *const *layer_ptr;
}; };
RenderingContextDriverVulkanIOS(); RenderingContextDriverVulkanAppleEmbedded();
~RenderingContextDriverVulkanIOS(); ~RenderingContextDriverVulkanAppleEmbedded();
}; };
#endif // VULKAN_ENABLED #endif // VULKAN_ENABLED

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* rendering_context_driver_vulkan_ios.mm */ /* rendering_context_driver_vulkan_apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "rendering_context_driver_vulkan_ios.h" #import "rendering_context_driver_vulkan_apple_embedded.h"
#ifdef VULKAN_ENABLED #ifdef VULKAN_ENABLED
@@ -38,11 +38,11 @@
#include <vulkan/vulkan_metal.h> #include <vulkan/vulkan_metal.h>
#endif #endif
const char *RenderingContextDriverVulkanIOS::_get_platform_surface_extension() const { const char *RenderingContextDriverVulkanAppleEmbedded::_get_platform_surface_extension() const {
return VK_EXT_METAL_SURFACE_EXTENSION_NAME; return VK_EXT_METAL_SURFACE_EXTENSION_NAME;
} }
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanIOS::surface_create(const void *p_platform_data) { RenderingContextDriver::SurfaceID RenderingContextDriverVulkanAppleEmbedded::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data); const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkMetalSurfaceCreateInfoEXT create_info = {}; VkMetalSurfaceCreateInfoEXT create_info = {};
@@ -58,11 +58,11 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanIOS::surface_creat
return SurfaceID(surface); return SurfaceID(surface);
} }
RenderingContextDriverVulkanIOS::RenderingContextDriverVulkanIOS() { RenderingContextDriverVulkanAppleEmbedded::RenderingContextDriverVulkanAppleEmbedded() {
// Does nothing. // Does nothing.
} }
RenderingContextDriverVulkanIOS::~RenderingContextDriverVulkanIOS() { RenderingContextDriverVulkanAppleEmbedded::~RenderingContextDriverVulkanAppleEmbedded() {
// Does nothing. // Does nothing.
} }

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* ios_terminal_logger.h */ /* terminal_logger_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -30,13 +30,13 @@
#pragma once #pragma once
#ifdef IOS_ENABLED #ifdef APPLE_EMBEDDED_ENABLED
#include "core/io/logger.h" #include "core/io/logger.h"
class IOSTerminalLogger : public StdLogger { class TerminalLoggerAppleEmbedded : public StdLogger {
public: public:
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces = {}) override; virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces = {}) override;
}; };
#endif // IOS_ENABLED #endif // APPLE_EMBEDDED_ENABLED

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* ios_terminal_logger.mm */ /* terminal_logger_apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "ios_terminal_logger.h" #import "terminal_logger_apple_embedded.h"
#ifdef IOS_ENABLED #ifdef APPLE_EMBEDDED_ENABLED
#import <os/log.h> #import <os/log.h>
void IOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces) { void TerminalLoggerAppleEmbedded::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces) {
if (!should_log(true)) { if (!should_log(true)) {
return; return;
} }
@@ -77,4 +77,4 @@ void IOSTerminalLogger::log_error(const char *p_function, const char *p_file, in
} }
} }
#endif // IOS_ENABLED #endif // APPLE_EMBEDDED_ENABLED

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* tts_ios.h */ /* tts_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -42,7 +42,7 @@
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
#endif #endif
@interface TTS_IOS : NSObject <AVSpeechSynthesizerDelegate> { @interface GDTTTS : NSObject <AVSpeechSynthesizerDelegate> {
bool speaking; bool speaking;
HashMap<id, int> ids; HashMap<id, int> ids;

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* tts_ios.mm */ /* tts_apple_embedded.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "tts_ios.h" #import "tts_apple_embedded.h"
@implementation TTS_IOS @implementation GDTTTS
- (id)init { - (id)init {
self = [super init]; self = [super init];

View File

@@ -32,13 +32,12 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@class GodotView; @class GDTView;
@class GodotNativeVideoView; @class GDTKeyboardInputView;
@class GodotKeyboardInputView;
@interface ViewController : UIViewController @interface GDTViewController : UIViewController
@property(nonatomic, readonly, strong) GodotView *godotView; @property(nonatomic, readonly, strong) GDTView *godotView;
@property(nonatomic, readonly, strong) GodotKeyboardInputView *keyboardView; @property(nonatomic, readonly, strong) GDTKeyboardInputView *keyboardView;
@end @end

View File

@@ -30,44 +30,44 @@
#import "view_controller.h" #import "view_controller.h"
#import "display_server_ios.h" #import "display_server_apple_embedded.h"
#import "godot_view.h" #import "godot_view_apple_embedded.h"
#import "godot_view_renderer.h" #import "godot_view_renderer.h"
#import "key_mapping_ios.h" #import "key_mapping_apple_embedded.h"
#import "keyboard_input_view.h" #import "keyboard_input_view.h"
#import "os_ios.h" #import "os_apple_embedded.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
#import <GameController/GameController.h> #import <GameController/GameController.h>
@interface ViewController () <GodotViewDelegate> @interface GDTViewController () <GDTViewDelegate>
@property(strong, nonatomic) GodotViewRenderer *renderer; @property(strong, nonatomic) GDTViewRenderer *renderer;
@property(strong, nonatomic) GodotKeyboardInputView *keyboardView; @property(strong, nonatomic) GDTKeyboardInputView *keyboardView;
@property(strong, nonatomic) UIView *godotLoadingOverlay; @property(strong, nonatomic) UIView *godotLoadingOverlay;
@end @end
@implementation ViewController @implementation GDTViewController
- (GodotView *)godotView { - (GDTView *)godotView {
return (GodotView *)self.view; return (GDTView *)self.view;
} }
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event { - (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
[super pressesBegan:presses withEvent:event]; [super pressesBegan:presses withEvent:event];
if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) { if (!DisplayServerAppleEmbedded::get_singleton() || DisplayServerAppleEmbedded::get_singleton()->is_keyboard_active()) {
return; return;
} }
if (@available(iOS 13.4, *)) { if (@available(iOS 13.4, *)) {
for (UIPress *press in presses) { for (UIPress *press in presses) {
String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]); String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]);
String u32text = String::utf8([press.key.characters UTF8String]); String u32text = String::utf8([press.key.characters UTF8String]);
Key key = KeyMappingIOS::remap_key(press.key.keyCode); Key key = KeyMappingAppleEmbedded::remap_key(press.key.keyCode);
if (press.key.keyCode == 0 && u32text.is_empty() && u32lbl.is_empty()) { if (press.key.keyCode == 0 && u32text.is_empty() && u32lbl.is_empty()) {
continue; continue;
@@ -78,15 +78,15 @@
us = u32lbl[0]; us = u32lbl[0];
} }
KeyLocation location = KeyMappingIOS::key_location(press.key.keyCode); KeyLocation location = KeyMappingAppleEmbedded::key_location(press.key.keyCode);
if (!u32text.is_empty() && !u32text.begins_with("UIKey")) { if (!u32text.is_empty() && !u32text.begins_with("UIKey")) {
for (int i = 0; i < u32text.length(); i++) { for (int i = 0; i < u32text.length(); i++) {
const char32_t c = u32text[i]; const char32_t c = u32text[i];
DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true, location); DisplayServerAppleEmbedded::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true, location);
} }
} else { } else {
DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true, location); DisplayServerAppleEmbedded::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true, location);
} }
} }
} }
@@ -95,13 +95,13 @@
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event { - (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
[super pressesEnded:presses withEvent:event]; [super pressesEnded:presses withEvent:event];
if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) { if (!DisplayServerAppleEmbedded::get_singleton() || DisplayServerAppleEmbedded::get_singleton()->is_keyboard_active()) {
return; return;
} }
if (@available(iOS 13.4, *)) { if (@available(iOS 13.4, *)) {
for (UIPress *press in presses) { for (UIPress *press in presses) {
String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]); String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]);
Key key = KeyMappingIOS::remap_key(press.key.keyCode); Key key = KeyMappingAppleEmbedded::remap_key(press.key.keyCode);
if (press.key.keyCode == 0 && u32lbl.is_empty()) { if (press.key.keyCode == 0 && u32lbl.is_empty()) {
continue; continue;
@@ -112,16 +112,16 @@
us = u32lbl[0]; us = u32lbl[0];
} }
KeyLocation location = KeyMappingIOS::key_location(press.key.keyCode); KeyLocation location = KeyMappingAppleEmbedded::key_location(press.key.keyCode);
DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false, location); DisplayServerAppleEmbedded::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false, location);
} }
} }
} }
- (void)loadView { - (void)loadView {
GodotView *view = [[GodotView alloc] init]; GDTView *view = GDTViewCreate();
GodotViewRenderer *renderer = [[GodotViewRenderer alloc] init]; GDTViewRenderer *renderer = [[GDTViewRenderer alloc] init];
self.renderer = renderer; self.renderer = renderer;
self.view = view; self.view = view;
@@ -170,7 +170,7 @@
- (void)observeKeyboard { - (void)observeKeyboard {
print_verbose("Setting up keyboard input view."); print_verbose("Setting up keyboard input view.");
self.keyboardView = [GodotKeyboardInputView new]; self.keyboardView = [GDTKeyboardInputView new];
[self.view addSubview:self.keyboardView]; [self.view addSubview:self.keyboardView];
print_verbose("Adding observer for keyboard show/hide."); print_verbose("Adding observer for keyboard show/hide.");
@@ -187,6 +187,7 @@
} }
- (void)displayLoadingOverlay { - (void)displayLoadingOverlay {
#if !defined(VISIONOS_ENABLED)
NSBundle *bundle = [NSBundle mainBundle]; NSBundle *bundle = [NSBundle mainBundle];
NSString *storyboardName = @"Launch Screen"; NSString *storyboardName = @"Launch Screen";
@@ -202,9 +203,10 @@
self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.godotLoadingOverlay]; [self.view addSubview:self.godotLoadingOverlay];
#endif
} }
- (BOOL)godotViewFinishedSetup:(GodotView *)view { - (BOOL)godotViewFinishedSetup:(GDTView *)view {
[self.godotLoadingOverlay removeFromSuperview]; [self.godotLoadingOverlay removeFromSuperview];
self.godotLoadingOverlay = nil; self.godotLoadingOverlay = nil;
@@ -235,11 +237,11 @@
} }
- (BOOL)shouldAutorotate { - (BOOL)shouldAutorotate {
if (!DisplayServerIOS::get_singleton()) { if (!DisplayServerAppleEmbedded::get_singleton()) {
return NO; return NO;
} }
switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { switch (DisplayServerAppleEmbedded::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
case DisplayServer::SCREEN_SENSOR: case DisplayServer::SCREEN_SENSOR:
case DisplayServer::SCREEN_SENSOR_LANDSCAPE: case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
case DisplayServer::SCREEN_SENSOR_PORTRAIT: case DisplayServer::SCREEN_SENSOR_PORTRAIT:
@@ -250,11 +252,11 @@
} }
- (UIInterfaceOrientationMask)supportedInterfaceOrientations { - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
if (!DisplayServerIOS::get_singleton()) { if (!DisplayServerAppleEmbedded::get_singleton()) {
return UIInterfaceOrientationMaskAll; return UIInterfaceOrientationMaskAll;
} }
switch (DisplayServerIOS::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) { switch (DisplayServerAppleEmbedded::get_singleton()->screen_get_orientation(DisplayServer::SCREEN_OF_MAIN_WINDOW)) {
case DisplayServer::SCREEN_PORTRAIT: case DisplayServer::SCREEN_PORTRAIT:
return UIInterfaceOrientationMaskPortrait; return UIInterfaceOrientationMaskPortrait;
case DisplayServer::SCREEN_REVERSE_LANDSCAPE: case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
@@ -305,14 +307,14 @@
CGRect rawFrame = [value CGRectValue]; CGRect rawFrame = [value CGRectValue];
CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil]; CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil];
if (DisplayServerIOS::get_singleton()) { if (DisplayServerAppleEmbedded::get_singleton()) {
DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height); DisplayServerAppleEmbedded::get_singleton()->virtual_keyboard_set_height(keyboardFrame.size.height);
} }
} }
- (void)keyboardHidden:(NSNotification *)notification { - (void)keyboardHidden:(NSNotification *)notification {
if (DisplayServerIOS::get_singleton()) { if (DisplayServerAppleEmbedded::get_singleton()) {
DisplayServerIOS::get_singleton()->virtual_keyboard_set_height(0); DisplayServerAppleEmbedded::get_singleton()->virtual_keyboard_set_height(0);
} }
} }

View File

@@ -34,7 +34,6 @@
#include "core/string/print_string.h" #include "core/string/print_string.h"
#import <CoreAudio/HostTime.h>
#import <CoreServices/CoreServices.h> #import <CoreServices/CoreServices.h>
Mutex MIDIDriverCoreMidi::mutex; Mutex MIDIDriverCoreMidi::mutex;

View File

@@ -39,6 +39,9 @@ if "-std=gnu++17" in env_metal["CXXFLAGS"]:
env_metal["CXXFLAGS"].remove("-std=gnu++17") env_metal["CXXFLAGS"].remove("-std=gnu++17")
env_metal.Append(CXXFLAGS=["-std=c++20"]) env_metal.Append(CXXFLAGS=["-std=c++20"])
# Enable module support
env_metal.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
# Driver source files # Driver source files
driver_obj = [] driver_obj = []

View File

@@ -50,6 +50,8 @@
#import "metal_device_properties.h" #import "metal_device_properties.h"
#include "servers/rendering/renderer_rd/effects/metal_fx.h"
#import <Metal/Metal.h> #import <Metal/Metal.h>
#import <MetalFX/MetalFX.h> #import <MetalFX/MetalFX.h>
#import <spirv_cross.hpp> #import <spirv_cross.hpp>
@@ -63,7 +65,7 @@
#define MTLGPUFamilyApple9 (MTLGPUFamily)1009 #define MTLGPUFamilyApple9 (MTLGPUFamily)1009
#endif #endif
API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), visionos(1.0))
MTLGPUFamily &operator--(MTLGPUFamily &p_family) { MTLGPUFamily &operator--(MTLGPUFamily &p_family) {
p_family = static_cast<MTLGPUFamily>(static_cast<int>(p_family) - 1); p_family = static_cast<MTLGPUFamily>(static_cast<int>(p_family) - 1);
if (p_family < MTLGPUFamilyApple1) { if (p_family < MTLGPUFamilyApple1) {
@@ -126,7 +128,11 @@ void MetalDeviceProperties::init_features(id<MTLDevice> p_device) {
if (@available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) { if (@available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) {
features.metal_fx_spatial = [MTLFXSpatialScalerDescriptor supportsDevice:p_device]; features.metal_fx_spatial = [MTLFXSpatialScalerDescriptor supportsDevice:p_device];
#ifdef METAL_MFXTEMPORAL_ENABLED
features.metal_fx_temporal = [MTLFXTemporalScalerDescriptor supportsDevice:p_device]; features.metal_fx_temporal = [MTLFXTemporalScalerDescriptor supportsDevice:p_device];
#else
features.metal_fx_temporal = false;
#endif
} }
MTLCompileOptions *opts = [MTLCompileOptions new]; MTLCompileOptions *opts = [MTLCompileOptions new];
@@ -136,7 +142,7 @@ void MetalDeviceProperties::init_features(id<MTLDevice> p_device) {
features.mslVersion = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::make_msl_version(m_maj, m_min) features.mslVersion = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::make_msl_version(m_maj, m_min)
switch (features.mslVersionEnum) { switch (features.mslVersionEnum) {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 150000 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 180000 || __TV_OS_VERSION_MAX_ALLOWED >= 180000 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 150000 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 180000 || __TV_OS_VERSION_MAX_ALLOWED >= 180000 || __VISION_OS_VERSION_MAX_ALLOWED >= 20000
case MTLLanguageVersion3_2: case MTLLanguageVersion3_2:
setMSLVersion(3, 2); setMSLVersion(3, 2);
break; break;
@@ -170,7 +176,7 @@ void MetalDeviceProperties::init_features(id<MTLDevice> p_device) {
case MTLLanguageVersion1_1: case MTLLanguageVersion1_1:
setMSLVersion(1, 1); setMSLVersion(1, 1);
break; break;
#if TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST #if TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST && !TARGET_OS_VISION
case MTLLanguageVersion1_0: case MTLLanguageVersion1_0:
setMSLVersion(1, 0); setMSLVersion(1, 0);
break; break;
@@ -324,6 +330,7 @@ void MetalDeviceProperties::init_limits(id<MTLDevice> p_device) {
limits.maxDrawIndexedIndexValue = std::numeric_limits<uint32_t>::max() - 1; limits.maxDrawIndexedIndexValue = std::numeric_limits<uint32_t>::max() - 1;
#ifdef METAL_MFXTEMPORAL_ENABLED
if (@available(macOS 14.0, iOS 17.0, tvOS 17.0, *)) { if (@available(macOS 14.0, iOS 17.0, tvOS 17.0, *)) {
limits.temporalScalerInputContentMinScale = (double)[MTLFXTemporalScalerDescriptor supportedInputContentMinScaleForDevice:p_device]; limits.temporalScalerInputContentMinScale = (double)[MTLFXTemporalScalerDescriptor supportedInputContentMinScaleForDevice:p_device];
limits.temporalScalerInputContentMaxScale = (double)[MTLFXTemporalScalerDescriptor supportedInputContentMaxScaleForDevice:p_device]; limits.temporalScalerInputContentMaxScale = (double)[MTLFXTemporalScalerDescriptor supportedInputContentMaxScaleForDevice:p_device];
@@ -332,6 +339,11 @@ void MetalDeviceProperties::init_limits(id<MTLDevice> p_device) {
limits.temporalScalerInputContentMinScale = 1.0; limits.temporalScalerInputContentMinScale = 1.0;
limits.temporalScalerInputContentMaxScale = 3.0; limits.temporalScalerInputContentMaxScale = 3.0;
} }
#else
// Defaults taken from macOS 14+
limits.temporalScalerInputContentMinScale = 1.0;
limits.temporalScalerInputContentMaxScale = 3.0;
#endif
} }
MetalDeviceProperties::MetalDeviceProperties(id<MTLDevice> p_device) { MetalDeviceProperties::MetalDeviceProperties(id<MTLDevice> p_device) {

View File

@@ -114,6 +114,9 @@ bool PixelFormats::isSupportedOrSubstitutable(DataFormat p_format) {
} }
bool PixelFormats::isPVRTCFormat(MTLPixelFormat p_format) { bool PixelFormats::isPVRTCFormat(MTLPixelFormat p_format) {
#if defined(VISIONOS_ENABLED)
return false;
#else
switch (p_format) { switch (p_format) {
case MTLPixelFormatPVRTC_RGBA_2BPP: case MTLPixelFormatPVRTC_RGBA_2BPP:
case MTLPixelFormatPVRTC_RGBA_2BPP_sRGB: case MTLPixelFormatPVRTC_RGBA_2BPP_sRGB:
@@ -127,6 +130,7 @@ bool PixelFormats::isPVRTCFormat(MTLPixelFormat p_format) {
default: default:
return false; return false;
} }
#endif
} }
MTLFormatType PixelFormats::getFormatType(DataFormat p_format) { MTLFormatType PixelFormats::getFormatType(DataFormat p_format) {
@@ -668,11 +672,13 @@ void PixelFormats::initMTLPixelFormatCapabilities() {
addMTLPixelFormatDesc(RGBA32Sint, Color128, RWC); addMTLPixelFormatDesc(RGBA32Sint, Color128, RWC);
addMTLPixelFormatDesc(RGBA32Float, Color128, All); addMTLPixelFormatDesc(RGBA32Float, Color128, All);
#if !defined(VISIONOS_ENABLED)
// Compressed pixel formats // Compressed pixel formats
addMTLPixelFormatDesc(PVRTC_RGBA_2BPP, PVRTC_RGBA_2BPP, RF); addMTLPixelFormatDesc(PVRTC_RGBA_2BPP, PVRTC_RGBA_2BPP, RF);
addMTLPixelFormatDescSRGB(PVRTC_RGBA_2BPP_sRGB, PVRTC_RGBA_2BPP, RF, PVRTC_RGBA_2BPP); addMTLPixelFormatDescSRGB(PVRTC_RGBA_2BPP_sRGB, PVRTC_RGBA_2BPP, RF, PVRTC_RGBA_2BPP);
addMTLPixelFormatDesc(PVRTC_RGBA_4BPP, PVRTC_RGBA_4BPP, RF); addMTLPixelFormatDesc(PVRTC_RGBA_4BPP, PVRTC_RGBA_4BPP, RF);
addMTLPixelFormatDescSRGB(PVRTC_RGBA_4BPP_sRGB, PVRTC_RGBA_4BPP, RF, PVRTC_RGBA_4BPP); addMTLPixelFormatDescSRGB(PVRTC_RGBA_4BPP_sRGB, PVRTC_RGBA_4BPP, RF, PVRTC_RGBA_4BPP);
#endif
addMTLPixelFormatDesc(ETC2_RGB8, ETC2_RGB8, RF); addMTLPixelFormatDesc(ETC2_RGB8, ETC2_RGB8, RF);
addMTLPixelFormatDescSRGB(ETC2_RGB8_sRGB, ETC2_RGB8, RF, ETC2_RGB8); addMTLPixelFormatDescSRGB(ETC2_RGB8_sRGB, ETC2_RGB8, RF, ETC2_RGB8);

View File

@@ -290,7 +290,11 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create(const TextureFormat &p
// Usage. // Usage.
MTLResourceOptions options = 0; MTLResourceOptions options = 0;
#if defined(VISIONOS_ENABLED)
const bool supports_memoryless = true;
#else
const bool supports_memoryless = (*device_properties).features.highestFamily >= MTLGPUFamilyApple2 && (*device_properties).features.highestFamily < MTLGPUFamilyMac1; const bool supports_memoryless = (*device_properties).features.highestFamily >= MTLGPUFamilyApple2 && (*device_properties).features.highestFamily < MTLGPUFamilyMac1;
#endif
if (supports_memoryless && p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) { if (supports_memoryless && p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) {
options = MTLResourceStorageModeMemoryless | MTLResourceHazardTrackingModeTracked; options = MTLResourceStorageModeMemoryless | MTLResourceHazardTrackingModeTracked;
desc.storageMode = MTLStorageModeMemoryless; desc.storageMode = MTLStorageModeMemoryless;
@@ -2493,7 +2497,11 @@ RDD::ShaderID RenderingDeviceDriverMetal::shader_create_from_bytecode(const Vect
cd->name = binary_data.shader_name; cd->name = binary_data.shader_name;
cd->stage = shader_data.stage; cd->stage = shader_data.stage;
options.preserveInvariance = shader_data.is_position_invariant; options.preserveInvariance = shader_data.is_position_invariant;
#if defined(VISIONOS_ENABLED)
options.mathMode = MTLMathModeFast;
#else
options.fastMathEnabled = YES; options.fastMathEnabled = YES;
#endif
MDLibrary *library = [MDLibrary newLibraryWithCacheEntry:cd MDLibrary *library = [MDLibrary newLibraryWithCacheEntry:cd
device:device device:device
source:source source:source
@@ -4184,8 +4192,8 @@ Error RenderingDeviceDriverMetal::initialize(uint32_t p_device_index, uint32_t p
error_string += "- No support for image cube arrays.\n"; error_string += "- No support for image cube arrays.\n";
} }
#if defined(IOS_ENABLED) #if defined(APPLE_EMBEDDED_ENABLED)
// iOS platform ports currently don't exit themselves when this method returns `ERR_CANT_CREATE`. // Apple Embedded platforms exports currently don't exit themselves when this method returns `ERR_CANT_CREATE`.
OS::get_singleton()->alert(error_string + "\nClick OK to exit (black screen will be visible)."); OS::get_singleton()->alert(error_string + "\nClick OK to exit (black screen will be visible).");
#else #else
OS::get_singleton()->alert(error_string + "\nClick OK to exit."); OS::get_singleton()->alert(error_string + "\nClick OK to exit.");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
/**************************************************************************/
/* editor_export_platform_apple_embedded.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "plugin_config_apple_embedded.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 "editor/editor_settings.h"
#include "editor/export/editor_export_platform.h"
#include "main/splash.gen.h"
#include "scene/resources/image_texture.h"
#include <sys/stat.h>
// Optional environment variables for defining confidential information. If any
// of these is set, they will override the values set in the credentials file.
const String ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG = "GODOT_APPLE_PLATFORM_PROVISIONING_PROFILE_UUID_DEBUG";
const String ENV_APPLE_PLATFORM_PROFILE_UUID_RELEASE = "GODOT_APPLE_PLATFORM_PROVISIONING_PROFILE_UUID_RELEASE";
const String ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_DEBUG = "GODOT_APPLE_PLATFORM_PROFILE_SPECIFIER_DEBUG";
const String ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_RELEASE = "GODOT_APPLE_PLATFORM_PROFILE_SPECIFIER_RELEASE";
static const String storyboard_image_scale_mode[] = {
"center",
"scaleAspectFit",
"scaleAspectFill",
"scaleToFill",
};
class EditorExportPlatformAppleEmbedded : public EditorExportPlatform {
GDCLASS(EditorExportPlatformAppleEmbedded, EditorExportPlatform);
Ref<ImageTexture> logo;
Ref<ImageTexture> run_icon;
// Plugins
mutable SafeFlag plugins_changed;
SafeFlag devices_changed;
struct Device {
String id;
String name;
bool wifi = false;
bool use_ios_deploy = false;
};
Vector<Device> devices;
Mutex device_lock;
Mutex plugins_lock;
mutable Vector<PluginConfigAppleEmbedded> plugins;
#ifdef MACOS_ENABLED
Thread check_for_changes_thread;
SafeFlag quit_request;
SafeFlag has_runnable_preset;
static bool _check_xcode_install();
static void _check_for_changes_poll_thread(void *ud);
void _update_preset_status();
#endif
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);
struct AppleEmbeddedConfigData {
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;
bool use_swift_runtime;
};
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 AppleEmbeddedExportAsset {
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 AppleEmbeddedConfigData &p_config, bool p_debug);
Vector<ExportArchitecture> _get_supported_architectures() const;
Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const;
void _check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const;
Error _convert_to_framework(const String &p_source, const String &p_destination, const String &p_id) const;
void _add_assets_to_project(const String &p_out_dir, const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<AppleEmbeddedExportAsset> &p_additional_assets);
Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<AppleEmbeddedExportAsset> &r_exported_assets);
Error _copy_asset(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<AppleEmbeddedExportAsset> &r_exported_assets);
Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<AppleEmbeddedExportAsset> &r_exported_assets);
Error _export_apple_embedded_plugins(const Ref<EditorExportPreset> &p_preset, AppleEmbeddedConfigData &p_config_data, const String &dest_dir, Vector<AppleEmbeddedExportAsset> &r_exported_assets, bool p_debug);
Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, bool p_oneclick);
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
protected:
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;
bool force_opaque;
};
void _blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p_src, bool p_rot);
virtual Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) { return OK; }
virtual Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) { return OK; }
virtual String get_platform_name() const = 0;
virtual String get_sdk_name() const = 0;
virtual String get_minimum_deployment_target() const = 0;
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) const override;
virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override;
virtual String get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const override;
virtual Vector<IconInfo> get_icon_infos() const = 0;
void _notification(int p_what);
virtual void get_platform_features(List<String> *r_features) const override {
r_features->push_back("mobile");
r_features->push_back("apple_embedded");
}
public:
virtual Ref<Texture2D> get_logo() const override { return logo; }
virtual Ref<Texture2D> get_run_icon() const override { return run_icon; }
virtual int get_options_count() const override;
virtual String get_options_tooltip() const override;
virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual bool poll_export() override {
bool dc = devices_changed.is_set();
if (dc) {
// don't clear unless we're reporting true, to avoid race
devices_changed.clear();
}
return dc;
}
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;
if (p_preset.is_valid()) {
bool project_only = p_preset->get("application/export_project_only");
if (project_only) {
list.push_back("xcodeproj");
} else {
list.push_back("ipa");
}
}
return list;
}
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override {
}
EditorExportPlatformAppleEmbedded(const char *p_platform_logo_svg, const char *p_run_icon_svg);
~EditorExportPlatformAppleEmbedded();
/// 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.path_join(file), false);
for (int i = 0; i < directory_files.size(); ++i) {
dir_files.push_back(file.path_join(directory_files[i]));
}
}
continue;
}
if (file.ends_with(PluginConfigAppleEmbedded::PLUGIN_CONFIG_EXT)) {
dir_files.push_back(file);
}
}
da->list_dir_end();
}
return dir_files;
}
static Vector<PluginConfigAppleEmbedded> get_plugins(const String &p_platform_name) {
Vector<PluginConfigAppleEmbedded> loaded_plugins;
String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().path_join(p_platform_name + "/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;
for (int i = 0; i < plugins_filenames.size(); i++) {
PluginConfigAppleEmbedded config = PluginConfigAppleEmbedded::load_plugin_config(config_file, plugins_dir.path_join(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<PluginConfigAppleEmbedded> get_enabled_plugins(const String &p_platform_name, const Ref<EditorExportPreset> &p_presets) {
Vector<PluginConfigAppleEmbedded> enabled_plugins;
Vector<PluginConfigAppleEmbedded> all_plugins = get_plugins(p_platform_name);
for (int i = 0; i < all_plugins.size(); i++) {
PluginConfigAppleEmbedded plugin = all_plugins[i];
bool enabled = p_presets->get("plugins/" + plugin.name);
if (enabled) {
enabled_plugins.push_back(plugin);
}
}
return enabled_plugins;
}
};

View File

@@ -67,55 +67,55 @@ void EditorExportPlugin::_add_shared_object(const SharedObject &p_shared_object)
shared_objects.push_back(p_shared_object); shared_objects.push_back(p_shared_object);
} }
void EditorExportPlugin::add_ios_framework(const String &p_path) { void EditorExportPlugin::add_apple_embedded_platform_framework(const String &p_path) {
ios_frameworks.push_back(p_path); apple_embedded_platform_frameworks.push_back(p_path);
} }
void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) { void EditorExportPlugin::add_apple_embedded_platform_embedded_framework(const String &p_path) {
ios_embedded_frameworks.push_back(p_path); apple_embedded_platform_embedded_frameworks.push_back(p_path);
} }
Vector<String> EditorExportPlugin::get_ios_frameworks() const { Vector<String> EditorExportPlugin::get_apple_embedded_platform_frameworks() const {
return ios_frameworks; return apple_embedded_platform_frameworks;
} }
Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const { Vector<String> EditorExportPlugin::get_apple_embedded_platform_embedded_frameworks() const {
return ios_embedded_frameworks; return apple_embedded_platform_embedded_frameworks;
} }
void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) { void EditorExportPlugin::add_apple_embedded_platform_plist_content(const String &p_plist_content) {
ios_plist_content += p_plist_content + "\n"; apple_embedded_platform_plist_content += p_plist_content + "\n";
} }
String EditorExportPlugin::get_ios_plist_content() const { String EditorExportPlugin::get_apple_embedded_platform_plist_content() const {
return ios_plist_content; return apple_embedded_platform_plist_content;
} }
void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) { void EditorExportPlugin::add_apple_embedded_platform_linker_flags(const String &p_flags) {
if (ios_linker_flags.length() > 0) { if (apple_embedded_platform_linker_flags.length() > 0) {
ios_linker_flags += ' '; apple_embedded_platform_linker_flags += ' ';
} }
ios_linker_flags += p_flags; apple_embedded_platform_linker_flags += p_flags;
} }
String EditorExportPlugin::get_ios_linker_flags() const { String EditorExportPlugin::get_apple_embedded_platform_linker_flags() const {
return ios_linker_flags; return apple_embedded_platform_linker_flags;
} }
void EditorExportPlugin::add_ios_bundle_file(const String &p_path) { void EditorExportPlugin::add_apple_embedded_platform_bundle_file(const String &p_path) {
ios_bundle_files.push_back(p_path); apple_embedded_platform_bundle_files.push_back(p_path);
} }
Vector<String> EditorExportPlugin::get_ios_bundle_files() const { Vector<String> EditorExportPlugin::get_apple_embedded_platform_bundle_files() const {
return ios_bundle_files; return apple_embedded_platform_bundle_files;
} }
void EditorExportPlugin::add_ios_cpp_code(const String &p_code) { void EditorExportPlugin::add_apple_embedded_platform_cpp_code(const String &p_code) {
ios_cpp_code += p_code; apple_embedded_platform_cpp_code += p_code;
} }
String EditorExportPlugin::get_ios_cpp_code() const { String EditorExportPlugin::get_apple_embedded_platform_cpp_code() const {
return ios_cpp_code; return apple_embedded_platform_cpp_code;
} }
void EditorExportPlugin::add_macos_plugin_file(const String &p_path) { void EditorExportPlugin::add_macos_plugin_file(const String &p_path) {
@@ -126,12 +126,12 @@ const Vector<String> &EditorExportPlugin::get_macos_plugin_files() const {
return macos_plugin_files; return macos_plugin_files;
} }
void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) { void EditorExportPlugin::add_apple_embedded_platform_project_static_lib(const String &p_path) {
ios_project_static_libs.push_back(p_path); apple_embedded_platform_project_static_libs.push_back(p_path);
} }
Vector<String> EditorExportPlugin::get_ios_project_static_libs() const { Vector<String> EditorExportPlugin::get_apple_embedded_platform_project_static_libs() const {
return ios_project_static_libs; return apple_embedded_platform_project_static_libs;
} }
Variant EditorExportPlugin::get_option(const StringName &p_name) const { Variant EditorExportPlugin::get_option(const StringName &p_name) const {
@@ -328,14 +328,26 @@ void EditorExportPlugin::skip() {
void EditorExportPlugin::_bind_methods() { void EditorExportPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object); ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object);
ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib);
ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework); ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_project_static_lib", "path"), &EditorExportPlugin::add_apple_embedded_platform_project_static_lib);
ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content); ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_framework", "path"), &EditorExportPlugin::add_apple_embedded_platform_framework);
ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags); ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_embedded_framework", "path"), &EditorExportPlugin::add_apple_embedded_platform_embedded_framework);
ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file); ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_plist_content", "plist_content"), &EditorExportPlugin::add_apple_embedded_platform_plist_content);
ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code); ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_linker_flags", "flags"), &EditorExportPlugin::add_apple_embedded_platform_linker_flags);
ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_bundle_file", "path"), &EditorExportPlugin::add_apple_embedded_platform_bundle_file);
ClassDB::bind_method(D_METHOD("add_apple_embedded_platform_cpp_code", "code"), &EditorExportPlugin::add_apple_embedded_platform_cpp_code);
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_apple_embedded_platform_project_static_lib);
ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_apple_embedded_platform_framework);
ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_apple_embedded_platform_embedded_framework);
ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_apple_embedded_platform_plist_content);
ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_apple_embedded_platform_linker_flags);
ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_apple_embedded_platform_bundle_file);
ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_apple_embedded_platform_cpp_code);
#endif
ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file); ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file);
ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
ClassDB::bind_method(D_METHOD("get_option", "name"), &EditorExportPlugin::get_option); ClassDB::bind_method(D_METHOD("get_option", "name"), &EditorExportPlugin::get_option);

View File

@@ -53,13 +53,13 @@ class EditorExportPlugin : public RefCounted {
Vector<ExtraFile> extra_files; Vector<ExtraFile> extra_files;
bool skipped = false; bool skipped = false;
Vector<String> ios_frameworks; Vector<String> apple_embedded_platform_frameworks;
Vector<String> ios_embedded_frameworks; Vector<String> apple_embedded_platform_embedded_frameworks;
Vector<String> ios_project_static_libs; Vector<String> apple_embedded_platform_project_static_libs;
String ios_plist_content; String apple_embedded_platform_plist_content;
String ios_linker_flags; String apple_embedded_platform_linker_flags;
Vector<String> ios_bundle_files; Vector<String> apple_embedded_platform_bundle_files;
String ios_cpp_code; String apple_embedded_platform_cpp_code;
Vector<String> macos_plugin_files; Vector<String> macos_plugin_files;
@@ -70,12 +70,12 @@ class EditorExportPlugin : public RefCounted {
} }
_FORCE_INLINE_ void _export_end_clear() { _FORCE_INLINE_ void _export_end_clear() {
ios_frameworks.clear(); apple_embedded_platform_frameworks.clear();
ios_embedded_frameworks.clear(); apple_embedded_platform_embedded_frameworks.clear();
ios_bundle_files.clear(); apple_embedded_platform_bundle_files.clear();
ios_plist_content = ""; apple_embedded_platform_plist_content = "";
ios_linker_flags = ""; apple_embedded_platform_linker_flags = "";
ios_cpp_code = ""; apple_embedded_platform_cpp_code = "";
macos_plugin_files.clear(); macos_plugin_files.clear();
} }
@@ -95,13 +95,13 @@ protected:
void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String()); void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
void _add_shared_object(const SharedObject &p_shared_object); void _add_shared_object(const SharedObject &p_shared_object);
void add_ios_framework(const String &p_path); void add_apple_embedded_platform_framework(const String &p_path);
void add_ios_embedded_framework(const String &p_path); void add_apple_embedded_platform_embedded_framework(const String &p_path);
void add_ios_project_static_lib(const String &p_path); void add_apple_embedded_platform_project_static_lib(const String &p_path);
void add_ios_plist_content(const String &p_plist_content); void add_apple_embedded_platform_plist_content(const String &p_plist_content);
void add_ios_linker_flags(const String &p_flags); void add_apple_embedded_platform_linker_flags(const String &p_flags);
void add_ios_bundle_file(const String &p_path); void add_apple_embedded_platform_bundle_file(const String &p_path);
void add_ios_cpp_code(const String &p_code); void add_apple_embedded_platform_cpp_code(const String &p_code);
void add_macos_plugin_file(const String &p_path); void add_macos_plugin_file(const String &p_path);
void skip(); void skip();
@@ -177,13 +177,13 @@ public:
virtual String get_android_manifest_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const; virtual String get_android_manifest_element_contents(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual PackedByteArray update_android_prebuilt_manifest(const Ref<EditorExportPlatform> &p_export_platform, const PackedByteArray &p_manifest_data) const; virtual PackedByteArray update_android_prebuilt_manifest(const Ref<EditorExportPlatform> &p_export_platform, const PackedByteArray &p_manifest_data) const;
Vector<String> get_ios_frameworks() const; Vector<String> get_apple_embedded_platform_frameworks() const;
Vector<String> get_ios_embedded_frameworks() const; Vector<String> get_apple_embedded_platform_embedded_frameworks() const;
Vector<String> get_ios_project_static_libs() const; Vector<String> get_apple_embedded_platform_project_static_libs() const;
String get_ios_plist_content() const; String get_apple_embedded_platform_plist_content() const;
String get_ios_linker_flags() const; String get_apple_embedded_platform_linker_flags() const;
Vector<String> get_ios_bundle_files() const; Vector<String> get_apple_embedded_platform_bundle_files() const;
String get_ios_cpp_code() const; String get_apple_embedded_platform_cpp_code() const;
const Vector<String> &get_macos_plugin_files() const; const Vector<String> &get_macos_plugin_files() const;
Variant get_option(const StringName &p_name) const; Variant get_option(const StringName &p_name) const;
}; };

View File

@@ -111,6 +111,8 @@ public:
PLATFORM_TVOSSIMULATOR = 8, PLATFORM_TVOSSIMULATOR = 8,
PLATFORM_WATCHOSSIMULATOR = 9, PLATFORM_WATCHOSSIMULATOR = 9,
PLATFORM_DRIVERKIT = 10, PLATFORM_DRIVERKIT = 10,
PLATFORM_VISIONOS = 11,
PLATFORM_VISIONOSSIMULATOR = 12,
}; };
struct LoadCommandHeader { struct LoadCommandHeader {

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_plugin_config.cpp */ /* plugin_config_apple_embedded.cpp */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#include "godot_plugin_config.h" #include "plugin_config_apple_embedded.h"
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/io/dir_access.h" #include "core/io/dir_access.h"
#include "core/io/file_access.h" #include "core/io/file_access.h"
String PluginConfigIOS::resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String PluginConfigAppleEmbedded::resolve_local_dependency_path(String plugin_config_dir, String dependency_path) {
String absolute_path; String absolute_path;
if (dependency_path.is_empty()) { if (dependency_path.is_empty()) {
@@ -51,7 +51,7 @@ String PluginConfigIOS::resolve_local_dependency_path(String plugin_config_dir,
return absolute_path.replace(res_path, "res://"); return absolute_path.replace(res_path, "res://");
} }
String PluginConfigIOS::resolve_system_dependency_path(String dependency_path) { String PluginConfigAppleEmbedded::resolve_system_dependency_path(String dependency_path) {
String absolute_path; String absolute_path;
if (dependency_path.is_empty()) { if (dependency_path.is_empty()) {
@@ -67,7 +67,7 @@ String PluginConfigIOS::resolve_system_dependency_path(String dependency_path) {
return system_path.path_join(dependency_path); return system_path.path_join(dependency_path);
} }
Vector<String> PluginConfigIOS::resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths) { Vector<String> PluginConfigAppleEmbedded::resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths) {
Vector<String> paths; Vector<String> paths;
for (int i = 0; i < p_paths.size(); i++) { for (int i = 0; i < p_paths.size(); i++) {
@@ -83,7 +83,7 @@ Vector<String> PluginConfigIOS::resolve_local_dependencies(String plugin_config_
return paths; return paths;
} }
Vector<String> PluginConfigIOS::resolve_system_dependencies(Vector<String> p_paths) { Vector<String> PluginConfigAppleEmbedded::resolve_system_dependencies(Vector<String> p_paths) {
Vector<String> paths; Vector<String> paths;
for (int i = 0; i < p_paths.size(); i++) { for (int i = 0; i < p_paths.size(); i++) {
@@ -99,7 +99,7 @@ Vector<String> PluginConfigIOS::resolve_system_dependencies(Vector<String> p_pat
return paths; return paths;
} }
bool PluginConfigIOS::validate_plugin(PluginConfigIOS &plugin_config) { bool PluginConfigAppleEmbedded::validate_plugin(PluginConfigAppleEmbedded &plugin_config) {
bool valid_name = !plugin_config.name.is_empty(); bool valid_name = !plugin_config.name.is_empty();
bool valid_binary_name = !plugin_config.binary.is_empty(); bool valid_binary_name = !plugin_config.binary.is_empty();
bool valid_initialize = !plugin_config.initialization_method.is_empty(); bool valid_initialize = !plugin_config.initialization_method.is_empty();
@@ -134,7 +134,7 @@ bool PluginConfigIOS::validate_plugin(PluginConfigIOS &plugin_config) {
return plugin_config.valid_config; return plugin_config.valid_config;
} }
String PluginConfigIOS::get_plugin_main_binary(PluginConfigIOS &plugin_config, bool p_debug) { String PluginConfigAppleEmbedded::get_plugin_main_binary(PluginConfigAppleEmbedded &plugin_config, bool p_debug) {
if (!plugin_config.supports_targets) { if (!plugin_config.supports_targets) {
return plugin_config.binary; return plugin_config.binary;
} }
@@ -147,7 +147,7 @@ String PluginConfigIOS::get_plugin_main_binary(PluginConfigIOS &plugin_config, b
return plugin_binary_dir.path_join(plugin_file); return plugin_binary_dir.path_join(plugin_file);
} }
uint64_t PluginConfigIOS::get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path) { uint64_t PluginConfigAppleEmbedded::get_plugin_modification_time(const PluginConfigAppleEmbedded &plugin_config, const String &config_path) {
uint64_t last_updated = FileAccess::get_modified_time(config_path); uint64_t last_updated = FileAccess::get_modified_time(config_path);
if (!plugin_config.supports_targets) { if (!plugin_config.supports_targets) {
@@ -166,8 +166,8 @@ uint64_t PluginConfigIOS::get_plugin_modification_time(const PluginConfigIOS &pl
return last_updated; return last_updated;
} }
PluginConfigIOS PluginConfigIOS::load_plugin_config(Ref<ConfigFile> config_file, const String &path) { PluginConfigAppleEmbedded PluginConfigAppleEmbedded::load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
PluginConfigIOS plugin_config = {}; PluginConfigAppleEmbedded plugin_config = {};
if (config_file.is_null()) { if (config_file.is_null()) {
return plugin_config; return plugin_config;
@@ -183,19 +183,19 @@ PluginConfigIOS PluginConfigIOS::load_plugin_config(Ref<ConfigFile> config_file,
String config_base_dir = path.get_base_dir(); 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.name = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_NAME_KEY, String());
plugin_config.use_swift_runtime = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_USE_SWIFT_KEY, false); plugin_config.use_swift_runtime = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_USE_SWIFT_KEY, false);
plugin_config.initialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_INITIALIZE_KEY, String()); plugin_config.initialization_method = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_INITIALIZE_KEY, String());
plugin_config.deinitialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_DEINITIALIZE_KEY, String()); plugin_config.deinitialization_method = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_DEINITIALIZE_KEY, String());
String binary_path = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_BINARY_KEY, String()); String binary_path = config_file->get_value(PluginConfigAppleEmbedded::CONFIG_SECTION, PluginConfigAppleEmbedded::CONFIG_BINARY_KEY, String());
plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path); plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path);
if (config_file->has_section(PluginConfigIOS::DEPENDENCIES_SECTION)) { if (config_file->has_section(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION)) {
Vector<String> linked_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKED_KEY, Vector<String>()); Vector<String> linked_dependencies = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_LINKED_KEY, Vector<String>());
Vector<String> embedded_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_EMBEDDED_KEY, Vector<String>()); Vector<String> embedded_dependencies = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_EMBEDDED_KEY, Vector<String>());
Vector<String> system_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_SYSTEM_KEY, Vector<String>()); Vector<String> system_dependencies = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_SYSTEM_KEY, Vector<String>());
Vector<String> files = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_FILES_KEY, Vector<String>()); Vector<String> files = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_FILES_KEY, Vector<String>());
plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies); 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.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies);
@@ -203,77 +203,77 @@ PluginConfigIOS PluginConfigIOS::load_plugin_config(Ref<ConfigFile> config_file,
plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files); 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.capabilities = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_CAPABILITIES_KEY, Vector<String>());
plugin_config.linker_flags = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKER_FLAGS, Vector<String>()); plugin_config.linker_flags = config_file->get_value(PluginConfigAppleEmbedded::DEPENDENCIES_SECTION, PluginConfigAppleEmbedded::DEPENDENCIES_LINKER_FLAGS, Vector<String>());
} }
if (config_file->has_section(PluginConfigIOS::PLIST_SECTION)) { if (config_file->has_section(PluginConfigAppleEmbedded::PLIST_SECTION)) {
Vector<String> keys = config_file->get_section_keys(PluginConfigIOS::PLIST_SECTION); Vector<String> keys = config_file->get_section_keys(PluginConfigAppleEmbedded::PLIST_SECTION);
for (const String &key : keys) { for (const String &key : keys) {
Vector<String> key_components = key.split(":"); Vector<String> key_components = key.split(":");
String key_value = ""; String key_value = "";
PluginConfigIOS::PlistItemType key_type = PluginConfigIOS::PlistItemType::UNKNOWN; PluginConfigAppleEmbedded::PlistItemType key_type = PluginConfigAppleEmbedded::PlistItemType::UNKNOWN;
if (key_components.size() == 1) { if (key_components.size() == 1) {
key_value = key_components[0]; key_value = key_components[0];
key_type = PluginConfigIOS::PlistItemType::STRING; key_type = PluginConfigAppleEmbedded::PlistItemType::STRING;
} else if (key_components.size() == 2) { } else if (key_components.size() == 2) {
key_value = key_components[0]; key_value = key_components[0];
if (key_components[1].to_lower() == "string") { if (key_components[1].to_lower() == "string") {
key_type = PluginConfigIOS::PlistItemType::STRING; key_type = PluginConfigAppleEmbedded::PlistItemType::STRING;
} else if (key_components[1].to_lower() == "integer") { } else if (key_components[1].to_lower() == "integer") {
key_type = PluginConfigIOS::PlistItemType::INTEGER; key_type = PluginConfigAppleEmbedded::PlistItemType::INTEGER;
} else if (key_components[1].to_lower() == "boolean") { } else if (key_components[1].to_lower() == "boolean") {
key_type = PluginConfigIOS::PlistItemType::BOOLEAN; key_type = PluginConfigAppleEmbedded::PlistItemType::BOOLEAN;
} else if (key_components[1].to_lower() == "raw") { } else if (key_components[1].to_lower() == "raw") {
key_type = PluginConfigIOS::PlistItemType::RAW; key_type = PluginConfigAppleEmbedded::PlistItemType::RAW;
} else if (key_components[1].to_lower() == "string_input") { } else if (key_components[1].to_lower() == "string_input") {
key_type = PluginConfigIOS::PlistItemType::STRING_INPUT; key_type = PluginConfigAppleEmbedded::PlistItemType::STRING_INPUT;
} }
} }
if (key_value.is_empty() || key_type == PluginConfigIOS::PlistItemType::UNKNOWN) { if (key_value.is_empty() || key_type == PluginConfigAppleEmbedded::PlistItemType::UNKNOWN) {
continue; continue;
} }
String value; String value;
switch (key_type) { switch (key_type) {
case PluginConfigIOS::PlistItemType::STRING: { case PluginConfigAppleEmbedded::PlistItemType::STRING: {
String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, key, String()); String raw_value = config_file->get_value(PluginConfigAppleEmbedded::PLIST_SECTION, key, String());
value = "<string>" + raw_value + "</string>"; value = "<string>" + raw_value + "</string>";
} break; } break;
case PluginConfigIOS::PlistItemType::INTEGER: { case PluginConfigAppleEmbedded::PlistItemType::INTEGER: {
int raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, key, 0); int raw_value = config_file->get_value(PluginConfigAppleEmbedded::PLIST_SECTION, key, 0);
Dictionary value_dictionary; Dictionary value_dictionary;
String value_format = "<integer>$value</integer>"; String value_format = "<integer>$value</integer>";
value_dictionary["value"] = raw_value; value_dictionary["value"] = raw_value;
value = value_format.format(value_dictionary, "$_"); value = value_format.format(value_dictionary, "$_");
} break; } break;
case PluginConfigIOS::PlistItemType::BOOLEAN: case PluginConfigAppleEmbedded::PlistItemType::BOOLEAN:
if (config_file->get_value(PluginConfigIOS::PLIST_SECTION, key, false)) { if (config_file->get_value(PluginConfigAppleEmbedded::PLIST_SECTION, key, false)) {
value = "<true/>"; value = "<true/>";
} else { } else {
value = "<false/>"; value = "<false/>";
} }
break; break;
case PluginConfigIOS::PlistItemType::RAW: { case PluginConfigAppleEmbedded::PlistItemType::RAW: {
String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, key, String()); String raw_value = config_file->get_value(PluginConfigAppleEmbedded::PLIST_SECTION, key, String());
value = raw_value; value = raw_value;
} break; } break;
case PluginConfigIOS::PlistItemType::STRING_INPUT: { case PluginConfigAppleEmbedded::PlistItemType::STRING_INPUT: {
String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, key, String()); String raw_value = config_file->get_value(PluginConfigAppleEmbedded::PLIST_SECTION, key, String());
value = raw_value; value = raw_value;
} break; } break;
default: default:
continue; continue;
} }
plugin_config.plist[key_value] = PluginConfigIOS::PlistItem{ key_type, value }; plugin_config.plist[key_value] = PluginConfigAppleEmbedded::PlistItem{ key_type, value };
} }
} }

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* godot_plugin_config.h */ /* plugin_config_apple_embedded.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -50,7 +50,7 @@ The `plist` section are optional.
- **key**: key and value that would be added in Info.plist file. - **key**: key and value that would be added in Info.plist file.
*/ */
struct PluginConfigIOS { struct PluginConfigAppleEmbedded {
inline static const char *PLUGIN_CONFIG_EXT = ".gdip"; inline static const char *PLUGIN_CONFIG_EXT = ".gdip";
inline static const char *CONFIG_SECTION = "config"; inline static const char *CONFIG_SECTION = "config";
@@ -121,11 +121,11 @@ struct PluginConfigIOS {
static Vector<String> resolve_system_dependencies(Vector<String> p_paths); static Vector<String> resolve_system_dependencies(Vector<String> p_paths);
static bool validate_plugin(PluginConfigIOS &plugin_config); static bool validate_plugin(PluginConfigAppleEmbedded &plugin_config);
static String get_plugin_main_binary(PluginConfigIOS &plugin_config, bool p_debug); static String get_plugin_main_binary(PluginConfigAppleEmbedded &plugin_config, bool p_debug);
static uint64_t get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path); static uint64_t get_plugin_modification_time(const PluginConfigAppleEmbedded &plugin_config, const String &config_path);
static PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, const String &path); static PluginConfigAppleEmbedded load_plugin_config(Ref<ConfigFile> config_file, const String &path);
}; };

View File

@@ -115,9 +115,9 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
libs_added.insert(library_path); libs_added.insert(library_path);
add_shared_object(library_path, tags); add_shared_object(library_path, tags);
if (p_features.has("ios") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) { if (p_features.has("apple_embedded") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) {
String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
"extern void add_ios_init_callback(void (*cb)());\n" "extern void add_apple_embedded_platform_init_callback(void (*cb)());\n"
"\n" "\n"
"extern \"C\" void $ENTRY();\n" "extern \"C\" void $ENTRY();\n"
"void $ENTRY_init() {\n" "void $ENTRY_init() {\n"
@@ -125,15 +125,15 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
"}\n" "}\n"
"struct $ENTRY_struct {\n" "struct $ENTRY_struct {\n"
" $ENTRY_struct() {\n" " $ENTRY_struct() {\n"
" add_ios_init_callback($ENTRY_init);\n" " add_apple_embedded_platform_init_callback($ENTRY_init);\n"
" }\n" " }\n"
"};\n" "};\n"
"$ENTRY_struct $ENTRY_struct_instance;\n\n"; "$ENTRY_struct $ENTRY_struct_instance;\n\n";
additional_code = additional_code.replace("$ENTRY", entry_symbol); additional_code = additional_code.replace("$ENTRY", entry_symbol);
add_ios_cpp_code(additional_code); add_apple_embedded_platform_cpp_code(additional_code);
String linker_flags = "-Wl,-U,_" + entry_symbol; String linker_flags = "-Wl,-U,_" + entry_symbol;
add_ios_linker_flags(linker_flags); add_apple_embedded_platform_linker_flags(linker_flags);
} }
// Update found library info. // Update found library info.

View File

@@ -195,7 +195,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin() {
#else #else
// Disable lightmap baking if the module is disabled at compile-time. // Disable lightmap baking if the module is disabled at compile-time.
bake->set_disabled(true); bake->set_disabled(true);
#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED) #if defined(ANDROID_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
bake->set_tooltip_text(vformat(TTR("Lightmaps cannot be baked on %s."), OS::get_singleton()->get_name())); bake->set_tooltip_text(vformat(TTR("Lightmaps cannot be baked on %s."), OS::get_singleton()->get_name()));
#else #else
bake->set_tooltip_text(TTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time.")); bake->set_tooltip_text(TTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time."));

View File

@@ -47,6 +47,7 @@
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/editor_vcs_interface.h" #include "editor/editor_vcs_interface.h"
#include "editor/export/editor_export_platform.h" #include "editor/export/editor_export_platform.h"
#include "editor/export/editor_export_platform_apple_embedded.h"
#include "editor/export/editor_export_platform_extension.h" #include "editor/export/editor_export_platform_extension.h"
#include "editor/export/editor_export_platform_pc.h" #include "editor/export/editor_export_platform_pc.h"
#include "editor/export/editor_export_plugin.h" #include "editor/export/editor_export_plugin.h"
@@ -163,6 +164,7 @@ void register_editor_types() {
GDREGISTER_CLASS(EditorExportPlugin); GDREGISTER_CLASS(EditorExportPlugin);
GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform); GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
GDREGISTER_ABSTRACT_CLASS(EditorExportPlatformPC); GDREGISTER_ABSTRACT_CLASS(EditorExportPlatformPC);
GDREGISTER_ABSTRACT_CLASS(EditorExportPlatformAppleEmbedded);
GDREGISTER_CLASS(EditorExportPlatformExtension); GDREGISTER_CLASS(EditorExportPlatformExtension);
GDREGISTER_ABSTRACT_CLASS(EditorExportPreset); GDREGISTER_ABSTRACT_CLASS(EditorExportPreset);

View File

@@ -2191,6 +2191,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, "vulkan"), "vulkan"); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, "vulkan"), "vulkan");
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, "vulkan"), "vulkan"); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, "vulkan"), "vulkan");
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal"); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal");
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.visionos", PROPERTY_HINT_ENUM, "metal"), "metal");
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal"); GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, "metal,vulkan"), "metal");
GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true); GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true);
@@ -2672,6 +2673,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default"); GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default");
GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default"); GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default");
GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default"); GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default");
GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.visionos", PROPERTY_HINT_ENUM_SUGGESTION, "default,visionOS,headless"), "default");
GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default"); GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default");
GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name()); GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
@@ -3797,7 +3799,7 @@ static MainTimerSync main_timer_sync;
int Main::start() { int Main::start() {
OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Start"); OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Start");
ERR_FAIL_COND_V(!_start_success, false); ERR_FAIL_COND_V(!_start_success, EXIT_FAILURE);
bool has_icon = false; bool has_icon = false;
String positional_arg; String positional_arg;

View File

@@ -609,17 +609,41 @@ def Run(env, function):
return Action(function, "$GENCOMSTR") return Action(function, "$GENCOMSTR")
def detect_darwin_toolchain_path(env):
var_name = "APPLE_TOOLCHAIN_PATH"
if not env[var_name]:
try:
xcode_path = subprocess.check_output(["xcode-select", "-p"]).strip().decode("utf-8")
if xcode_path:
env[var_name] = xcode_path + "/Toolchains/XcodeDefault.xctoolchain"
except (subprocess.CalledProcessError, OSError):
print_error("Failed to find SDK path while running 'xcode-select -p'.")
raise
def detect_darwin_sdk_path(platform, env): def detect_darwin_sdk_path(platform, env):
sdk_name = "" sdk_name = ""
if platform == "macos": if platform == "macos":
sdk_name = "macosx" sdk_name = "macosx"
var_name = "MACOS_SDK_PATH" var_name = "MACOS_SDK_PATH"
elif platform == "ios": elif platform == "ios":
sdk_name = "iphoneos" sdk_name = "iphoneos"
var_name = "IOS_SDK_PATH" var_name = "IOS_SDK_PATH"
elif platform == "iossimulator": elif platform == "iossimulator":
sdk_name = "iphonesimulator" sdk_name = "iphonesimulator"
var_name = "IOS_SDK_PATH" var_name = "IOS_SDK_PATH"
elif platform == "visionos":
sdk_name = "xros"
var_name = "VISIONOS_SDK_PATH"
elif platform == "visionossimulator":
sdk_name = "xrsimulator"
var_name = "VISIONOS_SDK_PATH"
else: else:
raise Exception("Invalid platform argument passed to detect_darwin_sdk_path") raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
@@ -629,7 +653,7 @@ def detect_darwin_sdk_path(platform, env):
if sdk_path: if sdk_path:
env[var_name] = sdk_path env[var_name] = sdk_path
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
print_error("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name)) print_error("Failed to find SDK path while running 'xcrun --sdk {} --show-sdk-path'.".format(sdk_name))
raise raise

View File

@@ -7,7 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
054F8BE62D38852F00B81423 /* MetalFX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054F8BE52D38852F00B81423 /* MetalFX.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; }; 1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; };
DEADBEEF2F582BE20003B888 /* $binary.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.xcframework */; }; DEADBEEF2F582BE20003B888 /* $binary.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.xcframework */; };
$modules_buildfile $modules_buildfile
@@ -43,7 +42,6 @@
1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "$binary.entitlements"; sourceTree = "<group>"; }; 1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "$binary.entitlements"; sourceTree = "<group>"; };
1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; }; 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; };
9039D3BD24C093AC0020482C /* MoltenVK.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MoltenVK; path = MoltenVK.xcframework; sourceTree = "<group>"; }; 9039D3BD24C093AC0020482C /* MoltenVK.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MoltenVK; path = MoltenVK.xcframework; sourceTree = "<group>"; };
054F8BE52D38852F00B81423 /* MetalFX.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalFX.framework; path = System/Library/Frameworks/MetalFX.framework; sourceTree = SDKROOT; };
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "$binary.app"; sourceTree = BUILT_PRODUCTS_DIR; }; D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "$binary.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; }; D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
@@ -62,7 +60,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
9039D3BE24C093AC0020482C /* MoltenVK.xcframework in Frameworks */, 9039D3BE24C093AC0020482C /* MoltenVK.xcframework in Frameworks */,
054F8BE62D38852F00B81423 /* MetalFX.framework in Frameworks */,
DEADBEEF2F582BE20003B888 /* $binary.xcframework */, DEADBEEF2F582BE20003B888 /* $binary.xcframework */,
$modules_buildphase $modules_buildphase
$additional_pbx_frameworks_build $additional_pbx_frameworks_build
@@ -97,7 +94,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
9039D3BD24C093AC0020482C /* MoltenVK.xcframework */, 9039D3BD24C093AC0020482C /* MoltenVK.xcframework */,
054F8BE52D38852F00B81423 /* MetalFX.framework */,
DEADBEEF1F582BE20003B888 /* $binary.xcframework */, DEADBEEF1F582BE20003B888 /* $binary.xcframework */,
$modules_buildgrp $modules_buildgrp
$additional_pbx_frameworks_refs $additional_pbx_frameworks_refs

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
$priv_api_types
$priv_tracking
$priv_collection
</dict>
</plist>

0
misc/dist/visionos_xcode/data.pck vendored Normal file
View File

View File

@@ -0,0 +1,402 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; };
DEADBEEF2F582BE20003B888 /* $binary.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.xcframework */; };
$modules_buildfile
$swift_runtime_buildfile
1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; };
D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; };
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; };
D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; };
F965960D2BC2C3A800579C7E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F965960C2BC2C3A800579C7E /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
90A13CD024AA68E500E8464F /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
$pbx_embeded_frameworks
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; };
DEADBEEF1F582BE20003B888 /* $binary.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = godot; path = "$binary.xcframework"; sourceTree = "<group>"; };
$modules_fileref
$swift_runtime_fileref
1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "$binary.entitlements"; sourceTree = "<group>"; };
1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; };
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "$binary.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
$pbx_locale_file_reference
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = "$binary.pck"; sourceTree = "<group>"; };
F965960C2BC2C3A800579C7E /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
/* End PBXFileReference section */
$additional_pbx_files
/* Begin PBXFrameworksBuildPhase section */
D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DEADBEEF2F582BE20003B888 /* $binary.xcframework */,
$modules_buildphase
$additional_pbx_frameworks_build
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D0BCFE2B18AEBDA2004A7AAE = {
isa = PBXGroup;
children = (
1F1575711F582BE20003B888 /* dylibs */,
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */,
D0BCFE4118AEBDA2004A7AAE /* $binary */,
D0BCFE3618AEBDA2004A7AAE /* Frameworks */,
D0BCFE3518AEBDA2004A7AAE /* Products */,
F965960C2BC2C3A800579C7E /* PrivacyInfo.xcprivacy */,
$additional_pbx_resources_refs
);
sourceTree = "<group>";
};
D0BCFE3518AEBDA2004A7AAE /* Products */ = {
isa = PBXGroup;
children = (
D0BCFE3418AEBDA2004A7AAE /* $binary.app */,
);
name = Products;
sourceTree = "<group>";
};
D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXGroup;
children = (
DEADBEEF1F582BE20003B888 /* $binary.xcframework */,
$modules_buildgrp
$additional_pbx_frameworks_refs
);
name = Frameworks;
sourceTree = "<group>";
};
D0BCFE4118AEBDA2004A7AAE /* $binary */ = {
isa = PBXGroup;
children = (
1FF4C1881F584E6300A41E41 /* $binary.entitlements */,
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */,
$swift_runtime_binary_files
);
path = "$binary";
sourceTree = "<group>";
};
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */ = {
isa = PBXGroup;
children = (
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */,
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D0BCFE3318AEBDA2004A7AAE /* $binary */ = {
isa = PBXNativeTarget;
buildConfigurationList = D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "$binary" */;
buildPhases = (
D0BCFE3018AEBDA2004A7AAE /* Sources */,
D0BCFE3118AEBDA2004A7AAE /* Frameworks */,
D0BCFE3218AEBDA2004A7AAE /* Resources */,
90A13CD024AA68E500E8464F /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "$binary";
productName = "$name";
productReference = D0BCFE3418AEBDA2004A7AAE /* $binary.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D0BCFE2C18AEBDA2004A7AAE /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = GodotEngine;
TargetAttributes = {
D0BCFE3318AEBDA2004A7AAE = {
DevelopmentTeam = $team_id;
$swift_runtime_migration
ProvisioningStyle = Automatic;
SystemCapabilities = {
};
};
};
};
buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = D0BCFE2B18AEBDA2004A7AAE;
productRefGroup = D0BCFE3518AEBDA2004A7AAE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D0BCFE3318AEBDA2004A7AAE /* $binary */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D0BCFE3218AEBDA2004A7AAE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */,
D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */,
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */,
F965960D2BC2C3A800579C7E /* PrivacyInfo.xcprivacy in Resources */,
$additional_pbx_resources_build
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D0BCFE3018AEBDA2004A7AAE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */,
$swift_runtime_build_phase
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D0BCFE4518AEBDA2004A7AAE /* en */,
$pbx_locale_build_reference
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D0BCFE6F18AEBDA3004A7AAE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "$code_sign_identity_debug";
"CODE_SIGN_IDENTITY[sdk=xros*]" = "$code_sign_identity_debug";
COPY_PHASE_STRIP = NO;
ENABLE_BITCODE = NO;
"FRAMEWORK_SEARCH_PATHS[arch=*]" = (
"$(PROJECT_DIR)/**",
);
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
XROS_DEPLOYMENT_TARGET = $min_version;
"LD_CLASSIC_1500" = "-ld_classic";
"LD_CLASSIC_1501" = "-ld_classic";
"LD_CLASSIC_1510" = "-ld_classic";
OTHER_LDFLAGS = "$(LD_CLASSIC_$(XCODE_VERSION_ACTUAL)) $linker_flags";
SDKROOT = xros;
TARGETED_DEVICE_FAMILY = 7;
};
name = Debug;
};
D0BCFE7018AEBDA3004A7AAE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$godot_archs";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=xros*]" = "$code_sign_identity_release";
COPY_PHASE_STRIP = YES;
ENABLE_BITCODE = NO;
"FRAMEWORK_SEARCH_PATHS[arch=*]" = (
"$(PROJECT_DIR)/**",
);
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
XROS_DEPLOYMENT_TARGET = $min_version;
"LD_CLASSIC_1500" = "-ld_classic";
"LD_CLASSIC_1501" = "-ld_classic";
"LD_CLASSIC_1510" = "-ld_classic";
OTHER_LDFLAGS = "$(LD_CLASSIC_$(XCODE_VERSION_ACTUAL)) $linker_flags";
SDKROOT = xros;
TARGETED_DEVICE_FAMILY = 7;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
D0BCFE7218AEBDA3004A7AAE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements";
CODE_SIGN_IDENTITY = "$code_sign_identity_debug";
"CODE_SIGN_IDENTITY[sdk=xros*]" = "$code_sign_identity_debug";
CODE_SIGN_STYLE = "$code_sign_style_debug";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
INFOPLIST_FILE = "$binary/$binary-Info.plist";
XROS_DEPLOYMENT_TARGET = $min_version;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/**",
);
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
INFOPLIST_KEY_CFBundleDisplayName = "$name";
PRODUCT_NAME = "$binary";
EXECUTABLE_NAME = "$binary";
MARKETING_VERSION = $short_version;
CURRENT_PROJECT_VERSION = $version;
PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
PROVISIONING_PROFILE_SPECIFIER = "$provisioning_profile_specifier_debug";
TARGETED_DEVICE_FAMILY = 7;
VALID_ARCHS = "arm64 x86_64";
WRAPPER_EXTENSION = app;
$swift_runtime_build_settings
};
name = Debug;
};
D0BCFE7318AEBDA3004A7AAE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$godot_archs";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "$binary/$binary.entitlements";
CODE_SIGN_IDENTITY = "$code_sign_identity_release";
"CODE_SIGN_IDENTITY[sdk=xros*]" = "$code_sign_identity_release";
CODE_SIGN_STYLE = "$code_sign_style_release";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
DEVELOPMENT_TEAM = $team_id;
INFOPLIST_FILE = "$binary/$binary-Info.plist";
XROS_DEPLOYMENT_TARGET = $min_version;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/**",
);
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
INFOPLIST_KEY_CFBundleDisplayName = "$name";
PRODUCT_NAME = "$binary";
EXECUTABLE_NAME = "$binary";
MARKETING_VERSION = $short_version;
CURRENT_PROJECT_VERSION = $version;
PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
PROVISIONING_PROFILE_SPECIFIER = "$provisioning_profile_specifier_release";
TARGETED_DEVICE_FAMILY = 7;
VALID_ARCHS = "arm64";
WRAPPER_EXTENSION = app;
$swift_runtime_build_settings
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D0BCFE6F18AEBDA3004A7AAE /* Debug */,
D0BCFE7018AEBDA3004A7AAE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "$binary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D0BCFE7218AEBDA3004A7AAE /* Debug */,
D0BCFE7318AEBDA3004A7AAE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
/* End XCConfigurationList section */
};
rootObject = D0BCFE2C18AEBDA2004A7AAE /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:$binary.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A340BDFEBCA49239A941883D"
BuildableName = "$binary.app"
BlueprintName = "$binary"
ReferencedContainer = "container:$binary.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A340BDFEBCA49239A941883D"
BuildableName = "$binary.app"
BlueprintName = "$binary"
ReferencedContainer = "container:$binary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "$default_build_config"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A340BDFEBCA49239A941883D"
BuildableName = "$binary.app"
BlueprintName = "$binary"
ReferencedContainer = "container:$binary.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "$default_build_config"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A340BDFEBCA49239A941883D"
BuildableName = "$binary.app"
BlueprintName = "$binary"
ReferencedContainer = "container:$binary.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "$default_build_config">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "$default_build_config"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "splash@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "splash@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,31 @@
/**************************************************************************/
/* dummy.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
$cpp_code

View File

@@ -0,0 +1,33 @@
/**************************************************************************/
/* dummy.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
// #import <Foundation/Foundation.h>

View File

@@ -0,0 +1,31 @@
/**************************************************************************/
/* dummy.swift */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
import Foundation

View File

@@ -0,0 +1 @@
Dummy file to make dylibs folder exported

View File

@@ -0,0 +1 @@
/* Localized versions of Info.plist keys */

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>$export_method</string>
<key>teamID</key>
<string>$team_id</string>
<key>provisioningProfiles</key>
<dict>
<key>$bundle_identifier</key>
<string>$provisioning_profile_uuid</string>
</dict>
<key>compileBitcode</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleSignature</key>
<string>$signature</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false />
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
$docs_in_place
<key>UIFileSharingEnabled</key>
$docs_sharing
<key>UIRequiredDeviceCapabilities</key>
<array>
$required_device_capabilities
</array>
<key>NSCameraUsageDescription</key>
<string>$camera_usage_description</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$photolibrary_usage_description</string>
<key>NSMicrophoneUsageDescription</key>
<string>$microphone_usage_description</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
$interface_orientations
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
$ipad_interface_orientations
</array>
$additional_plist_content
$plist_launch_screen_name
<key>CADisableMinimumFrameDurationOnPhone</key><true/>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
$entitlements_full
</dict>
</plist>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>LibraryIdentifier</key>
<string>xros-arm64</string>
<key>LibraryPath</key>
<string>libgodot.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>xros</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>xros-arm64-simulator</string>
<key>LibraryPath</key>
<string>libgodot.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>xros</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@@ -0,0 +1 @@
Dummy file to make dylibs folder exported

View File

@@ -0,0 +1 @@
Dummy file to make dylibs folder exported

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>LibraryIdentifier</key>
<string>xros-arm64</string>
<key>LibraryPath</key>
<string>libgodot.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>xros</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
<string>xros-arm64-simulator</string>
<key>LibraryPath</key>
<string>libgodot.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>xros</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@@ -0,0 +1 @@
Dummy file to make dylibs folder exported

View File

@@ -0,0 +1 @@
Dummy file to make dylibs folder exported

View File

@@ -406,7 +406,7 @@ namespace GodotTools.Export
{ {
if (platform == OS.Platforms.iOS && path.EndsWith(".dat", StringComparison.OrdinalIgnoreCase)) if (platform == OS.Platforms.iOS && path.EndsWith(".dat", StringComparison.OrdinalIgnoreCase))
{ {
AddIosBundleFile(path); AddAppleEmbeddedPlatformBundleFile(path);
} }
else else
{ {
@@ -453,7 +453,7 @@ namespace GodotTools.Export
throw new InvalidOperationException("Failed to generate xcframework."); throw new InvalidOperationException("Failed to generate xcframework.");
} }
AddIosEmbeddedFramework(xcFrameworkPath); AddAppleEmbeddedPlatformEmbeddedFramework(xcFrameworkPath);
} }
} }

View File

@@ -82,7 +82,7 @@ namespace {
String get_hostfxr_file_name() { String get_hostfxr_file_name() {
#if defined(WINDOWS_ENABLED) #if defined(WINDOWS_ENABLED)
return "hostfxr.dll"; return "hostfxr.dll";
#elif defined(MACOS_ENABLED) || defined(IOS_ENABLED) #elif defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
return "libhostfxr.dylib"; return "libhostfxr.dylib";
#else #else
return "libhostfxr.so"; return "libhostfxr.so";

View File

@@ -450,7 +450,7 @@ godot_plugins_initialize_fn try_load_native_aot_library(void *&r_aot_dll_handle)
#if defined(WINDOWS_ENABLED) #if defined(WINDOWS_ENABLED)
String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dll"); String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dll");
#elif defined(MACOS_ENABLED) || defined(IOS_ENABLED) #elif defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dylib"); String native_aot_so_path = GodotSharpDirs::get_api_assemblies_dir().path_join(assembly_name + ".dylib");
#elif defined(ANDROID_ENABLED) #elif defined(ANDROID_ENABLED)
String native_aot_so_path = "lib" + assembly_name + ".so"; String native_aot_so_path = "lib" + assembly_name + ".so";
@@ -599,7 +599,7 @@ void GDMono::initialize() {
godot_plugins_initialize_fn godot_plugins_initialize = nullptr; godot_plugins_initialize_fn godot_plugins_initialize = nullptr;
#if !defined(IOS_ENABLED) #if !defined(APPLE_EMBEDDED_ENABLED)
// Check that the .NET assemblies directory exists before trying to use it. // Check that the .NET assemblies directory exists before trying to use it.
if (!DirAccess::exists(GodotSharpDirs::get_api_assemblies_dir())) { if (!DirAccess::exists(GodotSharpDirs::get_api_assemblies_dir())) {
OS::get_singleton()->alert(vformat(RTR("Unable to find the .NET assemblies directory.\nMake sure the '%s' directory exists and contains the .NET assemblies."), GodotSharpDirs::get_api_assemblies_dir()), RTR(".NET assemblies not found")); OS::get_singleton()->alert(vformat(RTR("Unable to find the .NET assemblies directory.\nMake sure the '%s' directory exists and contains the .NET assemblies."), GodotSharpDirs::get_api_assemblies_dir()), RTR(".NET assemblies not found"));
@@ -640,7 +640,7 @@ void GDMono::initialize() {
void *godot_dll_handle = nullptr; void *godot_dll_handle = nullptr;
#if defined(UNIX_ENABLED) && !defined(MACOS_ENABLED) && !defined(IOS_ENABLED) #if defined(UNIX_ENABLED) && !defined(MACOS_ENABLED) && !defined(APPLE_EMBEDDED_ENABLED)
// Managed code can access it on its own on other platforms // Managed code can access it on its own on other platforms
godot_dll_handle = dlopen(nullptr, RTLD_NOW); godot_dll_handle = dlopen(nullptr, RTLD_NOW);
#endif #endif

View File

@@ -713,7 +713,7 @@ Vector<PluginConfigAndroid> EditorExportPlatformAndroid::get_plugins() {
Vector<String> plugins_filenames = list_gdap_files(plugins_dir); Vector<String> plugins_filenames = list_gdap_files(plugins_dir);
if (!plugins_filenames.is_empty()) { if (!plugins_filenames.is_empty()) {
Ref<ConfigFile> config_file = memnew(ConfigFile); Ref<ConfigFile> config_file;
for (int i = 0; i < plugins_filenames.size(); i++) { for (int i = 0; i < plugins_filenames.size(); i++) {
PluginConfigAndroid config = PluginConfigAndroid::load_plugin_config(config_file, plugins_dir.path_join(plugins_filenames[i])); PluginConfigAndroid config = PluginConfigAndroid::load_plugin_config(config_file, plugins_dir.path_join(plugins_filenames[i]));
if (config.valid_config) { if (config.valid_config) {

View File

@@ -3,6 +3,10 @@
This folder contains the C++, Objective-C and Objective-C++ code for the iOS This folder contains the C++, Objective-C and Objective-C++ code for the iOS
platform port. platform port.
This platform derives from the Apple embedded abstract platform ([`drivers/apple_embedded`](/drivers/apple_embedded)).
This platform uses shared Apple code ([`drivers/apple`](/drivers/apple)).
See also [`misc/dist/ios_xcode`](/misc/dist/ios_xcode) folder for the Xcode See also [`misc/dist/ios_xcode`](/misc/dist/ios_xcode) folder for the Xcode
project template used for packaging the iOS export templates. project template used for packaging the iOS export templates.

View File

@@ -1,28 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
from misc.utility.scons_hints import * from misc.utility.scons_hints import *
import platform_ios_builders from platform_ios_builders import generate_bundle
from platform_methods import combine_libs_apple_embedded
Import("env") Import("env")
ios_lib = [ ios_lib = [
"godot_ios.mm", "device_metrics.mm",
"os_ios.mm", "display_layer_ios.mm",
"main.m",
"app_delegate.mm",
"view_controller.mm",
"ios.mm",
"rendering_context_driver_vulkan_ios.mm",
"display_server_ios.mm", "display_server_ios.mm",
"godot_view.mm", "godot_view_ios.mm",
"tts_ios.mm", "main_ios.mm",
"display_layer.mm", "os_ios.mm",
"godot_app_delegate.m",
"godot_view_renderer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
"key_mapping_ios.mm",
"ios_terminal_logger.mm",
] ]
env_ios = env.Clone() env_ios = env.Clone()
@@ -31,12 +22,9 @@ ios_lib = env_ios.add_library("ios", ios_lib)
# (iOS) Enable module support # (iOS) Enable module support
env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
combine_command = env_ios.CommandNoCache( combine_command = env_ios.CommandNoCache(
"#bin/libgodot" + env_ios["LIBSUFFIX"], [ios_lib] + env_ios["LIBS"], env.Run(platform_ios_builders.combine_libs) "#bin/libgodot" + env_ios["LIBSUFFIX"], [ios_lib] + env_ios["LIBS"], env.Run(combine_libs_apple_embedded)
) )
if env["generate_bundle"]: if env["generate_bundle"]:
env.AlwaysBuild( env.AlwaysBuild(env.CommandNoCache("generate_bundle", combine_command, env.Run(generate_bundle)))
env.CommandNoCache("generate_bundle", combine_command, env.Run(platform_ios_builders.generate_bundle))
)

View File

@@ -33,11 +33,11 @@
#if defined(IOS_ENABLED) #if defined(IOS_ENABLED)
void register_ios_api() { void register_ios_api() {
godot_ios_plugins_initialize(); godot_apple_embedded_plugins_initialize();
} }
void unregister_ios_api() { void unregister_ios_api() {
godot_ios_plugins_deinitialize(); godot_apple_embedded_plugins_deinitialize();
} }
#else #else

View File

@@ -31,8 +31,8 @@
#pragma once #pragma once
#if defined(IOS_ENABLED) #if defined(IOS_ENABLED)
extern void godot_ios_plugins_initialize(); extern void godot_apple_embedded_plugins_initialize();
extern void godot_ios_plugins_deinitialize(); extern void godot_apple_embedded_plugins_deinitialize();
#endif #endif
void register_ios_api(); void register_ios_api();

View File

@@ -2,7 +2,7 @@ import os
import sys import sys
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from methods import detect_darwin_sdk_path, print_error, print_warning from methods import detect_darwin_sdk_path, detect_darwin_toolchain_path, print_error, print_warning
from platform_methods import validate_arch from platform_methods import validate_arch
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -25,14 +25,11 @@ def get_opts():
return [ return [
("vulkan_sdk_path", "Path to the Vulkan SDK", ""), ("vulkan_sdk_path", "Path to the Vulkan SDK", ""),
( # APPLE_TOOLCHAIN_PATH Example: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
"IOS_TOOLCHAIN_PATH", (("APPLE_TOOLCHAIN_PATH", "IOS_TOOLCHAIN_PATH"), "Path to the Apple toolchain", ""),
"Path to iOS toolchain",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
),
("IOS_SDK_PATH", "Path to the iOS SDK", ""), ("IOS_SDK_PATH", "Path to the iOS SDK", ""),
BoolVariable("ios_simulator", "Build for iOS Simulator", False), (("apple_target_triple", "ios_triple"), "Triple for the corresponding target Apple platform toolchain", ""),
("ios_triple", "Triple for ios toolchain", ""), BoolVariable(("simulator", "ios_simulator"), "Build for Simulator", False),
BoolVariable("generate_bundle", "Generate an APP bundle after building iOS/macOS binaries", False), BoolVariable("generate_bundle", "Generate an APP bundle after building iOS/macOS binaries", False),
] ]
@@ -62,6 +59,7 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_64", "arm64"] supported_arches = ["x86_64", "arm64"]
validate_arch(env["arch"], get_name(), supported_arches) validate_arch(env["arch"], get_name(), supported_arches)
detect_darwin_toolchain_path(env)
## LTO ## LTO
@@ -82,9 +80,9 @@ def configure(env: "SConsEnvironment"):
if "OSXCROSS_IOS" in os.environ: if "OSXCROSS_IOS" in os.environ:
env["osxcross"] = True env["osxcross"] = True
env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] env["ENV"]["PATH"] = env["APPLE_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}" compiler_path = "$APPLE_TOOLCHAIN_PATH/usr/bin/${apple_target_triple}"
ccache_path = os.environ.get("CCACHE") ccache_path = os.environ.get("CCACHE")
if ccache_path is None: if ccache_path is None:
@@ -102,7 +100,7 @@ def configure(env: "SConsEnvironment"):
## Compile flags ## Compile flags
if env["ios_simulator"]: if env["simulator"]:
detect_darwin_sdk_path("iossimulator", env) detect_darwin_sdk_path("iossimulator", env)
env.Append(ASFLAGS=["-mios-simulator-version-min=12.0"]) env.Append(ASFLAGS=["-mios-simulator-version-min=12.0"])
env.Append(CCFLAGS=["-mios-simulator-version-min=12.0"]) env.Append(CCFLAGS=["-mios-simulator-version-min=12.0"])
@@ -114,8 +112,8 @@ def configure(env: "SConsEnvironment"):
env.Append(CCFLAGS=["-miphoneos-version-min=12.0"]) env.Append(CCFLAGS=["-miphoneos-version-min=12.0"])
if env["arch"] == "x86_64": if env["arch"] == "x86_64":
if not env["ios_simulator"]: if not env["simulator"]:
print_error("Building for iOS with 'arch=x86_64' requires 'ios_simulator=yes'.") print_error("Building for iOS with 'arch=x86_64' requires 'simulator=yes'.")
sys.exit(255) sys.exit(255)
env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9" env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9"
@@ -149,10 +147,10 @@ def configure(env: "SConsEnvironment"):
) )
env.Prepend(CPPPATH=["#platform/ios"]) env.Prepend(CPPPATH=["#platform/ios"])
env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"]) env.Append(CPPDEFINES=["IOS_ENABLED", "APPLE_EMBEDDED_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED"])
if env["metal"] and env["ios_simulator"]: if env["metal"] and env["simulator"]:
print_warning("iOS simulator does not support the Metal rendering driver") print_warning("iOS Simulator does not support the Metal rendering driver")
env["metal"] = False env["metal"] = False
if env["metal"]: if env["metal"]:
@@ -166,8 +164,8 @@ def configure(env: "SConsEnvironment"):
) )
env.Prepend(CPPEXTPATH=["#thirdparty/spirv-cross"]) env.Prepend(CPPEXTPATH=["#thirdparty/spirv-cross"])
if env["vulkan"] and env["ios_simulator"]: if env["vulkan"] and env["simulator"]:
print_warning("iOS simulator does not support the Vulkan rendering driver") print_warning("iOS Simulator does not support the Vulkan rendering driver")
env["vulkan"] = False env["vulkan"] = False
if env["vulkan"]: if env["vulkan"]:

View File

@@ -32,7 +32,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface GodotDeviceMetrics : NSObject @interface GDTDeviceMetrics : NSObject
@property(nonatomic, class, readonly, strong) NSDictionary<NSArray *, NSNumber *> *dpiList; @property(nonatomic, class, readonly, strong) NSDictionary<NSArray *, NSNumber *> *dpiList;

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* device_metrics.m */ /* device_metrics.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -30,7 +30,7 @@
#import "device_metrics.h" #import "device_metrics.h"
@implementation GodotDeviceMetrics @implementation GDTDeviceMetrics
+ (NSDictionary *)dpiList { + (NSDictionary *)dpiList {
return @{ return @{

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* display_layer.h */ /* display_layer_ios.h */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -30,32 +30,25 @@
#pragma once #pragma once
#include "drivers/apple_embedded/display_layer_apple_embedded.h"
#import <OpenGLES/EAGLDrawable.h> #import <OpenGLES/EAGLDrawable.h>
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
@protocol DisplayLayer <NSObject>
- (void)startRenderDisplayLayer;
- (void)stopRenderDisplayLayer;
- (void)initializeDisplayLayer;
- (void)layoutDisplayLayer;
@end
// An ugly workaround for iOS simulator // An ugly workaround for iOS simulator
#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR #if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
#if defined(__IPHONE_13_0) #if defined(__IPHONE_13_0)
API_AVAILABLE(ios(13.0)) API_AVAILABLE(ios(13.0))
@interface GodotMetalLayer : CAMetalLayer <DisplayLayer> @interface GDTMetalLayer : CAMetalLayer <GDTDisplayLayer>
#else #else
@interface GodotMetalLayer : CALayer <DisplayLayer> @interface GDTMetalLayer : CALayer <GDTDisplayLayer>
#endif #endif
#else #else
@interface GodotMetalLayer : CAMetalLayer <DisplayLayer> @interface GDTMetalLayer : CAMetalLayer <GDTDisplayLayer>
#endif #endif
@end @end
API_DEPRECATED("OpenGLES is deprecated", ios(2.0, 12.0)) API_DEPRECATED("OpenGLES is deprecated", ios(2.0, 12.0))
@interface GodotOpenGLLayer : CAEAGLLayer <DisplayLayer> @interface GDTOpenGLLayer : CAEAGLLayer <GDTDisplayLayer>
@end @end

View File

@@ -1,5 +1,5 @@
/**************************************************************************/ /**************************************************************************/
/* display_layer.mm */ /* display_layer_ios.mm */
/**************************************************************************/ /**************************************************************************/
/* This file is part of: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
#import "display_layer.h" #import "display_layer_ios.h"
#import "display_server_ios.h" #import "display_server_ios.h"
#import "os_ios.h" #import "os_ios.h"
@@ -46,7 +46,7 @@
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@implementation GodotMetalLayer @implementation GDTMetalLayer
- (void)initializeDisplayLayer { - (void)initializeDisplayLayer {
#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR #if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
@@ -69,7 +69,7 @@
@end @end
@implementation GodotOpenGLLayer { @implementation GDTOpenGLLayer {
// The pixel dimensions of the backbuffer // The pixel dimensions of the backbuffer
GLint backingWidth; GLint backingWidth;
GLint backingHeight; GLint backingHeight;

View File

@@ -30,209 +30,25 @@
#pragma once #pragma once
#include "core/input/input.h" #include "drivers/apple_embedded/display_server_apple_embedded.h"
#include "servers/display_server.h"
#if defined(RD_ENABLED) class DisplayServerIOS : public DisplayServerAppleEmbedded {
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" GDSOFTCLASS(DisplayServerIOS, DisplayServerAppleEmbedded);
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#import "rendering_context_driver_vulkan_ios.h"
#include "drivers/vulkan/godot_vulkan.h"
#endif // VULKAN_ENABLED
#if defined(METAL_ENABLED)
#import "drivers/metal/rendering_context_driver_metal.h"
#endif // METAL_ENABLED
#endif // RD_ENABLED
#if defined(GLES3_ENABLED)
#include "drivers/gles3/rasterizer_gles3.h"
#endif // GLES3_ENABLED
#import <Foundation/Foundation.h>
#import <QuartzCore/CAMetalLayer.h>
class DisplayServerIOS : public DisplayServer {
GDSOFTCLASS(DisplayServerIOS, DisplayServer);
_THREAD_SAFE_CLASS_ _THREAD_SAFE_CLASS_
#if defined(RD_ENABLED)
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif
NativeMenu *native_menu = nullptr;
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;
Callable system_theme_changed;
int virtual_keyboard_height = 0;
void perform_event(const Ref<InputEvent> &p_event);
void initialize_tts() const;
DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error); DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error);
~DisplayServerIOS(); ~DisplayServerIOS();
public: public:
String rendering_driver;
static DisplayServerIOS *get_singleton(); static DisplayServerIOS *get_singleton();
static void register_ios_driver(); static void register_ios_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_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, 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;
void emit_system_theme_changed();
// MARK: - Input
// MARK: Touches and Apple Pencil
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, float p_pressure, Vector2 p_tilt);
void touches_canceled(int p_idx);
// MARK: Keyboard
void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location);
bool is_keyboard_active() const;
// MARK: Motion
void update_gravity(const Vector3 &p_gravity);
void update_accelerometer(const Vector3 &p_accelerometer);
void update_magnetometer(const Vector3 &p_magnetometer);
void update_gyroscope(const Vector3 &p_gyroscope);
// MARK: -
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override; virtual String get_name() const override;
virtual bool tts_is_speaking() const override;
virtual bool tts_is_paused() const override;
virtual TypedArray<Dictionary> 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 bool is_dark_mode_supported() const override;
virtual bool is_dark_mode() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override;
virtual Rect2i get_display_safe_area() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() 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 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_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 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 Point2i window_get_position_with_decorations(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_size_with_decorations(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 bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const 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 is_touchscreen_available() const override;
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, 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 bool has_hardware_keyboard() 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);
virtual void swap_buffers() override {}
}; };

View File

@@ -30,492 +30,33 @@
#import "display_server_ios.h" #import "display_server_ios.h"
#import "app_delegate.h"
#import "device_metrics.h" #import "device_metrics.h"
#import "godot_view.h"
#import "ios.h"
#import "key_mapping_ios.h"
#import "keyboard_input_view.h"
#import "os_ios.h"
#import "tts_ios.h"
#import "view_controller.h"
#include "core/config/project_settings.h"
#include "core/io/file_access_pack.h"
#import <UIKit/UIKit.h>
#import <sys/utsname.h> #import <sys/utsname.h>
#import <GameController/GameController.h>
static const float kDisplayServerIOSAcceleration = 1.f;
DisplayServerIOS *DisplayServerIOS::get_singleton() { DisplayServerIOS *DisplayServerIOS::get_singleton() {
return (DisplayServerIOS *)DisplayServer::get_singleton(); return (DisplayServerIOS *)DisplayServerAppleEmbedded::get_singleton();
} }
DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) { DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) :
KeyMappingIOS::initialize(); DisplayServerAppleEmbedded(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, p_parent_window, r_error) {
rendering_driver = p_rendering_driver;
// Init TTS
bool tts_enabled = GLOBAL_GET("audio/general/text_to_speech");
if (tts_enabled) {
initialize_tts();
}
native_menu = memnew(NativeMenu);
#if defined(RD_ENABLED)
rendering_context = nullptr;
rendering_device = nullptr;
CALayer *layer = nullptr;
union {
#ifdef VULKAN_ENABLED
RenderingContextDriverVulkanIOS::WindowPlatformData vulkan;
#endif
#ifdef METAL_ENABLED
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wunguarded-availability")
// Eliminate "RenderingContextDriverMetal is only available on iOS 14.0 or newer".
RenderingContextDriverMetal::WindowPlatformData metal;
GODOT_CLANG_WARNING_POP
#endif
} wpd;
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"vulkan"];
if (!layer) {
ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer.");
}
wpd.vulkan.layer_ptr = (CAMetalLayer *const *)&layer;
rendering_context = memnew(RenderingContextDriverVulkanIOS);
}
#endif
#ifdef METAL_ENABLED
if (rendering_driver == "metal") {
if (@available(iOS 14.0, *)) {
layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"metal"];
wpd.metal.layer = (CAMetalLayer *)layer;
rendering_context = memnew(RenderingContextDriverMetal);
} else {
OS::get_singleton()->alert("Metal is only supported on iOS 14.0 and later.");
r_error = ERR_UNAVAILABLE;
return;
}
}
#endif
if (rendering_context) {
if (rendering_context->initialize() != OK) {
memdelete(rendering_context);
rendering_context = nullptr;
#if defined(GLES3_ENABLED)
bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
if (fallback_to_opengl3 && rendering_driver != "opengl3") {
WARN_PRINT("Your device seem not to support MoltenVK or Metal, switching to OpenGL 3.");
rendering_driver = "opengl3";
OS::get_singleton()->set_current_rendering_method("gl_compatibility");
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
} else
#endif
{
ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
r_error = ERR_UNAVAILABLE;
return;
}
}
}
if (rendering_context) {
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
rendering_context->window_set_size(MAIN_WINDOW_ID, size.width, size.height);
rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);
rendering_device = memnew(RenderingDevice);
if (rendering_device->initialize(rendering_context, MAIN_WINDOW_ID) != OK) {
rendering_device = nullptr;
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
#endif
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"opengl3"];
if (!layer) {
ERR_FAIL_MSG("Failed to create iOS OpenGLES rendering layer.");
}
RasterizerGLES3::make_current(false);
}
#endif
bool keep_screen_on = bool(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
screen_set_keep_on(keep_screen_on);
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
} }
DisplayServerIOS::~DisplayServerIOS() { DisplayServerIOS::~DisplayServerIOS() {
if (native_menu) {
memdelete(native_menu);
native_menu = nullptr;
}
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->screen_free(MAIN_WINDOW_ID);
memdelete(rendering_device);
rendering_device = nullptr;
}
if (rendering_context) {
rendering_context->window_destroy(MAIN_WINDOW_ID);
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif
} }
DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) { DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {
return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, p_parent_window, r_error)); return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, p_parent_window, r_error));
} }
Vector<String> DisplayServerIOS::get_rendering_drivers_func() {
Vector<String> drivers;
#if defined(VULKAN_ENABLED)
drivers.push_back("vulkan");
#endif
#if defined(METAL_ENABLED)
if (@available(ios 14.0, *)) {
drivers.push_back("metal");
}
#endif
#if defined(GLES3_ENABLED)
drivers.push_back("opengl3");
#endif
return drivers;
}
void DisplayServerIOS::register_ios_driver() { void DisplayServerIOS::register_ios_driver() {
register_create_function("iOS", create_func, get_rendering_drivers_func); register_create_function("iOS", create_func, get_rendering_drivers_func);
} }
// MARK: Events
void DisplayServerIOS::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
window_resize_callback = p_callable;
}
void DisplayServerIOS::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
window_event_callback = p_callable;
}
void DisplayServerIOS::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) {
input_event_callback = p_callable;
}
void DisplayServerIOS::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) {
input_text_callback = p_callable;
}
void DisplayServerIOS::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) {
// Probably not supported for iOS
}
void DisplayServerIOS::process_events() {
Input::get_singleton()->flush_buffered_events();
}
void DisplayServerIOS::_dispatch_input_events(const Ref<InputEvent> &p_event) {
DisplayServerIOS::get_singleton()->send_input_event(p_event);
}
void DisplayServerIOS::send_input_event(const Ref<InputEvent> &p_event) const {
_window_callback(input_event_callback, p_event);
}
void DisplayServerIOS::send_input_text(const String &p_text) const {
_window_callback(input_text_callback, p_text);
}
void DisplayServerIOS::send_window_event(DisplayServer::WindowEvent p_event) const {
_window_callback(window_event_callback, int(p_event));
}
void DisplayServerIOS::_window_callback(const Callable &p_callable, const Variant &p_arg) const {
if (p_callable.is_valid()) {
p_callable.call(p_arg);
}
}
// MARK: - Input
// MARK: Touches
void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
Ref<InputEventScreenTouch> ev;
ev.instantiate();
ev->set_index(p_idx);
ev->set_pressed(p_pressed);
ev->set_position(Vector2(p_x, p_y));
ev->set_double_tap(p_double_click);
perform_event(ev);
}
void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt) {
Ref<InputEventScreenDrag> ev;
ev.instantiate();
ev->set_index(p_idx);
ev->set_pressure(p_pressure);
ev->set_tilt(p_tilt);
ev->set_position(Vector2(p_x, p_y));
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
ev->set_relative_screen_position(ev->get_relative());
perform_event(ev);
}
void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
Input::get_singleton()->parse_input_event(p_event);
}
void DisplayServerIOS::touches_canceled(int p_idx) {
touch_press(p_idx, -1, -1, false, false);
}
// MARK: Keyboard
void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
ev->set_keycode(fix_keycode(p_char, p_key));
if (@available(iOS 13.4, *)) {
if (p_key != Key::SHIFT) {
ev->set_shift_pressed(p_modifier & UIKeyModifierShift);
}
if (p_key != Key::CTRL) {
ev->set_ctrl_pressed(p_modifier & UIKeyModifierControl);
}
if (p_key != Key::ALT) {
ev->set_alt_pressed(p_modifier & UIKeyModifierAlternate);
}
if (p_key != Key::META) {
ev->set_meta_pressed(p_modifier & UIKeyModifierCommand);
}
}
ev->set_key_label(p_unshifted);
ev->set_physical_keycode(p_physical);
ev->set_unicode(fix_unicode(p_char));
ev->set_location(p_location);
perform_event(ev);
}
// MARK: Motion
void DisplayServerIOS::update_gravity(const Vector3 &p_gravity) {
Input::get_singleton()->set_gravity(p_gravity);
}
void DisplayServerIOS::update_accelerometer(const Vector3 &p_accelerometer) {
Input::get_singleton()->set_accelerometer(p_accelerometer / kDisplayServerIOSAcceleration);
}
void DisplayServerIOS::update_magnetometer(const Vector3 &p_magnetometer) {
Input::get_singleton()->set_magnetometer(p_magnetometer);
}
void DisplayServerIOS::update_gyroscope(const Vector3 &p_gyroscope) {
Input::get_singleton()->set_gyroscope(p_gyroscope);
}
// MARK: -
bool DisplayServerIOS::has_feature(Feature p_feature) const {
switch (p_feature) {
#ifndef DISABLE_DEPRECATED
case FEATURE_GLOBAL_MENU: {
return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));
} break;
#endif
// case FEATURE_CURSOR_SHAPE:
// case FEATURE_CUSTOM_CURSOR_SHAPE:
// case FEATURE_HIDPI:
// case FEATURE_ICON:
// case FEATURE_IME:
// case FEATURE_MOUSE:
// case FEATURE_MOUSE_WARP:
// case FEATURE_NATIVE_DIALOG:
// case FEATURE_NATIVE_DIALOG_INPUT:
// case FEATURE_NATIVE_DIALOG_FILE:
// case FEATURE_NATIVE_DIALOG_FILE_EXTRA:
// case FEATURE_NATIVE_DIALOG_FILE_MIME:
// 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 DisplayServerIOS::get_name() const { String DisplayServerIOS::get_name() const {
return "iOS"; return "iOS";
} }
void DisplayServerIOS::initialize_tts() const {
const_cast<DisplayServerIOS *>(this)->tts = [[TTS_IOS alloc] init];
}
bool DisplayServerIOS::tts_is_speaking() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, false);
return [tts isSpeaking];
}
bool DisplayServerIOS::tts_is_paused() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, false);
return [tts isPaused];
}
TypedArray<Dictionary> DisplayServerIOS::tts_get_voices() const {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL_V(tts, TypedArray<Dictionary>());
return [tts getVoices];
}
void DisplayServerIOS::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) {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(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 DisplayServerIOS::tts_pause() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts pauseSpeaking];
}
void DisplayServerIOS::tts_resume() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts resumeSpeaking];
}
void DisplayServerIOS::tts_stop() {
if (unlikely(!tts)) {
initialize_tts();
}
ERR_FAIL_NULL(tts);
[tts stopSpeaking];
}
bool DisplayServerIOS::is_dark_mode_supported() const {
if (@available(iOS 13.0, *)) {
return true;
} else {
return false;
}
}
bool DisplayServerIOS::is_dark_mode() const {
if (@available(iOS 13.0, *)) {
return [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark;
} else {
return false;
}
}
void DisplayServerIOS::set_system_theme_change_callback(const Callable &p_callable) {
system_theme_changed = p_callable;
}
void DisplayServerIOS::emit_system_theme_changed() {
if (system_theme_changed.is_valid()) {
Variant ret;
Callable::CallError ce;
system_theme_changed.callp(nullptr, 0, ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
}
}
}
Rect2i DisplayServerIOS::get_display_safe_area() const {
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);
}
int DisplayServerIOS::get_screen_count() const {
return 1;
}
int DisplayServerIOS::get_primary_screen() const {
return 0;
}
Point2i DisplayServerIOS::screen_get_position(int p_screen) const {
return Size2i();
}
Size2i DisplayServerIOS::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 DisplayServerIOS::screen_get_usable_rect(int p_screen) const {
return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
}
int DisplayServerIOS::screen_get_dpi(int p_screen) const { int DisplayServerIOS::screen_get_dpi(int p_screen) const {
struct utsname systemInfo; struct utsname systemInfo;
@@ -523,7 +64,7 @@ int DisplayServerIOS::screen_get_dpi(int p_screen) const {
NSString *string = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; NSString *string = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
NSDictionary *iOSModelToDPI = [GodotDeviceMetrics dpiList]; NSDictionary *iOSModelToDPI = [GDTDeviceMetrics dpiList];
for (NSArray *keyArray in iOSModelToDPI) { for (NSArray *keyArray in iOSModelToDPI) {
if ([keyArray containsObject:string]) { if ([keyArray containsObject:string]) {
@@ -565,283 +106,3 @@ float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const {
float DisplayServerIOS::screen_get_scale(int p_screen) const { float DisplayServerIOS::screen_get_scale(int p_screen) const {
return [UIScreen mainScreen].scale; return [UIScreen mainScreen].scale;
} }
Vector<DisplayServer::WindowID> DisplayServerIOS::get_window_list() const {
Vector<DisplayServer::WindowID> list;
list.push_back(MAIN_WINDOW_ID);
return list;
}
DisplayServer::WindowID DisplayServerIOS::get_window_at_screen_position(const Point2i &p_position) const {
return MAIN_WINDOW_ID;
}
int64_t DisplayServerIOS::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 DisplayServerIOS::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
window_attached_instance_id = p_instance;
}
ObjectID DisplayServerIOS::window_get_attached_instance_id(WindowID p_window) const {
return window_attached_instance_id;
}
void DisplayServerIOS::window_set_title(const String &p_title, WindowID p_window) {
// Probably not supported for iOS
}
int DisplayServerIOS::window_get_current_screen(WindowID p_window) const {
return SCREEN_OF_MAIN_WINDOW;
}
void DisplayServerIOS::window_set_current_screen(int p_screen, WindowID p_window) {
// Probably not supported for iOS
}
Point2i DisplayServerIOS::window_get_position(WindowID p_window) const {
return Point2i();
}
Point2i DisplayServerIOS::window_get_position_with_decorations(WindowID p_window) const {
return Point2i();
}
void DisplayServerIOS::window_set_position(const Point2i &p_position, WindowID p_window) {
// Probably not supported for single window iOS app
}
void DisplayServerIOS::window_set_transient(WindowID p_window, WindowID p_parent) {
// Probably not supported for iOS
}
void DisplayServerIOS::window_set_max_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerIOS::window_get_max_size(WindowID p_window) const {
return Size2i();
}
void DisplayServerIOS::window_set_min_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerIOS::window_get_min_size(WindowID p_window) const {
return Size2i();
}
void DisplayServerIOS::window_set_size(const Size2i p_size, WindowID p_window) {
// Probably not supported for iOS
}
Size2i DisplayServerIOS::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 DisplayServerIOS::window_get_size_with_decorations(WindowID p_window) const {
return window_get_size(p_window);
}
void DisplayServerIOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
// Probably not supported for iOS
}
DisplayServer::WindowMode DisplayServerIOS::window_get_mode(WindowID p_window) const {
return WindowMode::WINDOW_MODE_FULLSCREEN;
}
bool DisplayServerIOS::window_is_maximize_allowed(WindowID p_window) const {
return false;
}
void DisplayServerIOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
// Probably not supported for iOS
}
bool DisplayServerIOS::window_get_flag(WindowFlags p_flag, WindowID p_window) const {
return false;
}
void DisplayServerIOS::window_request_attention(WindowID p_window) {
// Probably not supported for iOS
}
void DisplayServerIOS::window_move_to_foreground(WindowID p_window) {
// Probably not supported for iOS
}
bool DisplayServerIOS::window_is_focused(WindowID p_window) const {
return true;
}
float DisplayServerIOS::screen_get_max_scale() const {
return screen_get_scale(SCREEN_OF_MAIN_WINDOW);
}
void DisplayServerIOS::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {
screen_orientation = p_orientation;
if (@available(iOS 16.0, *)) {
[AppDelegate.viewController setNeedsUpdateOfSupportedInterfaceOrientations];
} else {
[UIViewController attemptRotationToDeviceOrientation];
}
}
DisplayServer::ScreenOrientation DisplayServerIOS::screen_get_orientation(int p_screen) const {
return screen_orientation;
}
bool DisplayServerIOS::window_can_draw(WindowID p_window) const {
return true;
}
bool DisplayServerIOS::can_any_window_draw() const {
return true;
}
bool DisplayServerIOS::is_touchscreen_available() const {
return true;
}
_FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text, int p_pos) {
int limit = p_pos;
for (int i = 0; i < MIN(p_existing_text.length(), p_pos); i++) {
if (p_existing_text[i] > 0xffff) {
limit++;
}
}
return limit;
}
void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, 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.keyboardType = UIKeyboardTypeDefault;
AppDelegate.viewController.keyboardView.textContentType = nil;
switch (p_type) {
case KEYBOARD_TYPE_DEFAULT: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
} break;
case KEYBOARD_TYPE_MULTILINE: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
} break;
case KEYBOARD_TYPE_NUMBER: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeNumberPad;
} break;
case KEYBOARD_TYPE_NUMBER_DECIMAL: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDecimalPad;
} break;
case KEYBOARD_TYPE_PHONE: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypePhonePad;
AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeTelephoneNumber;
} break;
case KEYBOARD_TYPE_EMAIL_ADDRESS: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeEmailAddress;
AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeEmailAddress;
} break;
case KEYBOARD_TYPE_PASSWORD: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault;
AppDelegate.viewController.keyboardView.textContentType = UITextContentTypePassword;
} break;
case KEYBOARD_TYPE_URL: {
AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeWebSearch;
AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeURL;
} break;
}
[AppDelegate.viewController.keyboardView
becomeFirstResponderWithString:existingString
cursorStart:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_start)
cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)];
}
bool DisplayServerIOS::is_keyboard_active() const {
return [AppDelegate.viewController.keyboardView isFirstResponder];
}
void DisplayServerIOS::virtual_keyboard_hide() {
[AppDelegate.viewController.keyboardView resignFirstResponder];
}
void DisplayServerIOS::virtual_keyboard_set_height(int height) {
virtual_keyboard_height = height * screen_get_max_scale();
}
int DisplayServerIOS::virtual_keyboard_get_height() const {
return virtual_keyboard_height;
}
bool DisplayServerIOS::has_hardware_keyboard() const {
if (@available(iOS 14.0, *)) {
return [GCKeyboard coalescedKeyboard];
} else {
return false;
}
}
void DisplayServerIOS::clipboard_set(const String &p_text) {
[UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8().get_data()];
}
String DisplayServerIOS::clipboard_get() const {
NSString *text = [UIPasteboard generalPasteboard].string;
return String::utf8([text UTF8String]);
}
void DisplayServerIOS::screen_set_keep_on(bool p_enable) {
[UIApplication sharedApplication].idleTimerDisabled = p_enable;
}
bool DisplayServerIOS::screen_is_kept_on() const {
return [UIApplication sharedApplication].idleTimerDisabled;
}
void DisplayServerIOS::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_size(MAIN_WINDOW_ID, size.x, size.y);
}
#endif
Variant resize_rect = Rect2i(Point2i(), size);
_window_callback(window_resize_callback, resize_rect);
}
void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorExportPlatformIOS" inherits="EditorExportPlatform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <class name="EditorExportPlatformIOS" inherits="EditorExportPlatformAppleEmbedded" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description> <brief_description>
Exporter for iOS. Exporter for iOS.
</brief_description> </brief_description>
@@ -24,10 +24,10 @@
Unique application identifier in a reverse-DNS format, can only contain alphanumeric characters ([code]A-Z[/code], [code]a-z[/code], and [code]0-9[/code]), hyphens ([code]-[/code]), and periods ([code].[/code]). Unique application identifier in a reverse-DNS format, can only contain alphanumeric characters ([code]A-Z[/code], [code]a-z[/code], and [code]0-9[/code]), hyphens ([code]-[/code]), and periods ([code].[/code]).
</member> </member>
<member name="application/code_sign_identity_debug" type="String" setter="" getter=""> <member name="application/code_sign_identity_debug" type="String" setter="" getter="">
The "Full Name", "Common Name" or SHA-1 hash of the signing identity used for debug export. The "Full Name", "Common Name", or SHA-1 hash of the signing identity used for debug export.
</member> </member>
<member name="application/code_sign_identity_release" type="String" setter="" getter=""> <member name="application/code_sign_identity_release" type="String" setter="" getter="">
The "Full Name", "Common Name" or SHA-1 hash of the signing identity used for release export. The "Full Name", "Common Name", or SHA-1 hash of the signing identity used for release export.
</member> </member>
<member name="application/delete_old_export_files_unconditionally" type="bool" setter="" getter=""> <member name="application/delete_old_export_files_unconditionally" type="bool" setter="" getter="">
If [code]true[/code], existing "project name" and "project name.xcodeproj" in the export destination directory will be unconditionally deleted during export. If [code]true[/code], existing "project name" and "project name.xcodeproj" in the export destination directory will be unconditionally deleted during export.
@@ -48,20 +48,20 @@
Minimum version of iOS required for this application to run in the [code]major.minor.patch[/code] or [code]major.minor[/code] format, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]). Minimum version of iOS required for this application to run in the [code]major.minor.patch[/code] or [code]major.minor[/code] format, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]).
</member> </member>
<member name="application/provisioning_profile_specifier_debug" type="String" setter="" getter=""> <member name="application/provisioning_profile_specifier_debug" type="String" setter="" getter="">
Name of the provisioning profile. Sets XCode PROVISIONING_PROFILE_SPECIFIER for debug. [url=https://developer.apple.com/documentation/xcode/build-settings-reference#Provisioning-Profile]Used for manual provisioning[/url]. Name of the provisioning profile. Sets Xcode PROVISIONING_PROFILE_SPECIFIER for debug. [url=https://developer.apple.com/documentation/xcode/build-settings-reference#Provisioning-Profile]Used for manual provisioning[/url].
Can be overridden with the environment variable [code]GODOT_IOS_PROFILE_SPECIFIER_DEBUG[/code]. Can be overridden with the environment variable [code]GODOT_APPLE_PLATFORM_PROFILE_SPECIFIER_DEBUG[/code].
</member> </member>
<member name="application/provisioning_profile_specifier_release" type="String" setter="" getter=""> <member name="application/provisioning_profile_specifier_release" type="String" setter="" getter="">
Name of the provisioning profile. Sets XCode PROVISIONING_PROFILE_SPECIFIER for release. [url=https://developer.apple.com/documentation/xcode/build-settings-reference#Provisioning-Profile]Used for manual provisioning[/url]. Name of the provisioning profile. Sets Xcode PROVISIONING_PROFILE_SPECIFIER for release. [url=https://developer.apple.com/documentation/xcode/build-settings-reference#Provisioning-Profile]Used for manual provisioning[/url].
Can be overridden with the environment variable [code]GODOT_IOS_PROFILE_SPECIFIER_RELEASE[/code]. Can be overridden with the environment variable [code]GODOT_APPLE_PLATFORM_PROFILE_SPECIFIER_RELEASE[/code].
</member> </member>
<member name="application/provisioning_profile_uuid_debug" type="String" setter="" getter=""> <member name="application/provisioning_profile_uuid_debug" type="String" setter="" getter="">
UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url]. UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url].
Can be overridden with the environment variable [code]GODOT_IOS_PROVISIONING_PROFILE_UUID_DEBUG[/code]. Can be overridden with the environment variable [code]GODOT_APPLE_PLATFORM_PROVISIONING_PROFILE_UUID_DEBUG[/code].
</member> </member>
<member name="application/provisioning_profile_uuid_release" type="String" setter="" getter=""> <member name="application/provisioning_profile_uuid_release" type="String" setter="" getter="">
UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url]. UUID of the provisioning profile. If left empty, Xcode will download or create a provisioning profile automatically. See [url=https://developer.apple.com/help/account/manage-profiles/edit-download-or-delete-profiles]Edit, download, or delete provisioning profiles[/url].
Can be overridden with the environment variable [code]GODOT_IOS_PROVISIONING_PROFILE_UUID_RELEASE[/code]. Can be overridden with the environment variable [code]GODOT_APPLE_PLATFORM_PROVISIONING_PROFILE_UUID_RELEASE[/code].
</member> </member>
<member name="application/short_version" type="String" setter="" getter=""> <member name="application/short_version" type="String" setter="" getter="">
Application version visible to the user, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]). Falls back to [member ProjectSettings.application/config/version] if left empty. Application version visible to the user, can only contain numeric characters ([code]0-9[/code]) and periods ([code].[/code]). Falls back to [member ProjectSettings.application/config/version] if left empty.
@@ -86,7 +86,7 @@
</member> </member>
<member name="capabilities/performance_a12" type="bool" setter="" getter=""> <member name="capabilities/performance_a12" type="bool" setter="" getter="">
Requires the graphics performance and features of the A12 Bionic and later chips (devices supporting all Vulkan renderer features). Requires the graphics performance and features of the A12 Bionic and later chips (devices supporting all Vulkan renderer features).
Enabling this option limits supported devices to: iPhone XS, iPhone XR, iPad Mini (5th gen.), iPad Air (3rd gen.), iPad (8th gen) and newer. Enabling this option limits supported devices to: iPhone XS, iPhone XR, iPad Mini (5th gen.), iPad Air (3rd gen.), iPad (8th gen), and newer.
</member> </member>
<member name="capabilities/performance_gaming_tier" type="bool" setter="" getter=""> <member name="capabilities/performance_gaming_tier" type="bool" setter="" getter="">
Requires the graphics performance and features of the A17 Pro and later chips. Requires the graphics performance and features of the A17 Pro and later chips.

File diff suppressed because it is too large Load Diff

View File

@@ -30,268 +30,35 @@
#pragma once #pragma once
#include "godot_plugin_config.h" #include "editor/export/editor_export_platform_apple_embedded.h"
#include "core/config/project_settings.h" class EditorExportPlatformIOS : public EditorExportPlatformAppleEmbedded {
#include "core/io/file_access.h" GDCLASS(EditorExportPlatformIOS, EditorExportPlatformAppleEmbedded);
#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 "editor/editor_settings.h"
#include "editor/export/editor_export_platform.h"
#include "main/splash.gen.h"
#include "scene/resources/image_texture.h"
#include <sys/stat.h> virtual String get_platform_name() const override { return "ios"; }
// Optional environment variables for defining confidential information. If any virtual String get_sdk_name() const override { return "iphoneos"; }
// of these is set, they will override the values set in the credentials file.
const String ENV_IOS_PROFILE_UUID_DEBUG = "GODOT_IOS_PROVISIONING_PROFILE_UUID_DEBUG";
const String ENV_IOS_PROFILE_UUID_RELEASE = "GODOT_IOS_PROVISIONING_PROFILE_UUID_RELEASE";
const String ENV_IOS_PROFILE_SPECIFIER_DEBUG = "GODOT_IOS_PROFILE_SPECIFIER_DEBUG";
const String ENV_IOS_PROFILE_SPECIFIER_RELEASE = "GODOT_IOS_PROFILE_SPECIFIER_RELEASE";
class EditorExportPlatformIOS : public EditorExportPlatform { virtual String get_minimum_deployment_target() const override { return "14.0"; }
GDCLASS(EditorExportPlatformIOS, EditorExportPlatform);
Ref<ImageTexture> logo; virtual Vector<IconInfo> get_icon_infos() const override;
Ref<ImageTexture> run_icon;
// Plugins
mutable SafeFlag plugins_changed;
SafeFlag devices_changed;
struct Device {
String id;
String name;
bool wifi = false;
bool use_ios_deploy = false;
};
Vector<Device> devices;
Mutex device_lock;
Mutex plugins_lock;
mutable Vector<PluginConfigIOS> plugins;
#ifdef MACOS_ENABLED
Thread check_for_changes_thread;
SafeFlag quit_request;
SafeFlag has_runnable_preset;
static bool _check_xcode_install();
static void _check_for_changes_poll_thread(void *ud);
void _update_preset_status();
#endif
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;
bool use_swift_runtime;
};
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_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() const;
Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const;
void _check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const;
Error _convert_to_framework(const String &p_source, const String &p_destination, const String &p_id) const;
void _add_assets_to_project(const String &p_out_dir, const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
Error _export_additional_assets(const Ref<EditorExportPreset> &p_preset, 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 Ref<EditorExportPreset> &p_preset, 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 Ref<EditorExportPreset> &p_preset, 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);
Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, bool p_oneclick);
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) const override; virtual void get_export_options(List<ExportOption> *r_options) const override;
virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override; virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual String get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const override;
void _notification(int p_what); virtual Error _export_loading_screen_file(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) override;
virtual Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) override;
virtual HashMap<String, Variant> get_custom_project_settings(const Ref<EditorExportPreset> &p_preset) const override;
public: public:
virtual String get_name() const override { return "iOS"; } virtual String get_name() const override { return "iOS"; }
virtual String get_os_name() const override { return "iOS"; } virtual String get_os_name() const override { return "iOS"; }
virtual Ref<Texture2D> get_logo() const override { return logo; }
virtual Ref<Texture2D> get_run_icon() const override { return run_icon; }
virtual int get_options_count() const override;
virtual String get_options_tooltip() const override;
virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual bool poll_export() override {
bool dc = devices_changed.is_set();
if (dc) {
// don't clear unless we're reporting true, to avoid race
devices_changed.clear();
}
return dc;
}
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;
if (p_preset.is_valid()) {
bool project_only = p_preset->get("application/export_project_only");
if (project_only) {
list.push_back("xcodeproj");
} else {
list.push_back("ipa");
}
}
return list;
}
virtual HashMap<String, Variant> get_custom_project_settings(const Ref<EditorExportPreset> &p_preset) const override;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
virtual void get_platform_features(List<String> *r_features) const override { virtual void get_platform_features(List<String> *r_features) const override {
r_features->push_back("mobile"); EditorExportPlatformAppleEmbedded::get_platform_features(r_features);
r_features->push_back("ios"); r_features->push_back("ios");
} }
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override {
}
EditorExportPlatformIOS(); EditorExportPlatformIOS();
~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.path_join(file), false);
for (int i = 0; i < directory_files.size(); ++i) {
dir_files.push_back(file.path_join(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().path_join("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.path_join(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;
}
}; };

View File

@@ -0,0 +1,37 @@
/**************************************************************************/
/* godot_view_ios.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "drivers/apple_embedded/godot_view_apple_embedded.h"
@interface GDTViewIOS : GDTView
@end

View File

@@ -0,0 +1,87 @@
/**************************************************************************/
/* godot_view_ios.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#import "godot_view_ios.h"
#import "display_layer_ios.h"
#include "core/error/error_macros.h"
@interface GDTViewIOS ()
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wobjc-property-synthesis")
@property(strong, nonatomic) CALayer<GDTDisplayLayer> *renderingLayer;
GODOT_CLANG_WARNING_POP
@end
@implementation GDTViewIOS
- (CALayer<GDTDisplayLayer> *)initializeRenderingForDriver:(NSString *)driverName {
if (self.renderingLayer) {
return self.renderingLayer;
}
CALayer<GDTDisplayLayer> *layer;
if ([driverName isEqualToString:@"vulkan"] || [driverName isEqualToString:@"metal"]) {
#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
if (@available(iOS 13, *)) {
layer = [GDTMetalLayer layer];
} else {
return nil;
}
#else
layer = [GDTMetalLayer layer];
#endif
} else if ([driverName isEqualToString:@"opengl3"]) {
GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations") // OpenGL is deprecated in iOS 12.0.
layer = [GDTOpenGLLayer layer];
GODOT_CLANG_WARNING_POP
} else {
return nil;
}
layer.frame = self.bounds;
layer.contentsScale = self.contentScaleFactor;
[self.layer addSublayer:layer];
self.renderingLayer = layer;
[layer initializeDisplayLayer];
return self.renderingLayer;
}
@end
GDTView *GDTViewCreate() {
return [GDTViewIOS new];
}

View File

@@ -30,30 +30,8 @@
#pragma once #pragma once
#include "core/object/class_db.h" #include "drivers/apple_embedded/apple_embedded.h"
#import <CoreHaptics/CoreHaptics.h> class iOS : public AppleEmbedded {
GDCLASS(iOS, AppleEmbedded);
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, float p_amplitude);
String get_model() const;
String get_rate_url(int p_app_id) const;
iOS();
}; };

Some files were not shown because too many files have changed in this diff Show More