@@ -306,6 +306,12 @@ bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportP
306306 return false ;
307307 }
308308
309+ #ifndef MACOS_ENABLED
310+ if (p_option == " application/liquid_glass_icon" ) {
311+ return false ;
312+ }
313+ #endif
314+
309315 String custom_prof = p_preset->get (" codesign/entitlements/custom_file" );
310316 if (!custom_prof.is_empty () && p_option != " codesign/entitlements/custom_file" && p_option.begins_with (" codesign/entitlements/" )) {
311317 return false ;
@@ -467,6 +473,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
467473 r_options->push_back (ExportOption (PropertyInfo (Variant::STRING, " custom_template/release" , PROPERTY_HINT_GLOBAL_FILE, " *.zip" ), " " ));
468474
469475 r_options->push_back (ExportOption (PropertyInfo (Variant::INT, " debug/export_console_wrapper" , PROPERTY_HINT_ENUM, " No,Debug Only,Debug and Release" ), 1 ));
476+ r_options->push_back (ExportOption (PropertyInfo (Variant::STRING, " application/liquid_glass_icon" , PROPERTY_HINT_FILE, " *.icon" ), " " ));
470477 r_options->push_back (ExportOption (PropertyInfo (Variant::STRING, " application/icon" , PROPERTY_HINT_FILE, " *.icns,*.png,*.webp,*.svg" ), " " ));
471478 r_options->push_back (ExportOption (PropertyInfo (Variant::INT, " application/icon_interpolation" , PROPERTY_HINT_ENUM, " Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos" ), 4 ));
472479 r_options->push_back (ExportOption (PropertyInfo (Variant::STRING, " application/bundle_identifier" , PROPERTY_HINT_PLACEHOLDER_TEXT, " com.example.game" ), " " , false , true ));
@@ -828,7 +835,7 @@ void EditorExportPlatformMacOS::_fix_privacy_manifest(const Ref<EditorExportPres
828835 }
829836}
830837
831- void EditorExportPlatformMacOS::_fix_plist (const Ref<EditorExportPreset> &p_preset, Vector<uint8_t > &plist, const String &p_binary) {
838+ void EditorExportPlatformMacOS::_fix_plist (const Ref<EditorExportPreset> &p_preset, Vector<uint8_t > &plist, const String &p_binary, bool p_lg_icon_exported, const String &p_lg_icon ) {
832839 String str = String::utf8 ((const char *)plist.ptr (), plist.size ());
833840 String strnew;
834841 Vector<String> lines = str.split (" \n " );
@@ -872,6 +879,12 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres
872879 strnew += lines[i].replace (" $xcodever" , p_preset->get (" xcode/xcode_version" )) + " \n " ;
873880 } else if (lines[i].contains (" $xcodebuild" )) {
874881 strnew += lines[i].replace (" $xcodebuild" , p_preset->get (" xcode/xcode_build" )) + " \n " ;
882+ } else if (lines[i].contains (" $liquid_glass_icon" )) {
883+ if (p_lg_icon_exported) {
884+ strnew += lines[i].replace (" $liquid_glass_icon" , " \t <key>CFBundleIconName</key>\n\t <string>" + p_lg_icon + " </string>\n " );
885+ } else {
886+ strnew += lines[i].replace (" $liquid_glass_icon" , " " );
887+ }
875888 } else if (lines[i].contains (" $usage_descriptions" )) {
876889 String descriptions;
877890 if (!((String)p_preset->get (" privacy/microphone_usage_description" )).is_empty ()) {
@@ -933,6 +946,76 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres
933946 }
934947}
935948
949+ Error EditorExportPlatformMacOS::_export_liquid_glass_icon (const Ref<EditorExportPreset> &p_preset, const String &p_app_path, const String &p_icon_path) {
950+ String actool = EDITOR_GET (" export/macos/actool" ).operator String ();
951+ if (actool.is_empty ()) {
952+ actool = " actool" ;
953+ }
954+
955+ List<String> args;
956+ args.push_back (" --version" );
957+ String str;
958+ String err_str;
959+ int exitcode = 0 ;
960+
961+ Error err = OS::get_singleton ()->execute (actool, args, &str, &exitcode, true );
962+ if (err != OK) {
963+ add_message (EXPORT_MESSAGE_WARNING, TTR (" Liquid Glass Icons" ), TTR (" Could not start 'actool' executable." ));
964+ return err;
965+ }
966+ PList info_plist;
967+ if (!info_plist.load_string (str, err_str)) {
968+ print_verbose (str);
969+ add_message (EXPORT_MESSAGE_WARNING, TTR (" Liquid Glass Icons" ), TTR (" Could not read 'actool' version." ));
970+ return err;
971+ }
972+ if (info_plist.get_root ()->data_type == PList::PLNodeType::PL_NODE_TYPE_DICT && info_plist.get_root ()->data_dict .has (" com.apple.actool.version" )) {
973+ Ref<PListNode> dict = info_plist.get_root ()->data_dict [" com.apple.actool.version" ];
974+ if (dict->data_type == PList::PLNodeType::PL_NODE_TYPE_DICT && dict->data_dict .has (" short-bundle-version" )) {
975+ float version = String::utf8 (dict->data_dict [" short-bundle-version" ]->data_string .get_data ()).to_float ();
976+ if (version < 26.0 ) {
977+ add_message (EXPORT_MESSAGE_WARNING, TTR (" Liquid Glass Icons" ), vformat (TTR (" At least version 26.0 of 'actool' is required (version %f found)." ), version));
978+ return ERR_UNAVAILABLE;
979+ }
980+ }
981+ }
982+ str.clear ();
983+
984+ String plist = EditorPaths::get_singleton ()->get_temp_dir ().path_join (" assetcatalog.plist" );
985+ args.clear ();
986+ args.push_back (ProjectSettings::get_singleton ()->globalize_path (p_icon_path));
987+ args.push_back (" --compile" );
988+ args.push_back (p_app_path + " /Contents/Resources/" );
989+ args.push_back (" --output-format" );
990+ args.push_back (" human-readable-text" );
991+ args.push_back (" --lightweight-asset-runtime-mode" );
992+ args.push_back (" enabled" );
993+ args.push_back (" --app-icon" );
994+ args.push_back (p_icon_path.get_file ().get_basename ());
995+ args.push_back (" --include-all-app-icons" );
996+ args.push_back (" --enable-on-demand-resources" );
997+ args.push_back (" NO" );
998+ args.push_back (" --development-region" );
999+ args.push_back (" en" );
1000+ args.push_back (" --target-device" );
1001+ args.push_back (" mac" );
1002+ args.push_back (" --minimum-deployment-target" );
1003+ args.push_back (" 26" );
1004+ args.push_back (" --platform" );
1005+ args.push_back (" macosx" );
1006+ args.push_back (" --output-partial-info-plist" );
1007+ args.push_back (plist);
1008+
1009+ err = OS::get_singleton ()->execute (actool, args, &str, &exitcode, true );
1010+ if (err != OK || str.contains (" error:" ) || !FileAccess::exists (p_app_path + " /Contents/Resources/Assets.car" ) || !FileAccess::exists (plist)) {
1011+ print_verbose (str);
1012+ add_message (EXPORT_MESSAGE_WARNING, TTR (" Liquid Glass Icons" ), TTR (" Could not export liquid glass icon:" ) + " \n " + str);
1013+ return err;
1014+ }
1015+
1016+ return OK;
1017+ }
1018+
9361019/* *
9371020 * If we're running the macOS version of the Godot editor we'll:
9381021 * - export our application bundle to a temporary folder
@@ -1861,7 +1944,16 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
18611944 }
18621945
18631946 if (file == " Contents/Info.plist" ) {
1864- _fix_plist (p_preset, data, pkg_name);
1947+ bool lg_icon_expored = false ;
1948+ String lg_icon = p_preset->get (" application/liquid_glass_icon" );
1949+ #ifdef MACOS_ENABLED
1950+ // Export liquid glass.
1951+ if (!lg_icon.is_empty ()) {
1952+ lg_icon_expored = (_export_liquid_glass_icon (p_preset, tmp_app_path_name, lg_icon) == OK);
1953+ }
1954+ #endif
1955+ // Modify plist.
1956+ _fix_plist (p_preset, data, pkg_name, lg_icon_expored, lg_icon.get_file ().get_basename ());
18651957 }
18661958
18671959 if (file == " Contents/Resources/PrivacyInfo.xcprivacy" ) {
0 commit comments