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/detect.py2
-rw-r--r--platform/iphone/display_server_iphone.h15
-rw-r--r--platform/iphone/display_server_iphone.mm101
-rw-r--r--platform/iphone/export/export.cpp126
-rw-r--r--platform/iphone/godot_app_delegate.m2
-rw-r--r--platform/iphone/godot_iphone.mm4
-rw-r--r--platform/iphone/godot_view.mm22
-rw-r--r--platform/iphone/ios.mm8
-rw-r--r--platform/iphone/joypad_iphone.mm2
-rw-r--r--platform/iphone/keyboard_input_view.mm6
-rw-r--r--platform/iphone/native_video_view.h41
-rw-r--r--platform/iphone/native_video_view.m266
-rw-r--r--platform/iphone/os_iphone.mm12
-rw-r--r--platform/iphone/plugin/godot_plugin_config.h92
-rw-r--r--platform/iphone/view_controller.h5
-rw-r--r--platform/iphone/view_controller.mm24
-rw-r--r--platform/iphone/vulkan_context_iphone.h2
-rw-r--r--platform/iphone/vulkan_context_iphone.mm8
19 files changed, 251 insertions, 488 deletions
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index ee7b2f4ab5..58b574a72f 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -19,7 +19,6 @@ iphone_lib = [
"godot_view_gesture_recognizer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
- "native_video_view.m",
]
env_ios = env.Clone()
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 17796beb6f..cf358e0878 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -54,7 +54,7 @@ def configure(env):
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["-O2", "-ftree-vectorize", "-fomit-frame-pointer"])
env.Append(LINKFLAGS=["-O2"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["-Os", "-ftree-vectorize"])
env.Append(LINKFLAGS=["-Os"])
diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h
index 31a44723a5..6f64130b23 100644
--- a/platform/iphone/display_server_iphone.h
+++ b/platform/iphone/display_server_iphone.h
@@ -67,7 +67,7 @@ class DisplayServerIPhone : public DisplayServer {
void perform_event(const Ref<InputEvent> &p_event);
- DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerIPhone();
public:
@@ -76,7 +76,7 @@ public:
static DisplayServerIPhone *get_singleton();
static void register_iphone_driver();
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
// MARK: - Events
@@ -99,7 +99,7 @@ public:
// MARK: Touches
- void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick);
+ void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click);
void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y);
void touches_cancelled(int p_idx);
@@ -176,6 +176,9 @@ public:
virtual bool can_any_window_draw() const override;
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
+
virtual bool screen_is_touchscreen(int p_screen) const override;
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) override;
@@ -190,12 +193,6 @@ public:
virtual void screen_set_keep_on(bool p_enable) override;
virtual bool screen_is_kept_on() const override;
- virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
- virtual bool native_video_is_playing() const override;
- virtual void native_video_pause() override;
- virtual void native_video_unpause() override;
- virtual void native_video_stop() override;
-
void resize_window(CGSize size);
};
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index 05dc78bb4d..bd95e2c703 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -36,7 +36,6 @@
#import "godot_view.h"
#include "ios.h"
#import "keyboard_input_view.h"
-#import "native_video_view.h"
#include "os_iphone.h"
#import "view_controller.h"
@@ -49,7 +48,7 @@ DisplayServerIPhone *DisplayServerIPhone::get_singleton() {
return (DisplayServerIPhone *)DisplayServer::get_singleton();
}
-DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+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;
#if defined(OPENGL_ENABLED)
@@ -109,7 +108,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Displ
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
- if (context_vulkan->window_create(MAIN_WINDOW_ID, layer, size.width, size.height) != OK) {
+ if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) {
memdelete(context_vulkan);
context_vulkan = nullptr;
ERR_FAIL_MSG("Failed to create Vulkan window.");
@@ -136,20 +135,20 @@ DisplayServerIPhone::~DisplayServerIPhone() {
if (rendering_device_vulkan) {
rendering_device_vulkan->finalize();
memdelete(rendering_device_vulkan);
- rendering_device_vulkan = NULL;
+ rendering_device_vulkan = nullptr;
}
if (context_vulkan) {
context_vulkan->window_destroy(MAIN_WINDOW_ID);
memdelete(context_vulkan);
- context_vulkan = NULL;
+ context_vulkan = nullptr;
}
}
#endif
}
-DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerIPhone::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ return memnew(DisplayServerIPhone(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
}
Vector<String> DisplayServerIPhone::get_rendering_drivers_func() {
@@ -222,10 +221,10 @@ void DisplayServerIPhone::_window_callback(const Callable &p_callable, const Var
// MARK: Touches
-void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_doubleclick) {
+void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
Ref<InputEventScreenTouch> ev;
- ev.instance();
+ ev.instantiate();
ev->set_index(p_idx);
ev->set_pressed(p_pressed);
@@ -237,7 +236,7 @@ void DisplayServerIPhone::touch_press(int p_idx, int p_x, int p_y, bool p_presse
void DisplayServerIPhone::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
if (!GLOBAL_DEF("debug/disable_touch", false)) {
Ref<InputEventScreenDrag> ev;
- ev.instance();
+ ev.instantiate();
ev->set_index(p_idx);
ev->set_position(Vector2(p_x, p_y));
ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
@@ -257,7 +256,7 @@ void DisplayServerIPhone::touches_cancelled(int p_idx) {
void DisplayServerIPhone::key(uint32_t p_key, bool p_pressed) {
Ref<InputEventKey> ev;
- ev.instance();
+ ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
ev->set_keycode(p_key);
@@ -305,7 +304,6 @@ bool DisplayServerIPhone::has_feature(Feature p_feature) const {
// case FEATURE_MOUSE_WARP:
// case FEATURE_NATIVE_DIALOG:
// case FEATURE_NATIVE_ICON:
- // case FEATURE_NATIVE_VIDEO:
// case FEATURE_WINDOW_TRANSPARENCY:
case FEATURE_CLIPBOARD:
case FEATURE_KEEP_SCREEN_ON:
@@ -569,69 +567,6 @@ bool DisplayServerIPhone::screen_is_kept_on() const {
return [UIApplication sharedApplication].idleTimerDisabled;
}
-Error DisplayServerIPhone::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- bool exists = f && f->is_open();
-
- String user_data_dir = OSIPhone::get_singleton()->get_user_data_dir();
-
- if (!exists) {
- return FAILED;
- }
-
- String tempFile = OSIPhone::get_singleton()->get_user_data_dir();
-
- if (p_path.begins_with("res://")) {
- if (PackedData::get_singleton()->has_path(p_path)) {
- printf("Unable to play %s using the native player as it resides in a .pck file\n", p_path.utf8().get_data());
- return ERR_INVALID_PARAMETER;
- } else {
- p_path = p_path.replace("res:/", ProjectSettings::get_singleton()->get_resource_path());
- }
- } else if (p_path.begins_with("user://")) {
- p_path = p_path.replace("user:/", user_data_dir);
- }
-
- memdelete(f);
-
- printf("Playing video: %s\n", p_path.utf8().get_data());
-
- String file_path = ProjectSettings::get_singleton()->globalize_path(p_path);
-
- NSString *filePath = [[NSString alloc] initWithUTF8String:file_path.utf8().get_data()];
- NSString *audioTrack = [NSString stringWithUTF8String:p_audio_track.utf8()];
- NSString *subtitleTrack = [NSString stringWithUTF8String:p_subtitle_track.utf8()];
-
- if (![AppDelegate.viewController playVideoAtPath:filePath
- volume:p_volume
- audio:audioTrack
- subtitle:subtitleTrack]) {
- return OK;
- }
-
- return FAILED;
-}
-
-bool DisplayServerIPhone::native_video_is_playing() const {
- return [AppDelegate.viewController.videoView isVideoPlaying];
-}
-
-void DisplayServerIPhone::native_video_pause() {
- if (native_video_is_playing()) {
- [AppDelegate.viewController.videoView pauseVideo];
- }
-}
-
-void DisplayServerIPhone::native_video_unpause() {
- [AppDelegate.viewController.videoView unpauseVideo];
-};
-
-void DisplayServerIPhone::native_video_stop() {
- if (native_video_is_playing()) {
- [AppDelegate.viewController.videoView stopVideo];
- }
-}
-
void DisplayServerIPhone::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
@@ -646,3 +581,19 @@ void DisplayServerIPhone::resize_window(CGSize viewSize) {
Variant resize_rect = Rect2i(Point2i(), size);
_window_callback(window_resize_callback, resize_rect);
}
+
+void DisplayServerIPhone::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerIPhone::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index c585c2afbe..f21a14e84b 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -31,11 +31,11 @@
#include "export.h"
#include "core/config/project_settings.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
#include "core/io/zip_io.h"
-#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/templates/safe_refcount.h"
#include "core/version.h"
@@ -353,6 +353,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/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"), ""));
@@ -365,6 +367,31 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
for (int i = 0; i < found_plugins.size(); i++) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
}
+
+ Set<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) {
+ case PluginConfigIOS::PlistItemType::STRING_INPUT: {
+ String preset_name = "plugins_plist/" + key;
+ if (!plist_keys.has(preset_name)) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+ plist_keys.insert(preset_name);
+ }
+ } break;
+ default:
+ continue;
+ }
+ }
+ }
+
plugins_changed.clear();
plugins = found_plugins;
@@ -378,11 +405,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
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::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::BOOL, "orientation/portrait"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_left"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_right"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_upside_down"), true));
-
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "icons/generate_missing"), false));
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
@@ -396,7 +418,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
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::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::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false));
@@ -453,6 +475,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
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) {
+ strnew += lines[i].replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n";
} else if (lines[i].find("$export_method") != -1) {
int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n";
@@ -473,6 +497,20 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
} else if (lines[i].find("$linker_flags") != -1) {
strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
+ } else if (lines[i].find("$targeted_device_family") != -1) {
+ String xcode_value;
+ switch ((int)p_preset->get("application/targeted_device_family")) {
+ case 0: // iPhone
+ xcode_value = "1";
+ break;
+ case 1: // iPad
+ xcode_value = "2";
+ break;
+ case 2: // iPhone & iPad
+ xcode_value = "1,2";
+ break;
+ }
+ strnew += lines[i].replace("$targeted_device_family", xcode_value) + "\n";
} else if (lines[i].find("$cpp_code") != -1) {
strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else if (lines[i].find("$docs_in_place") != -1) {
@@ -501,18 +539,39 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$required_device_capabilities", capabilities);
} else if (lines[i].find("$interface_orientations") != -1) {
String orientations;
+ const DisplayServer::ScreenOrientation screen_orientation =
+ DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation")));
- if ((bool)p_preset->get("orientation/portrait")) {
- orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
- }
- if ((bool)p_preset->get("orientation/landscape_left")) {
- orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
- }
- if ((bool)p_preset->get("orientation/landscape_right")) {
- orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
- }
- if ((bool)p_preset->get("orientation/portrait_upside_down")) {
- orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ switch (screen_orientation) {
+ case DisplayServer::SCREEN_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ break;
+ case DisplayServer::SCREEN_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
+ // Allow both landscape orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_PORTRAIT:
+ // Allow both portrait orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR:
+ // Allow all screen orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
}
strnew += lines[i].replace("$interface_orientations", orientations);
@@ -786,7 +845,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");
- image.instance();
+ image.instantiate();
Error err = image->load(custom_launch_image_2x);
if (err) {
@@ -800,7 +859,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
image.unref();
image_path = p_dest_dir.plus_file("splash@3x.png");
- image.instance();
+ image.instantiate();
err = image->load(custom_launch_image_3x);
if (err) {
@@ -817,7 +876,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image");
if (!splash_path.is_empty()) {
- splash.instance();
+ splash.instantiate();
const Error err = splash->load(splash_path);
if (err) {
splash.unref();
@@ -1433,13 +1492,28 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
while ((K = plugin.plist.next(K))) {
String key = *K;
- String value = plugin.plist[key];
+ PluginConfigIOS::PlistItem item = plugin.plist[key];
+
+ String value;
+
+ switch (item.type) {
+ case PluginConfigIOS::PlistItemType::STRING_INPUT: {
+ String preset_name = "plugins_plist/" + key;
+ String input_value = p_preset->get(preset_name);
+ value = "<string>" + input_value + "</string>";
+ } break;
+ default:
+ value = item.value;
+ break;
+ }
if (key.is_empty() || value.is_empty()) {
continue;
}
- plist_values[key] = value;
+ String plist_key = "<key>" + key + "</key>";
+
+ plist_values[plist_key] = value;
}
// CPP Code
@@ -1466,7 +1540,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
continue;
}
- p_config_data.plist_content += "<key>" + key + "</key><string>" + value + "</string>\n";
+ p_config_data.plist_content += key + value + "\n";
}
}
@@ -1965,7 +2039,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
EditorExportPlatformIOS::EditorExportPlatformIOS() {
Ref<Image> img = memnew(Image(_iphone_logo));
- logo.instance();
+ logo.instantiate();
logo->create_from_image(img);
plugins_changed.set();
@@ -1980,7 +2054,7 @@ EditorExportPlatformIOS::~EditorExportPlatformIOS() {
void register_iphone_exporter() {
Ref<EditorExportPlatformIOS> platform;
- platform.instance();
+ platform.instantiate();
EditorExport::get_singleton()->add_export_platform(platform);
}
diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m
index 3ce9bffc79..6c433c5c3c 100644
--- a/platform/iphone/godot_app_delegate.m
+++ b/platform/iphone/godot_app_delegate.m
@@ -56,7 +56,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil;
[services addObject:service];
}
-// UIApplicationDelegate documantation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
+// UIApplicationDelegate documentation can be found here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
// MARK: Window
diff --git a/platform/iphone/godot_iphone.mm b/platform/iphone/godot_iphone.mm
index 62bc2e6e52..6c3e1eabde 100644
--- a/platform/iphone/godot_iphone.mm
+++ b/platform/iphone/godot_iphone.mm
@@ -50,7 +50,7 @@ int add_path(int p_argc, char **p_args) {
p_args[p_argc++] = (char *)"--path";
p_args[p_argc++] = (char *)[str cStringUsingEncoding:NSUTF8StringEncoding];
- p_args[p_argc] = NULL;
+ p_args[p_argc] = nullptr;
return p_argc;
};
@@ -69,7 +69,7 @@ int add_cmdline(int p_argc, char **p_args) {
p_args[p_argc++] = (char *)[str cStringUsingEncoding:NSUTF8StringEncoding];
};
- p_args[p_argc] = NULL;
+ p_args[p_argc] = nullptr;
return p_argc;
};
diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm
index 887297848e..00a88d79c5 100644
--- a/platform/iphone/godot_view.mm
+++ b/platform/iphone/godot_view.mm
@@ -39,6 +39,7 @@
#import <CoreMotion/CoreMotion.h>
static const int max_touches = 8;
+static const float earth_gravity = 9.80665;
@interface GodotView () {
UITouch *godot_touches[max_touches];
@@ -290,14 +291,14 @@ static const int max_touches = 8;
- (void)initTouches {
for (int i = 0; i < max_touches; i++) {
- godot_touches[i] = NULL;
+ godot_touches[i] = nullptr;
}
}
- (int)getTouchIDForTouch:(UITouch *)p_touch {
int first = -1;
for (int i = 0; i < max_touches; i++) {
- if (first == -1 && godot_touches[i] == NULL) {
+ if (first == -1 && godot_touches[i] == nullptr) {
first = i;
continue;
}
@@ -317,11 +318,11 @@ static const int max_touches = 8;
- (int)removeTouch:(UITouch *)p_touch {
int remaining = 0;
for (int i = 0; i < max_touches; i++) {
- if (godot_touches[i] == NULL) {
+ if (godot_touches[i] == nullptr) {
continue;
}
if (godot_touches[i] == p_touch) {
- godot_touches[i] = NULL;
+ godot_touches[i] = nullptr;
} else {
++remaining;
}
@@ -331,7 +332,7 @@ static const int max_touches = 8;
- (void)clearTouches {
for (int i = 0; i < max_touches; i++) {
- godot_touches[i] = NULL;
+ godot_touches[i] = nullptr;
}
}
@@ -402,10 +403,19 @@ static const int max_touches = 8;
// https://developer.apple.com/reference/coremotion/cmmotionmanager?language=objc
// Apple splits our accelerometer date into a gravity and user movement
- // component. We add them back together
+ // component. We add them back together.
CMAcceleration gravity = self.motionManager.deviceMotion.gravity;
CMAcceleration acceleration = self.motionManager.deviceMotion.userAcceleration;
+ // To be consistent with Android we convert the unit of measurement from g (Earth's gravity)
+ // to m/s^2.
+ gravity.x *= earth_gravity;
+ gravity.y *= earth_gravity;
+ gravity.z *= earth_gravity;
+ acceleration.x *= earth_gravity;
+ acceleration.y *= earth_gravity;
+ acceleration.z *= earth_gravity;
+
///@TODO We don't seem to be getting data here, is my device broken or
/// is this code incorrect?
CMMagneticField magnetic = self.motionManager.deviceMotion.magneticField.field;
diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm
index cef03534c4..3430a9cba7 100644
--- a/platform/iphone/ios.mm
+++ b/platform/iphone/ios.mm
@@ -56,16 +56,16 @@ void iOS::alert(const char *p_alert, const char *p_title) {
String iOS::get_model() const {
// [[UIDevice currentDevice] model] only returns "iPad" or "iPhone".
size_t size;
- sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+ sysctlbyname("hw.machine", nullptr, &size, nullptr, 0);
char *model = (char *)malloc(size);
- if (model == NULL) {
+ if (model == nullptr) {
return "";
}
- sysctlbyname("hw.machine", model, &size, NULL, 0);
+ sysctlbyname("hw.machine", model, &size, nullptr, 0);
NSString *platform = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
free(model);
const char *str = [platform UTF8String];
- return String(str != NULL ? str : "");
+ return String(str != nullptr ? str : "");
}
String iOS::get_rate_url(int p_app_id) const {
diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm
index a0f0eee5d3..45842b38aa 100644
--- a/platform/iphone/joypad_iphone.mm
+++ b/platform/iphone/joypad_iphone.mm
@@ -287,7 +287,7 @@ void JoypadIPhone::start_processing() {
gamepad.dpad.right.isPressed);
};
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
jx.min = -1;
if (element == gamepad.leftThumbstick) {
jx.value = gamepad.leftThumbstick.xAxis.value;
diff --git a/platform/iphone/keyboard_input_view.mm b/platform/iphone/keyboard_input_view.mm
index 1408f78e90..0e5a98a3e6 100644
--- a/platform/iphone/keyboard_input_view.mm
+++ b/platform/iphone/keyboard_input_view.mm
@@ -88,13 +88,15 @@
self.text = existingString;
self.previousText = existingString;
+ NSInteger safeStartIndex = MAX(start, 0);
+
NSRange textRange;
// Either a simple cursor or a selection.
if (end > 0) {
- textRange = NSMakeRange(start, end - start);
+ textRange = NSMakeRange(safeStartIndex, end - start);
} else {
- textRange = NSMakeRange(start, 0);
+ textRange = NSMakeRange(safeStartIndex, 0);
}
self.selectedRange = textRange;
diff --git a/platform/iphone/native_video_view.h b/platform/iphone/native_video_view.h
deleted file mode 100644
index 2df5e27fa4..0000000000
--- a/platform/iphone/native_video_view.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* native_video_view.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#import <UIKit/UIKit.h>
-
-@interface GodotNativeVideoView : UIView
-
-- (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack;
-- (BOOL)isVideoPlaying;
-- (void)pauseVideo;
-- (void)unpauseVideo;
-- (void)stopVideo;
-
-@end
diff --git a/platform/iphone/native_video_view.m b/platform/iphone/native_video_view.m
deleted file mode 100644
index f126749600..0000000000
--- a/platform/iphone/native_video_view.m
+++ /dev/null
@@ -1,266 +0,0 @@
-/*************************************************************************/
-/* native_video_view.m */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#import "native_video_view.h"
-#import <AVFoundation/AVFoundation.h>
-
-@interface GodotNativeVideoView ()
-
-@property(strong, nonatomic) AVAsset *avAsset;
-@property(strong, nonatomic) AVPlayerItem *avPlayerItem;
-@property(strong, nonatomic) AVPlayer *avPlayer;
-@property(strong, nonatomic) AVPlayerLayer *avPlayerLayer;
-@property(assign, nonatomic) CMTime videoCurrentTime;
-@property(assign, nonatomic) BOOL isVideoCurrentlyPlaying;
-
-@end
-
-@implementation GodotNativeVideoView
-
-- (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
-
- if (self) {
- [self godot_commonInit];
- }
-
- return self;
-}
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
-
- if (self) {
- [self godot_commonInit];
- }
-
- return self;
-}
-
-- (void)godot_commonInit {
- self.isVideoCurrentlyPlaying = NO;
- self.videoCurrentTime = kCMTimeZero;
-
- [self observeVideoAudio];
-}
-
-- (void)layoutSubviews {
- [super layoutSubviews];
-
- self.avPlayerLayer.frame = self.bounds;
-}
-
-- (void)observeVideoAudio {
- printf("******** adding observer for sound routing changes\n");
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(audioRouteChangeListenerCallback:)
- name:AVAudioSessionRouteChangeNotification
- object:nil];
-}
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- if (object == self.avPlayerItem && [keyPath isEqualToString:@"status"]) {
- [self handleVideoOrPlayerStatus];
- }
-
- if (object == self.avPlayer && [keyPath isEqualToString:@"rate"]) {
- [self handleVideoPlayRate];
- }
-}
-
-// MARK: Video Audio
-
-- (void)audioRouteChangeListenerCallback:(NSNotification *)notification {
- printf("*********** route changed!\n");
- NSDictionary *interuptionDict = notification.userInfo;
-
- NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
-
- switch (routeChangeReason) {
- case AVAudioSessionRouteChangeReasonNewDeviceAvailable: {
- NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
- NSLog(@"Headphone/Line plugged in");
- } break;
- case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: {
- NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
- NSLog(@"Headphone/Line was pulled. Resuming video play....");
- if ([self isVideoPlaying]) {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
- [self.avPlayer play]; // NOTE: change this line according your current player implementation
- NSLog(@"resumed play");
- });
- }
- } break;
- case AVAudioSessionRouteChangeReasonCategoryChange: {
- // called at start - also when other audio wants to play
- NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
- } break;
- }
-}
-
-// MARK: Native Video Player
-
-- (void)handleVideoOrPlayerStatus {
- if (self.avPlayerItem.status == AVPlayerItemStatusFailed || self.avPlayer.status == AVPlayerStatusFailed) {
- [self stopVideo];
- }
-
- if (self.avPlayer.status == AVPlayerStatusReadyToPlay && self.avPlayerItem.status == AVPlayerItemStatusReadyToPlay && CMTimeCompare(self.videoCurrentTime, kCMTimeZero) == 0) {
- // NSLog(@"time: %@", self.video_current_time);
- [self.avPlayer seekToTime:self.videoCurrentTime];
- self.videoCurrentTime = kCMTimeZero;
- }
-}
-
-- (void)handleVideoPlayRate {
- NSLog(@"Player playback rate changed: %.5f", self.avPlayer.rate);
- if ([self isVideoPlaying] && self.avPlayer.rate == 0.0 && !self.avPlayer.error) {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
- [self.avPlayer play]; // NOTE: change this line according your current player implementation
- NSLog(@"resumed play");
- });
-
- NSLog(@" . . . PAUSED (or just started)");
- }
-}
-
-- (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack {
- self.avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:filePath]];
-
- self.avPlayerItem = [AVPlayerItem playerItemWithAsset:self.avAsset];
- [self.avPlayerItem addObserver:self forKeyPath:@"status" options:0 context:nil];
-
- self.avPlayer = [AVPlayer playerWithPlayerItem:self.avPlayerItem];
- self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
-
- [self.avPlayer addObserver:self forKeyPath:@"status" options:0 context:nil];
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(playerItemDidReachEnd:)
- name:AVPlayerItemDidPlayToEndTimeNotification
- object:[self.avPlayer currentItem]];
-
- [self.avPlayer addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0];
-
- [self.avPlayerLayer setFrame:self.bounds];
- [self.layer addSublayer:self.avPlayerLayer];
- [self.avPlayer play];
-
- AVMediaSelectionGroup *audioGroup = [self.avAsset mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicAudible];
-
- NSMutableArray *allAudioParams = [NSMutableArray array];
- for (id track in audioGroup.options) {
- NSString *language = [[track locale] localeIdentifier];
- NSLog(@"subtitle lang: %@", language);
-
- if ([language isEqualToString:audioTrack]) {
- AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters];
- [audioInputParams setVolume:videoVolume atTime:kCMTimeZero];
- [audioInputParams setTrackID:[track trackID]];
- [allAudioParams addObject:audioInputParams];
-
- AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
- [audioMix setInputParameters:allAudioParams];
-
- [self.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup:audioGroup];
- [self.avPlayer.currentItem setAudioMix:audioMix];
-
- break;
- }
- }
-
- AVMediaSelectionGroup *subtitlesGroup = [self.avAsset mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
- NSArray *useableTracks = [AVMediaSelectionGroup mediaSelectionOptionsFromArray:subtitlesGroup.options withoutMediaCharacteristics:[NSArray arrayWithObject:AVMediaCharacteristicContainsOnlyForcedSubtitles]];
-
- for (id track in useableTracks) {
- NSString *language = [[track locale] localeIdentifier];
- NSLog(@"subtitle lang: %@", language);
-
- if ([language isEqualToString:subtitleTrack]) {
- [self.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup:subtitlesGroup];
- break;
- }
- }
-
- self.isVideoCurrentlyPlaying = YES;
-
- return true;
-}
-
-- (BOOL)isVideoPlaying {
- if (self.avPlayer.error) {
- printf("Error during playback\n");
- }
- return (self.avPlayer.rate > 0 && !self.avPlayer.error);
-}
-
-- (void)pauseVideo {
- self.videoCurrentTime = self.avPlayer.currentTime;
- [self.avPlayer pause];
- self.isVideoCurrentlyPlaying = NO;
-}
-
-- (void)unpauseVideo {
- [self.avPlayer play];
- self.isVideoCurrentlyPlaying = YES;
-}
-
-- (void)playerItemDidReachEnd:(NSNotification *)notification {
- [self stopVideo];
-}
-
-- (void)finishPlayingVideo {
- [self.avPlayer pause];
- [self.avPlayerLayer removeFromSuperlayer];
- self.avPlayerLayer = nil;
-
- if (self.avPlayerItem) {
- [self.avPlayerItem removeObserver:self forKeyPath:@"status"];
- self.avPlayerItem = nil;
- }
-
- if (self.avPlayer) {
- [self.avPlayer removeObserver:self forKeyPath:@"status"];
- self.avPlayer = nil;
- }
-
- self.avAsset = nil;
-
- self.isVideoCurrentlyPlaying = NO;
-}
-
-- (void)stopVideo {
- [self finishPlayingVideo];
-
- [self removeFromSuperview];
-}
-
-@end
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 51c4da2960..1f08901082 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -33,9 +33,9 @@
#include "os_iphone.h"
#import "app_delegate.h"
#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
#include "display_server_iphone.h"
#include "drivers/unix/syslog_logger.h"
#import "godot_view.h"
@@ -301,10 +301,6 @@ void OSIPhone::on_focus_out() {
[AppDelegate.viewController.godotView stopRendering];
- if (DisplayServerIPhone::get_singleton() && DisplayServerIPhone::get_singleton()->native_video_is_playing()) {
- DisplayServerIPhone::get_singleton()->native_video_pause();
- }
-
audio_driver.stop();
}
}
@@ -319,10 +315,6 @@ void OSIPhone::on_focus_in() {
[AppDelegate.viewController.godotView startRendering];
- if (DisplayServerIPhone::get_singleton() && DisplayServerIPhone::get_singleton()->native_video_is_playing()) {
- DisplayServerIPhone::get_singleton()->native_video_unpause();
- }
-
audio_driver.start();
}
}
diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h
index f4e30c8349..f9c5d7e51f 100644
--- a/platform/iphone/plugin/godot_plugin_config.h
+++ b/platform/iphone/plugin/godot_plugin_config.h
@@ -70,6 +70,20 @@ struct PluginConfigIOS {
inline static const char *PLIST_SECTION = "plist";
+ enum PlistItemType {
+ UNKNOWN,
+ STRING,
+ INTEGER,
+ BOOLEAN,
+ RAW,
+ STRING_INPUT,
+ };
+
+ struct PlistItem {
+ PlistItemType type;
+ String value;
+ };
+
// Set to true when the config file is properly loaded.
bool valid_config = false;
bool supports_targets = false;
@@ -93,8 +107,10 @@ struct PluginConfigIOS {
Vector<String> linker_flags;
// Optional plist section
- // Supports only string types for now
- HashMap<String, String> plist;
+ // String value is default value.
+ // Currently supports `string`, `boolean`, `integer`, `raw`, `string_input` types
+ // <name>:<type> = <value>
+ HashMap<String, PlistItem> plist;
};
static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) {
@@ -104,7 +120,7 @@ static inline String resolve_local_dependency_path(String plugin_config_dir, Str
return absolute_path;
}
- if (dependency_path.is_abs_path()) {
+ if (dependency_path.is_absolute_path()) {
return dependency_path;
}
@@ -121,7 +137,7 @@ static inline String resolve_system_dependency_path(String dependency_path) {
return absolute_path;
}
- if (dependency_path.is_abs_path()) {
+ if (dependency_path.is_absolute_path()) {
return dependency_path;
}
@@ -218,8 +234,9 @@ static inline uint64_t get_plugin_modification_time(const PluginConfigIOS &plugi
} else {
String file_path = plugin_config.binary.get_base_dir();
String file_name = plugin_config.binary.get_basename().get_file();
- String release_file_name = file_path.plus_file(file_name + ".release.a");
- String debug_file_name = file_path.plus_file(file_name + ".debug.a");
+ String plugin_extension = plugin_config.binary.get_extension();
+ String release_file_name = file_path.plus_file(file_name + ".release." + plugin_extension);
+ String debug_file_name = file_path.plus_file(file_name + ".debug." + plugin_extension);
last_updated = MAX(last_updated, FileAccess::get_modified_time(release_file_name));
last_updated = MAX(last_updated, FileAccess::get_modified_time(debug_file_name));
@@ -235,6 +252,8 @@ static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, co
return plugin_config;
}
+ config_file->clear();
+
Error err = config_file->load(path);
if (err != OK) {
@@ -272,13 +291,68 @@ static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, co
config_file->get_section_keys(PluginConfigIOS::PLIST_SECTION, &keys);
for (int i = 0; i < keys.size(); i++) {
- String value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String());
+ Vector<String> key_components = keys[i].split(":");
+
+ String key_value = "";
+ PluginConfigIOS::PlistItemType key_type = PluginConfigIOS::PlistItemType::UNKNOWN;
+
+ if (key_components.size() == 1) {
+ key_value = key_components[0];
+ key_type = PluginConfigIOS::PlistItemType::STRING;
+ } else if (key_components.size() == 2) {
+ key_value = key_components[0];
+
+ if (key_components[1].to_lower() == "string") {
+ key_type = PluginConfigIOS::PlistItemType::STRING;
+ } else if (key_components[1].to_lower() == "integer") {
+ key_type = PluginConfigIOS::PlistItemType::INTEGER;
+ } else if (key_components[1].to_lower() == "boolean") {
+ key_type = PluginConfigIOS::PlistItemType::BOOLEAN;
+ } else if (key_components[1].to_lower() == "raw") {
+ key_type = PluginConfigIOS::PlistItemType::RAW;
+ } else if (key_components[1].to_lower() == "string_input") {
+ key_type = PluginConfigIOS::PlistItemType::STRING_INPUT;
+ }
+ }
- if (value.is_empty()) {
+ if (key_value.is_empty() || key_type == PluginConfigIOS::PlistItemType::UNKNOWN) {
continue;
}
- plugin_config.plist[keys[i]] = value;
+ String value;
+
+ switch (key_type) {
+ case PluginConfigIOS::PlistItemType::STRING: {
+ String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String());
+ value = "<string>" + raw_value + "</string>";
+ } break;
+ case PluginConfigIOS::PlistItemType::INTEGER: {
+ int raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], 0);
+ Dictionary value_dictionary;
+ String value_format = "<integer>$value</integer>";
+ value_dictionary["value"] = raw_value;
+ value = value_format.format(value_dictionary, "$_");
+ } break;
+ case PluginConfigIOS::PlistItemType::BOOLEAN:
+ if (config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], false)) {
+ value = "<true/>";
+ } else {
+ value = "<false/>";
+ }
+ break;
+ case PluginConfigIOS::PlistItemType::RAW: {
+ String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String());
+ value = raw_value;
+ } break;
+ case PluginConfigIOS::PlistItemType::STRING_INPUT: {
+ String raw_value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String());
+ value = raw_value;
+ } break;
+ default:
+ continue;
+ }
+
+ plugin_config.plist[key_value] = PluginConfigIOS::PlistItem{ key_type, value };
}
}
diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h
index 52fb6fbbf2..400145b8b7 100644
--- a/platform/iphone/view_controller.h
+++ b/platform/iphone/view_controller.h
@@ -37,11 +37,6 @@
@interface ViewController : UIViewController
@property(nonatomic, readonly, strong) GodotView *godotView;
-@property(nonatomic, readonly, strong) GodotNativeVideoView *videoView;
@property(nonatomic, readonly, strong) GodotKeyboardInputView *keyboardView;
-// MARK: Native Video Player
-
-- (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack;
-
@end
diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm
index 6cef244567..2723ac4706 100644
--- a/platform/iphone/view_controller.mm
+++ b/platform/iphone/view_controller.mm
@@ -34,7 +34,6 @@
#import "godot_view.h"
#import "godot_view_renderer.h"
#import "keyboard_input_view.h"
-#import "native_video_view.h"
#include "os_iphone.h"
#import <AVFoundation/AVFoundation.h>
@@ -43,7 +42,6 @@
@interface ViewController () <GodotViewDelegate>
@property(strong, nonatomic) GodotViewRenderer *renderer;
-@property(strong, nonatomic) GodotNativeVideoView *videoView;
@property(strong, nonatomic) GodotKeyboardInputView *keyboardView;
@property(strong, nonatomic) UIView *godotLoadingOverlay;
@@ -151,10 +149,6 @@
}
- (void)dealloc {
- [self.videoView stopVideo];
-
- self.videoView = nil;
-
self.keyboardView = nil;
self.renderer = nil;
@@ -243,22 +237,4 @@
}
}
-// MARK: Native Video Player
-
-- (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack {
- // If we are showing some video already, reuse existing view for new video.
- if (self.videoView) {
- return [self.videoView playVideoAtPath:filePath volume:videoVolume audio:audioTrack subtitle:subtitleTrack];
- } else {
- // Create autoresizing view for video playback.
- GodotNativeVideoView *videoView = [[GodotNativeVideoView alloc] initWithFrame:self.view.bounds];
- videoView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- [self.view addSubview:videoView];
-
- self.videoView = videoView;
-
- return [self.videoView playVideoAtPath:filePath volume:videoVolume audio:audioTrack subtitle:subtitleTrack];
- }
-}
-
@end
diff --git a/platform/iphone/vulkan_context_iphone.h b/platform/iphone/vulkan_context_iphone.h
index 88764e270e..ec6aaf46e8 100644
--- a/platform/iphone/vulkan_context_iphone.h
+++ b/platform/iphone/vulkan_context_iphone.h
@@ -39,7 +39,7 @@ class VulkanContextIPhone : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- Error window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height);
+ Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height);
VulkanContextIPhone();
~VulkanContextIPhone();
diff --git a/platform/iphone/vulkan_context_iphone.mm b/platform/iphone/vulkan_context_iphone.mm
index b980ae99f0..17f2b167b3 100644
--- a/platform/iphone/vulkan_context_iphone.mm
+++ b/platform/iphone/vulkan_context_iphone.mm
@@ -35,19 +35,19 @@ const char *VulkanContextIPhone::_get_platform_surface_extension() const {
return VK_MVK_IOS_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, CALayer *p_metal_layer, int p_width, int p_height) {
+Error VulkanContextIPhone::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, CALayer *p_metal_layer, int p_width, int p_height) {
VkIOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
- createInfo.pNext = NULL;
+ createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.pView = (__bridge const void *)p_metal_layer;
VkSurfaceKHR surface;
VkResult err =
- vkCreateIOSSurfaceMVK(_get_instance(), &createInfo, NULL, &surface);
+ vkCreateIOSSurfaceMVK(_get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextIPhone::VulkanContextIPhone() {}