From d4c541c25a6533ebb966ddaa581523fe9326433a Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Tue, 7 Jul 2020 00:01:35 +0300 Subject: iOS Export: add option to use storyboard for launch screen --- platform/iphone/export/export.cpp | 123 +++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) (limited to 'platform') diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 4393a4ae9f..2033209ca9 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -92,7 +92,8 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String _get_linker_flags(); String _get_cpp_code(); void _fix_config_file(const Ref &p_preset, Vector &pfile, const IOSConfigData &p_config, bool p_debug); - Error _export_loading_screens(const Ref &p_preset, const String &p_dest_dir); + Error _export_loading_screen_images(const Ref &p_preset, const String &p_dest_dir); + Error _export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir); Error _export_icons(const Ref &p_preset, const String &p_iconset_dir); Vector _get_supported_architectures(); @@ -255,6 +256,8 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) 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::BOOL, "storyboard/use_launch_screen_storyboard"), false)); + 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) { @@ -390,6 +393,48 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ } else if (lines[i].find("$photolibrary_usage_description") != -1) { String description = p_preset->get("privacy/photolibrary_usage_description"); strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; + } else if (lines[i].find("$plist_launch_screen_name") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "UILaunchStoryboardName\nLaunch Screen" : ""; + strnew += lines[i].replace("$plist_launch_screen_name", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_file_reference") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"\"; };" : ""; + strnew += lines[i].replace("$pbx_launch_screen_file_reference", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_copy_files") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */," : ""; + strnew += lines[i].replace("$pbx_launch_screen_copy_files", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_build_phase") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */," : ""; + strnew += lines[i].replace("$pbx_launch_screen_build_phase", value) + "\n"; + } else if (lines[i].find("$pbx_launch_screen_build_reference") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };" : ""; + strnew += lines[i].replace("$pbx_launch_screen_build_reference", value) + "\n"; + } else if (lines[i].find("$pbx_launch_image_usage_setting") != -1) { + bool is_on = p_preset->get("storyboard/use_launch_screen_storyboard"); + String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; + strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; + } else if (lines[i].find("$launch_screen_image_mode") != -1) { + String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); + // If custom logo is not specified, Godot does not scale default one, so we should do the same. + String value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n"; + } else if (lines[i].find("$launch_screen_background_color") != -1) { + Color color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); + const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; + + Dictionary value_dictionary; + value_dictionary["red"] = color.r; + value_dictionary["green"] = color.g; + value_dictionary["blue"] = color.b; + value_dictionary["alpha"] = color.a; + String value = value_format.format(value_dictionary, "$_"); + + strnew += lines[i].replace("$launch_screen_background_color", value) + "\n"; } else { strnew += lines[i] + "\n"; } @@ -591,7 +636,42 @@ Error EditorExportPlatformIOS::_export_icons(const Ref &p_pr return OK; } -Error EditorExportPlatformIOS::_export_loading_screens(const Ref &p_preset, const String &p_dest_dir) { +Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir) { + Ref splash; + + const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + + if (!splash_path.empty()) { + splash.instance(); + const Error err = splash->load(splash_path); + if (err) { + splash.unref(); + } + } + + if (splash.is_null()) { + splash = Ref(memnew(Image(boot_splash_png))); + } + + // Using same image for both @2x and @3x + // because Godot's own boot logo uses single image for all resolutions. + // Also not using @1x image, because devices using this image variant + // are not supported by iOS 9, which is minimal target. + const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); + const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + + if (splash->save_png(splash_png_path_2x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + if (splash->save_png(splash_png_path_3x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + return OK; +} + +Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref &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 + "'."); @@ -1172,6 +1252,7 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata"); files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme"); files_to_parse.insert("godot_ios/godot_ios.entitlements"); + files_to_parse.insert("godot_ios/Launch Screen.storyboard"); IOSConfigData config_data = { pkg_name, @@ -1347,7 +1428,43 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p return err; } - err = _export_loading_screens(p_preset, dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/"); + 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/"; + + DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + + if (!launch_screen_da) { + return ERR_CANT_CREATE; + } + + if (use_storyboard) { + print_line("Using Launch Storyboard"); + + if (launch_screen_da->change_dir(launch_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(launch_image_path); + } + + err = _export_loading_screen_file(p_preset, splash_image_path); + } else { + print_line("Using Launch Images"); + + const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard"; + + launch_screen_da->remove(launch_screen_path); + + if (launch_screen_da->change_dir(splash_image_path) == OK) { + launch_screen_da->erase_contents_recursive(); + launch_screen_da->remove(splash_image_path); + } + + err = _export_loading_screen_images(p_preset, launch_image_path); + } + + memdelete(launch_screen_da); + if (err) { return err; } -- cgit v1.2.3 From 96e204bb0d9f464b634b9064d330135ee43d51d9 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Tue, 7 Jul 2020 01:39:57 +0300 Subject: iOS Export: Storyboard custom values --- platform/iphone/export/export.cpp | 108 +++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 26 deletions(-) (limited to 'platform') diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 2033209ca9..900c60a7ac 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -257,6 +257,11 @@ void EditorExportPlatformIOS::get_export_options(List *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::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@3x", PROPERTY_HINT_FILE, "*.png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_custom_bg_color"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "storyboard/custom_bg_color"), Color())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "launch_screens/generate_missing"), false)); @@ -277,6 +282,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ "ad-hoc", "enterprise" }; + static const String storyboard_image_scale_mode[] = { + "center", + "scaleAspectFit", + "scaleAspectFill", + "scaleToFill" + }; String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -418,13 +429,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ String value = is_on ? "" : "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;"; strnew += lines[i].replace("$pbx_launch_image_usage_setting", value) + "\n"; } else if (lines[i].find("$launch_screen_image_mode") != -1) { - String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - // If custom logo is not specified, Godot does not scale default one, so we should do the same. - String value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + int image_scale_mode = p_preset->get("storyboard/image_scale_mode"); + String value; + + switch (image_scale_mode) { + case 0: { + String logo_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + bool is_on = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); + // If custom logo is not specified, Godot does not scale default one, so we should do the same. + value = (is_on && logo_path.length() > 0) ? "scaleAspectFit" : "center"; + } break; + default: { + value = storyboard_image_scale_mode[image_scale_mode - 1]; + } + } + strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n"; } else if (lines[i].find("$launch_screen_background_color") != -1) { - Color color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); + bool use_custom = p_preset->get("storyboard/use_custom_bg_color"); + Color color = use_custom ? p_preset->get("storyboard/custom_bg_color") : ProjectSettings::get_singleton()->get("application/boot_splash/bg_color"); const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; Dictionary value_dictionary; @@ -637,35 +660,68 @@ Error EditorExportPlatformIOS::_export_icons(const Ref &p_pr } Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref &p_preset, const String &p_dest_dir) { - Ref splash; + const String custom_launch_image_2x = p_preset->get("storyboard/custom_image@2x"); + const String custom_launch_image_3x = p_preset->get("storyboard/custom_image@3x"); - const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) { + Ref image; + String image_path = p_dest_dir.plus_file("splash@2x.png"); + image.instance(); + Error err = image->load(custom_launch_image_2x); - if (!splash_path.empty()) { - splash.instance(); - const Error err = splash->load(splash_path); if (err) { - splash.unref(); + image.unref(); + return err; } - } - if (splash.is_null()) { - splash = Ref(memnew(Image(boot_splash_png))); - } + if (image->save_png(image_path) != OK) { + return ERR_FILE_CANT_WRITE; + } - // Using same image for both @2x and @3x - // because Godot's own boot logo uses single image for all resolutions. - // Also not using @1x image, because devices using this image variant - // are not supported by iOS 9, which is minimal target. - const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); - const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + image.unref(); + image_path = p_dest_dir.plus_file("splash@3x.png"); + image.instance(); + err = image->load(custom_launch_image_3x); - if (splash->save_png(splash_png_path_2x) != OK) { - return ERR_FILE_CANT_WRITE; - } + if (err) { + image.unref(); + return err; + } + + if (image->save_png(image_path) != OK) { + return ERR_FILE_CANT_WRITE; + } + } else { + Ref splash; + + const String splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); + + if (!splash_path.empty()) { + splash.instance(); + const Error err = splash->load(splash_path); + if (err) { + splash.unref(); + } + } - if (splash->save_png(splash_png_path_3x) != OK) { - return ERR_FILE_CANT_WRITE; + if (splash.is_null()) { + splash = Ref(memnew(Image(boot_splash_png))); + } + + // Using same image for both @2x and @3x + // because Godot's own boot logo uses single image for all resolutions. + // Also not using @1x image, because devices using this image variant + // are not supported by iOS 9, which is minimal target. + const String splash_png_path_2x = p_dest_dir.plus_file("splash@2x.png"); + const String splash_png_path_3x = p_dest_dir.plus_file("splash@3x.png"); + + if (splash->save_png(splash_png_path_2x) != OK) { + return ERR_FILE_CANT_WRITE; + } + + if (splash->save_png(splash_png_path_3x) != OK) { + return ERR_FILE_CANT_WRITE; + } } return OK; -- cgit v1.2.3