summaryrefslogtreecommitdiff
path: root/platform/iphone
diff options
context:
space:
mode:
Diffstat (limited to 'platform/iphone')
-rw-r--r--platform/iphone/SCsub1
-rw-r--r--platform/iphone/api/api.cpp4
-rw-r--r--platform/iphone/api/api.h4
-rw-r--r--platform/iphone/app_delegate.h4
-rw-r--r--platform/iphone/app_delegate.mm15
-rw-r--r--platform/iphone/detect.py38
-rw-r--r--platform/iphone/device_metrics.h4
-rw-r--r--platform/iphone/device_metrics.m4
-rw-r--r--platform/iphone/display_layer.h4
-rw-r--r--platform/iphone/display_layer.mm16
-rw-r--r--platform/iphone/display_server_iphone.h24
-rw-r--r--platform/iphone/display_server_iphone.mm151
-rw-r--r--platform/iphone/export/export.cpp4
-rw-r--r--platform/iphone/export/export.h4
-rw-r--r--platform/iphone/export/export_plugin.cpp560
-rw-r--r--platform/iphone/export/export_plugin.h19
-rw-r--r--platform/iphone/export/godot_plugin_config.cpp4
-rw-r--r--platform/iphone/export/godot_plugin_config.h4
-rw-r--r--platform/iphone/godot_app_delegate.h4
-rw-r--r--platform/iphone/godot_app_delegate.m4
-rw-r--r--platform/iphone/godot_iphone.mm16
-rw-r--r--platform/iphone/godot_view.h9
-rw-r--r--platform/iphone/godot_view.mm20
-rw-r--r--platform/iphone/godot_view_gesture_recognizer.h4
-rw-r--r--platform/iphone/godot_view_gesture_recognizer.mm37
-rw-r--r--platform/iphone/godot_view_renderer.h4
-rw-r--r--platform/iphone/godot_view_renderer.mm7
-rw-r--r--platform/iphone/ios.h15
-rw-r--r--platform/iphone/ios.mm108
-rw-r--r--platform/iphone/joypad_iphone.h4
-rw-r--r--platform/iphone/joypad_iphone.mm59
-rw-r--r--platform/iphone/keyboard_input_view.h4
-rw-r--r--platform/iphone/keyboard_input_view.mm4
-rw-r--r--platform/iphone/main.m4
-rw-r--r--platform/iphone/os_iphone.h13
-rw-r--r--platform/iphone/os_iphone.mm47
-rw-r--r--platform/iphone/platform_config.h4
-rw-r--r--platform/iphone/tts_ios.h63
-rw-r--r--platform/iphone/tts_ios.mm164
-rw-r--r--platform/iphone/view_controller.h4
-rw-r--r--platform/iphone/view_controller.mm6
-rw-r--r--platform/iphone/vulkan_context_iphone.h4
-rw-r--r--platform/iphone/vulkan_context_iphone.mm4
43 files changed, 980 insertions, 496 deletions
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 58b574a72f..5e10bf5646 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -13,6 +13,7 @@ iphone_lib = [
"display_server_iphone.mm",
"joypad_iphone.mm",
"godot_view.mm",
+ "tts_ios.mm",
"display_layer.mm",
"godot_app_delegate.m",
"godot_view_renderer.mm",
diff --git a/platform/iphone/api/api.cpp b/platform/iphone/api/api.cpp
index a23791fe1c..f2e6fd7a7a 100644
--- a/platform/iphone/api/api.cpp
+++ b/platform/iphone/api/api.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/api/api.h b/platform/iphone/api/api.h
index c6570da7ec..ece91a9f1a 100644
--- a/platform/iphone/api/api.h
+++ b/platform/iphone/api/api.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/app_delegate.h b/platform/iphone/app_delegate.h
index 76c28b2272..0ec1dc071b 100644
--- a/platform/iphone/app_delegate.h
+++ b/platform/iphone/app_delegate.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index c6f91665c5..c5c9b5a5f9 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#import "app_delegate.h"
+
#include "core/config/project_settings.h"
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#import "godot_view.h"
@@ -76,7 +77,7 @@ static ViewController *mainViewController = nil;
// bail, things did not go very well for us, should probably output a message on screen with our error code...
exit(0);
return NO;
- };
+ }
ViewController *viewController = [[ViewController alloc] init];
viewController.godotView.useCADisplayLink = bool(GLOBAL_DEF("display.iOS/use_cadisplaylink", true)) ? YES : NO;
@@ -99,7 +100,7 @@ static ViewController *mainViewController = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
return YES;
-};
+}
- (void)onAudioInterruption:(NSNotification *)notification {
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
@@ -111,17 +112,17 @@ static ViewController *mainViewController = nil;
OSIPhone::get_singleton()->on_focus_in();
}
}
-};
+}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_MEMORY_WARNING);
}
-};
+}
- (void)applicationWillTerminate:(UIApplication *)application {
iphone_finish();
-};
+}
// When application goes to background (e.g. user switches to another app or presses Home),
// then applicationWillResignActive -> applicationDidEnterBackground are called.
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 0d28aa2f06..392a0151be 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -47,8 +47,11 @@ def configure(env):
if env["target"].startswith("release"):
env.Append(CPPDEFINES=["NDEBUG", ("NS_BLOCK_ASSERTIONS", 1)])
if env["optimize"] == "speed": # optimize for speed (default)
- env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"])
- env.Append(LINKFLAGS=["-O2"])
+ # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces
+ # when using `target=release_debug`.
+ opt = "-O3" if env["target"] == "release" else "-O2"
+ env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"])
+ env.Append(LINKFLAGS=[opt])
elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["-Os", "-ftree-vectorize"])
env.Append(LINKFLAGS=["-Os"])
@@ -62,16 +65,9 @@ def configure(env):
env.Append(LINKFLAGS=["-flto"])
## Architecture
- if env["arch"] == "x86": # i386
- env["bits"] = "32"
- elif env["arch"] == "x86_64":
- env["bits"] = "64"
- elif env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32": # arm
- env["arch"] = "arm"
- env["bits"] = "32"
- else: # armv64
+ env["bits"] = "64"
+ if env["arch"] != "x86_64":
env["arch"] = "arm64"
- env["bits"] = "64"
## Compiler configuration
@@ -108,28 +104,15 @@ def configure(env):
detect_darwin_sdk_path("iphone", env)
env.Append(CCFLAGS=["-miphoneos-version-min=11.0"])
- if env["arch"] == "x86" or env["arch"] == "x86_64":
+ if env["arch"] == "x86_64":
env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9"
- arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
env.Append(
CCFLAGS=(
- "-fobjc-arc -arch "
- + arch_flag
- + " -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks"
+ "-fobjc-arc -arch x86_64"
+ " -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks"
" -fasm-blocks -isysroot $IPHONESDK"
).split()
)
- elif env["arch"] == "arm":
- env.Append(
- CCFLAGS=(
- "-fobjc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing"
- " -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits"
- " -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb"
- ' "-DIBOutlet=__attribute__((iboutlet))"'
- ' "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))"'
- ' "-DIBAction=void)__attribute__((ibaction)" -MMD -MT dependencies'.split()
- )
- )
elif env["arch"] == "arm64":
env.Append(
CCFLAGS=(
@@ -140,7 +123,6 @@ def configure(env):
)
)
env.Append(CPPDEFINES=["NEED_LONG_INT"])
- env.Append(CPPDEFINES=["LIBYUV_DISABLE_NEON"])
# Disable exceptions on non-tools (template) builds
if not env["tools"]:
diff --git a/platform/iphone/device_metrics.h b/platform/iphone/device_metrics.h
index bc8f761dde..b9fb9b2fd9 100644
--- a/platform/iphone/device_metrics.h
+++ b/platform/iphone/device_metrics.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/device_metrics.m b/platform/iphone/device_metrics.m
index 306ca95d03..ec4dd8130d 100644
--- a/platform/iphone/device_metrics.m
+++ b/platform/iphone/device_metrics.m
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/display_layer.h b/platform/iphone/display_layer.h
index 1b8435d959..a17c75dba1 100644
--- a/platform/iphone/display_layer.h
+++ b/platform/iphone/display_layer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/display_layer.mm b/platform/iphone/display_layer.mm
index afe612e1a5..92e81448ac 100644
--- a/platform/iphone/display_layer.mm
+++ b/platform/iphone/display_layer.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#import "display_layer.h"
+
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#include "display_server_iphone.h"
@@ -153,17 +154,6 @@
return NO;
}
- // if (OS::get_singleton()) {
- // OS::VideoMode vm;
- // vm.fullscreen = true;
- // vm.width = backingWidth;
- // vm.height = backingHeight;
- // vm.resizable = false;
- // OS::get_singleton()->set_video_mode(vm);
- // OSIPhone::get_singleton()->set_base_framebuffer(viewFramebuffer);
- // };
- // gl_view_base_fb = viewFramebuffer;
-
return YES;
}
diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h
index 5cfcc1765c..7af222e3f8 100644
--- a/platform/iphone/display_server_iphone.h
+++ b/platform/iphone/display_server_iphone.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -54,10 +54,12 @@ class DisplayServerIPhone : public DisplayServer {
_THREAD_SAFE_CLASS_
#if defined(VULKAN_ENABLED)
- VulkanContextIPhone *context_vulkan;
- RenderingDeviceVulkan *rendering_device_vulkan;
+ VulkanContextIPhone *context_vulkan = nullptr;
+ RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
#endif
+ id tts = nullptr;
+
DisplayServer::ScreenOrientation screen_orientation;
ObjectID window_attached_instance_id;
@@ -123,18 +125,32 @@ public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
+ virtual bool tts_is_speaking() const override;
+ virtual bool tts_is_paused() const override;
+ virtual Array tts_get_voices() const override;
+
+ virtual void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.f, float p_rate = 1.f, int p_utterance_id = 0, bool p_interrupt = false) override;
+ virtual void tts_pause() override;
+ virtual void tts_resume() override;
+ virtual void tts_stop() override;
+
+ virtual Rect2i get_display_safe_area() const override;
+
virtual int get_screen_count() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
virtual WindowID
get_window_at_screen_position(const Point2i &p_position) const override;
+ virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override;
+
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index b746c60d4e..573ee9b7a8 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "display_server_iphone.h"
+
#import "app_delegate.h"
#include "core/config/project_settings.h"
#include "core/io/file_access_pack.h"
@@ -37,6 +38,7 @@
#include "ios.h"
#import "keyboard_input_view.h"
#include "os_iphone.h"
+#include "tts_ios.h"
#import "view_controller.h"
#import <Foundation/Foundation.h>
@@ -51,9 +53,14 @@ DisplayServerIPhone *DisplayServerIPhone::get_singleton() {
DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
+ // Init TTS
+ tts = [[TTS_IOS alloc] init];
+
#if defined(GLES3_ENABLED)
// FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented
// again,
+ // Note that we should be checking "opengl3" as the driver, might never enable this seeing OpenGL is deprecated on iOS
+ // We are hardcoding the rendering_driver to "vulkan" down below
if (rendering_driver == "opengl_es") {
bool gl_initialization_error = false;
@@ -131,18 +138,16 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Windo
DisplayServerIPhone::~DisplayServerIPhone() {
#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- if (rendering_device_vulkan) {
- rendering_device_vulkan->finalize();
- memdelete(rendering_device_vulkan);
- rendering_device_vulkan = nullptr;
- }
+ if (rendering_device_vulkan) {
+ rendering_device_vulkan->finalize();
+ memdelete(rendering_device_vulkan);
+ rendering_device_vulkan = nullptr;
+ }
- if (context_vulkan) {
- context_vulkan->window_destroy(MAIN_WINDOW_ID);
- memdelete(context_vulkan);
- context_vulkan = nullptr;
- }
+ if (context_vulkan) {
+ context_vulkan->window_destroy(MAIN_WINDOW_ID);
+ memdelete(context_vulkan);
+ context_vulkan = nullptr;
}
#endif
}
@@ -231,7 +236,7 @@ void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_presse
ev->set_position(Vector2(p_x, p_y));
perform_event(ev);
}
-};
+}
void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
@@ -241,16 +246,16 @@ void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int
ev->set_position(Vector2(p_x, p_y));
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
perform_event(ev);
- };
-};
+ }
+}
void DisplayServerIPhone::perform_event(const Ref<InputEvent> &p_event) {
Input::get_singleton()->parse_input_event(p_event);
-};
+}
void DisplayServerIPhone::touches_cancelled(int p_idx) {
touch_press(p_idx, -1, -1, false, false);
-};
+}
// MARK: Keyboard
@@ -263,13 +268,13 @@ void DisplayServerIPhone::key(Key p_key, bool p_pressed) {
ev->set_physical_keycode(p_key);
ev->set_unicode((char32_t)p_key);
perform_event(ev);
-};
+}
// MARK: Motion
void DisplayServerIPhone::update_gravity(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_gravity(Vector3(p_x, p_y, p_z));
-};
+}
void DisplayServerIPhone::update_accelerometer(float p_x, float p_y, float p_z) {
// Found out the Z should not be negated! Pass as is!
@@ -279,21 +284,20 @@ void DisplayServerIPhone::update_accelerometer(float p_x, float p_y, float p_z)
p_z / kDisplayServerIPhoneAcceleration);
Input::get_singleton()->set_accelerometer(v_accelerometer);
-};
+}
void DisplayServerIPhone::update_magnetometer(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_magnetometer(Vector3(p_x, p_y, p_z));
-};
+}
void DisplayServerIPhone::update_gyroscope(float p_x, float p_y, float p_z) {
Input::get_singleton()->set_gyroscope(Vector3(p_x, p_y, p_z));
-};
+}
// MARK: -
bool DisplayServerIPhone::has_feature(Feature p_feature) const {
switch (p_feature) {
- // case FEATURE_CONSOLE_WINDOW:
// case FEATURE_CURSOR_SHAPE:
// case FEATURE_CUSTOM_CURSOR_SHAPE:
// case FEATURE_GLOBAL_MENU:
@@ -310,6 +314,7 @@ bool DisplayServerIPhone::has_feature(Feature p_feature) const {
case FEATURE_ORIENTATION:
case FEATURE_TOUCHSCREEN:
case FEATURE_VIRTUAL_KEYBOARD:
+ case FEATURE_TEXT_TO_SPEECH:
return true;
default:
return false;
@@ -320,6 +325,57 @@ String DisplayServerIPhone::get_name() const {
return "iPhone";
}
+bool DisplayServerIPhone::tts_is_speaking() const {
+ ERR_FAIL_COND_V(!tts, false);
+ return [tts isSpeaking];
+}
+
+bool DisplayServerIPhone::tts_is_paused() const {
+ ERR_FAIL_COND_V(!tts, false);
+ return [tts isPaused];
+}
+
+Array DisplayServerIPhone::tts_get_voices() const {
+ ERR_FAIL_COND_V(!tts, Array());
+ return [tts getVoices];
+}
+
+void DisplayServerIPhone::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {
+ ERR_FAIL_COND(!tts);
+ [tts speak:p_text voice:p_voice volume:p_volume pitch:p_pitch rate:p_rate utterance_id:p_utterance_id interrupt:p_interrupt];
+}
+
+void DisplayServerIPhone::tts_pause() {
+ ERR_FAIL_COND(!tts);
+ [tts pauseSpeaking];
+}
+
+void DisplayServerIPhone::tts_resume() {
+ ERR_FAIL_COND(!tts);
+ [tts resumeSpeaking];
+}
+
+void DisplayServerIPhone::tts_stop() {
+ ERR_FAIL_COND(!tts);
+ [tts stopSpeaking];
+}
+
+Rect2i DisplayServerIPhone::get_display_safe_area() const {
+ if (@available(iOS 11, *)) {
+ UIEdgeInsets insets = UIEdgeInsetsZero;
+ UIView *view = AppDelegate.viewController.godotView;
+ if ([view respondsToSelector:@selector(safeAreaInsets)]) {
+ insets = [view safeAreaInsets];
+ }
+ float scale = screen_get_scale();
+ Size2i insets_position = Size2i(insets.left, insets.top) * scale;
+ Size2i insets_size = Size2i(insets.left + insets.right, insets.top + insets.bottom) * scale;
+ return Rect2i(screen_get_position() + insets_position, screen_get_size() - insets_size);
+ } else {
+ return Rect2i(screen_get_position(), screen_get_size());
+ }
+}
+
int DisplayServerIPhone::get_screen_count() const {
return 1;
}
@@ -339,22 +395,7 @@ Size2i DisplayServerIPhone::screen_get_size(int p_screen) const {
}
Rect2i DisplayServerIPhone::screen_get_usable_rect(int p_screen) const {
- if (@available(iOS 11, *)) {
- UIEdgeInsets insets = UIEdgeInsetsZero;
- UIView *view = AppDelegate.viewController.godotView;
-
- if ([view respondsToSelector:@selector(safeAreaInsets)]) {
- insets = [view safeAreaInsets];
- }
-
- float scale = screen_get_scale(p_screen);
- 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(p_screen) + insets_position, screen_get_size(p_screen) - insets_size);
- } else {
- return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
- }
+ return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
}
int DisplayServerIPhone::screen_get_dpi(int p_screen) const {
@@ -394,6 +435,10 @@ int DisplayServerIPhone::screen_get_dpi(int p_screen) const {
}
}
+float DisplayServerIPhone::screen_get_refresh_rate(int p_screen) const {
+ return [UIScreen mainScreen].maximumFramesPerSecond;
+}
+
float DisplayServerIPhone::screen_get_scale(int p_screen) const {
return [UIScreen mainScreen].nativeScale;
}
@@ -408,6 +453,24 @@ DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const
return MAIN_WINDOW_ID;
}
+int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
+ ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0);
+ switch (p_handle_type) {
+ case DISPLAY_HANDLE: {
+ return 0; // Not supported.
+ }
+ case WINDOW_HANDLE: {
+ return (int64_t)AppDelegate.viewController;
+ }
+ case WINDOW_VIEW: {
+ return (int64_t)AppDelegate.viewController.godotView;
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
window_attached_instance_id = p_instance;
}
@@ -499,7 +562,7 @@ void DisplayServerIPhone::window_move_to_foreground(WindowID p_window) {
float DisplayServerIPhone::screen_get_max_scale() const {
return screen_get_scale(SCREEN_OF_MAIN_WINDOW);
-};
+}
void DisplayServerIPhone::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {
screen_orientation = p_orientation;
@@ -565,10 +628,8 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- if (context_vulkan) {
- context_vulkan->window_resize(MAIN_WINDOW_ID, size.x, size.y);
- }
+ if (context_vulkan) {
+ context_vulkan->window_resize(MAIN_WINDOW_ID, size.x, size.y);
}
#endif
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 208626ae36..3b02e661c1 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/export/export.h b/platform/iphone/export/export.h
index 4a79ca279f..adb3c23957 100644
--- a/platform/iphone/export/export.h
+++ b/platform/iphone/export/export.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index 247b456b26..1f5e378098 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,13 +30,12 @@
#include "export_plugin.h"
+#include "editor/editor_node.h"
+
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
- r_features->push_back("pvrtc");
- if (driver == "vulkan") {
- // FIXME: Review if this is correct.
- r_features->push_back("etc2");
- }
+ // Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
+ r_features->push_back("etc2");
Vector<String> architectures = _get_preset_architectures(p_preset);
for (int i = 0; i < architectures.size(); ++i) {
@@ -46,7 +45,6 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() {
Vector<ExportArchitecture> archs;
- archs.push_back(ExportArchitecture("armv7", false)); // Disabled by default, not included in official templates.
archs.push_back(ExportArchitecture("arm64", true));
return archs;
}
@@ -60,18 +58,18 @@ struct LoadingScreenInfo {
};
static const LoadingScreenInfo loading_screen_infos[] = {
- { "landscape_launch_screens/iphone_2436x1125", "Default-Landscape-X.png", 2436, 1125, false },
- { "landscape_launch_screens/iphone_2208x1242", "Default-Landscape-736h@3x.png", 2208, 1242, false },
- { "landscape_launch_screens/ipad_1024x768", "Default-Landscape.png", 1024, 768, false },
- { "landscape_launch_screens/ipad_2048x1536", "Default-Landscape@2x.png", 2048, 1536, false },
-
- { "portrait_launch_screens/iphone_640x960", "Default-480h@2x.png", 640, 960, true },
- { "portrait_launch_screens/iphone_640x1136", "Default-568h@2x.png", 640, 1136, true },
- { "portrait_launch_screens/iphone_750x1334", "Default-667h@2x.png", 750, 1334, true },
- { "portrait_launch_screens/iphone_1125x2436", "Default-Portrait-X.png", 1125, 2436, true },
- { "portrait_launch_screens/ipad_768x1024", "Default-Portrait.png", 768, 1024, true },
- { "portrait_launch_screens/ipad_1536x2048", "Default-Portrait@2x.png", 1536, 2048, true },
- { "portrait_launch_screens/iphone_1242x2208", "Default-Portrait-736h@3x.png", 1242, 2208, true }
+ { PNAME("landscape_launch_screens/iphone_2436x1125"), "Default-Landscape-X.png", 2436, 1125, false },
+ { PNAME("landscape_launch_screens/iphone_2208x1242"), "Default-Landscape-736h@3x.png", 2208, 1242, false },
+ { PNAME("landscape_launch_screens/ipad_1024x768"), "Default-Landscape.png", 1024, 768, false },
+ { PNAME("landscape_launch_screens/ipad_2048x1536"), "Default-Landscape@2x.png", 2048, 1536, false },
+
+ { PNAME("portrait_launch_screens/iphone_640x960"), "Default-480h@2x.png", 640, 960, true },
+ { PNAME("portrait_launch_screens/iphone_640x1136"), "Default-568h@2x.png", 640, 1136, true },
+ { PNAME("portrait_launch_screens/iphone_750x1334"), "Default-667h@2x.png", 750, 1334, true },
+ { PNAME("portrait_launch_screens/iphone_1125x2436"), "Default-Portrait-X.png", 1125, 2436, true },
+ { PNAME("portrait_launch_screens/ipad_768x1024"), "Default-Portrait.png", 768, 1024, true },
+ { PNAME("portrait_launch_screens/ipad_1536x2048"), "Default-Portrait@2x.png", 1536, 2048, true },
+ { PNAME("portrait_launch_screens/iphone_1242x2208"), "Default-Portrait-736h@3x.png", 1242, 2208, true }
};
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
@@ -80,13 +78,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
Vector<ExportArchitecture> architectures = _get_supported_architectures();
for (int i = 0; i < architectures.size(); ++i) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + architectures[i].name), architectures[i].is_default));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), architectures[i].name)), architectures[i].is_default));
}
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), ""));
@@ -94,34 +92,28 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), found_plugins[i].name)), false));
}
- Set<String> plist_keys;
+ HashSet<String> plist_keys;
for (int i = 0; i < found_plugins.size(); i++) {
// Editable plugin plist values
PluginConfigIOS plugin = found_plugins[i];
- const String *K = nullptr;
- while ((K = plugin.plist.next(K))) {
- String key = *K;
- PluginConfigIOS::PlistItem item = plugin.plist[key];
- switch (item.type) {
+ for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) {
+ switch (E.value.type) {
case PluginConfigIOS::PlistItemType::STRING_INPUT: {
- String preset_name = "plugins_plist/" + key;
+ String preset_name = "plugins_plist/" + E.key;
if (!plist_keys.has(preset_name)) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), E.value.value));
plist_keys.insert(preset_name);
}
} break;
@@ -141,20 +133,23 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "icons/generate_missing"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad with Retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad Pro
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with retina HD display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad with retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad Pro
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with Retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
@@ -163,8 +158,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "launch_screens/generate_missing"), false));
-
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), ""));
}
@@ -183,6 +176,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
"scaleAspectFill",
"scaleToFill"
};
+ String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug");
+ String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release");
+ bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer");
+ bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution");
String str;
String strnew;
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
@@ -200,8 +197,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
} else if (lines[i].find("$name") != -1) {
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
- } else if (lines[i].find("$info") != -1) {
- strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
} else if (lines[i].find("$bundle_identifier") != -1) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
@@ -210,8 +205,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
} else if (lines[i].find("$signature") != -1) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
- } else if (lines[i].find("$copyright") != -1) {
- strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$team_id") != -1) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (lines[i].find("$default_build_config") != -1) {
@@ -223,13 +216,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n";
} else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) {
strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n";
+ } else if (lines[i].find("$code_sign_style_debug") != -1) {
+ if (dbg_manual) {
+ strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n";
+ } else {
+ strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n";
+ }
+ } else if (lines[i].find("$code_sign_style_release") != -1) {
+ if (rel_manual) {
+ strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n";
+ } else {
+ strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n";
+ }
} else if (lines[i].find("$provisioning_profile_uuid") != -1) {
String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release");
strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (lines[i].find("$code_sign_identity_debug") != -1) {
- strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n";
+ strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n";
} else if (lines[i].find("$code_sign_identity_release") != -1) {
- strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n";
+ strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n";
} else if (lines[i].find("$additional_plist_content") != -1) {
strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n";
} else if (lines[i].find("$godot_archs") != -1) {
@@ -377,6 +382,36 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String value = value_format.format(value_dictionary, "$_");
strnew += lines[i].replace("$launch_screen_background_color", value) + "\n";
+ } else if (lines[i].find("$pbx_locale_file_reference") != -1) {
+ String locale_files;
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ int index = 0;
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String lang = tr->get_locale();
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };";
+ }
+ index++;
+ }
+ }
+ strnew += lines[i].replace("$pbx_locale_file_reference", locale_files);
+ } else if (lines[i].find("$pbx_locale_build_reference") != -1) {
+ String locale_files;
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ int index = 0;
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String lang = tr->get_locale();
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,";
+ }
+ index++;
+ }
+ }
+ strnew += lines[i].replace("$pbx_locale_build_reference", locale_files);
} else {
strnew += lines[i] + "\n";
}
@@ -466,69 +501,57 @@ struct IconInfo {
const char *actual_size_side;
const char *scale;
const char *unscaled_size;
- bool is_required = false;
};
static const IconInfo icon_infos[] = {
- { "required_icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", true },
- { "required_icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", true },
-
- { "required_icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", true },
- { "required_icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
-
- { "optional_icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false },
-
- { "optional_icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false },
-
- { "optional_icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
-
- { "optional_icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false },
-
- { "optional_icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false },
- { "optional_icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false }
+ // Home screen on iPhone
+ { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60" },
+ { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40" },
+ { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60" },
+
+ // Home screen on iPad
+ { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76" },
+ { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76" },
+ { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5" },
+
+ // App Store
+ { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024" },
+
+ // Spotlight
+ { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40" },
+ { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40" },
+ { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40" }
};
Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) {
String json_description = "{\"images\":[";
String sizes;
- DirAccess *da = DirAccess::open(p_iconset_dir);
- ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
+ Ref<DirAccess> da = DirAccess::open(p_iconset_dir);
+ ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
int side_size = String(info.actual_size_side).to_int();
String icon_path = p_preset->get(info.preset_key);
if (icon_path.length() == 0) {
- if ((bool)p_preset->get("icons/generate_missing")) {
- // Resize main app icon
- icon_path = ProjectSettings::get_singleton()->get("application/config/icon");
- Ref<Image> img = memnew(Image);
- Error err = ImageLoader::load_image(icon_path, img);
- if (err != OK) {
- ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'.");
- return ERR_UNCONFIGURED;
- }
- img->resize(side_size, side_size);
- err = img->save_png(p_iconset_dir + info.export_name);
- if (err) {
- String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
- ERR_PRINT(err_str.utf8().get_data());
- return err;
- }
- } else {
- if (info.is_required) {
- String err_str = String("Required icon (") + info.preset_key + ") is not specified in the preset.";
- ERR_PRINT(err_str);
- return ERR_UNCONFIGURED;
- } else {
- String err_str = String("Icon (") + info.preset_key + ") is not specified in the preset.";
- WARN_PRINT(err_str);
- }
- continue;
+ // Resize main app icon
+ icon_path = ProjectSettings::get_singleton()->get("application/config/icon");
+ Ref<Image> img = memnew(Image);
+ Error err = ImageLoader::load_image(icon_path, img);
+ if (err != OK) {
+ ERR_PRINT("Invalid icon (" + String(info.preset_key) + "): '" + icon_path + "'.");
+ return ERR_UNCONFIGURED;
+ }
+ img->resize(side_size, side_size);
+ err = img->save_png(p_iconset_dir + info.export_name);
+ if (err) {
+ String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
+ ERR_PRINT(err_str.utf8().get_data());
+ return err;
}
} else {
- // Load custom icon
+ // Load custom icon and resize if required
Ref<Image> img = memnew(Image);
Error err = ImageLoader::load_image(icon_path, img);
if (err != OK) {
@@ -536,13 +559,14 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
return ERR_UNCONFIGURED;
}
if (img->get_width() != side_size || img->get_height() != side_size) {
- ERR_PRINT("Invalid icon size (" + String(info.preset_key) + "): '" + icon_path + "'.");
- return ERR_UNCONFIGURED;
+ WARN_PRINT("Icon (" + String(info.preset_key) + "): '" + icon_path + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(side_size) + "x" + String::num_int64(side_size) + ".");
+ img->resize(side_size, side_size);
+ err = img->save_png(p_iconset_dir + info.export_name);
+ } else {
+ err = da->copy(icon_path, p_iconset_dir + info.export_name);
}
- err = da->copy(icon_path, p_iconset_dir + info.export_name);
if (err) {
- memdelete(da);
String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
ERR_PRINT(err_str.utf8().get_data());
return err;
@@ -560,19 +584,16 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
json_description += String("}");
}
json_description += "]}";
- memdelete(da);
- FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
- ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE);
+ Ref<FileAccess> json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
+ ERR_FAIL_COND_V(json_file.is_null(), ERR_CANT_CREATE);
CharString json_utf8 = json_description.utf8();
json_file->store_buffer((const uint8_t *)json_utf8.get_data(), json_utf8.length());
- memdelete(json_file);
- FileAccess *sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
- ERR_FAIL_COND_V(!sizes_file, ERR_CANT_CREATE);
+ Ref<FileAccess> sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
+ ERR_FAIL_COND_V(sizes_file.is_null(), ERR_CANT_CREATE);
CharString sizes_utf8 = sizes.utf8();
sizes_file->store_buffer((const uint8_t *)sizes_utf8.get_data(), sizes_utf8.length());
- memdelete(sizes_file);
return OK;
}
@@ -646,14 +667,19 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
}
Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) {
- DirAccess *da = DirAccess::open(p_dest_dir);
- ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
+ Ref<DirAccess> da = DirAccess::open(p_dest_dir);
+ ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
LoadingScreenInfo info = loading_screen_infos[i];
String loading_screen_file = p_preset->get(info.preset_key);
+
+ Color boot_bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color");
+ String boot_logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image");
+ bool boot_logo_scale = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize");
+
if (loading_screen_file.size() > 0) {
- // Load custom loading screens
+ // Load custom loading screens, and resize if required.
Ref<Image> img = memnew(Image);
Error err = ImageLoader::load_image(loading_screen_file, img);
if (err != OK) {
@@ -661,22 +687,30 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
return ERR_UNCONFIGURED;
}
if (img->get_width() != info.width || img->get_height() != info.height) {
- ERR_PRINT("Invalid loading screen size (" + String(info.preset_key) + "): '" + loading_screen_file + "'.");
- return ERR_UNCONFIGURED;
+ WARN_PRINT("Loading screen (" + String(info.preset_key) + "): '" + loading_screen_file + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(info.width) + "x" + String::num_int64(info.height) + ".");
+ float aspect_ratio = (float)img->get_width() / (float)img->get_height();
+ if (boot_logo_scale) {
+ if (info.height * aspect_ratio <= info.width) {
+ img->resize(info.height * aspect_ratio, info.height);
+ } else {
+ img->resize(info.width, info.width / aspect_ratio);
+ }
+ }
+ Ref<Image> new_img = memnew(Image);
+ new_img->create(info.width, info.height, false, Image::FORMAT_RGBA8);
+ new_img->fill(boot_bg_color);
+ _blend_and_rotate(new_img, img, false);
+ err = new_img->save_png(p_dest_dir + info.export_name);
+ } else {
+ err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
}
- err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
if (err) {
- memdelete(da);
String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'.";
ERR_PRINT(err_str.utf8().get_data());
return err;
}
- } else if ((bool)p_preset->get("launch_screens/generate_missing")) {
+ } else {
// Generate loading screen from the splash screen
- Color boot_bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color");
- String boot_logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image");
- bool boot_logo_scale = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize");
-
Ref<Image> img = memnew(Image);
img->create(info.width, info.height, false, Image::FORMAT_RGBA8);
img->fill(boot_bg_color);
@@ -716,17 +750,13 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
String err_str = String("Failed to export loading screen (") + info.preset_key + ") from splash screen.";
WARN_PRINT(err_str.utf8().get_data());
}
- } else {
- String err_str = String("No loading screen (") + info.preset_key + ") specified.";
- WARN_PRINT(err_str.utf8().get_data());
}
}
- memdelete(da);
return OK;
}
-Error EditorExportPlatformIOS::_walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata) {
+Error EditorExportPlatformIOS::_walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata) {
Vector<String> dirs;
String current_dir = p_da->get_current_dir();
p_da->list_dir_begin();
@@ -772,12 +802,20 @@ struct CodesignData {
Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) {
if (p_file.ends_with(".dylib")) {
- CodesignData *data = (CodesignData *)p_userdata;
+ CodesignData *data = static_cast<CodesignData *>(p_userdata);
print_line(String("Signing ") + p_file);
+
+ String sign_id;
+ if (data->debug) {
+ sign_id = data->preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : data->preset->get("application/code_sign_identity_debug");
+ } else {
+ sign_id = data->preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : data->preset->get("application/code_sign_identity_release");
+ }
+
List<String> codesign_args;
codesign_args.push_back("-f");
codesign_args.push_back("-s");
- codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release"));
+ codesign_args.push_back(sign_id);
codesign_args.push_back(p_file);
return OS::get_singleton()->execute("codesign", codesign_args);
}
@@ -919,21 +957,15 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
}
Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
- DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
-
String binary_name = p_out_dir.get_file().get_basename();
- DirAccess *da = DirAccess::create_for_path(p_asset);
- if (!da) {
- memdelete(filesystem_da);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_asset);
+ if (da.is_null()) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + ".");
}
bool file_exists = da->file_exists(p_asset);
bool dir_exists = da->dir_exists(p_asset);
if (!file_exists && !dir_exists) {
- memdelete(da);
- memdelete(filesystem_da);
return ERR_FILE_NOT_FOUND;
}
@@ -993,19 +1025,18 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
destination = p_out_dir.plus_file(asset_path);
}
+ Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
+
if (!filesystem_da->dir_exists(destination_dir)) {
Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
if (make_dir_err) {
- memdelete(da);
- memdelete(filesystem_da);
return make_dir_err;
}
}
Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination);
- memdelete(da);
if (err) {
- memdelete(filesystem_da);
return err;
}
IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
@@ -1061,17 +1092,13 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
String info_plist = info_plist_format.replace("$name", file_name);
- FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_string(info_plist);
- f->close();
- memdelete(f);
}
}
}
- memdelete(filesystem_da);
-
return OK;
}
@@ -1151,7 +1178,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
Vector<String> added_embedded_dependenciy_names;
HashMap<String, String> plist_values;
- Set<String> plugin_linker_flags;
+ HashSet<String> plugin_linker_flags;
Error err;
@@ -1228,11 +1255,10 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
// Plist
// Using hash map container to remove duplicates
- const String *K = nullptr;
- while ((K = plugin.plist.next(K))) {
- String key = *K;
- PluginConfigIOS::PlistItem item = plugin.plist[key];
+ for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) {
+ String key = E.key;
+ const PluginConfigIOS::PlistItem &item = E.value;
String value;
@@ -1271,10 +1297,9 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
// Updating `Info.plist`
{
- const String *K = nullptr;
- while ((K = plist_values.next(K))) {
- String key = *K;
- String value = plist_values[key];
+ for (const KeyValue<String, String> &E : plist_values) {
+ String key = E.key;
+ String value = E.value;
if (key.is_empty() || value.is_empty()) {
continue;
@@ -1325,8 +1350,8 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
// Update Linker Flag Values
{
String result_linker_flags = " ";
- for (Set<String>::Element *E = plugin_linker_flags.front(); E; E = E->next()) {
- const String &flag = E->get();
+ for (const String &E : plugin_linker_flags) {
+ const String &flag = E;
if (flag.length() == 0) {
continue;
@@ -1376,29 +1401,29 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_BAD_PATH;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (da) {
- String current_dir = da->get_current_dir();
-
- // remove leftovers from last export so they don't interfere
- // in case some files are no longer needed
- if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
- da->erase_contents_recursive();
- }
- if (da->change_dir(dest_dir + binary_name) == OK) {
- da->erase_contents_recursive();
- }
+ {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da.is_valid()) {
+ String current_dir = da->get_current_dir();
+
+ // remove leftovers from last export so they don't interfere
+ // in case some files are no longer needed
+ if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
+ da->erase_contents_recursive();
+ }
+ if (da->change_dir(dest_dir + binary_name) == OK) {
+ da->erase_contents_recursive();
+ }
- da->change_dir(current_dir);
+ da->change_dir(current_dir);
- if (!da->dir_exists(dest_dir + binary_name)) {
- Error err = da->make_dir(dest_dir + binary_name);
- if (err) {
- memdelete(da);
- return err;
+ if (!da->dir_exists(dest_dir + binary_name)) {
+ Error err = da->make_dir(dest_dir + binary_name);
+ if (err) {
+ return err;
+ }
}
}
- memdelete(da);
}
if (ep.step("Making .pck", 0)) {
@@ -1406,7 +1431,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
String pack_path = dest_dir + binary_name + ".pck";
Vector<SharedObject> libraries;
- Error err = save_pack(p_preset, pack_path, &libraries);
+ Error err = save_pack(p_preset, p_debug, pack_path, &libraries);
if (err) {
return err;
}
@@ -1419,9 +1444,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
print_line("Static framework: " + library_to_use);
String pkg_name;
- if (p_preset->get("application/name") != "") {
- pkg_name = p_preset->get("application/name"); // app_name
- } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
+ if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
} else {
pkg_name = "Unnamed";
@@ -1430,7 +1453,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
bool found_library = false;
const String project_file = "godot_ios.xcodeproj/project.pbxproj";
- Set<String> files_to_parse;
+ HashSet<String> files_to_parse;
files_to_parse.insert("godot_ios/godot_ios-Info.plist");
files_to_parse.insert(project_file);
files_to_parse.insert("godot_ios/export_options.plist");
@@ -1456,12 +1479,12 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Vector<IOSExportAsset> assets;
- DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
+ Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir);
+ ERR_FAIL_COND_V(tmp_app_path.is_null(), ERR_CANT_CREATE);
print_line("Unzipping...");
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ Ref<FileAccess> io_fa;
+ zlib_filefunc_def io = zipio_create_io(&io_fa);
unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
if (!src_pkg_zip) {
EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name);
@@ -1483,8 +1506,11 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
unz_file_info info;
char fname[16384];
ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0);
+ if (ret != UNZ_OK) {
+ break;
+ }
- String file = fname;
+ String file = String::utf8(fname);
print_line("READ: " + file);
Vector<uint8_t> data;
@@ -1535,22 +1561,20 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (dir_err) {
ERR_PRINT("Can't create '" + dir_name + "'.");
unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
return ERR_CANT_CREATE;
}
}
/* write the file */
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (!f) {
- ERR_PRINT("Can't write '" + file + "'.");
- unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
- return ERR_CANT_CREATE;
- };
- f->store_buffer(data.ptr(), data.size());
- f->close();
- memdelete(f);
+ {
+ Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
+ if (f.is_null()) {
+ ERR_PRINT("Can't write '" + file + "'.");
+ unzClose(src_pkg_zip);
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(data.ptr(), data.size());
+ }
#if defined(OSX_ENABLED) || defined(X11_ENABLED)
if (is_execute) {
@@ -1568,10 +1592,53 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!found_library) {
ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
- memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
+ Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
+ Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
+ Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");
+
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ {
+ String fname = dest_dir + binary_name + "/en.lproj";
+ tmp_app_path->make_dir_recursive(fname);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
+ f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
+ }
+
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String lang = tr->get_locale();
+ String fname = dest_dir + binary_name + "/" + lang + ".lproj";
+ tmp_app_path->make_dir_recursive(fname);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ if (appnames.has(lang)) {
+ f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
+ }
+ if (camera_usage_descriptions.has(lang)) {
+ f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (microphone_usage_descriptions.has(lang)) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (photolibrary_usage_descriptions.has(lang)) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";");
+ }
+ }
+ }
+ }
+
// Copy project static libs to the project
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
@@ -1582,7 +1649,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path);
if (lib_copy_err != OK) {
ERR_PRINT("Can't copy '" + static_lib_path + "'.");
- memdelete(tmp_app_path);
return lib_copy_err;
}
}
@@ -1593,7 +1659,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!tmp_app_path->dir_exists(iconset_dir)) {
err = tmp_app_path->make_dir_recursive(iconset_dir);
}
- memdelete(tmp_app_path);
if (err) {
return err;
}
@@ -1603,43 +1668,42 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return err;
}
- bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
+ {
+ bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
- String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
- String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
+ String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
+ String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
- DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (launch_screen_da.is_null()) {
+ return ERR_CANT_CREATE;
+ }
- if (!launch_screen_da) {
- return ERR_CANT_CREATE;
- }
+ if (use_storyboard) {
+ print_line("Using Launch Storyboard");
- if (use_storyboard) {
- print_line("Using Launch Storyboard");
+ if (launch_screen_da->change_dir(launch_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(launch_image_path);
+ }
- if (launch_screen_da->change_dir(launch_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(launch_image_path);
- }
+ err = _export_loading_screen_file(p_preset, splash_image_path);
+ } else {
+ print_line("Using Launch Images");
- err = _export_loading_screen_file(p_preset, splash_image_path);
- } else {
- print_line("Using Launch Images");
+ const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
- const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
+ launch_screen_da->remove(launch_screen_path);
- launch_screen_da->remove(launch_screen_path);
+ if (launch_screen_da->change_dir(splash_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(splash_image_path);
+ }
- if (launch_screen_da->change_dir(splash_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(splash_image_path);
+ err = _export_loading_screen_images(p_preset, launch_image_path);
}
-
- err = _export_loading_screen_images(p_preset, launch_image_path);
}
- memdelete(launch_screen_da);
-
if (err) {
return err;
}
@@ -1648,25 +1712,26 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
_export_additional_assets(dest_dir + binary_name, libraries, assets);
_add_assets_to_project(p_preset, project_file_data, assets);
String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
- FileAccess *f = FileAccess::open(project_file_name, FileAccess::WRITE);
- if (!f) {
- ERR_PRINT("Can't write '" + project_file_name + "'.");
- return ERR_CANT_CREATE;
- };
- f->store_buffer(project_file_data.ptr(), project_file_data.size());
- f->close();
- memdelete(f);
+ {
+ Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE);
+ if (f.is_null()) {
+ ERR_PRINT("Can't write '" + project_file_name + "'.");
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(project_file_data.ptr(), project_file_data.size());
+ }
#ifdef OSX_ENABLED
- if (ep.step("Code-signing dylibs", 2)) {
- return ERR_SKIP;
+ {
+ if (ep.step("Code-signing dylibs", 2)) {
+ return ERR_SKIP;
+ }
+ Ref<DirAccess> dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
+ ERR_FAIL_COND_V(dylibs_dir.is_null(), ERR_CANT_OPEN);
+ CodesignData codesign_data(p_preset, p_debug);
+ err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
+ ERR_FAIL_COND_V(err, err);
}
- DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
- ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
- CodesignData codesign_data(p_preset, p_debug);
- err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
- memdelete(dylibs_dir);
- ERR_FAIL_COND_V(err, err);
if (ep.step("Making .xcarchive", 3)) {
return ERR_SKIP;
@@ -1684,6 +1749,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
archive_args.push_back("-destination");
archive_args.push_back("generic/platform=iOS");
archive_args.push_back("archive");
+ archive_args.push_back("-allowProvisioningUpdates");
archive_args.push_back("-archivePath");
archive_args.push_back(archive_path);
String archive_str;
@@ -1754,19 +1820,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
valid = false;
}
- for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
- IconInfo info = icon_infos[i];
- String icon_path = p_preset->get(info.preset_key);
- if (icon_path.length() == 0) {
- if (info.is_required) {
- err += TTR("Required icon is not specified in the preset.") + "\n";
- valid = false;
- }
- break;
- }
- }
-
- String etc_error = test_etc2_or_pvrtc();
+ const String etc_error = test_etc2();
if (!etc_error.is_empty()) {
valid = false;
err += etc_error;
diff --git a/platform/iphone/export/export_plugin.h b/platform/iphone/export/export_plugin.h
index 359f855d86..1db7418e3f 100644
--- a/platform/iphone/export/export_plugin.h
+++ b/platform/iphone/export/export_plugin.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,7 +41,6 @@
#include "core/templates/safe_refcount.h"
#include "core/version.h"
#include "editor/editor_export.h"
-#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "main/splash.gen.h"
#include "platform/iphone/logo.gen.h"
@@ -54,8 +53,6 @@
class EditorExportPlatformIOS : public EditorExportPlatform {
GDCLASS(EditorExportPlatformIOS, EditorExportPlatform);
- int version_code;
-
Ref<ImageTexture> logo;
// Plugins
@@ -66,7 +63,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Vector<PluginConfigIOS> plugins;
typedef Error (*FileHandler)(String p_file, void *p_userdata);
- static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, 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);
@@ -130,7 +127,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
for (int i = 0; i < pname.length(); i++) {
char32_t c = pname[i];
- if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) {
+ if (!(is_ascii_alphanumeric_char(c) || c == '-' || c == '.')) {
if (r_error) {
*r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c));
}
@@ -142,7 +139,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
}
static void _check_for_changes_poll_thread(void *ud) {
- EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud;
+ EditorExportPlatformIOS *ea = static_cast<EditorExportPlatformIOS *>(ud);
while (!ea->quit_request.is_set()) {
// Nothing to do if we already know the plugins have changed.
@@ -207,7 +204,7 @@ public:
r_features->push_back("ios");
}
- virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override {
+ virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override {
}
EditorExportPlatformIOS();
@@ -216,8 +213,8 @@ public:
/// 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;
- DirAccessRef da = DirAccess::open(p_path);
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ if (da.is_valid()) {
da->list_dir_begin();
while (true) {
String file = da->get_next();
diff --git a/platform/iphone/export/godot_plugin_config.cpp b/platform/iphone/export/godot_plugin_config.cpp
index 9d0324f41a..9118b95337 100644
--- a/platform/iphone/export/godot_plugin_config.cpp
+++ b/platform/iphone/export/godot_plugin_config.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/export/godot_plugin_config.h b/platform/iphone/export/godot_plugin_config.h
index 1add281627..9ef8aa8c6d 100644
--- a/platform/iphone/export/godot_plugin_config.h
+++ b/platform/iphone/export/godot_plugin_config.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_app_delegate.h b/platform/iphone/godot_app_delegate.h
index 6335ada50e..703a906bda 100644
--- a/platform/iphone/godot_app_delegate.h
+++ b/platform/iphone/godot_app_delegate.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m
index 6c433c5c3c..84347f9a30 100644
--- a/platform/iphone/godot_app_delegate.m
+++ b/platform/iphone/godot_app_delegate.m
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_iphone.mm b/platform/iphone/godot_iphone.mm
index 6f6f9d0708..49474ef554 100644
--- a/platform/iphone/godot_iphone.mm
+++ b/platform/iphone/godot_iphone.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,7 +53,7 @@ int add_path(int p_argc, char **p_args) {
p_args[p_argc] = nullptr;
return p_argc;
-};
+}
int add_cmdline(int p_argc, char **p_args) {
NSArray *arr = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"godot_cmdline"];
@@ -67,12 +67,12 @@ int add_cmdline(int p_argc, char **p_args) {
continue;
}
p_args[p_argc++] = (char *)[str cStringUsingEncoding:NSUTF8StringEncoding];
- };
+ }
p_args[p_argc] = nullptr;
return p_argc;
-};
+}
int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
size_t len = strlen(argv[0]);
@@ -103,7 +103,7 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
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);
@@ -119,10 +119,10 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
os->initialize_modules();
return 0;
-};
+}
void iphone_finish() {
printf("iphone_finish\n");
Main::cleanup();
delete os;
-};
+}
diff --git a/platform/iphone/godot_view.h b/platform/iphone/godot_view.h
index 265f826173..fcb97fa63a 100644
--- a/platform/iphone/godot_view.h
+++ b/platform/iphone/godot_view.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -59,4 +59,9 @@ class String;
- (void)stopRendering;
- (void)startRendering;
+- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
+
@end
diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm
index 00a88d79c5..e48dd2e507 100644
--- a/platform/iphone/godot_view.mm
+++ b/platform/iphone/godot_view.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#import "godot_view.h"
+
#include "core/os/keyboard.h"
#include "core/string/ustring.h"
#import "display_layer.h"
@@ -153,6 +154,8 @@ static const float earth_gravity = 9.80665;
[self initTouches];
+ self.multipleTouchEnabled = YES;
+
// Configure and start accelerometer
if (!self.motionManager) {
self.motionManager = [[CMMotionManager alloc] init];
@@ -226,8 +229,9 @@ static const float earth_gravity = 9.80665;
[self.displayLink setPaused:YES];
// Process all input events
- while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource)
- ;
+ while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource) {
+ // Continue.
+ }
// We are good to go, resume the CADisplayLink
[self.displayLink setPaused:NO];
@@ -336,7 +340,7 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)touchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
+- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
NSArray *tlist = [event.allTouches allObjects];
for (unsigned int i = 0; i < [tlist count]; i++) {
if ([touchesSet containsObject:[tlist objectAtIndex:i]]) {
@@ -349,7 +353,7 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *tlist = [event.allTouches allObjects];
for (unsigned int i = 0; i < [tlist count]; i++) {
if ([touches containsObject:[tlist objectAtIndex:i]]) {
@@ -363,7 +367,7 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *tlist = [event.allTouches allObjects];
for (unsigned int i = 0; i < [tlist count]; i++) {
if ([touches containsObject:[tlist objectAtIndex:i]]) {
@@ -377,7 +381,7 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *tlist = [event.allTouches allObjects];
for (unsigned int i = 0; i < [tlist count]; i++) {
if ([touches containsObject:[tlist objectAtIndex:i]]) {
diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/iphone/godot_view_gesture_recognizer.h
index 61438ef22f..9fd8a6b222 100644
--- a/platform/iphone/godot_view_gesture_recognizer.h
+++ b/platform/iphone/godot_view_gesture_recognizer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_view_gesture_recognizer.mm b/platform/iphone/godot_view_gesture_recognizer.mm
index cf6e5c5883..49a92add5e 100644
--- a/platform/iphone/godot_view_gesture_recognizer.mm
+++ b/platform/iphone/godot_view_gesture_recognizer.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,8 @@
#import "godot_view_gesture_recognizer.h"
+#import "godot_view.h"
+
#include "core/config/project_settings.h"
// Minimum distance for touches to move to fire
@@ -58,12 +60,17 @@ const CGFloat kGLGestureMovementDistance = 0.5;
@implementation GodotViewGestureRecognizer
+- (GodotView *)godotView {
+ return (GodotView *)self.view;
+}
+
- (instancetype)init {
self = [super init];
self.cancelsTouchesInView = YES;
self.delaysTouchesBegan = YES;
self.delaysTouchesEnded = YES;
+ self.requiresExclusiveTouchType = NO;
self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay");
@@ -104,7 +111,7 @@ const CGFloat kGLGestureMovementDistance = 0.5;
self.delayTimer = nil;
if (self.delayedTouches) {
- [self.view touchesBegan:self.delayedTouches withEvent:self.delayedEvent];
+ [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent];
}
self.delayedTouches = nil;
@@ -114,6 +121,8 @@ const CGFloat kGLGestureMovementDistance = 0.5;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan];
[self delayTouches:cleared andEvent:event];
+
+ [super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -123,8 +132,8 @@ const CGFloat kGLGestureMovementDistance = 0.5;
// We should check if movement was significant enough to fire an event
// for dragging to work correctly.
for (UITouch *touch in cleared) {
- CGPoint from = [touch locationInView:self.view];
- CGPoint to = [touch previousLocationInView:self.view];
+ CGPoint from = [touch locationInView:self.godotView];
+ CGPoint to = [touch previousLocationInView:self.godotView];
CGFloat xDistance = from.x - to.x;
CGFloat yDistance = from.y - to.y;
@@ -133,7 +142,7 @@ const CGFloat kGLGestureMovementDistance = 0.5;
// Early exit, since one of touches has moved enough to fire a drag event.
if (distance > kGLGestureMovementDistance) {
[self.delayTimer fire];
- [self.view touchesMoved:cleared withEvent:event];
+ [self.godotView godotTouchesMoved:cleared withEvent:event];
return;
}
}
@@ -141,26 +150,32 @@ const CGFloat kGLGestureMovementDistance = 0.5;
return;
}
- [self.view touchesMoved:cleared withEvent:event];
+ [self.godotView godotTouchesMoved:cleared withEvent:event];
+
+ [super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self.delayTimer fire];
NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded];
- [self.view touchesEnded:cleared withEvent:event];
+ [self.godotView godotTouchesEnded:cleared withEvent:event];
+
+ [super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self.delayTimer fire];
- [self.view touchesCancelled:touches withEvent:event];
-};
+ [self.godotView godotTouchesCancelled:touches withEvent:event];
+
+ [super touchesCancelled:touches withEvent:event];
+}
- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave {
NSMutableSet *cleared = [touches mutableCopy];
for (UITouch *touch in touches) {
- if (touch.phase != phaseToSave) {
+ if (touch.view != self.view || touch.phase != phaseToSave) {
[cleared removeObject:touch];
}
}
diff --git a/platform/iphone/godot_view_renderer.h b/platform/iphone/godot_view_renderer.h
index c6b0a05a4e..b3ee23ae4f 100644
--- a/platform/iphone/godot_view_renderer.h
+++ b/platform/iphone/godot_view_renderer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/godot_view_renderer.mm b/platform/iphone/godot_view_renderer.mm
index 07d664715a..32477ae41c 100644
--- a/platform/iphone/godot_view_renderer.mm
+++ b/platform/iphone/godot_view_renderer.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#import "godot_view_renderer.h"
+
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#import "display_server_iphone.h"
@@ -101,7 +102,7 @@
double dval = [n doubleValue];
ProjectSettings::get_singleton()->set("Info.plist/" + ukey, dval);
- };
+ }
// do stuff
}
}
diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h
index 4bf64d4bc1..0607d7b395 100644
--- a/platform/iphone/ios.h
+++ b/platform/iphone/ios.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,15 +32,26 @@
#define IOS_H
#include "core/object/class_db.h"
+#import <CoreHaptics/CoreHaptics.h>
class iOS : public Object {
GDCLASS(iOS, Object);
static void _bind_methods();
+private:
+ CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr;
+
+ CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13));
+ void start_haptic_engine();
+ void stop_haptic_engine();
+
public:
static void alert(const char *p_alert, const char *p_title);
+ bool supports_haptic_engine();
+ void vibrate_haptic_engine(float p_duration_seconds);
+
String get_model() const;
String get_rate_url(int p_app_id) const;
diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm
index 3430a9cba7..79baae028a 100644
--- a/platform/iphone/ios.mm
+++ b/platform/iphone/ios.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,15 +29,115 @@
/*************************************************************************/
#include "ios.h"
+
#import "app_delegate.h"
#import "view_controller.h"
+
+#import <CoreHaptics/CoreHaptics.h>
#import <UIKit/UIKit.h>
#include <sys/sysctl.h>
void iOS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url);
+ ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine);
+ ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine);
+ ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine);
};
+bool iOS::supports_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware];
+ return capabilities.supportsHaptics;
+ }
+
+ return false;
+}
+
+CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
+ if (haptic_engine == nullptr) {
+ NSError *error = nullptr;
+ haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error];
+
+ if (!error) {
+ [haptic_engine setAutoShutdownEnabled:true];
+ } else {
+ haptic_engine = nullptr;
+ NSLog(@"Could not initialize haptic engine: %@", error);
+ }
+ }
+
+ return haptic_engine;
+}
+
+void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) {
+ if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy...
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ NSDictionary *hapticDict = @{
+ CHHapticPatternKeyPattern : @[
+ @{CHHapticPatternKeyEvent : @{
+ CHHapticPatternKeyEventType : CHHapticEventTypeHapticContinuous,
+ CHHapticPatternKeyTime : @(CHHapticTimeImmediate),
+ CHHapticPatternKeyEventDuration : @(p_duration_seconds)
+ },
+ },
+ ],
+ };
+
+ NSError *error;
+ CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error];
+
+ [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error];
+
+ NSLog(@"Could not vibrate using haptic engine: %@", error);
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
+}
+
+void iOS::start_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ [haptic_engine startWithCompletionHandler:^(NSError *returnedError) {
+ if (returnedError) {
+ NSLog(@"Could not start haptic engine: %@", returnedError);
+ }
+ }];
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
+}
+
+void iOS::stop_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) {
+ if (returnedError) {
+ NSLog(@"Could not stop haptic engine: %@", returnedError);
+ }
+ }];
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
+}
+
void iOS::alert(const char *p_alert, const char *p_title) {
NSString *title = [NSString stringWithUTF8String:p_title];
NSString *message = [NSString stringWithUTF8String:p_alert];
@@ -65,7 +165,7 @@ String iOS::get_model() const {
NSString *platform = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
free(model);
const char *str = [platform UTF8String];
- return String(str != nullptr ? str : "");
+ return String::utf8(str != nullptr ? str : "");
}
String iOS::get_rate_url(int p_app_id) const {
@@ -75,6 +175,6 @@ String iOS::get_rate_url(int p_app_id) const {
printf("returning rate url %s\n", ret.utf8().get_data());
return ret;
-};
+}
iOS::iOS() {}
diff --git a/platform/iphone/joypad_iphone.h b/platform/iphone/joypad_iphone.h
index 329cc8207f..37e272a2c9 100644
--- a/platform/iphone/joypad_iphone.h
+++ b/platform/iphone/joypad_iphone.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm
index 1bf5462d91..9c2feeaaca 100644
--- a/platform/iphone/joypad_iphone.mm
+++ b/platform/iphone/joypad_iphone.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,7 @@
/*************************************************************************/
#import "joypad_iphone.h"
+
#include "core/config/project_settings.h"
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "main/main.h"
@@ -139,10 +140,10 @@ void JoypadIPhone::start_processing() {
for (NSNumber *key in keys) {
int joy_id = [key intValue];
return joy_id;
- };
+ }
return -1;
-};
+}
- (void)addiOSJoypad:(GCController *)controller {
// get a new id for our controller
@@ -156,10 +157,10 @@ void JoypadIPhone::start_processing() {
// assign our player index
if (controller.playerIndex == GCControllerPlayerIndexUnset) {
controller.playerIndex = [self getFreePlayerIndex];
- };
+ }
// tell Godot about our new controller
- Input::get_singleton()->joy_connection_changed(joy_id, true, [controller.vendorName UTF8String]);
+ Input::get_singleton()->joy_connection_changed(joy_id, true, String::utf8([controller.vendorName UTF8String]));
// add it to our dictionary, this will retain our controllers
[self.connectedJoypads setObject:controller forKey:[NSNumber numberWithInt:joy_id]];
@@ -202,8 +203,8 @@ void JoypadIPhone::start_processing() {
// and remove it from our dictionary
[self.connectedJoypads removeObjectForKey:key];
- };
-};
+ }
+}
- (GCControllerPlayerIndex)getFreePlayerIndex {
bool have_player_1 = false;
@@ -223,9 +224,9 @@ void JoypadIPhone::start_processing() {
have_player_3 = true;
} else if (controller.playerIndex == GCControllerPlayerIndex4) {
have_player_4 = true;
- };
- };
- };
+ }
+ }
+ }
if (!have_player_1) {
return GCControllerPlayerIndex1;
@@ -237,7 +238,7 @@ void JoypadIPhone::start_processing() {
return GCControllerPlayerIndex4;
} else {
return GCControllerPlayerIndexUnset;
- };
+ }
}
- (void)setControllerInputHandler:(GCController *)controller {
@@ -285,27 +286,25 @@ void JoypadIPhone::start_processing() {
gamepad.dpad.left.isPressed);
Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT,
gamepad.dpad.right.isPressed);
- };
+ }
- Input::JoyAxisValue jx;
- jx.min = -1;
if (element == gamepad.leftThumbstick) {
- jx.value = gamepad.leftThumbstick.xAxis.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_X, jx);
- jx.value = -gamepad.leftThumbstick.yAxis.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_Y, jx);
+ float value = gamepad.leftThumbstick.xAxis.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_X, value);
+ value = -gamepad.leftThumbstick.yAxis.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_Y, value);
} else if (element == gamepad.rightThumbstick) {
- jx.value = gamepad.rightThumbstick.xAxis.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_X, jx);
- jx.value = -gamepad.rightThumbstick.yAxis.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_Y, jx);
+ float value = gamepad.rightThumbstick.xAxis.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_X, value);
+ value = -gamepad.rightThumbstick.yAxis.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_Y, value);
} else if (element == gamepad.leftTrigger) {
- jx.value = gamepad.leftTrigger.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_LEFT, jx);
+ float value = gamepad.leftTrigger.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_LEFT, value);
} else if (element == gamepad.rightTrigger) {
- jx.value = gamepad.rightTrigger.value;
- Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, jx);
- };
+ float value = gamepad.rightTrigger.value;
+ Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value);
+ }
};
} else if (controller.microGamepad != nil) {
// micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad
@@ -331,7 +330,7 @@ void JoypadIPhone::start_processing() {
gamepad.dpad.down.isPressed);
Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_LEFT, gamepad.dpad.left.isPressed);
Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT, gamepad.dpad.right.isPressed);
- };
+ }
};
}
@@ -340,6 +339,6 @@ void JoypadIPhone::start_processing() {
///@TODO need to add support for controllerPausedHandler which should be a
/// toggle
-};
+}
@end
diff --git a/platform/iphone/keyboard_input_view.h b/platform/iphone/keyboard_input_view.h
index cfbfc7a120..33fa5d571a 100644
--- a/platform/iphone/keyboard_input_view.h
+++ b/platform/iphone/keyboard_input_view.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/keyboard_input_view.mm b/platform/iphone/keyboard_input_view.mm
index b11d04181e..f2a7b22483 100644
--- a/platform/iphone/keyboard_input_view.mm
+++ b/platform/iphone/keyboard_input_view.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/main.m b/platform/iphone/main.m
index d2c41d4d84..acfa7ab731 100644
--- a/platform/iphone/main.m
+++ b/platform/iphone/main.m
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 7a81d8f593..d03403bbb4 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -52,11 +52,11 @@ private:
AudioDriverCoreAudio audio_driver;
- iOS *ios;
+ iOS *ios = nullptr;
- JoypadIPhone *joypad_iphone;
+ JoypadIPhone *joypad_iphone = nullptr;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
virtual void initialize_core() override;
virtual void initialize() override;
@@ -92,7 +92,7 @@ public:
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
- virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
@@ -109,6 +109,7 @@ public:
virtual String get_locale() const override;
virtual String get_unique_id() const override;
+ virtual String get_processor_name() const override;
virtual void vibrate_handheld(int p_duration_ms = 500) override;
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index fc07d321b7..95b06b728e 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#ifdef IPHONE_ENABLED
#include "os_iphone.h"
+
#import "app_delegate.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
@@ -45,6 +46,7 @@
#import <AudioToolbox/AudioServices.h>
#import <UIKit/UIKit.h>
#import <dlfcn.h>
+#include <sys/sysctl.h>
#if defined(VULKAN_ENABLED)
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
@@ -168,7 +170,7 @@ void OSIPhone::delete_main_loop() {
if (main_loop) {
main_loop->finalize();
memdelete(main_loop);
- };
+ }
main_loop = nullptr;
}
@@ -197,17 +199,22 @@ void OSIPhone::finalize() {
deinitialize_modules();
// Already gets called
- // delete_main_loop();
+ //delete_main_loop();
}
// MARK: Dynamic Libraries
-Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
+Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
if (p_path.length() == 0) {
p_library_handle = RTLD_SELF;
+
+ if (r_resolved_path != nullptr) {
+ *r_resolved_path = p_path;
+ }
+
return OK;
}
- return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path);
+ return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path);
}
Error OSIPhone::close_dynamic_library(void *p_library_handle) {
@@ -230,12 +237,13 @@ Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const
String OSIPhone::get_name() const {
return "iOS";
-};
+}
String OSIPhone::get_model_name() const {
String model = ios->get_model();
- if (model != "")
+ if (model != "") {
return model;
+ }
return OS_Unix::get_model_name();
}
@@ -253,14 +261,12 @@ Error OSIPhone::shell_open(String p_uri) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
return OK;
-};
+}
void OSIPhone::set_user_data_dir(String p_dir) {
- DirAccess *da = DirAccess::open(p_dir);
-
+ Ref<DirAccess> da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
- memdelete(da);
}
String OSIPhone::get_user_data_dir() const {
@@ -287,9 +293,22 @@ String OSIPhone::get_unique_id() const {
return String::utf8([uuid UTF8String]);
}
+String OSIPhone::get_processor_name() const {
+ char buffer[256];
+ size_t buffer_len = 256;
+ if (sysctlbyname("machdep.cpu.brand_string", &buffer, &buffer_len, NULL, 0) == 0) {
+ return String::utf8(buffer, buffer_len);
+ }
+ ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
+}
+
void OSIPhone::vibrate_handheld(int p_duration_ms) {
- // iOS does not support duration for vibration
- AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
+ if (ios->supports_haptic_engine()) {
+ ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f);
+ } else {
+ // iOS <13 does not support duration for vibration
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
+ }
}
bool OSIPhone::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h
index 68ef4e31a7..fed77d8932 100644
--- a/platform/iphone/platform_config.h
+++ b/platform/iphone/platform_config.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/tts_ios.h b/platform/iphone/tts_ios.h
new file mode 100644
index 0000000000..064316b0b2
--- /dev/null
+++ b/platform/iphone/tts_ios.h
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* tts_ios.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TTS_IOS_H
+#define TTS_IOS_H
+
+#if __has_include(<AVFAudio/AVSpeechSynthesis.h>)
+#import <AVFAudio/AVSpeechSynthesis.h>
+#else
+#import <AVFoundation/AVFoundation.h>
+#endif
+
+#include "core/string/ustring.h"
+#include "core/templates/list.h"
+#include "core/templates/rb_map.h"
+#include "core/variant/array.h"
+#include "servers/display_server.h"
+
+@interface TTS_IOS : NSObject <AVSpeechSynthesizerDelegate> {
+ bool speaking;
+ HashMap<id, int> ids;
+
+ AVSpeechSynthesizer *av_synth;
+ List<DisplayServer::TTSUtterance> queue;
+}
+
+- (void)pauseSpeaking;
+- (void)resumeSpeaking;
+- (void)stopSpeaking;
+- (bool)isSpeaking;
+- (bool)isPaused;
+- (void)speak:(const String &)text voice:(const String &)voice volume:(int)volume pitch:(float)pitch rate:(float)rate utterance_id:(int)utterance_id interrupt:(bool)interrupt;
+- (Array)getVoices;
+@end
+
+#endif // TTS_IOS_H
diff --git a/platform/iphone/tts_ios.mm b/platform/iphone/tts_ios.mm
new file mode 100644
index 0000000000..a079d02add
--- /dev/null
+++ b/platform/iphone/tts_ios.mm
@@ -0,0 +1,164 @@
+/*************************************************************************/
+/* tts_ios.mm */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "tts_ios.h"
+
+@implementation TTS_IOS
+
+- (id)init {
+ self = [super init];
+ self->speaking = false;
+ self->av_synth = [[AVSpeechSynthesizer alloc] init];
+ [self->av_synth setDelegate:self];
+ print_verbose("Text-to-Speech: AVSpeechSynthesizer initialized.");
+ return self;
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance {
+ NSString *string = [utterance speechString];
+
+ // Convert from UTF-16 to UTF-32 position.
+ int pos = 0;
+ for (NSUInteger i = 0; i < MIN(characterRange.location, string.length); i++) {
+ unichar c = [string characterAtIndex:i];
+ if ((c & 0xfffffc00) == 0xd800) {
+ i++;
+ }
+ pos++;
+ }
+
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_BOUNDARY, ids[utterance], pos);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth didCancelSpeechUtterance:(AVSpeechUtterance *)utterance {
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, ids[utterance]);
+ ids.erase(utterance);
+ speaking = false;
+ [self update];
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)av_synth didFinishSpeechUtterance:(AVSpeechUtterance *)utterance {
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, ids[utterance]);
+ ids.erase(utterance);
+ speaking = false;
+ [self update];
+}
+
+- (void)update {
+ if (!speaking && queue.size() > 0) {
+ DisplayServer::TTSUtterance &message = queue.front()->get();
+
+ AVSpeechUtterance *new_utterance = [[AVSpeechUtterance alloc] initWithString:[NSString stringWithUTF8String:message.text.utf8().get_data()]];
+ [new_utterance setVoice:[AVSpeechSynthesisVoice voiceWithIdentifier:[NSString stringWithUTF8String:message.voice.utf8().get_data()]]];
+ if (message.rate > 1.f) {
+ [new_utterance setRate:Math::range_lerp(message.rate, 1.f, 10.f, AVSpeechUtteranceDefaultSpeechRate, AVSpeechUtteranceMaximumSpeechRate)];
+ } else if (message.rate < 1.f) {
+ [new_utterance setRate:Math::range_lerp(message.rate, 0.1f, 1.f, AVSpeechUtteranceMinimumSpeechRate, AVSpeechUtteranceDefaultSpeechRate)];
+ }
+ [new_utterance setPitchMultiplier:message.pitch];
+ [new_utterance setVolume:(Math::range_lerp(message.volume, 0.f, 100.f, 0.f, 1.f))];
+
+ ids[new_utterance] = message.id;
+ [av_synth speakUtterance:new_utterance];
+
+ queue.pop_front();
+
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_STARTED, message.id);
+ speaking = true;
+ }
+}
+
+- (void)pauseSpeaking {
+ [av_synth pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
+}
+
+- (void)resumeSpeaking {
+ [av_synth continueSpeaking];
+}
+
+- (void)stopSpeaking {
+ for (DisplayServer::TTSUtterance &message : queue) {
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, message.id);
+ }
+ queue.clear();
+ [av_synth stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
+ speaking = false;
+}
+
+- (bool)isSpeaking {
+ return speaking || (queue.size() > 0);
+}
+
+- (bool)isPaused {
+ return [av_synth isPaused];
+}
+
+- (void)speak:(const String &)text voice:(const String &)voice volume:(int)volume pitch:(float)pitch rate:(float)rate utterance_id:(int)utterance_id interrupt:(bool)interrupt {
+ if (interrupt) {
+ [self stopSpeaking];
+ }
+
+ if (text.is_empty()) {
+ DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_CANCELED, utterance_id);
+ return;
+ }
+
+ DisplayServer::TTSUtterance message;
+ message.text = text;
+ message.voice = voice;
+ message.volume = CLAMP(volume, 0, 100);
+ message.pitch = CLAMP(pitch, 0.f, 2.f);
+ message.rate = CLAMP(rate, 0.1f, 10.f);
+ message.id = utterance_id;
+ queue.push_back(message);
+
+ if ([self isPaused]) {
+ [self resumeSpeaking];
+ } else {
+ [self update];
+ }
+}
+
+- (Array)getVoices {
+ Array list;
+ for (AVSpeechSynthesisVoice *voice in [AVSpeechSynthesisVoice speechVoices]) {
+ NSString *voiceIdentifierString = [voice identifier];
+ NSString *voiceLocaleIdentifier = [voice language];
+ NSString *voiceName = [voice name];
+ Dictionary voice_d;
+ voice_d["name"] = String::utf8([voiceName UTF8String]);
+ voice_d["id"] = String::utf8([voiceIdentifierString UTF8String]);
+ voice_d["language"] = String::utf8([voiceLocaleIdentifier UTF8String]);
+ list.push_back(voice_d);
+ }
+ return list;
+}
+
+@end
diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h
index 400145b8b7..c8b37a4d11 100644
--- a/platform/iphone/view_controller.h
+++ b/platform/iphone/view_controller.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm
index 2723ac4706..4f4ef4f046 100644
--- a/platform/iphone/view_controller.mm
+++ b/platform/iphone/view_controller.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -203,7 +203,7 @@
case DisplayServer::SCREEN_LANDSCAPE:
return UIInterfaceOrientationMaskLandscapeLeft;
}
-};
+}
- (BOOL)prefersStatusBarHidden {
return YES;
diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/iphone/vulkan_context_iphone.h
index ec6aaf46e8..7576525755 100644
--- a/platform/iphone/vulkan_context_iphone.h
+++ b/platform/iphone/vulkan_context_iphone.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/iphone/vulkan_context_iphone.mm
index 547cee9570..17cb0f6009 100644
--- a/platform/iphone/vulkan_context_iphone.mm
+++ b/platform/iphone/vulkan_context_iphone.mm
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */