Merge pull request #107789 from rsanchezsaez/apple/apple-embedded-export-template

Replace iOS/visionOS Xcode templates by new Apple embedded template
This commit is contained in:
Thaddeus Crews 2025-09-19 13:07:09 -05:00
commit 14bdf39806
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
55 changed files with 609 additions and 1197 deletions

View file

@ -369,449 +369,392 @@ void EditorExportPlatformAppleEmbedded::get_export_options(List<ExportOption> *r
}
}
void EditorExportPlatformAppleEmbedded::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const AppleEmbeddedConfigData &p_config, bool p_debug) {
String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "Apple Development" : p_preset->get("application/code_sign_identity_debug");
String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "Apple Distribution" : p_preset->get("application/code_sign_identity_release");
bool dbg_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG).operator String().is_empty() || (dbg_sign_id != "Apple Development" && dbg_sign_id != "Apple Distribution");
bool rel_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_APPLE_PLATFORM_PROFILE_UUID_RELEASE).operator String().is_empty() || (rel_sign_id != "Apple Development" && rel_sign_id != "Apple Distribution");
void EditorExportPlatformAppleEmbedded::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_file, const AppleEmbeddedConfigData &p_config, bool p_debug) {
CodeSigningDetails code_signing(p_preset);
String provisioning_profile_specifier_dbg = p_preset->get_or_env("application/provisioning_profile_specifier_debug", ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_DEBUG).operator String();
bool valid_dbg_specifier = !provisioning_profile_specifier_dbg.is_empty();
dbg_manual |= valid_dbg_specifier;
String provisioning_profile_specifier_rel = p_preset->get_or_env("application/provisioning_profile_specifier_release", ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_RELEASE).operator String();
bool valid_rel_specifier = !provisioning_profile_specifier_rel.is_empty();
rel_manual |= valid_rel_specifier;
String str = String::utf8((const char *)pfile.ptr(), pfile.size());
String str = String::utf8((const char *)p_file.ptr(), p_file.size());
String strnew;
Vector<String> lines = str.split("\n");
for (int i = 0; i < lines.size(); i++) {
if (lines[i].contains("$binary")) {
strnew += lines[i].replace("$binary", p_config.binary_name) + "\n";
} else if (lines[i].contains("$modules_buildfile")) {
strnew += lines[i].replace("$modules_buildfile", p_config.modules_buildfile) + "\n";
} else if (lines[i].contains("$modules_fileref")) {
strnew += lines[i].replace("$modules_fileref", p_config.modules_fileref) + "\n";
} else if (lines[i].contains("$modules_buildphase")) {
strnew += lines[i].replace("$modules_buildphase", p_config.modules_buildphase) + "\n";
} else if (lines[i].contains("$modules_buildgrp")) {
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
} else if (lines[i].contains("$name")) {
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
} else if (lines[i].contains("$bundle_identifier")) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].contains("$short_version")) {
strnew += lines[i].replace("$short_version", p_preset->get_version("application/short_version")) + "\n";
} else if (lines[i].contains("$version")) {
strnew += lines[i].replace("$version", p_preset->get_version("application/version")) + "\n";
} else if (lines[i].contains("$min_version")) {
strnew += lines[i].replace("$min_version",
p_preset->get("application/min_" + get_platform_name() + "_version")) +
"\n";
} else if (lines[i].contains("$signature")) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
} else if (lines[i].contains("$team_id")) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (lines[i].contains("$default_build_config")) {
strnew += lines[i].replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n";
} else if (lines[i].contains("$export_method")) {
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";
} else if (lines[i].contains("$provisioning_profile_specifier_debug")) {
strnew += lines[i].replace("$provisioning_profile_specifier_debug", provisioning_profile_specifier_dbg) + "\n";
} else if (lines[i].contains("$provisioning_profile_specifier_release")) {
strnew += lines[i].replace("$provisioning_profile_specifier_release", provisioning_profile_specifier_rel) + "\n";
} else if (lines[i].contains("$provisioning_profile_specifier")) {
String specifier = p_debug ? provisioning_profile_specifier_dbg : provisioning_profile_specifier_rel;
strnew += lines[i].replace("$provisioning_profile_specifier", specifier) + "\n";
} else if (lines[i].contains("$provisioning_profile_uuid_release")) {
strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_APPLE_PLATFORM_PROFILE_UUID_RELEASE)) + "\n";
} else if (lines[i].contains("$provisioning_profile_uuid_debug")) {
strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG)) + "\n";
} else if (lines[i].contains("$code_sign_style_debug")) {
if (dbg_manual) {
strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n";
} else {
strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n";
}
} else if (lines[i].contains("$code_sign_style_release")) {
if (rel_manual) {
strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n";
} else {
strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n";
}
} else if (lines[i].contains("$provisioning_profile_uuid")) {
String uuid = p_debug ? p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG) : p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_APPLE_PLATFORM_PROFILE_UUID_RELEASE);
if (uuid.is_empty()) {
Variant variant = p_debug ? provisioning_profile_specifier_dbg : provisioning_profile_specifier_rel;
bool valid = p_debug ? valid_dbg_specifier : valid_rel_specifier;
uuid = valid ? variant : "";
}
strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (lines[i].contains("$code_sign_identity_debug")) {
strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n";
} else if (lines[i].contains("$code_sign_identity_release")) {
strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n";
} else if (lines[i].contains("$additional_plist_content")) {
strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n";
} else if (lines[i].contains("$godot_archs")) {
strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n";
} else if (lines[i].contains("$linker_flags")) {
strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n";
} else if (lines[i].contains("$targeted_device_family")) {
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].contains("$cpp_code")) {
strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n";
} else if (lines[i].contains("$docs_in_place")) {
strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n";
} else if (lines[i].contains("$docs_sharing")) {
strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n";
} else if (lines[i].contains("$entitlements_full")) {
String entitlements;
if ((String)p_preset->get("entitlements/push_notifications") != "Disabled") {
entitlements += "<key>aps-environment</key>\n<string>" + p_preset->get("entitlements/push_notifications").operator String().to_lower() + "</string>" + "\n";
}
if ((bool)p_preset->get("entitlements/game_center")) {
entitlements += "<key>com.apple.developer.game-center</key>\n<true/>\n";
}
if ((bool)p_preset->get("entitlements/increased_memory_limit")) {
entitlements += "<key>com.apple.developer.kernel.increased-memory-limit</key>\n<true/>\n";
}
entitlements += p_preset->get("entitlements/additional").operator String() + "\n";
for (const String &line : lines) {
strnew += _process_config_file_line(p_preset, line, p_config, p_debug, code_signing);
}
strnew += lines[i].replace("$entitlements_full", entitlements);
} else if (lines[i].contains("$required_device_capabilities")) {
String capabilities;
// Write (size - 1) to avoid outputting the null terminator.
CharString cs = strnew.utf8();
p_file.resize(cs.size() - 1);
uint8_t *p_file_ptrw = p_file.ptrw();
for (int i = 0; i < cs.size() - 1; i++) {
p_file_ptrw[i] = cs[i];
}
}
// I've removed armv7 as we can run on 64bit only devices
// Note that capabilities listed here are requirements for the app to be installed.
// They don't enable anything.
Vector<String> capabilities_list = p_config.capabilities;
String EditorExportPlatformAppleEmbedded::_process_config_file_line(const Ref<EditorExportPreset> &p_preset, const String &p_line, const AppleEmbeddedConfigData &p_config, bool p_debug, const CodeSigningDetails &p_code_signing) {
String strnew;
if (p_line.contains("$binary")) {
strnew += p_line.replace("$binary", p_config.binary_name) + "\n";
} else if (p_line.contains("$modules_buildfile")) {
strnew += p_line.replace("$modules_buildfile", p_config.modules_buildfile) + "\n";
} else if (p_line.contains("$modules_fileref")) {
strnew += p_line.replace("$modules_fileref", p_config.modules_fileref) + "\n";
} else if (p_line.contains("$modules_buildphase")) {
strnew += p_line.replace("$modules_buildphase", p_config.modules_buildphase) + "\n";
} else if (p_line.contains("$modules_buildgrp")) {
strnew += p_line.replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
} else if (p_line.contains("$name")) {
strnew += p_line.replace("$name", p_config.pkg_name) + "\n";
} else if (p_line.contains("$bundle_identifier")) {
strnew += p_line.replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (p_line.contains("$short_version")) {
strnew += p_line.replace("$short_version", p_preset->get_version("application/short_version")) + "\n";
} else if (p_line.contains("$version")) {
strnew += p_line.replace("$version", p_preset->get_version("application/version")) + "\n";
} else if (p_line.contains("$signature")) {
strnew += p_line.replace("$signature", p_preset->get("application/signature")) + "\n";
} else if (p_line.contains("$team_id")) {
strnew += p_line.replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (p_line.contains("$default_build_config")) {
strnew += p_line.replace("$default_build_config", p_debug ? "Debug" : "Release") + "\n";
} else if (p_line.contains("$export_method")) {
int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
strnew += p_line.replace("$export_method", export_method_string[export_method]) + "\n";
} else if (p_line.contains("$provisioning_profile_specifier_debug")) {
strnew += p_line.replace("$provisioning_profile_specifier_debug", p_code_signing.debug_provisioning_profile_specifier) + "\n";
} else if (p_line.contains("$provisioning_profile_specifier_release")) {
strnew += p_line.replace("$provisioning_profile_specifier_release", p_code_signing.release_provisioning_profile_specifier) + "\n";
} else if (p_line.contains("$provisioning_profile_specifier")) {
String specifier = p_debug ? p_code_signing.debug_provisioning_profile_specifier : p_code_signing.release_provisioning_profile_specifier;
strnew += p_line.replace("$provisioning_profile_specifier", specifier) + "\n";
} else if (p_line.contains("$provisioning_profile_uuid_release")) {
strnew += p_line.replace("$provisioning_profile_uuid_release", p_code_signing.release_provisioning_profile_uuid) + "\n";
} else if (p_line.contains("$provisioning_profile_uuid_debug")) {
strnew += p_line.replace("$provisioning_profile_uuid_debug", p_code_signing.debug_provisioning_profile_uuid) + "\n";
} else if (p_line.contains("$code_sign_style_debug")) {
if (p_code_signing.debug_manual_signing) {
strnew += p_line.replace("$code_sign_style_debug", "Manual") + "\n";
} else {
strnew += p_line.replace("$code_sign_style_debug", "Automatic") + "\n";
}
} else if (p_line.contains("$code_sign_style_release")) {
if (p_code_signing.release_manual_signing) {
strnew += p_line.replace("$code_sign_style_release", "Manual") + "\n";
} else {
strnew += p_line.replace("$code_sign_style_release", "Automatic") + "\n";
}
} else if (p_line.contains("$provisioning_profile_uuid")) {
String uuid = p_debug ? p_code_signing.debug_provisioning_profile_uuid : p_code_signing.release_provisioning_profile_uuid;
if (uuid.is_empty()) {
uuid = p_debug ? p_code_signing.debug_provisioning_profile_specifier : p_code_signing.release_provisioning_profile_specifier;
}
strnew += p_line.replace("$provisioning_profile_uuid", uuid) + "\n";
} else if (p_line.contains("$code_sign_identity_debug")) {
strnew += p_line.replace("$code_sign_identity_debug", p_code_signing.debug_signing_identity) + "\n";
} else if (p_line.contains("$code_sign_identity_release")) {
strnew += p_line.replace("$code_sign_identity_release", p_code_signing.release_signing_identity) + "\n";
} else if (p_line.contains("$additional_plist_content")) {
strnew += p_line.replace("$additional_plist_content", p_config.plist_content) + "\n";
} else if (p_line.contains("$godot_archs")) {
strnew += p_line.replace("$godot_archs", p_config.architectures) + "\n";
} else if (p_line.contains("$linker_flags")) {
strnew += p_line.replace("$linker_flags", p_config.linker_flags) + "\n";
} else if (p_line.contains("$targeted_device_family")) {
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 += p_line.replace("$targeted_device_family", xcode_value) + "\n";
} else if (p_line.contains("$cpp_code")) {
strnew += p_line.replace("$cpp_code", p_config.cpp_code) + "\n";
} else if (p_line.contains("$docs_in_place")) {
strnew += p_line.replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n";
} else if (p_line.contains("$docs_sharing")) {
strnew += p_line.replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n";
} else if (p_line.contains("$entitlements_full")) {
String entitlements;
if ((String)p_preset->get("entitlements/push_notifications") != "Disabled") {
entitlements += "<key>aps-environment</key>\n<string>" + p_preset->get("entitlements/push_notifications").operator String().to_lower() + "</string>" + "\n";
}
if ((bool)p_preset->get("entitlements/game_center")) {
entitlements += "<key>com.apple.developer.game-center</key>\n<true/>\n";
}
if ((bool)p_preset->get("entitlements/increased_memory_limit")) {
entitlements += "<key>com.apple.developer.kernel.increased-memory-limit</key>\n<true/>\n";
}
entitlements += p_preset->get("entitlements/additional").operator String() + "\n";
if ((bool)p_preset->get("capabilities/access_wifi") && !capabilities_list.has("wifi")) {
capabilities_list.push_back("wifi");
}
if ((bool)p_preset->get("capabilities/performance_gaming_tier") && !capabilities_list.has("iphone-performance-gaming-tier")) {
capabilities_list.push_back("iphone-performance-gaming-tier");
}
if ((bool)p_preset->get("capabilities/performance_a12") && !capabilities_list.has("iphone-ipad-minimum-performance-a12")) {
capabilities_list.push_back("iphone-ipad-minimum-performance-a12");
}
for (int idx = 0; idx < capabilities_list.size(); idx++) {
capabilities += "<string>" + capabilities_list[idx] + "</string>\n";
}
for (const String &cap : p_preset->get("capabilities/additional").operator PackedStringArray()) {
capabilities += "<string>" + cap + "</string>\n";
}
strnew += p_line.replace("$entitlements_full", entitlements);
} else if (p_line.contains("$required_device_capabilities")) {
String capabilities;
strnew += lines[i].replace("$required_device_capabilities", capabilities);
} else if (lines[i].contains("$interface_orientations")) {
String orientations;
const DisplayServer::ScreenOrientation screen_orientation =
DisplayServer::ScreenOrientation(int(get_project_setting(p_preset, "display/window/handheld/orientation")));
// I've removed armv7 as we can run on 64bit only devices
// Note that capabilities listed here are requirements for the app to be installed.
// They don't enable anything.
Vector<String> capabilities_list = p_config.capabilities;
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;
}
if ((bool)p_preset->get("capabilities/access_wifi") && !capabilities_list.has("wifi")) {
capabilities_list.push_back("wifi");
}
if ((bool)p_preset->get("capabilities/performance_gaming_tier") && !capabilities_list.has("iphone-performance-gaming-tier")) {
capabilities_list.push_back("iphone-performance-gaming-tier");
}
if ((bool)p_preset->get("capabilities/performance_a12") && !capabilities_list.has("iphone-ipad-minimum-performance-a12")) {
capabilities_list.push_back("iphone-ipad-minimum-performance-a12");
}
for (const String &capability : capabilities_list) {
capabilities += "<string>" + capability + "</string>\n";
}
for (const String &cap : p_preset->get("capabilities/additional").operator PackedStringArray()) {
capabilities += "<string>" + cap + "</string>\n";
}
strnew += lines[i].replace("$interface_orientations", orientations);
} else if (lines[i].contains("$ipad_interface_orientations")) {
String orientations;
const DisplayServer::ScreenOrientation screen_orientation =
DisplayServer::ScreenOrientation(int(get_project_setting(p_preset, "display/window/handheld/orientation")));
strnew += p_line.replace("$required_device_capabilities", capabilities);
} else if (p_line.contains("$interface_orientations")) {
String orientations;
const DisplayServer::ScreenOrientation screen_orientation =
DisplayServer::ScreenOrientation(int(get_project_setting(p_preset, "display/window/handheld/orientation")));
switch (screen_orientation) {
case DisplayServer::SCREEN_LANDSCAPE:
orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
break;
case DisplayServer::SCREEN_PORTRAIT:
orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
break;
case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
orientations += "<string>UIInterfaceOrientationLandscapeLeft</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;
}
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("$ipad_interface_orientations", orientations);
} else if (lines[i].contains("$camera_usage_description")) {
String description = p_preset->get("privacy/camera_usage_description");
strnew += lines[i].replace("$camera_usage_description", description) + "\n";
} else if (lines[i].contains("$microphone_usage_description")) {
String description = p_preset->get("privacy/microphone_usage_description");
strnew += lines[i].replace("$microphone_usage_description", description) + "\n";
} else if (lines[i].contains("$photolibrary_usage_description")) {
String description = p_preset->get("privacy/photolibrary_usage_description");
strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n";
} else if (lines[i].contains("$plist_launch_screen_name")) {
String value = "<key>UILaunchStoryboardName</key>\n<string>Launch Screen</string>";
strnew += lines[i].replace("$plist_launch_screen_name", value) + "\n";
} else if (lines[i].contains("$pbx_launch_screen_file_reference")) {
String value = "90DD2D9D24B36E8000717FE1 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"<group>\"; };";
strnew += lines[i].replace("$pbx_launch_screen_file_reference", value) + "\n";
} else if (lines[i].contains("$pbx_launch_screen_copy_files")) {
String value = "90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */,";
strnew += lines[i].replace("$pbx_launch_screen_copy_files", value) + "\n";
} else if (lines[i].contains("$pbx_launch_screen_build_phase")) {
String value = "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */,";
strnew += lines[i].replace("$pbx_launch_screen_build_phase", value) + "\n";
} else if (lines[i].contains("$pbx_launch_screen_build_reference")) {
String value = "90DD2D9E24B36E8000717FE1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DD2D9D24B36E8000717FE1 /* Launch Screen.storyboard */; };";
strnew += lines[i].replace("$pbx_launch_screen_build_reference", value) + "\n";
#ifndef DISABLE_DEPRECATED
} else if (lines[i].contains("$pbx_launch_image_usage_setting")) {
strnew += lines[i].replace("$pbx_launch_image_usage_setting", "") + "\n";
#endif
} else if (lines[i].contains("$launch_screen_image_mode")) {
int image_scale_mode = p_preset->get("storyboard/image_scale_mode");
String value;
strnew += p_line.replace("$interface_orientations", orientations);
} else if (p_line.contains("$ipad_interface_orientations")) {
String orientations;
const DisplayServer::ScreenOrientation screen_orientation =
DisplayServer::ScreenOrientation(int(get_project_setting(p_preset, "display/window/handheld/orientation")));
switch (image_scale_mode) {
case 0: {
String logo_path = get_project_setting(p_preset, "application/boot_splash/image");
bool is_on = get_project_setting(p_preset, "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];
switch (screen_orientation) {
case DisplayServer::SCREEN_LANDSCAPE:
orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
break;
case DisplayServer::SCREEN_PORTRAIT:
orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
break;
case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
orientations += "<string>UIInterfaceOrientationLandscapeLeft</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 += p_line.replace("$ipad_interface_orientations", orientations);
} else if (p_line.contains("$camera_usage_description")) {
String description = p_preset->get("privacy/camera_usage_description");
strnew += p_line.replace("$camera_usage_description", description) + "\n";
} else if (p_line.contains("$microphone_usage_description")) {
String description = p_preset->get("privacy/microphone_usage_description");
strnew += p_line.replace("$microphone_usage_description", description) + "\n";
} else if (p_line.contains("$photolibrary_usage_description")) {
String description = p_preset->get("privacy/photolibrary_usage_description");
strnew += p_line.replace("$photolibrary_usage_description", description) + "\n";
} else if (p_line.contains("$pbx_locale_file_reference")) {
String locale_files;
Vector<String> translations = get_project_setting(p_preset, "internationalization/locale/translations");
if (translations.size() > 0) {
HashSet<String> languages;
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid() && tr->get_locale() != "en") {
languages.insert(tr->get_locale());
}
}
strnew += lines[i].replace("$launch_screen_image_mode", value) + "\n";
} else if (lines[i].contains("$launch_screen_background_color")) {
bool use_custom = p_preset->get("storyboard/use_custom_bg_color");
Color color = use_custom ? p_preset->get("storyboard/custom_bg_color") : get_project_setting(p_preset, "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 if (lines[i].contains("$pbx_locale_file_reference")) {
String locale_files;
Vector<String> translations = get_project_setting(p_preset, "internationalization/locale/translations");
if (translations.size() > 0) {
HashSet<String> languages;
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
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++;
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++;
}
}
strnew += p_line.replace("$pbx_locale_file_reference", locale_files);
} else if (p_line.contains("$pbx_locale_build_reference")) {
String locale_files;
Vector<String> translations = get_project_setting(p_preset, "internationalization/locale/translations");
if (translations.size() > 0) {
HashSet<String> languages;
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid() && tr->get_locale() != "en") {
languages.insert(tr->get_locale());
}
}
strnew += lines[i].replace("$pbx_locale_file_reference", locale_files);
} else if (lines[i].contains("$pbx_locale_build_reference")) {
String locale_files;
Vector<String> translations = get_project_setting(p_preset, "internationalization/locale/translations");
if (translations.size() > 0) {
HashSet<String> languages;
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
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++;
}
int index = 0;
for (const String &lang : languages) {
locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,\n";
index++;
}
strnew += lines[i].replace("$pbx_locale_build_reference", locale_files);
} else if (lines[i].contains("$swift_runtime_migration")) {
String value = !p_config.use_swift_runtime ? "" : "LastSwiftMigration = 1250;";
strnew += lines[i].replace("$swift_runtime_migration", value) + "\n";
} else if (lines[i].contains("$swift_runtime_build_settings")) {
String value = !p_config.use_swift_runtime ? "" : R"(
CLANG_ENABLE_MODULES = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$binary/dummy.h";
SWIFT_VERSION = 5.0;
)";
value = value.replace("$binary", p_config.binary_name);
strnew += lines[i].replace("$swift_runtime_build_settings", value) + "\n";
} else if (lines[i].contains("$swift_runtime_fileref")) {
String value = !p_config.use_swift_runtime ? "" : R"(
90B4C2AA2680BC560039117A /* dummy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "dummy.h"; sourceTree = "<group>"; };
90B4C2B52680C7E90039117A /* dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "dummy.swift"; sourceTree = "<group>"; };
)";
strnew += lines[i].replace("$swift_runtime_fileref", value) + "\n";
} else if (lines[i].contains("$swift_runtime_binary_files")) {
String value = !p_config.use_swift_runtime ? "" : R"(
90B4C2AA2680BC560039117A /* dummy.h */,
90B4C2B52680C7E90039117A /* dummy.swift */,
)";
strnew += lines[i].replace("$swift_runtime_binary_files", value) + "\n";
} else if (lines[i].contains("$swift_runtime_buildfile")) {
String value = !p_config.use_swift_runtime ? "" : "90B4C2B62680C7E90039117A /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90B4C2B52680C7E90039117A /* dummy.swift */; };";
strnew += lines[i].replace("$swift_runtime_buildfile", value) + "\n";
} else if (lines[i].contains("$swift_runtime_build_phase")) {
String value = !p_config.use_swift_runtime ? "" : "90B4C2B62680C7E90039117A /* dummy.swift */,";
strnew += lines[i].replace("$swift_runtime_build_phase", value) + "\n";
} else if (lines[i].contains("$priv_collection")) {
bool section_opened = false;
for (uint64_t j = 0; j < std::size(data_collect_type_info); ++j) {
bool data_collected = p_preset->get(vformat("privacy/collected_data/%s/collected", data_collect_type_info[j].prop_name));
bool linked = p_preset->get(vformat("privacy/collected_data/%s/linked_to_user", data_collect_type_info[j].prop_name));
bool tracking = p_preset->get(vformat("privacy/collected_data/%s/used_for_tracking", data_collect_type_info[j].prop_name));
int purposes = p_preset->get(vformat("privacy/collected_data/%s/collection_purposes", data_collect_type_info[j].prop_name));
if (data_collected) {
if (!section_opened) {
section_opened = true;
strnew += "\t<key>NSPrivacyCollectedDataTypes</key>\n";
strnew += "\t<array>\n";
}
strnew += "\t\t<dict>\n";
strnew += "\t\t\t<key>NSPrivacyCollectedDataType</key>\n";
strnew += vformat("\t\t\t<string>%s</string>\n", data_collect_type_info[j].type_name);
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypeLinked</key>\n";
if (linked) {
strnew += "\t\t\t\t<true/>\n";
} else {
strnew += "\t\t\t\t<false/>\n";
}
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypeTracking</key>\n";
if (tracking) {
strnew += "\t\t\t\t<true/>\n";
} else {
strnew += "\t\t\t\t<false/>\n";
}
if (purposes != 0) {
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypePurposes</key>\n";
strnew += "\t\t\t\t<array>\n";
for (uint64_t k = 0; k < std::size(data_collect_purpose_info); ++k) {
if (purposes & (1 << k)) {
strnew += vformat("\t\t\t\t\t<string>%s</string>\n", data_collect_purpose_info[k].type_name);
}
}
strnew += p_line.replace("$pbx_locale_build_reference", locale_files);
} else if (p_line.contains("$swift_runtime_migration")) {
String value = !p_config.use_swift_runtime ? "" : "LastSwiftMigration = 1250;";
strnew += p_line.replace("$swift_runtime_migration", value) + "\n";
} else if (p_line.contains("$swift_runtime_build_settings")) {
String value = !p_config.use_swift_runtime ? "" : R"(
CLANG_ENABLE_MODULES = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$binary/dummy.h";
SWIFT_VERSION = 5.0;
)";
value = value.replace("$binary", p_config.binary_name);
strnew += p_line.replace("$swift_runtime_build_settings", value) + "\n";
} else if (p_line.contains("$swift_runtime_fileref")) {
String value = !p_config.use_swift_runtime ? "" : R"(
90B4C2AA2680BC560039117A /* dummy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "dummy.h"; sourceTree = "<group>"; };
90B4C2B52680C7E90039117A /* dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "dummy.swift"; sourceTree = "<group>"; };
)";
strnew += p_line.replace("$swift_runtime_fileref", value) + "\n";
} else if (p_line.contains("$swift_runtime_binary_files")) {
String value = !p_config.use_swift_runtime ? "" : R"(
90B4C2AA2680BC560039117A /* dummy.h */,
90B4C2B52680C7E90039117A /* dummy.swift */,
)";
strnew += p_line.replace("$swift_runtime_binary_files", value) + "\n";
} else if (p_line.contains("$swift_runtime_buildfile")) {
String value = !p_config.use_swift_runtime ? "" : "90B4C2B62680C7E90039117A /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90B4C2B52680C7E90039117A /* dummy.swift */; };";
strnew += p_line.replace("$swift_runtime_buildfile", value) + "\n";
} else if (p_line.contains("$swift_runtime_build_phase")) {
String value = !p_config.use_swift_runtime ? "" : "90B4C2B62680C7E90039117A /* dummy.swift */,";
strnew += p_line.replace("$swift_runtime_build_phase", value) + "\n";
} else if (p_line.contains("$priv_collection")) {
bool section_opened = false;
for (uint64_t j = 0; j < std::size(data_collect_type_info); ++j) {
bool data_collected = p_preset->get(vformat("privacy/collected_data/%s/collected", data_collect_type_info[j].prop_name));
bool linked = p_preset->get(vformat("privacy/collected_data/%s/linked_to_user", data_collect_type_info[j].prop_name));
bool tracking = p_preset->get(vformat("privacy/collected_data/%s/used_for_tracking", data_collect_type_info[j].prop_name));
int purposes = p_preset->get(vformat("privacy/collected_data/%s/collection_purposes", data_collect_type_info[j].prop_name));
if (data_collected) {
if (!section_opened) {
section_opened = true;
strnew += "\t<key>NSPrivacyCollectedDataTypes</key>\n";
strnew += "\t<array>\n";
}
strnew += "\t\t<dict>\n";
strnew += "\t\t\t<key>NSPrivacyCollectedDataType</key>\n";
strnew += vformat("\t\t\t<string>%s</string>\n", data_collect_type_info[j].type_name);
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypeLinked</key>\n";
if (linked) {
strnew += "\t\t\t\t<true/>\n";
} else {
strnew += "\t\t\t\t<false/>\n";
}
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypeTracking</key>\n";
if (tracking) {
strnew += "\t\t\t\t<true/>\n";
} else {
strnew += "\t\t\t\t<false/>\n";
}
if (purposes != 0) {
strnew += "\t\t\t\t<key>NSPrivacyCollectedDataTypePurposes</key>\n";
strnew += "\t\t\t\t<array>\n";
for (uint64_t k = 0; k < std::size(data_collect_purpose_info); ++k) {
if (purposes & (1 << k)) {
strnew += vformat("\t\t\t\t\t<string>%s</string>\n", data_collect_purpose_info[k].type_name);
}
strnew += "\t\t\t\t</array>\n";
}
strnew += "\t\t\t</dict>\n";
strnew += "\t\t\t\t</array>\n";
}
strnew += "\t\t\t</dict>\n";
}
if (section_opened) {
strnew += "\t</array>\n";
}
} else if (lines[i].contains("$priv_tracking")) {
bool tracking = p_preset->get("privacy/tracking_enabled");
strnew += "\t<key>NSPrivacyTracking</key>\n";
if (tracking) {
strnew += "\t<true/>\n";
} else {
strnew += "\t<false/>\n";
}
Vector<String> tracking_domains = p_preset->get("privacy/tracking_domains");
if (!tracking_domains.is_empty()) {
strnew += "\t<key>NSPrivacyTrackingDomains</key>\n";
strnew += "\t<array>\n";
for (const String &E : tracking_domains) {
strnew += "\t\t<string>" + E + "</string>\n";
}
strnew += "\t</array>\n";
}
} else if (lines[i].contains("$priv_api_types")) {
}
if (section_opened) {
strnew += "\t</array>\n";
}
} else if (p_line.contains("$priv_tracking")) {
bool tracking = p_preset->get("privacy/tracking_enabled");
strnew += "\t<key>NSPrivacyTracking</key>\n";
if (tracking) {
strnew += "\t<true/>\n";
} else {
strnew += "\t<false/>\n";
}
Vector<String> tracking_domains = p_preset->get("privacy/tracking_domains");
if (!tracking_domains.is_empty()) {
strnew += "\t<key>NSPrivacyTrackingDomains</key>\n";
strnew += "\t<array>\n";
for (uint64_t j = 0; j < std::size(api_info); ++j) {
int api_access = p_preset->get(vformat("privacy/%s_access_reasons", api_info[j].prop_name));
if (api_access != 0) {
strnew += "\t\t<dict>\n";
strnew += "\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n";
strnew += "\t\t\t<array>\n";
for (int k = 0; k < api_info[j].prop_flag_value.size(); k++) {
if (api_access & (1 << k)) {
strnew += vformat("\t\t\t\t<string>%s</string>\n", api_info[j].prop_flag_value[k]);
}
}
strnew += "\t\t\t</array>\n";
strnew += "\t\t\t<key>NSPrivacyAccessedAPIType</key>\n";
strnew += vformat("\t\t\t<string>%s</string>\n", api_info[j].type_name);
strnew += "\t\t</dict>\n";
}
for (const String &E : tracking_domains) {
strnew += "\t\t<string>" + E + "</string>\n";
}
strnew += "\t</array>\n";
} else {
strnew += lines[i] + "\n";
}
}
} else if (p_line.contains("$priv_api_types")) {
strnew += "\t<array>\n";
for (uint64_t j = 0; j < std::size(api_info); ++j) {
int api_access = p_preset->get(vformat("privacy/%s_access_reasons", api_info[j].prop_name));
if (api_access != 0) {
strnew += "\t\t<dict>\n";
strnew += "\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n";
strnew += "\t\t\t<array>\n";
for (int k = 0; k < api_info[j].prop_flag_value.size(); k++) {
if (api_access & (1 << k)) {
strnew += vformat("\t\t\t\t<string>%s</string>\n", api_info[j].prop_flag_value[k]);
}
}
strnew += "\t\t\t</array>\n";
strnew += "\t\t\t<key>NSPrivacyAccessedAPIType</key>\n";
strnew += vformat("\t\t\t<string>%s</string>\n", api_info[j].type_name);
strnew += "\t\t</dict>\n";
}
}
strnew += "\t</array>\n";
} else if (p_line.contains("$sdkroot")) {
strnew += p_line.replace("$sdkroot", get_sdk_name()) + "\n";
// !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero...
// should apply the same fix in our macOS export.
CharString cs = strnew.utf8();
pfile.resize(cs.size() - 1);
for (int i = 0; i < cs.size() - 1; i++) {
pfile.write[i] = cs[i];
} else {
strnew += p_line + "\n";
}
return strnew;
}
String EditorExportPlatformAppleEmbedded::_get_additional_plist_content() {
@ -1852,17 +1795,16 @@ Error EditorExportPlatformAppleEmbedded::_export_project_helper(const Ref<Editor
bool found_library = false;
const String godot_platform = "godot_" + get_platform_name();
const String project_file = godot_platform + ".xcodeproj/project.pbxproj";
HashSet<String> files_to_parse;
files_to_parse.insert(godot_platform + "/godot_" + get_platform_name() + "-Info.plist");
const String project_file = "godot_apple_embedded.xcodeproj/project.pbxproj";
files_to_parse.insert(project_file);
files_to_parse.insert(godot_platform + "/export_options.plist");
files_to_parse.insert(godot_platform + "/dummy.cpp");
files_to_parse.insert(godot_platform + ".xcodeproj/project.xcworkspace/contents.xcworkspacedata");
files_to_parse.insert(godot_platform + ".xcodeproj/xcshareddata/xcschemes/godot_" + get_platform_name() + ".xcscheme");
files_to_parse.insert(godot_platform + "/godot_" + get_platform_name() + ".entitlements");
files_to_parse.insert(godot_platform + "/Launch Screen.storyboard");
files_to_parse.insert("godot_apple_embedded.xcodeproj/project.xcworkspace/contents.xcworkspacedata");
files_to_parse.insert("godot_apple_embedded.xcodeproj/xcshareddata/xcschemes/godot_apple_embedded.xcscheme");
files_to_parse.insert("godot_apple_embedded/godot_apple_embedded-Info.plist");
files_to_parse.insert("godot_apple_embedded/godot_apple_embedded.entitlements");
files_to_parse.insert("godot_apple_embedded/export_options.plist");
files_to_parse.insert("godot_apple_embedded/dummy.cpp");
files_to_parse.insert("godot_apple_embedded/Launch Screen.storyboard");
files_to_parse.insert("PrivacyInfo.xcprivacy");
AppleEmbeddedConfigData config_data = {
@ -1958,7 +1900,7 @@ Error EditorExportPlatformAppleEmbedded::_export_project_helper(const Ref<Editor
///@TODO need to parse logo files
if (data.size() > 0) {
file = file.replace("godot_" + get_platform_name(), binary_name);
file = file.replace("godot_apple_embedded", binary_name);
print_line("ADDING: " + file + " size: " + itos(data.size()));

View file

@ -107,21 +107,6 @@ private:
static Error _walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata);
static Error _codesign(String p_file, void *p_userdata);
struct AppleEmbeddedConfigData {
String pkg_name;
String binary_name;
String plist_content;
String architectures;
String linker_flags;
String cpp_code;
String modules_buildfile;
String modules_fileref;
String modules_buildphase;
String modules_buildgrp;
Vector<String> capabilities;
bool use_swift_runtime;
};
struct ExportArchitecture {
String name;
bool is_default = false;
@ -143,6 +128,62 @@ private:
String _get_additional_plist_content();
String _get_linker_flags();
String _get_cpp_code();
protected:
struct AppleEmbeddedConfigData {
String pkg_name;
String binary_name;
String plist_content;
String architectures;
String linker_flags;
String cpp_code;
String modules_buildfile;
String modules_fileref;
String modules_buildphase;
String modules_buildgrp;
Vector<String> capabilities;
bool use_swift_runtime;
};
struct CodeSigningDetails {
String debug_signing_identity;
String release_signing_identity;
String debug_provisioning_profile_uuid;
String release_provisioning_profile_uuid;
String debug_provisioning_profile_specifier;
String release_provisioning_profile_specifier;
bool debug_manual_signing = false;
bool release_manual_signing = false;
CodeSigningDetails(const Ref<EditorExportPreset> &p_preset) {
debug_signing_identity = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "Apple Development" : p_preset->get("application/code_sign_identity_debug");
release_signing_identity = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "Apple Distribution" : p_preset->get("application/code_sign_identity_release");
debug_provisioning_profile_uuid = p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG).operator String();
release_provisioning_profile_uuid = p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_APPLE_PLATFORM_PROFILE_UUID_DEBUG).operator String();
debug_manual_signing = !debug_provisioning_profile_uuid.is_empty() || (debug_signing_identity != "Apple Development" && debug_signing_identity != "Apple Distribution");
release_manual_signing = !release_provisioning_profile_uuid.is_empty() || (release_signing_identity != "Apple Development" && release_signing_identity != "Apple Distribution");
debug_provisioning_profile_specifier = p_preset->get_or_env("application/provisioning_profile_specifier_debug", ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_DEBUG).operator String();
debug_manual_signing |= !debug_provisioning_profile_specifier.is_empty();
release_provisioning_profile_specifier = p_preset->get_or_env("application/provisioning_profile_specifier_release", ENV_APPLE_PLATFORM_PROFILE_SPECIFIER_RELEASE).operator String();
release_manual_signing |= !release_provisioning_profile_specifier.is_empty();
}
};
struct IconInfo {
const char *preset_key;
const char *idiom;
const char *export_name;
const char *actual_size_side;
const char *scale;
const char *unscaled_size;
bool force_opaque;
};
private:
void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const AppleEmbeddedConfigData &p_config, bool p_debug);
Vector<ExportArchitecture> _get_supported_architectures() const;
@ -162,15 +203,7 @@ private:
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
protected:
struct IconInfo {
const char *preset_key;
const char *idiom;
const char *export_name;
const char *actual_size_side;
const char *scale;
const char *unscaled_size;
bool force_opaque;
};
virtual String _process_config_file_line(const Ref<EditorExportPreset> &p_preset, const String &p_line, const AppleEmbeddedConfigData &p_config, bool p_debug, const CodeSigningDetails &p_code_signing);
void _blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p_src, bool p_rot);