feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -37,8 +37,9 @@ void register_macos_exporter_types() {
}
void register_macos_exporter() {
// TODO: Move to editor_settings.cpp
#ifndef ANDROID_ENABLED
EDITOR_DEF("export/macos/rcodesign", "");
EDITOR_DEF_BASIC("export/macos/rcodesign", "");
#ifdef WINDOWS_ENABLED
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/macos/rcodesign", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
#else

View file

@ -47,10 +47,7 @@
#include "editor/themes/editor_scale.h"
#include "scene/resources/image_texture.h"
#include "modules/modules_enabled.gen.h" // For svg and regex.
#ifdef MODULE_SVG_ENABLED
#include "modules/svg/image_loader_svg.h"
#endif
void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
r_features->push_back(p_preset->get("binary_format/architecture"));
@ -65,6 +62,11 @@ void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset
} else {
ERR_PRINT("Invalid architecture");
}
if (architecture == "universal") {
r_features->push_back("x86_64");
r_features->push_back("arm64");
}
}
String EditorExportPlatformMacOS::get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const {
@ -327,7 +329,21 @@ bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportP
}
bool advanced_options_enabled = p_preset->are_advanced_options_enabled();
if (p_option.begins_with("privacy")) {
if (p_option.begins_with("privacy") ||
p_option == "codesign/entitlements/additional" ||
p_option == "custom_template/debug" ||
p_option == "custom_template/release" ||
p_option == "application/additional_plist_content" ||
p_option == "application/export_angle" ||
p_option == "application/icon_interpolation" ||
p_option == "application/signature" ||
p_option == "display/high_res" ||
p_option == "xcode/platform_build" ||
p_option == "xcode/sdk_build" ||
p_option == "xcode/sdk_name" ||
p_option == "xcode/sdk_version" ||
p_option == "xcode/xcode_build" ||
p_option == "xcode/xcode_version") {
return advanced_options_enabled;
}
}
@ -357,17 +373,13 @@ List<String> EditorExportPlatformMacOS::get_binary_extensions(const Ref<EditorEx
list.push_back("dmg");
#endif
list.push_back("zip");
#ifndef WINDOWS_ENABLED
list.push_back("app");
#endif
} else if (dist_type == 1) {
#ifdef MACOS_ENABLED
list.push_back("dmg");
#endif
list.push_back("zip");
#ifndef WINDOWS_ENABLED
list.push_back("app");
#endif
} else if (dist_type == 2) {
#ifdef MACOS_ENABLED
list.push_back("pkg");
@ -451,13 +463,15 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_macos_version"), "10.12"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_macos_version_x86_64"), "10.12"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_macos_version_arm64"), "11.00"));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_angle", PROPERTY_HINT_ENUM, "Auto,Yes,No"), 0, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/additional_plist_content", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/platform_build"), "14C18"));
// TODO(sgc): Need to set appropriate version when using Metal
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_version"), "13.1"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_build"), "22C55"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_name"), "macosx13.1"));
@ -503,6 +517,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_user_selected", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/additional", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
#ifdef MACOS_ENABLED
@ -822,8 +837,12 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres
strnew += lines[i].replace("$app_category", cat.to_lower()) + "\n";
} else if (lines[i].contains("$copyright")) {
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].contains("$min_version_arm64")) {
strnew += lines[i].replace("$min_version_arm64", p_preset->get("application/min_macos_version_arm64")) + "\n";
} else if (lines[i].contains("$min_version_x86_64")) {
strnew += lines[i].replace("$min_version_x86_64", p_preset->get("application/min_macos_version_x86_64")) + "\n";
} else if (lines[i].contains("$min_version")) {
strnew += lines[i].replace("$min_version", p_preset->get("application/min_macos_version")) + "\n";
strnew += lines[i].replace("$min_version", p_preset->get("application/min_macos_version_x86_64")) + "\n"; // Old template, use x86-64 version for both.
} else if (lines[i].contains("$highres")) {
strnew += lines[i].replace("$highres", p_preset->get("display/high_res") ? "\t<true/>" : "\t<false/>") + "\n";
} else if (lines[i].contains("$additional_plist_content")) {
@ -962,7 +981,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
return Error::FAILED;
} else {
print_verbose("rcodesign (" + p_path + "):\n" + str);
int next_nl = str.find("\n", rq_offset);
int next_nl = str.find_char('\n', rq_offset);
String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 23, -1) : str.substr(rq_offset + 23, next_nl - rq_offset - 23);
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour."));
@ -1046,7 +1065,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
return Error::FAILED;
} else {
print_verbose("notarytool (" + p_path + "):\n" + str);
int next_nl = str.find("\n", rq_offset);
int next_nl = str.find_char('\n', rq_offset);
String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 4, -1) : str.substr(rq_offset + 4, next_nl - rq_offset - 4);
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour."));
@ -1069,16 +1088,12 @@ void EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pres
switch (codesign_tool) {
case 1: { // built-in ad-hoc
print_verbose("using built-in codesign...");
#ifdef MODULE_REGEX_ENABLED
String error_msg;
Error err = CodeSign::codesign(false, true, p_path, p_ent_path, error_msg);
if (err != OK) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg));
return;
}
#else
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module."));
#endif
} break;
case 2: { // "rcodesign"
print_verbose("using rcodesign codesign...");
@ -1092,7 +1107,7 @@ void EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pres
List<String> args;
args.push_back("sign");
if (p_path.get_extension() != "dmg") {
if (!p_ent_path.is_empty()) {
args.push_back("--entitlements-xml-path");
args.push_back(p_ent_path);
}
@ -1153,7 +1168,7 @@ void EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pres
args.push_back("runtime");
}
if (p_path.get_extension() != "dmg") {
if (!p_ent_path.is_empty()) {
args.push_back("--entitlements");
args.push_back(p_ent_path);
}
@ -1237,7 +1252,7 @@ void EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPrese
}
if (extensions_to_sign.has(current_file.get_extension())) {
String ent_path = p_ent_path;
String ent_path;
bool set_bundle_id = false;
if (sandbox && FileAccess::exists(current_file_path)) {
int ftype = MachO::get_filetype(current_file_path);
@ -1281,18 +1296,18 @@ Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access
#endif
print_verbose("export framework: " + p_src_path + " -> " + p_in_app_path);
bool plist_misssing = false;
bool plist_missing = false;
Ref<PList> plist;
plist.instantiate();
plist->load_file(p_src_path.path_join("Resources").path_join("Info.plist"));
Ref<PListNode> root_node = plist->get_root();
if (root_node.is_null()) {
plist_misssing = true;
plist_missing = true;
} else {
Dictionary root = root_node->get_value();
if (!root.has("CFBundleExecutable") || !root.has("CFBundleIdentifier") || !root.has("CFBundlePackageType") || !root.has("CFBundleInfoDictionaryVersion") || !root.has("CFBundleName") || !root.has("CFBundleSupportedPlatforms")) {
plist_misssing = true;
plist_missing = true;
}
}
@ -1300,7 +1315,7 @@ Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access
if (err == OK) {
err = dir_access->copy_dir(p_src_path, p_in_app_path, -1, true);
}
if (err == OK && plist_misssing) {
if (err == OK && plist_missing) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Export"), vformat(TTR("\"%s\": Info.plist missing or invalid, new Info.plist generated."), p_src_path.get_file()));
// Generate Info.plist
String lib_name = p_src_path.get_basename().get_file();
@ -1357,7 +1372,7 @@ Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access
_code_sign_directory(p_preset, p_in_app_path, p_ent_path, p_helper_ent_path, p_should_error_on_non_code_sign);
} else {
if (extensions_to_sign.has(p_in_app_path.get_extension())) {
String ent_path = p_ent_path;
String ent_path;
bool set_bundle_id = false;
if (p_sandbox && FileAccess::exists(p_in_app_path)) {
int ftype = MachO::get_filetype(p_in_app_path);
@ -1504,7 +1519,7 @@ Error EditorExportPlatformMacOS::_export_debug_script(const Ref<EditorExportPres
return OK;
}
Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String base_dir = p_path.get_base_dir();
@ -1584,7 +1599,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
tmp_app_path_name = p_path;
scr_path = p_path.get_basename() + ".command";
} else {
tmp_base_path_name = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name);
tmp_base_path_name = EditorPaths::get_singleton()->get_temp_dir().path_join(pkg_name);
tmp_app_path_name = tmp_base_path_name.path_join(tmp_app_dir_name);
scr_path = tmp_base_path_name.path_join(pkg_name + ".command");
}
@ -1868,10 +1883,8 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
icon->get_buffer(&data.write[0], icon->get_length());
}
} else {
Ref<Image> icon;
icon.instantiate();
err = ImageLoader::load_image(icon_path, icon);
if (err == OK && !icon->is_empty()) {
Ref<Image> icon = _load_icon_or_splash_image(icon_path, &err);
if (err == OK && icon.is_valid() && !icon->is_empty()) {
_make_icon(p_preset, icon, data);
}
}
@ -1897,6 +1910,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
if (is_executable(file)) {
// chmod with 0755 if the file is executable.
FileAccess::set_unix_permissions(file, 0755);
#ifndef UNIX_ENABLED
if (export_format == "app") {
add_message(EXPORT_MESSAGE_INFO, TTR("Export"), vformat(TTR("Unable to set Unix permissions for executable \"%s\". Use \"chmod +x\" to set it after transferring the exported .app to macOS or Linux."), "Contents/MacOS/" + file.get_file()));
}
#endif
}
} else {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not open \"%s\"."), file));
@ -1922,6 +1940,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
if ((con_scr == 1 && p_debug) || (con_scr == 2)) {
err = _export_debug_script(p_preset, pkg_name, tmp_app_path_name.get_file() + "/Contents/MacOS/" + pkg_name, scr_path);
FileAccess::set_unix_permissions(scr_path, 0755);
#ifndef UNIX_ENABLED
if (export_format == "app") {
add_message(EXPORT_MESSAGE_INFO, TTR("Export"), vformat(TTR("Unable to set Unix permissions for executable \"%s\". Use \"chmod +x\" to set it after transferring the exported .app to macOS or Linux."), scr_path.get_file()));
}
#endif
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not create console wrapper."));
}
@ -1969,9 +1992,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
bool sandbox = p_preset->get("codesign/entitlements/app_sandbox/enabled");
String ent_path = p_preset->get("codesign/entitlements/custom_file");
String hlp_ent_path = sandbox ? EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + "_helper.entitlements") : ent_path;
String hlp_ent_path = sandbox ? EditorPaths::get_singleton()->get_temp_dir().path_join(pkg_name + "_helper.entitlements") : ent_path;
if (sign_enabled && (ent_path.is_empty())) {
ent_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + ".entitlements");
ent_path = EditorPaths::get_singleton()->get_temp_dir().path_join(pkg_name + ".entitlements");
Ref<FileAccess> ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
if (ent_f.is_valid()) {
@ -2114,6 +2137,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
}
}
const String &additional_entitlements = p_preset->get("codesign/entitlements/additional");
if (!additional_entitlements.is_empty()) {
ent_f->store_line(additional_entitlements);
}
ent_f->store_line("</dict>");
ent_f->store_line("</plist>");
} else {
@ -2150,6 +2178,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
_code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path, false, true);
}
FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755);
#ifndef UNIX_ENABLED
if (export_format == "app") {
add_message(EXPORT_MESSAGE_INFO, TTR("Export"), vformat(TTR("Unable to set Unix permissions for executable \"%s\". Use \"chmod +x\" to set it after transferring the exported .app to macOS or Linux."), "Contents/Helpers/" + hlp_path.get_file()));
}
#endif
}
}
@ -2241,7 +2274,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
} else if (export_format == "app" && noto_enabled) {
// Create temporary ZIP.
if (err == OK) {
noto_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + ".zip");
noto_path = EditorPaths::get_singleton()->get_temp_dir().path_join(pkg_name + ".zip");
if (ep.step(TTR("Making ZIP"), 3)) {
return ERR_SKIP;
@ -2271,6 +2304,14 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
}
}
if (FileAccess::exists(ent_path)) {
print_verbose("entitlements:\n" + FileAccess::get_file_as_string(ent_path));
}
if (FileAccess::exists(hlp_ent_path)) {
print_verbose("helper entitlements:\n" + FileAccess::get_file_as_string(hlp_ent_path));
}
// Clean up temporary entitlements files.
if (FileAccess::exists(hlp_ent_path)) {
DirAccess::remove_file_or_error(hlp_ent_path);
@ -2510,7 +2551,7 @@ void EditorExportPlatformMacOS::cleanup() {
cleanup_commands.clear();
}
Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
cleanup();
if (p_device) { // Stop command, cleanup only.
return OK;
@ -2518,7 +2559,7 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
EditorProgress ep("run", TTR("Running..."), 5);
const String dest = EditorPaths::get_singleton()->get_cache_dir().path_join("macos");
const String dest = EditorPaths::get_singleton()->get_temp_dir().path_join("macos");
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da->dir_exists(dest)) {
Error err = da->make_dir_recursive(dest);
@ -2572,8 +2613,7 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
String cmd_args;
{
Vector<String> cmd_args_list;
gen_debug_flags(cmd_args_list, p_debug_flags);
Vector<String> cmd_args_list = gen_export_flags(p_debug_flags);
for (int i = 0; i < cmd_args_list.size(); i++) {
if (i != 0) {
cmd_args += " ";
@ -2582,7 +2622,7 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
}
}
const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
print_line("Creating temporary directory...");
@ -2667,7 +2707,6 @@ Error EditorExportPlatformMacOS::run(const Ref<EditorExportPreset> &p_preset, in
EditorExportPlatformMacOS::EditorExportPlatformMacOS() {
if (EditorNode::get_singleton()) {
#ifdef MODULE_SVG_ENABLED
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
@ -2676,7 +2715,6 @@ EditorExportPlatformMacOS::EditorExportPlatformMacOS() {
ImageLoaderSVG::create_image_from_string(img, _macos_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {

View file

@ -34,6 +34,7 @@
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/image.h"
#include "core/io/marshalls.h"
#include "core/io/resource_saver.h"
#include "core/os/os.h"
@ -68,14 +69,14 @@ class EditorExportPlatformMacOS : public EditorExportPlatform {
String cmd_args;
bool wait = false;
SSHCleanupCommand(){};
SSHCleanupCommand() {}
SSHCleanupCommand(const String &p_host, const String &p_port, const Vector<String> &p_ssh_arg, const String &p_cmd_args, bool p_wait = false) {
host = p_host;
port = p_port;
ssh_args = p_ssh_arg;
cmd_args = p_cmd_args;
wait = p_wait;
};
}
};
Ref<ImageTexture> run_icon;
@ -147,7 +148,7 @@ public:
virtual bool is_executable(const String &p_path) const override;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
@ -167,7 +168,7 @@ public:
virtual int get_options_count() const override;
virtual String get_option_label(int p_index) const override;
virtual String get_option_tooltip(int p_index) const override;
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual void cleanup() override;
EditorExportPlatformMacOS();