Path: blob/master/editor/export/editor_export_preset.cpp
9896 views
/**************************************************************************/1/* editor_export_preset.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "editor_export.h"3132#include "core/config/project_settings.h"3334bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) {35values[p_name] = p_value;36EditorExport::singleton->save_presets();37if (update_visibility.has(p_name)) {38if (update_visibility[p_name]) {39update_value_overrides();40notify_property_list_changed();41}42return true;43}4445return false;46}4748bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {49if (value_overrides.has(p_name)) {50r_ret = value_overrides[p_name];51return true;52}5354if (values.has(p_name)) {55r_ret = values[p_name];56return true;57}5859return false;60}6162Variant EditorExportPreset::get_project_setting(const StringName &p_name) {63List<String> ftr_list;64platform->get_platform_features(&ftr_list);65platform->get_preset_features(this, &ftr_list);6667Vector<String> features;68for (const String &E : ftr_list) {69features.push_back(E);70}7172if (!get_custom_features().is_empty()) {73Vector<String> tmp_custom_list = get_custom_features().split(",");7475for (int i = 0; i < tmp_custom_list.size(); i++) {76String f = tmp_custom_list[i].strip_edges();77if (!f.is_empty()) {78features.push_back(f);79}80}81}82return ProjectSettings::get_singleton()->get_setting_with_override_and_custom_features(p_name, features);83}8485void EditorExportPreset::_bind_methods() {86ClassDB::bind_method(D_METHOD("_get_property_warning", "name"), &EditorExportPreset::_get_property_warning);8788ClassDB::bind_method(D_METHOD("has", "property"), &EditorExportPreset::has);8990ClassDB::bind_method(D_METHOD("get_files_to_export"), &EditorExportPreset::get_files_to_export);91ClassDB::bind_method(D_METHOD("get_customized_files"), &EditorExportPreset::get_customized_files);92ClassDB::bind_method(D_METHOD("get_customized_files_count"), &EditorExportPreset::get_customized_files_count);93ClassDB::bind_method(D_METHOD("has_export_file", "path"), &EditorExportPreset::has_export_file);94ClassDB::bind_method(D_METHOD("get_file_export_mode", "path", "default"), &EditorExportPreset::get_file_export_mode, DEFVAL(MODE_FILE_NOT_CUSTOMIZED));95ClassDB::bind_method(D_METHOD("get_project_setting", "name"), &EditorExportPreset::get_project_setting);9697ClassDB::bind_method(D_METHOD("get_preset_name"), &EditorExportPreset::get_name);98ClassDB::bind_method(D_METHOD("is_runnable"), &EditorExportPreset::is_runnable);99ClassDB::bind_method(D_METHOD("are_advanced_options_enabled"), &EditorExportPreset::are_advanced_options_enabled);100ClassDB::bind_method(D_METHOD("is_dedicated_server"), &EditorExportPreset::is_dedicated_server);101ClassDB::bind_method(D_METHOD("get_export_filter"), &EditorExportPreset::get_export_filter);102ClassDB::bind_method(D_METHOD("get_include_filter"), &EditorExportPreset::get_include_filter);103ClassDB::bind_method(D_METHOD("get_exclude_filter"), &EditorExportPreset::get_exclude_filter);104ClassDB::bind_method(D_METHOD("get_custom_features"), &EditorExportPreset::get_custom_features);105ClassDB::bind_method(D_METHOD("get_patches"), &EditorExportPreset::get_patches);106ClassDB::bind_method(D_METHOD("get_export_path"), &EditorExportPreset::get_export_path);107ClassDB::bind_method(D_METHOD("get_encryption_in_filter"), &EditorExportPreset::get_enc_in_filter);108ClassDB::bind_method(D_METHOD("get_encryption_ex_filter"), &EditorExportPreset::get_enc_ex_filter);109ClassDB::bind_method(D_METHOD("get_encrypt_pck"), &EditorExportPreset::get_enc_pck);110ClassDB::bind_method(D_METHOD("get_encrypt_directory"), &EditorExportPreset::get_enc_directory);111ClassDB::bind_method(D_METHOD("get_encryption_key"), &EditorExportPreset::get_script_encryption_key);112ClassDB::bind_method(D_METHOD("get_script_export_mode"), &EditorExportPreset::get_script_export_mode);113114ClassDB::bind_method(D_METHOD("get_or_env", "name", "env_var"), &EditorExportPreset::_get_or_env);115ClassDB::bind_method(D_METHOD("get_version", "name", "windows_version"), &EditorExportPreset::get_version);116117BIND_ENUM_CONSTANT(EXPORT_ALL_RESOURCES);118BIND_ENUM_CONSTANT(EXPORT_SELECTED_SCENES);119BIND_ENUM_CONSTANT(EXPORT_SELECTED_RESOURCES);120BIND_ENUM_CONSTANT(EXCLUDE_SELECTED_RESOURCES);121BIND_ENUM_CONSTANT(EXPORT_CUSTOMIZED);122123BIND_ENUM_CONSTANT(MODE_FILE_NOT_CUSTOMIZED);124BIND_ENUM_CONSTANT(MODE_FILE_STRIP);125BIND_ENUM_CONSTANT(MODE_FILE_KEEP);126BIND_ENUM_CONSTANT(MODE_FILE_REMOVE);127128BIND_ENUM_CONSTANT(MODE_SCRIPT_TEXT);129BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS);130BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS_COMPRESSED);131}132133String EditorExportPreset::_get_property_warning(const StringName &p_name) const {134if (value_overrides.has(p_name)) {135return String();136}137138String warning = platform->get_export_option_warning(this, p_name);139if (!warning.is_empty()) {140warning += "\n";141}142143// Get property warning from editor export plugins.144Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();145for (int i = 0; i < export_plugins.size(); i++) {146if (!export_plugins[i]->supports_platform(platform)) {147continue;148}149150export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));151String plugin_warning = export_plugins[i]->_get_export_option_warning(platform, p_name);152if (!plugin_warning.is_empty()) {153warning += plugin_warning + "\n";154}155}156157return warning;158}159160void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {161for (const KeyValue<StringName, PropertyInfo> &E : properties) {162if (!value_overrides.has(E.key)) {163bool property_visible = platform->get_export_option_visibility(this, E.key);164if (!property_visible) {165continue;166}167168// Get option visibility from editor export plugins.169Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();170for (int i = 0; i < export_plugins.size(); i++) {171if (!export_plugins[i]->supports_platform(platform)) {172continue;173}174175export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));176property_visible = export_plugins[i]->_get_export_option_visibility(platform, E.key);177if (!property_visible) {178break;179}180}181182if (property_visible) {183p_list->push_back(E.value);184}185}186}187}188189Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {190return platform;191}192193void EditorExportPreset::update_files() {194{195Vector<String> to_remove;196for (const String &E : selected_files) {197if (!FileAccess::exists(E)) {198to_remove.push_back(E);199}200}201for (int i = 0; i < to_remove.size(); ++i) {202selected_files.erase(to_remove[i]);203}204}205206{207Vector<String> to_remove;208for (const KeyValue<String, FileExportMode> &E : customized_files) {209if (!FileAccess::exists(E.key) && !DirAccess::exists(E.key)) {210to_remove.push_back(E.key);211}212}213for (int i = 0; i < to_remove.size(); ++i) {214customized_files.erase(to_remove[i]);215}216}217}218219void EditorExportPreset::update_value_overrides() {220Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();221HashMap<StringName, Variant> new_value_overrides;222223value_overrides.clear();224225for (int i = 0; i < export_plugins.size(); i++) {226if (!export_plugins[i]->supports_platform(platform)) {227continue;228}229230export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));231232Dictionary plugin_overrides = export_plugins[i]->_get_export_options_overrides(platform);233if (!plugin_overrides.is_empty()) {234for (const KeyValue<Variant, Variant> &kv : plugin_overrides) {235const StringName &key = kv.key;236const Variant &value = kv.value;237if (new_value_overrides.has(key) && new_value_overrides[key] != value) {238WARN_PRINT_ED(vformat("Editor export plugin '%s' overrides pre-existing export option override '%s' with new value.", export_plugins[i]->get_name(), key));239}240new_value_overrides[key] = value;241}242}243}244245value_overrides = new_value_overrides;246notify_property_list_changed();247}248249Vector<String> EditorExportPreset::get_files_to_export() const {250Vector<String> files;251for (const String &E : selected_files) {252files.push_back(E);253}254return files;255}256257Dictionary EditorExportPreset::get_customized_files() const {258Dictionary files;259for (const KeyValue<String, FileExportMode> &E : customized_files) {260String mode;261switch (E.value) {262case MODE_FILE_NOT_CUSTOMIZED: {263continue;264} break;265case MODE_FILE_STRIP: {266mode = "strip";267} break;268case MODE_FILE_KEEP: {269mode = "keep";270} break;271case MODE_FILE_REMOVE: {272mode = "remove";273}274}275files[E.key] = mode;276}277return files;278}279280int EditorExportPreset::get_customized_files_count() const {281return customized_files.size();282}283284void EditorExportPreset::set_customized_files(const Dictionary &p_files) {285for (const Variant *key = p_files.next(nullptr); key; key = p_files.next(key)) {286EditorExportPreset::FileExportMode mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;287String value = p_files[*key];288if (value == "strip") {289mode = EditorExportPreset::MODE_FILE_STRIP;290} else if (value == "keep") {291mode = EditorExportPreset::MODE_FILE_KEEP;292} else if (value == "remove") {293mode = EditorExportPreset::MODE_FILE_REMOVE;294}295set_file_export_mode(*key, mode);296}297}298299void EditorExportPreset::set_name(const String &p_name) {300name = p_name;301EditorExport::singleton->save_presets();302}303304String EditorExportPreset::get_name() const {305return name;306}307308void EditorExportPreset::set_runnable(bool p_enable) {309runnable = p_enable;310EditorExport::singleton->emit_presets_runnable_changed();311EditorExport::singleton->save_presets();312}313314bool EditorExportPreset::is_runnable() const {315return runnable;316}317318void EditorExportPreset::set_advanced_options_enabled(bool p_enabled) {319if (advanced_options_enabled == p_enabled) {320return;321}322advanced_options_enabled = p_enabled;323EditorExport::singleton->save_presets();324notify_property_list_changed();325}326327bool EditorExportPreset::are_advanced_options_enabled() const {328return advanced_options_enabled;329}330331void EditorExportPreset::set_dedicated_server(bool p_enable) {332dedicated_server = p_enable;333EditorExport::singleton->save_presets();334}335336bool EditorExportPreset::is_dedicated_server() const {337return dedicated_server;338}339340void EditorExportPreset::set_export_filter(ExportFilter p_filter) {341export_filter = p_filter;342EditorExport::singleton->save_presets();343}344345EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {346return export_filter;347}348349void EditorExportPreset::set_include_filter(const String &p_include) {350include_filter = p_include;351EditorExport::singleton->save_presets();352}353354String EditorExportPreset::get_include_filter() const {355return include_filter;356}357358void EditorExportPreset::set_export_path(const String &p_path) {359export_path = p_path;360/* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,361* this should be removed. */362if (export_path.is_absolute_path()) {363String res_path = OS::get_singleton()->get_resource_dir();364export_path = res_path.path_to_file(export_path);365}366EditorExport::singleton->save_presets();367}368369String EditorExportPreset::get_export_path() const {370return export_path;371}372373void EditorExportPreset::set_exclude_filter(const String &p_exclude) {374exclude_filter = p_exclude;375EditorExport::singleton->save_presets();376}377378String EditorExportPreset::get_exclude_filter() const {379return exclude_filter;380}381382void EditorExportPreset::add_export_file(const String &p_path) {383selected_files.insert(p_path);384EditorExport::singleton->save_presets();385}386387void EditorExportPreset::remove_export_file(const String &p_path) {388selected_files.erase(p_path);389EditorExport::singleton->save_presets();390}391392bool EditorExportPreset::has_export_file(const String &p_path) {393return selected_files.has(p_path);394}395396void EditorExportPreset::set_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_mode) {397if (p_mode == FileExportMode::MODE_FILE_NOT_CUSTOMIZED) {398customized_files.erase(p_path);399} else {400customized_files.insert(p_path, p_mode);401}402EditorExport::singleton->save_presets();403}404405EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_default) const {406HashMap<String, FileExportMode>::ConstIterator i = customized_files.find(p_path);407if (i) {408return i->value;409}410return p_default;411}412413void EditorExportPreset::add_patch(const String &p_path, int p_at_pos) {414ERR_FAIL_COND_EDMSG(patches.has(p_path), vformat("Failed to add patch \"%s\". Patches must be unique.", p_path));415416if (p_at_pos < 0) {417patches.push_back(p_path);418} else {419patches.insert(p_at_pos, p_path);420}421422EditorExport::singleton->save_presets();423}424425void EditorExportPreset::set_patch(int p_index, const String &p_path) {426remove_patch(p_index);427add_patch(p_path, p_index);428}429430String EditorExportPreset::get_patch(int p_index) {431ERR_FAIL_INDEX_V(p_index, patches.size(), String());432return patches[p_index];433}434435void EditorExportPreset::remove_patch(int p_index) {436ERR_FAIL_INDEX(p_index, patches.size());437patches.remove_at(p_index);438EditorExport::singleton->save_presets();439}440441void EditorExportPreset::set_patches(const Vector<String> &p_patches) {442patches = p_patches;443}444445Vector<String> EditorExportPreset::get_patches() const {446return patches;447}448449void EditorExportPreset::set_custom_features(const String &p_custom_features) {450custom_features = p_custom_features;451EditorExport::singleton->save_presets();452}453454String EditorExportPreset::get_custom_features() const {455return custom_features;456}457458void EditorExportPreset::set_enc_in_filter(const String &p_filter) {459enc_in_filters = p_filter;460EditorExport::singleton->save_presets();461}462463String EditorExportPreset::get_enc_in_filter() const {464return enc_in_filters;465}466467void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {468enc_ex_filters = p_filter;469EditorExport::singleton->save_presets();470}471472String EditorExportPreset::get_enc_ex_filter() const {473return enc_ex_filters;474}475476void EditorExportPreset::set_seed(uint64_t p_seed) {477seed = p_seed;478EditorExport::singleton->save_presets();479}480481uint64_t EditorExportPreset::get_seed() const {482return seed;483}484485void EditorExportPreset::set_enc_pck(bool p_enabled) {486enc_pck = p_enabled;487EditorExport::singleton->save_presets();488}489490bool EditorExportPreset::get_enc_pck() const {491return enc_pck;492}493494void EditorExportPreset::set_enc_directory(bool p_enabled) {495enc_directory = p_enabled;496EditorExport::singleton->save_presets();497}498499bool EditorExportPreset::get_enc_directory() const {500return enc_directory;501}502503void EditorExportPreset::set_script_encryption_key(const String &p_key) {504script_key = p_key;505EditorExport::singleton->save_presets();506}507508String EditorExportPreset::get_script_encryption_key() const {509return script_key;510}511512void EditorExportPreset::set_script_export_mode(int p_mode) {513script_mode = p_mode;514EditorExport::singleton->save_presets();515}516517int EditorExportPreset::get_script_export_mode() const {518return script_mode;519}520521Variant EditorExportPreset::get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid) const {522const String from_env = OS::get_singleton()->get_environment(p_env_var);523if (!from_env.is_empty()) {524if (r_valid) {525*r_valid = true;526}527return from_env;528}529return get(p_name, r_valid);530}531532_FORCE_INLINE_ bool _check_digits(const String &p_str) {533for (int i = 0; i < p_str.length(); i++) {534char32_t c = p_str.operator[](i);535if (!is_digit(c)) {536return false;537}538}539return true;540}541542String EditorExportPreset::get_version(const StringName &p_preset_string, bool p_windows_version) const {543String result = get(p_preset_string);544if (result.is_empty()) {545result = GLOBAL_GET("application/config/version");546547// Split and validate version number components.548const PackedStringArray result_split = result.split(".", false);549bool valid_version = !result_split.is_empty();550for (const String &E : result_split) {551if (!_check_digits(E)) {552valid_version = false;553break;554}555}556557if (valid_version) {558if (p_windows_version) {559// Modify version number to match Windows constraints (version numbers must have 4 components).560if (result_split.size() == 1) {561result = result + ".0.0.0";562} else if (result_split.size() == 2) {563result = result + ".0.0";564} else if (result_split.size() == 3) {565result = result + ".0";566} else {567result = vformat("%s.%s.%s.%s", result_split[0], result_split[1], result_split[2], result_split[3]);568}569} else {570result = String(".").join(result_split);571}572} else {573if (!result.is_empty()) {574WARN_PRINT(vformat("Invalid version number \"%s\". The version number can only contain numeric characters (0-9) and non-consecutive periods (.).", result));575}576if (p_windows_version) {577result = "1.0.0.0";578} else {579result = "1.0.0";580}581}582}583584return result;585}586587588