summaryrefslogtreecommitdiff
path: root/platform/ios
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios')
-rw-r--r--platform/ios/README.md14
-rw-r--r--platform/ios/detect.py65
-rw-r--r--platform/ios/display_layer.mm10
-rw-r--r--platform/ios/display_server_ios.mm4
-rw-r--r--platform/ios/export/export_plugin.cpp166
-rw-r--r--platform/ios/export/export_plugin.h8
-rw-r--r--platform/ios/export/godot_plugin_config.cpp14
-rw-r--r--platform/ios/godot_view.mm2
-rw-r--r--platform/ios/os_ios.h8
-rw-r--r--platform/ios/os_ios.mm9
-rw-r--r--platform/ios/tts_ios.mm6
11 files changed, 176 insertions, 130 deletions
diff --git a/platform/ios/README.md b/platform/ios/README.md
new file mode 100644
index 0000000000..82c275ad31
--- /dev/null
+++ b/platform/ios/README.md
@@ -0,0 +1,14 @@
+# iOS platform port
+
+This folder contains the C++, Objective-C and Objective-C++ code for the iOS
+platform port.
+
+See also [`misc/dist/ios_xcode`](/misc/dist/ios_xcode) folder for the Xcode
+project template used for packaging the iOS export templates.
+
+## Documentation
+
+- [Compiling for iOS](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_ios.html)
+ - Instructions on building this platform port from source.
+- [Exporting for iOS](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_ios.html)
+ - Instructions on using the compiled export templates to export a project.
diff --git a/platform/ios/detect.py b/platform/ios/detect.py
index 67c90b10a0..38e62134b5 100644
--- a/platform/ios/detect.py
+++ b/platform/ios/detect.py
@@ -2,6 +2,11 @@ import os
import sys
from methods import detect_darwin_sdk_path
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from SCons import Environment
+
def is_active():
return True
@@ -36,38 +41,34 @@ def get_opts():
def get_flags():
return [
- ("tools", False),
+ ("arch", "arm64"), # Default for convenience.
+ ("target", "template_debug"),
("use_volk", False),
]
-def configure(env):
- ## Build type
-
- if env["target"].startswith("release"):
- env.Append(CPPDEFINES=["NDEBUG", ("NS_BLOCK_ASSERTIONS", 1)])
- if env["optimize"] == "speed": # optimize for speed (default)
- # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces
- # when using `target=release_debug`.
- opt = "-O3" if env["target"] == "release" else "-O2"
- env.Append(CCFLAGS=[opt, "-ftree-vectorize", "-fomit-frame-pointer"])
- env.Append(LINKFLAGS=[opt])
- elif env["optimize"] == "size": # optimize for size
- env.Append(CCFLAGS=["-Os", "-ftree-vectorize"])
- env.Append(LINKFLAGS=["-Os"])
+def configure(env: "Environment"):
+ # Validate arch.
+ supported_arches = ["x86_64", "arm64"]
+ if env["arch"] not in supported_arches:
+ print(
+ 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.'
+ % (env["arch"], ", ".join(supported_arches))
+ )
+ sys.exit()
- elif env["target"] == "debug":
- env.Append(CCFLAGS=["-gdwarf-2", "-O0"])
- env.Append(CPPDEFINES=["_DEBUG", ("DEBUG", 1)])
+ ## LTO
- if env["use_lto"]:
- env.Append(CCFLAGS=["-flto"])
- env.Append(LINKFLAGS=["-flto"])
+ if env["lto"] == "auto": # Disable by default as it makes linking in Xcode very slow.
+ env["lto"] = "none"
- ## Architecture
- env["bits"] = "64"
- if env["arch"] != "x86_64":
- env["arch"] = "arm64"
+ if env["lto"] != "none":
+ if env["lto"] == "thin":
+ env.Append(CCFLAGS=["-flto=thin"])
+ env.Append(LINKFLAGS=["-flto=thin"])
+ else:
+ env.Append(CCFLAGS=["-flto"])
+ env.Append(LINKFLAGS=["-flto"])
## Compiler configuration
@@ -107,6 +108,10 @@ def configure(env):
env.Append(CCFLAGS=["-miphoneos-version-min=11.0"])
if env["arch"] == "x86_64":
+ if not env["ios_simulator"]:
+ print("ERROR: Building for iOS with 'arch=x86_64' requires 'ios_simulator=yes'.")
+ sys.exit(255)
+
env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9"
env.Append(
CCFLAGS=(
@@ -128,12 +133,10 @@ def configure(env):
env.Append(ASFLAGS=["-arch", "arm64"])
env.Append(CPPDEFINES=["NEED_LONG_INT"])
- # Disable exceptions on non-tools (template) builds
- if not env["tools"]:
- if env["ios_exceptions"]:
- env.Append(CCFLAGS=["-fexceptions"])
- else:
- env.Append(CCFLAGS=["-fno-exceptions"])
+ if env["ios_exceptions"]:
+ env.Append(CCFLAGS=["-fexceptions"])
+ else:
+ env.Append(CCFLAGS=["-fno-exceptions"])
# Temp fix for ABS/MAX/MIN macros in iOS SDK blocking compilation
env.Append(CCFLAGS=["-Wno-ambiguous-macro"])
diff --git a/platform/ios/display_layer.mm b/platform/ios/display_layer.mm
index 7c83494768..74c760ae9a 100644
--- a/platform/ios/display_layer.mm
+++ b/platform/ios/display_layer.mm
@@ -89,12 +89,12 @@
// FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
- // Create GL ES 2 context
- if (GLOBAL_GET("rendering/driver/driver_name") == "opengl3") {
- context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- NSLog(@"Setting up an OpenGL ES 2.0 context.");
+ // Create GL ES 3 context
+ if (GLOBAL_GET("rendering/renderer/rendering_method") == "gl_compatibility") {
+ context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
+ NSLog(@"Setting up an OpenGL ES 3.0 context.");
if (!context) {
- NSLog(@"Failed to create OpenGL ES 2.0 context!");
+ NSLog(@"Failed to create OpenGL ES 3.0 context!");
return;
}
}
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 74d6bc2e97..d3a0f38463 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -62,7 +62,7 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
// 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") {
+ if (rendering_driver == "opengl3") {
bool gl_initialization_error = false;
// FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
@@ -163,7 +163,7 @@ Vector<String> DisplayServerIOS::get_rendering_drivers_func() {
drivers.push_back("vulkan");
#endif
#if defined(GLES3_ENABLED)
- drivers.push_back("opengl_es");
+ drivers.push_back("opengl3");
#endif
return drivers;
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 425a977569..74a57dc614 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -34,7 +34,6 @@
#include "editor/editor_node.h"
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
- String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
// Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
r_features->push_back("etc2");
@@ -140,27 +139,27 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone/iPod Touch with Retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone with Retina HD display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad Pro
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad with Retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad Pro
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // 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::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight on devices with Retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color()));
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
}
}
@@ -387,13 +386,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String locale_files;
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
- int index = 0;
+ HashSet<String> languages;
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>\"; };";
+ if (tr.is_valid() && tr->get_locale() != "en") {
+ languages.insert(tr->get_locale());
}
+ }
+
+ int index = 0;
+ for (const String &lang : languages) {
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n";
index++;
}
}
@@ -402,13 +405,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String locale_files;
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
- int index = 0;
+ HashSet<String> languages;
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 + " */,";
+ if (tr.is_valid() && tr->get_locale() != "en") {
+ languages.insert(tr->get_locale());
}
+ }
+
+ int index = 0;
+ for (const String &lang : languages) {
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,\n";
index++;
}
}
@@ -531,26 +538,27 @@ struct IconInfo {
const char *actual_size_side;
const char *scale;
const char *unscaled_size;
+ const bool force_opaque;
};
static const IconInfo icon_infos[] = {
// Home screen on iPhone
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60" },
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40" },
- { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60" },
+ { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", false },
+ { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", false },
+ { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false },
// 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" },
+ { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", false },
+ { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false },
+ { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
// App Store
- { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024" },
+ { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
// 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" }
+ { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false },
+ { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false },
+ { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false }
};
Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) {
@@ -570,14 +578,17 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
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 + "'.");
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
+ return ERR_UNCONFIGURED;
+ }
+ if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
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());
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path));
return err;
}
} else {
@@ -585,11 +596,15 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
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 + "'.");
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
+ return ERR_UNCONFIGURED;
+ }
+ if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
return ERR_UNCONFIGURED;
}
if (img->get_width() != side_size || img->get_height() != side_size) {
- WARN_PRINT("Icon (" + String(info.preset_key) + "): '" + icon_path + "' has incorrect size (" + String::num_int64(img->get_width()) + "x" + String::num_int64(img->get_height()) + ") and was automatically resized to " + String::num_int64(side_size) + "x" + String::num_int64(side_size) + ".");
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s): '%s' has incorrect size %s and was automatically resized to %s.", info.preset_key, icon_path, img->get_size(), Vector2i(side_size, side_size)));
img->resize(side_size, side_size);
err = img->save_png(p_iconset_dir + info.export_name);
} else {
@@ -597,8 +612,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
}
if (err) {
- String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
- ERR_PRINT(err_str.utf8().get_data());
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path));
return err;
}
}
@@ -634,7 +648,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) {
Ref<Image> image;
- String image_path = p_dest_dir.plus_file("splash@2x.png");
+ String image_path = p_dest_dir.path_join("splash@2x.png");
image.instantiate();
Error err = image->load(custom_launch_image_2x);
@@ -648,7 +662,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
}
image.unref();
- image_path = p_dest_dir.plus_file("splash@3x.png");
+ image_path = p_dest_dir.path_join("splash@3x.png");
image.instantiate();
err = image->load(custom_launch_image_3x);
@@ -681,8 +695,8 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
// because Godot's own boot logo uses single image for all resolutions.
// Also not using @1x image, because devices using this image variant
// are not supported by iOS 9, which is minimal target.
- const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png");
- const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png");
+ const String splash_png_path_2x = p_dest_dir.path_join("splash@2x.png");
+ const String splash_png_path_3x = p_dest_dir.path_join("splash@3x.png");
if (splash->save_png(splash_png_path_2x) != OK) {
return ERR_FILE_CANT_WRITE;
@@ -797,7 +811,7 @@ Error EditorExportPlatformIOS::_walk_dir_recursive(Ref<DirAccess> &p_da, FileHan
dirs.push_back(path);
}
} else {
- Error err = p_handler(current_dir.plus_file(path), p_userdata);
+ Error err = p_handler(current_dir.path_join(path), p_userdata);
if (err) {
p_da->list_dir_end();
return err;
@@ -1013,7 +1027,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
if (p_is_framework && p_asset.ends_with(".dylib")) {
// For iOS we need to turn .dylib into .framework
// to be able to send application to AppStore
- asset_path = String("dylibs").plus_file(base_dir);
+ asset_path = String("dylibs").path_join(base_dir);
String file_name;
@@ -1025,12 +1039,12 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
String framework_name = file_name + ".framework";
- asset_path = asset_path.plus_file(framework_name);
- destination_dir = p_out_dir.plus_file(asset_path);
- destination = destination_dir.plus_file(file_name);
+ asset_path = asset_path.path_join(framework_name);
+ destination_dir = p_out_dir.path_join(asset_path);
+ destination = destination_dir.path_join(file_name);
create_framework = true;
} else if (p_is_framework && (p_asset.ends_with(".framework") || p_asset.ends_with(".xcframework"))) {
- asset_path = String("dylibs").plus_file(base_dir);
+ asset_path = String("dylibs").path_join(base_dir);
String file_name;
@@ -1040,8 +1054,8 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
file_name = *p_custom_file_name;
}
- asset_path = asset_path.plus_file(file_name);
- destination_dir = p_out_dir.plus_file(asset_path);
+ asset_path = asset_path.path_join(file_name);
+ destination_dir = p_out_dir.path_join(asset_path);
destination = destination_dir;
} else {
asset_path = base_dir;
@@ -1054,9 +1068,9 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
file_name = *p_custom_file_name;
}
- destination_dir = p_out_dir.plus_file(asset_path);
- asset_path = asset_path.plus_file(file_name);
- destination = p_out_dir.plus_file(asset_path);
+ destination_dir = p_out_dir.path_join(asset_path);
+ asset_path = asset_path.path_join(file_name);
+ destination = p_out_dir.path_join(asset_path);
}
Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@@ -1073,7 +1087,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
if (err) {
return err;
}
- IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
+ IOSExportAsset exported_asset = { binary_name.path_join(asset_path), p_is_framework, p_should_embed };
r_exported_assets.push_back(exported_asset);
if (create_framework) {
@@ -1091,7 +1105,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
{
List<String> install_name_args;
install_name_args.push_back("-id");
- install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name));
+ install_name_args.push_back(String("@rpath").path_join(framework_name).path_join(file_name));
install_name_args.push_back(destination);
OS::get_singleton()->execute("install_name_tool", install_name_args);
@@ -1126,7 +1140,7 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
String info_plist = info_plist_format.replace("$name", file_name);
- Ref<FileAccess> f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(destination_dir.path_join("Info.plist"), FileAccess::WRITE);
if (f.is_valid()) {
f->store_string(info_plist);
}
@@ -1651,27 +1665,31 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
}
+ HashSet<String> languages;
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() + "\";");
- }
+ if (tr.is_valid() && tr->get_locale() != "en") {
+ languages.insert(tr->get_locale());
+ }
+ }
+
+ for (const String &lang : languages) {
+ 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() + "\";");
}
}
}
diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h
index abda8e218a..639f2416a5 100644
--- a/platform/ios/export/export_plugin.h
+++ b/platform/ios/export/export_plugin.h
@@ -238,9 +238,9 @@ public:
if (da->current_is_dir()) {
if (p_check_directories) {
- Vector<String> directory_files = list_plugin_config_files(p_path.plus_file(file), false);
+ Vector<String> directory_files = list_plugin_config_files(p_path.path_join(file), false);
for (int i = 0; i < directory_files.size(); ++i) {
- dir_files.push_back(file.plus_file(directory_files[i]));
+ dir_files.push_back(file.path_join(directory_files[i]));
}
}
@@ -260,7 +260,7 @@ public:
static Vector<PluginConfigIOS> get_plugins() {
Vector<PluginConfigIOS> loaded_plugins;
- String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins");
+ String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().path_join("ios/plugins");
if (DirAccess::exists(plugins_dir)) {
Vector<String> plugins_filenames = list_plugin_config_files(plugins_dir, true);
@@ -268,7 +268,7 @@ public:
if (!plugins_filenames.is_empty()) {
Ref<ConfigFile> config_file = memnew(ConfigFile);
for (int i = 0; i < plugins_filenames.size(); i++) {
- PluginConfigIOS config = PluginConfigIOS::load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
+ PluginConfigIOS config = PluginConfigIOS::load_plugin_config(config_file, plugins_dir.path_join(plugins_filenames[i]));
if (config.valid_config) {
loaded_plugins.push_back(config);
} else {
diff --git a/platform/ios/export/godot_plugin_config.cpp b/platform/ios/export/godot_plugin_config.cpp
index 24a95a11a4..42797d449b 100644
--- a/platform/ios/export/godot_plugin_config.cpp
+++ b/platform/ios/export/godot_plugin_config.cpp
@@ -46,7 +46,7 @@ String PluginConfigIOS::resolve_local_dependency_path(String plugin_config_dir,
}
String res_path = ProjectSettings::get_singleton()->globalize_path("res://");
- absolute_path = plugin_config_dir.plus_file(dependency_path);
+ absolute_path = plugin_config_dir.path_join(dependency_path);
return absolute_path.replace(res_path, "res://");
}
@@ -64,7 +64,7 @@ String PluginConfigIOS::resolve_system_dependency_path(String dependency_path) {
String system_path = "/System/Library/Frameworks";
- return system_path.plus_file(dependency_path);
+ return system_path.path_join(dependency_path);
}
Vector<String> PluginConfigIOS::resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths) {
@@ -121,8 +121,8 @@ bool PluginConfigIOS::validate_plugin(PluginConfigIOS &plugin_config) {
String file_path = plugin_config.binary.get_base_dir();
String file_name = plugin_config.binary.get_basename().get_file();
String file_extension = plugin_config.binary.get_extension();
- String release_file_name = file_path.plus_file(file_name + ".release." + file_extension);
- String debug_file_name = file_path.plus_file(file_name + ".debug." + file_extension);
+ String release_file_name = file_path.path_join(file_name + ".release." + file_extension);
+ String debug_file_name = file_path.path_join(file_name + ".debug." + file_extension);
if ((plugin_extension == "a" && FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) ||
(plugin_extension == "xcframework" && DirAccess::exists(release_file_name) && DirAccess::exists(debug_file_name))) {
@@ -144,7 +144,7 @@ String PluginConfigIOS::get_plugin_main_binary(PluginConfigIOS &plugin_config, b
String plugin_extension = plugin_config.binary.get_extension();
String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + "." + plugin_extension;
- return plugin_binary_dir.plus_file(plugin_file);
+ return plugin_binary_dir.path_join(plugin_file);
}
uint64_t PluginConfigIOS::get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path) {
@@ -156,8 +156,8 @@ uint64_t PluginConfigIOS::get_plugin_modification_time(const PluginConfigIOS &pl
String file_path = plugin_config.binary.get_base_dir();
String file_name = plugin_config.binary.get_basename().get_file();
String plugin_extension = plugin_config.binary.get_extension();
- String release_file_name = file_path.plus_file(file_name + ".release." + plugin_extension);
- String debug_file_name = file_path.plus_file(file_name + ".debug." + plugin_extension);
+ String release_file_name = file_path.path_join(file_name + ".release." + plugin_extension);
+ String debug_file_name = file_path.path_join(file_name + ".debug." + plugin_extension);
last_updated = MAX(last_updated, FileAccess::get_modified_time(release_file_name));
last_updated = MAX(last_updated, FileAccess::get_modified_time(debug_file_name));
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 9ed219508c..ff90c05b1d 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -74,7 +74,7 @@ static const float earth_gravity = 9.80665;
if ([driverName isEqualToString:@"vulkan"]) {
layer = [GodotMetalLayer layer];
- } else if ([driverName isEqualToString:@"opengl_es"]) {
+ } else if ([driverName isEqualToString:@"opengl3"]) {
if (@available(iOS 13, *)) {
NSLog(@"OpenGL ES is deprecated on iOS 13");
}
diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h
index 3b88f53b6a..400040875f 100644
--- a/platform/ios/os_ios.h
+++ b/platform/ios/os_ios.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef IOS_ENABLED
-
#ifndef OS_IOS_H
#define OS_IOS_H
+#ifdef IOS_ENABLED
+
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
#include "ios.h"
@@ -100,6 +100,8 @@ public:
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual String get_model_name() const override;
virtual Error shell_open(String p_uri) override;
@@ -122,6 +124,6 @@ public:
void on_focus_in();
};
-#endif // OS_IOS_H
+#endif // IOS_ENABLED
#endif // OS_IOS_H
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index b9d186f355..a674498620 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -240,6 +240,15 @@ String OS_IOS::get_name() const {
return "iOS";
}
+String OS_IOS::get_distribution_name() const {
+ return get_name();
+}
+
+String OS_IOS::get_version() const {
+ NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
+ return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
+}
+
String OS_IOS::get_model_name() const {
String model = ios->get_model();
if (model != "") {
diff --git a/platform/ios/tts_ios.mm b/platform/ios/tts_ios.mm
index a079d02add..8319cad117 100644
--- a/platform/ios/tts_ios.mm
+++ b/platform/ios/tts_ios.mm
@@ -78,12 +78,12 @@
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)];
+ [new_utterance setRate:Math::remap(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 setRate:Math::remap(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))];
+ [new_utterance setVolume:(Math::remap(message.volume, 0.f, 100.f, 0.f, 1.f))];
ids[new_utterance] = message.id;
[av_synth speakUtterance:new_utterance];