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

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -30,20 +30,17 @@
#include "codesign.h"
#include "core/crypto/crypto_core.h"
#include "core/io/dir_access.h"
#include "core/io/plist.h"
#include "editor/editor_paths.h"
#include "lipo.h"
#include "macho.h"
#include "core/io/plist.h"
#include "core/os/os.h"
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#include "modules/modules_enabled.gen.h" // For regex.
#include "modules/regex/regex.h"
#include <ctime>
#ifdef MODULE_REGEX_ENABLED
/*************************************************************************/
/* CodeSignCodeResources */
/*************************************************************************/
@ -214,7 +211,7 @@ bool CodeSignCodeResources::add_nested_file(const String &p_root, const String &
Vector<String> files_to_add;
if (LipO::is_lipo(p_exepath)) {
String tmp_path_name = EditorPaths::get_singleton()->get_cache_dir().path_join("_lipo");
String tmp_path_name = EditorPaths::get_singleton()->get_temp_dir().path_join("_lipo");
Error err = da->make_dir_recursive(tmp_path_name);
ERR_FAIL_COND_V_MSG(err != OK, false, vformat("CodeSign/CodeResources: Failed to create \"%s\" subfolder.", tmp_path_name));
LipO lip;
@ -1248,7 +1245,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
Vector<String> files_to_sign;
if (LipO::is_lipo(main_exe)) {
print_verbose(vformat("CodeSign: Executable is fat, extracting..."));
String tmp_path_name = EditorPaths::get_singleton()->get_cache_dir().path_join("_lipo");
String tmp_path_name = EditorPaths::get_singleton()->get_temp_dir().path_join("_lipo");
Error err = da->make_dir_recursive(tmp_path_name);
if (err != OK) {
r_error_msg = vformat(TTR("Failed to create \"%s\" subfolder."), tmp_path_name);
@ -1381,14 +1378,14 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
r_error_msg = TTR("Invalid entitlements file.");
ERR_FAIL_V_MSG(FAILED, "CodeSign: Invalid entitlements file.");
}
cet = Ref<CodeSignEntitlementsText>(memnew(CodeSignEntitlementsText(entitlements)));
ceb = Ref<CodeSignEntitlementsBinary>(memnew(CodeSignEntitlementsBinary(entitlements)));
cet.instantiate(entitlements);
ceb.instantiate(entitlements);
}
print_verbose("CodeSign: Generating requirements...");
Ref<CodeSignRequirements> rq;
String team_id = "";
rq = Ref<CodeSignRequirements>(memnew(CodeSignRequirements()));
rq.instantiate();
// Sign executables.
for (int i = 0; i < files_to_sign.size(); i++) {
@ -1487,7 +1484,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
print_verbose("CodeSign: Generating signature...");
Ref<CodeSignSignature> cs;
cs = Ref<CodeSignSignature>(memnew(CodeSignSignature()));
cs.instantiate();
print_verbose("CodeSign: Writing signature superblob...");
// Write signature data to the executable.
@ -1569,5 +1566,3 @@ Error CodeSign::codesign(bool p_use_hardened_runtime, bool p_force, const String
ERR_FAIL_V_MSG(FAILED, "CodeSign: Unknown object type.");
}
}
#endif // MODULE_REGEX_ENABLED

View file

@ -41,19 +41,9 @@
// - Requirements code generator is not implemented (only hard-coded requirements for the ad-hoc signing is supported).
// - RFC5652/CMS blob generation is not implemented, supports ad-hoc signing only.
#include "core/crypto/crypto_core.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/plist.h"
#include "core/object/ref_counted.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif
#ifdef MODULE_REGEX_ENABLED
/*************************************************************************/
/* CodeSignCodeResources */
/*************************************************************************/
@ -166,7 +156,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000002; };
virtual uint32_t get_index_type() const override { return 0x00000002; }
virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
@ -188,7 +178,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000005; };
virtual uint32_t get_index_type() const override { return 0x00000005; }
virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
@ -210,7 +200,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000007; };
virtual uint32_t get_index_type() const override { return 0x00000007; }
virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
@ -285,7 +275,7 @@ private:
uint32_t spare3; // Not used.
uint64_t code_limit_64; // Set to 0 and ignore.
// Version 0x20400
uint64_t exec_seg_base; // Start of the signed code segmet.
uint64_t exec_seg_base; // Start of the signed code segment.
uint64_t exec_seg_limit; // Code segment (__TEXT) vmsize.
uint64_t exec_seg_flags; // Executable segment flags.
// Version 0x20500
@ -311,7 +301,7 @@ public:
virtual PackedByteArray get_hash_sha256() const override;
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000000; };
virtual uint32_t get_index_type() const override { return 0x00000000; }
virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
@ -330,7 +320,7 @@ public:
virtual PackedByteArray get_hash_sha256() const override;
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00010000; };
virtual uint32_t get_index_type() const override { return 0x00010000; }
virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
@ -362,6 +352,4 @@ public:
static Error codesign(bool p_use_hardened_runtime, bool p_force, const String &p_path, const String &p_ent_path, String &r_error_msg);
};
#endif // MODULE_REGEX_ENABLED
#endif // CODESIGN_H

View file

@ -83,8 +83,12 @@ void EditorExport::_save() {
config->set_value(section, "include_filter", preset->get_include_filter());
config->set_value(section, "exclude_filter", preset->get_exclude_filter());
config->set_value(section, "export_path", preset->get_export_path());
config->set_value(section, "patches", preset->get_patches());
config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter());
config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
config->set_value(section, "seed", preset->get_seed());
config->set_value(section, "encrypt_pck", preset->get_enc_pck());
config->set_value(section, "encrypt_directory", preset->get_enc_directory());
config->set_value(section, "script_export_mode", preset->get_script_export_mode());
@ -124,7 +128,17 @@ void EditorExport::_bind_methods() {
void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
export_platforms.push_back(p_platform);
should_update_presets = true;
should_reload_presets = true;
}
void EditorExport::remove_export_platform(const Ref<EditorExportPlatform> &p_platform) {
export_platforms.erase(p_platform);
p_platform->cleanup();
should_update_presets = true;
should_reload_presets = true;
}
int EditorExport::get_export_platform_count() {
@ -242,9 +256,9 @@ void EditorExport::load_config() {
}
}
if (!preset.is_valid()) {
if (preset.is_null()) {
index++;
ERR_CONTINUE(!preset.is_valid());
continue; // Unknown platform, skip without error (platform might be loaded later).
}
preset->set_name(config->get_value(section, "name"));
@ -293,7 +307,11 @@ void EditorExport::load_config() {
preset->set_exclude_filter(config->get_value(section, "exclude_filter"));
preset->set_export_path(config->get_value(section, "export_path", ""));
preset->set_script_export_mode(config->get_value(section, "script_export_mode", EditorExportPreset::MODE_SCRIPT_BINARY_TOKENS_COMPRESSED));
preset->set_patches(config->get_value(section, "patches", Vector<String>()));
if (config->has_section_key(section, "seed")) {
preset->set_seed(config->get_value(section, "seed"));
}
if (config->has_section_key(section, "encrypt_pck")) {
preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
}
@ -343,6 +361,12 @@ void EditorExport::load_config() {
void EditorExport::update_export_presets() {
HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
if (should_reload_presets) {
should_reload_presets = false;
export_presets.clear();
load_config();
}
for (int i = 0; i < export_platforms.size(); i++) {
Ref<EditorExportPlatform> platform = export_platforms[i];

View file

@ -47,6 +47,7 @@ class EditorExport : public Node {
Timer *save_timer = nullptr;
bool block_save = false;
bool should_update_presets = false;
bool should_reload_presets = false;
static EditorExport *singleton;
@ -66,6 +67,7 @@ public:
void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
int get_export_platform_count();
Ref<EditorExportPlatform> get_export_platform(int p_idx);
void remove_export_platform(const Ref<EditorExportPlatform> &p_platform);
void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1);
int get_export_preset_count() const;

File diff suppressed because it is too large Load diff

View file

@ -53,9 +53,18 @@ protected:
static void _bind_methods();
public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
typedef Error (*EditorExportRemoveFunction)(void *p_userdata, const String &p_path);
typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
enum DebugFlags {
DEBUG_FLAG_DUMB_CLIENT = 1,
DEBUG_FLAG_REMOTE_DEBUG = 2,
DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4,
DEBUG_FLAG_VIEW_COLLISIONS = 8,
DEBUG_FLAG_VIEW_NAVIGATION = 16,
};
enum ExportMessageType {
EXPORT_MESSAGE_NONE,
EXPORT_MESSAGE_INFO,
@ -74,6 +83,7 @@ private:
uint64_t ofs = 0;
uint64_t size = 0;
bool encrypted = false;
bool removal = false;
Vector<uint8_t> md5;
CharString path_utf8;
@ -92,6 +102,8 @@ private:
struct ZipData {
void *zip = nullptr;
EditorProgress *ep = nullptr;
Vector<SharedObject> *so_files = nullptr;
int file_count = 0;
};
Vector<ExportMessage> messages;
@ -100,13 +112,30 @@ private:
void _export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths);
void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
static bool _check_hash(const uint8_t *p_hash, const Vector<uint8_t> &p_data);
static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
static Error _save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
static Error _pack_add_shared_object(void *p_userdata, const SharedObject &p_so);
static Error _remove_pack_file(void *p_userdata, const String &p_path);
static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
static Error _save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
static Error _zip_add_shared_object(void *p_userdata, const SharedObject &p_so);
struct ScriptCallbackData {
Callable file_cb;
Callable so_cb;
};
static Error _script_save_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key, uint64_t p_seed);
static Error _script_add_shared_object(void *p_userdata, const SharedObject &p_so);
void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude);
void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude);
static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
static Vector<uint8_t> _filter_extension_list_config_file(const String &p_config_path, const HashSet<String> &p_paths);
struct FileExportCache {
uint64_t source_modified_time = 0;
@ -126,23 +155,55 @@ private:
protected:
struct ExportNotifier {
ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags);
~ExportNotifier();
};
HashSet<String> get_features(const Ref<EditorExportPreset> &p_preset, bool p_debug) const;
bool exists_export_template(const String &template_file_name, String *err) const;
String find_export_template(const String &template_file_name, String *err = nullptr) const;
void gen_export_flags(Vector<String> &r_flags, int p_flags);
void gen_debug_flags(Vector<String> &r_flags, int p_flags);
Dictionary _find_export_template(const String &p_template_file_name) const {
Dictionary ret;
String err;
String path = find_export_template(p_template_file_name, &err);
ret["result"] = (err.is_empty() && !path.is_empty()) ? OK : FAILED;
ret["path"] = path;
ret["error_string"] = err;
return ret;
}
bool exists_export_template(const String &p_template_file_name, String *r_err) const;
String find_export_template(const String &p_template_file_name, String *r_err = nullptr) const;
Vector<String> gen_export_flags(BitField<EditorExportPlatform::DebugFlags> p_flags);
virtual void zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name);
Error _ssh_run_on_remote(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, Array r_output = Array(), int p_port_fwd = -1) const {
String pipe;
Error err = ssh_run_on_remote(p_host, p_port, p_ssh_args, p_cmd_args, &pipe, p_port_fwd);
r_output.push_back(pipe);
return err;
}
OS::ProcessID _ssh_run_on_remote_no_wait(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, int p_port_fwd = -1) const {
OS::ProcessID pid = 0;
Error err = ssh_run_on_remote_no_wait(p_host, p_port, p_ssh_args, p_cmd_args, &pid, p_port_fwd);
if (err != OK) {
return -1;
} else {
return pid;
}
}
Error ssh_run_on_remote(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, String *r_out = nullptr, int p_port_fwd = -1) const;
Error ssh_run_on_remote_no_wait(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, OS::ProcessID *r_pid = nullptr, int p_port_fwd = -1) const;
Error ssh_push_to_remote(const String &p_host, const String &p_port, const Vector<String> &p_scp_args, const String &p_src_file, const String &p_dst_file) const;
Error _load_patches(const Vector<String> &p_patches);
void _unload_patches();
Ref<Image> _load_icon_or_splash_image(const String &p_path, Error *r_error) const;
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0;
@ -195,6 +256,21 @@ public:
return messages[p_index];
}
virtual ExportMessageType _get_message_type(int p_index) const {
ERR_FAIL_INDEX_V(p_index, messages.size(), EXPORT_MESSAGE_NONE);
return messages[p_index].msg_type;
}
virtual String _get_message_category(int p_index) const {
ERR_FAIL_INDEX_V(p_index, messages.size(), String());
return messages[p_index].category;
}
virtual String _get_message_text(int p_index) const {
ERR_FAIL_INDEX_V(p_index, messages.size(), String());
return messages[p_index].text;
}
virtual ExportMessageType get_worst_message_type() const {
ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
for (int i = 0; i < messages.size(); i++) {
@ -203,6 +279,8 @@ public:
return worst_type;
}
Dictionary get_internal_export_files(const Ref<EditorExportPreset> &p_preset, bool p_debug);
static Vector<String> get_forced_export_files();
virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);
@ -216,10 +294,22 @@ public:
virtual String get_name() const = 0;
virtual Ref<Texture2D> get_logo() const = 0;
Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr);
Array get_current_presets() const;
Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr);
Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
Error _export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, const Callable &p_save_func, const Callable &p_so_func);
Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_save_func, EditorExportRemoveFunction p_remove_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr);
Dictionary _save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, bool p_embed = false);
Dictionary _save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
Dictionary _save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
Dictionary _save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr, EditorExportRemoveFunction p_remove_func = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr);
Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr);
Error save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr);
Error save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr);
virtual bool poll_export() { return false; }
virtual int get_options_count() const { return 0; }
@ -229,31 +319,29 @@ public:
virtual String get_option_tooltip(int p_device) const { return ""; }
virtual String get_device_architecture(int p_device) const { return ""; }
enum DebugFlags {
DEBUG_FLAG_DUMB_CLIENT = 1,
DEBUG_FLAG_REMOTE_DEBUG = 2,
DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4,
DEBUG_FLAG_VIEW_COLLISIONS = 8,
DEBUG_FLAG_VIEW_NAVIGATION = 16,
};
virtual void cleanup() {}
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) { return OK; }
virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const;
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const;
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const = 0;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const = 0;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0;
virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) = 0;
virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0);
virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0);
virtual Error export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0);
virtual Error export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0);
virtual void get_platform_features(List<String> *r_features) const = 0;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {}
virtual String get_debug_protocol() const { return "tcp://"; }
virtual HashMap<String, Variant> get_custom_project_settings(const Ref<EditorExportPreset> &p_preset) const { return HashMap<String, Variant>(); }
EditorExportPlatform();
};
VARIANT_ENUM_CAST(EditorExportPlatform::ExportMessageType)
VARIANT_BITFIELD_CAST(EditorExportPlatform::DebugFlags);
#endif // EDITOR_EXPORT_PLATFORM_H

View file

@ -0,0 +1,357 @@
/**************************************************************************/
/* editor_export_platform_extension.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "editor_export_platform_extension.h"
void EditorExportPlatformExtension::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_config_error", "error_text"), &EditorExportPlatformExtension::set_config_error);
ClassDB::bind_method(D_METHOD("get_config_error"), &EditorExportPlatformExtension::get_config_error);
ClassDB::bind_method(D_METHOD("set_config_missing_templates", "missing_templates"), &EditorExportPlatformExtension::set_config_missing_templates);
ClassDB::bind_method(D_METHOD("get_config_missing_templates"), &EditorExportPlatformExtension::get_config_missing_templates);
GDVIRTUAL_BIND(_get_preset_features, "preset");
GDVIRTUAL_BIND(_is_executable, "path");
GDVIRTUAL_BIND(_get_export_options);
GDVIRTUAL_BIND(_should_update_export_options);
GDVIRTUAL_BIND(_get_export_option_visibility, "preset", "option");
GDVIRTUAL_BIND(_get_export_option_warning, "preset", "option");
GDVIRTUAL_BIND(_get_os_name);
GDVIRTUAL_BIND(_get_name);
GDVIRTUAL_BIND(_get_logo);
GDVIRTUAL_BIND(_poll_export);
GDVIRTUAL_BIND(_get_options_count);
GDVIRTUAL_BIND(_get_options_tooltip);
GDVIRTUAL_BIND(_get_option_icon, "device");
GDVIRTUAL_BIND(_get_option_label, "device");
GDVIRTUAL_BIND(_get_option_tooltip, "device");
GDVIRTUAL_BIND(_get_device_architecture, "device");
GDVIRTUAL_BIND(_cleanup);
GDVIRTUAL_BIND(_run, "preset", "device", "debug_flags");
GDVIRTUAL_BIND(_get_run_icon);
GDVIRTUAL_BIND(_can_export, "preset", "debug");
GDVIRTUAL_BIND(_has_valid_export_configuration, "preset", "debug");
GDVIRTUAL_BIND(_has_valid_project_configuration, "preset");
GDVIRTUAL_BIND(_get_binary_extensions, "preset");
GDVIRTUAL_BIND(_export_project, "preset", "debug", "path", "flags");
GDVIRTUAL_BIND(_export_pack, "preset", "debug", "path", "flags");
GDVIRTUAL_BIND(_export_zip, "preset", "debug", "path", "flags");
GDVIRTUAL_BIND(_export_pack_patch, "preset", "debug", "path", "patches", "flags");
GDVIRTUAL_BIND(_export_zip_patch, "preset", "debug", "path", "patches", "flags");
GDVIRTUAL_BIND(_get_platform_features);
GDVIRTUAL_BIND(_get_debug_protocol);
}
void EditorExportPlatformExtension::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
Vector<String> ret;
if (GDVIRTUAL_CALL(_get_preset_features, p_preset, ret) && r_features) {
for (const String &E : ret) {
r_features->push_back(E);
}
}
}
bool EditorExportPlatformExtension::is_executable(const String &p_path) const {
bool ret = false;
GDVIRTUAL_CALL(_is_executable, p_path, ret);
return ret;
}
void EditorExportPlatformExtension::get_export_options(List<ExportOption> *r_options) const {
TypedArray<Dictionary> ret;
if (GDVIRTUAL_CALL(_get_export_options, ret) && r_options) {
for (const Variant &var : ret) {
const Dictionary &d = var;
ERR_CONTINUE(!d.has("name"));
ERR_CONTINUE(!d.has("type"));
PropertyInfo pinfo = PropertyInfo::from_dict(d);
ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE));
ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX);
Variant default_value;
if (d.has("default_value")) {
default_value = d["default_value"];
}
bool update_visibility = false;
if (d.has("update_visibility")) {
update_visibility = d["update_visibility"];
}
bool required = false;
if (d.has("required")) {
required = d["required"];
}
r_options->push_back(ExportOption(pinfo, default_value, update_visibility, required));
}
}
}
bool EditorExportPlatformExtension::should_update_export_options() {
bool ret = false;
GDVIRTUAL_CALL(_should_update_export_options, ret);
return ret;
}
bool EditorExportPlatformExtension::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const {
bool ret = true;
GDVIRTUAL_CALL(_get_export_option_visibility, Ref<EditorExportPreset>(p_preset), p_option, ret);
return ret;
}
String EditorExportPlatformExtension::get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const {
String ret;
GDVIRTUAL_CALL(_get_export_option_warning, Ref<EditorExportPreset>(p_preset), p_name, ret);
return ret;
}
String EditorExportPlatformExtension::get_os_name() const {
String ret;
GDVIRTUAL_CALL(_get_os_name, ret);
return ret;
}
String EditorExportPlatformExtension::get_name() const {
String ret;
GDVIRTUAL_CALL(_get_name, ret);
return ret;
}
Ref<Texture2D> EditorExportPlatformExtension::get_logo() const {
Ref<Texture2D> ret;
GDVIRTUAL_CALL(_get_logo, ret);
return ret;
}
bool EditorExportPlatformExtension::poll_export() {
bool ret = false;
GDVIRTUAL_CALL(_poll_export, ret);
return ret;
}
int EditorExportPlatformExtension::get_options_count() const {
int ret = 0;
GDVIRTUAL_CALL(_get_options_count, ret);
return ret;
}
String EditorExportPlatformExtension::get_options_tooltip() const {
String ret;
GDVIRTUAL_CALL(_get_options_tooltip, ret);
return ret;
}
Ref<ImageTexture> EditorExportPlatformExtension::get_option_icon(int p_index) const {
Ref<ImageTexture> ret;
if (GDVIRTUAL_CALL(_get_option_icon, p_index, ret)) {
return ret;
}
return EditorExportPlatform::get_option_icon(p_index);
}
String EditorExportPlatformExtension::get_option_label(int p_device) const {
String ret;
GDVIRTUAL_CALL(_get_option_label, p_device, ret);
return ret;
}
String EditorExportPlatformExtension::get_option_tooltip(int p_device) const {
String ret;
GDVIRTUAL_CALL(_get_option_tooltip, p_device, ret);
return ret;
}
String EditorExportPlatformExtension::get_device_architecture(int p_device) const {
String ret;
GDVIRTUAL_CALL(_get_device_architecture, p_device, ret);
return ret;
}
void EditorExportPlatformExtension::cleanup() {
GDVIRTUAL_CALL(_cleanup);
}
Error EditorExportPlatformExtension::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
Error ret = OK;
GDVIRTUAL_CALL(_run, p_preset, p_device, p_debug_flags, ret);
return ret;
}
Ref<Texture2D> EditorExportPlatformExtension::get_run_icon() const {
Ref<Texture2D> ret;
if (GDVIRTUAL_CALL(_get_run_icon, ret)) {
return ret;
}
return EditorExportPlatform::get_run_icon();
}
bool EditorExportPlatformExtension::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
bool ret = false;
config_error = r_error;
config_missing_templates = r_missing_templates;
if (GDVIRTUAL_CALL(_can_export, p_preset, p_debug, ret)) {
r_error = config_error;
r_missing_templates = config_missing_templates;
return ret;
}
return EditorExportPlatform::can_export(p_preset, r_error, r_missing_templates, p_debug);
}
bool EditorExportPlatformExtension::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
bool ret = false;
config_error = r_error;
config_missing_templates = r_missing_templates;
if (GDVIRTUAL_CALL(_has_valid_export_configuration, p_preset, p_debug, ret)) {
r_error = config_error;
r_missing_templates = config_missing_templates;
}
return ret;
}
bool EditorExportPlatformExtension::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
bool ret = false;
config_error = r_error;
if (GDVIRTUAL_CALL(_has_valid_project_configuration, p_preset, ret)) {
r_error = config_error;
}
return ret;
}
List<String> EditorExportPlatformExtension::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
List<String> ret_list;
Vector<String> ret;
if (GDVIRTUAL_CALL(_get_binary_extensions, p_preset, ret)) {
for (const String &E : ret) {
ret_list.push_back(E);
}
}
return ret_list;
}
Error EditorExportPlatformExtension::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);
Error ret = FAILED;
GDVIRTUAL_CALL(_export_project, p_preset, p_debug, p_path, p_flags, ret);
return ret;
}
Error EditorExportPlatformExtension::export_pack(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);
Error ret = FAILED;
if (GDVIRTUAL_CALL(_export_pack, p_preset, p_debug, p_path, p_flags, ret)) {
return ret;
}
return save_pack(p_preset, p_debug, p_path);
}
Error EditorExportPlatformExtension::export_zip(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);
Error ret = FAILED;
if (GDVIRTUAL_CALL(_export_zip, p_preset, p_debug, p_path, p_flags, ret)) {
return ret;
}
return save_zip(p_preset, p_debug, p_path);
}
Error EditorExportPlatformExtension::export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches);
if (err != OK) {
return err;
}
Error ret = FAILED;
if (GDVIRTUAL_CALL(_export_pack_patch, p_preset, p_debug, p_path, p_patches, p_flags, ret)) {
_unload_patches();
return ret;
}
err = save_pack_patch(p_preset, p_debug, p_path);
_unload_patches();
return err;
}
Error EditorExportPlatformExtension::export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches);
if (err != OK) {
return err;
}
Error ret = FAILED;
if (GDVIRTUAL_CALL(_export_zip_patch, p_preset, p_debug, p_path, p_patches, p_flags, ret)) {
_unload_patches();
return ret;
}
err = save_zip_patch(p_preset, p_debug, p_path);
_unload_patches();
return err;
}
void EditorExportPlatformExtension::get_platform_features(List<String> *r_features) const {
Vector<String> ret;
if (GDVIRTUAL_CALL(_get_platform_features, ret) && r_features) {
for (const String &E : ret) {
r_features->push_back(E);
}
}
}
String EditorExportPlatformExtension::get_debug_protocol() const {
String ret;
if (GDVIRTUAL_CALL(_get_debug_protocol, ret)) {
return ret;
}
return EditorExportPlatform::get_debug_protocol();
}
EditorExportPlatformExtension::EditorExportPlatformExtension() {
//NOP
}
EditorExportPlatformExtension::~EditorExportPlatformExtension() {
//NOP
}

View file

@ -0,0 +1,155 @@
/**************************************************************************/
/* editor_export_platform_extension.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_EXPORT_PLATFORM_EXTENSION_H
#define EDITOR_EXPORT_PLATFORM_EXTENSION_H
#include "editor_export_platform.h"
#include "editor_export_preset.h"
class EditorExportPlatformExtension : public EditorExportPlatform {
GDCLASS(EditorExportPlatformExtension, EditorExportPlatform);
mutable String config_error;
mutable bool config_missing_templates = false;
protected:
static void _bind_methods();
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
GDVIRTUAL1RC_REQUIRED(Vector<String>, _get_preset_features, Ref<EditorExportPreset>);
virtual bool is_executable(const String &p_path) const override;
GDVIRTUAL1RC(bool, _is_executable, const String &);
virtual void get_export_options(List<ExportOption> *r_options) const override;
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_export_options);
virtual bool should_update_export_options() override;
GDVIRTUAL0R(bool, _should_update_export_options);
virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override;
GDVIRTUAL2RC(bool, _get_export_option_visibility, Ref<EditorExportPreset>, const String &);
virtual String get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const override;
GDVIRTUAL2RC(String, _get_export_option_warning, Ref<EditorExportPreset>, const StringName &);
virtual String get_os_name() const override;
GDVIRTUAL0RC_REQUIRED(String, _get_os_name);
virtual String get_name() const override;
GDVIRTUAL0RC_REQUIRED(String, _get_name);
virtual Ref<Texture2D> get_logo() const override;
GDVIRTUAL0RC_REQUIRED(Ref<Texture2D>, _get_logo);
virtual bool poll_export() override;
GDVIRTUAL0R(bool, _poll_export);
virtual int get_options_count() const override;
GDVIRTUAL0RC(int, _get_options_count);
virtual String get_options_tooltip() const override;
GDVIRTUAL0RC(String, _get_options_tooltip);
virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
GDVIRTUAL1RC(Ref<ImageTexture>, _get_option_icon, int);
virtual String get_option_label(int p_device) const override;
GDVIRTUAL1RC(String, _get_option_label, int);
virtual String get_option_tooltip(int p_device) const override;
GDVIRTUAL1RC(String, _get_option_tooltip, int);
virtual String get_device_architecture(int p_device) const override;
GDVIRTUAL1RC(String, _get_device_architecture, int);
virtual void cleanup() override;
GDVIRTUAL0(_cleanup);
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
GDVIRTUAL3R(Error, _run, Ref<EditorExportPreset>, int, BitField<EditorExportPlatform::DebugFlags>);
virtual Ref<Texture2D> get_run_icon() const override;
GDVIRTUAL0RC(Ref<Texture2D>, _get_run_icon);
void set_config_error(const String &p_error) const {
config_error = p_error;
}
String get_config_error() const {
return config_error;
}
void set_config_missing_templates(bool p_missing_templates) const {
config_missing_templates = p_missing_templates;
}
bool get_config_missing_templates() const {
return config_missing_templates;
}
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
GDVIRTUAL2RC(bool, _can_export, Ref<EditorExportPreset>, bool);
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
GDVIRTUAL2RC_REQUIRED(bool, _has_valid_export_configuration, Ref<EditorExportPreset>, bool);
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
GDVIRTUAL1RC_REQUIRED(bool, _has_valid_project_configuration, Ref<EditorExportPreset>);
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
GDVIRTUAL1RC_REQUIRED(Vector<String>, _get_binary_extensions, Ref<EditorExportPreset>);
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
GDVIRTUAL4R_REQUIRED(Error, _export_project, Ref<EditorExportPreset>, bool, const String &, BitField<EditorExportPlatform::DebugFlags>);
virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
GDVIRTUAL4R(Error, _export_pack, Ref<EditorExportPreset>, bool, const String &, BitField<EditorExportPlatform::DebugFlags>);
virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
GDVIRTUAL4R(Error, _export_zip, Ref<EditorExportPreset>, bool, const String &, BitField<EditorExportPlatform::DebugFlags>);
virtual Error export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
GDVIRTUAL5R(Error, _export_pack_patch, Ref<EditorExportPreset>, bool, const String &, const Vector<String> &, BitField<EditorExportPlatform::DebugFlags>);
virtual Error export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
GDVIRTUAL5R(Error, _export_zip_patch, Ref<EditorExportPreset>, bool, const String &, const Vector<String> &, BitField<EditorExportPlatform::DebugFlags>);
virtual void get_platform_features(List<String> *r_features) const override;
GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_platform_features);
virtual String get_debug_protocol() const override;
GDVIRTUAL0RC(String, _get_debug_protocol);
EditorExportPlatformExtension();
~EditorExportPlatformExtension();
};
#endif // EDITOR_EXPORT_PLATFORM_EXTENSION_H

View file

@ -115,7 +115,7 @@ bool EditorExportPlatformPC::has_valid_project_configuration(const Ref<EditorExp
return true;
}
Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
Error EditorExportPlatformPC::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);
Error err = prepare_template(p_preset, p_debug, p_path, p_flags);
@ -129,7 +129,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
return err;
}
Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
if (!DirAccess::exists(p_path.get_base_dir())) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist."));
return ERR_FILE_BAD_PATH;
@ -182,7 +182,7 @@ Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_
return err;
}
Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
String pck_path;
if (p_preset->get("binary_format/embed_pck")) {
pck_path = p_path;
@ -194,7 +194,7 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset>
int64_t embedded_pos;
int64_t embedded_size;
Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size);
Error err = save_pack(p_preset, p_debug, pck_path, &so_files, nullptr, nullptr, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size);
if (err == OK && p_preset->get("binary_format/embed_pck")) {
if (embedded_size >= 0x100000000 && String(p_preset->get("binary_format/architecture")).contains("32")) {
add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
@ -222,9 +222,15 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset>
err = da->make_dir_recursive(target_path);
if (err == OK) {
err = da->copy_dir(src_path, target_path, -1, true);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), vformat(TTR("Failed to copy shared object \"%s\"."), src_path));
}
}
} else {
err = da->copy(src_path, target_path);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("GDExtension"), vformat(TTR("Failed to copy shared object \"%s\"."), src_path));
}
if (err == OK) {
err = sign_shared_object(p_preset, p_debug, target_path);
}

View file

@ -54,13 +54,13 @@ public:
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;
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 Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0;
virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; };
virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags);
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) { return OK; }
virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags);
void set_name(const String &p_name);
void set_os_name(const String &p_name);

View file

@ -31,12 +31,7 @@
#include "editor_export_plugin.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#include "editor/export/editor_export_platform.h"
#include "scene/resources/resource_format_text.h"
void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
if (p_preset.is_valid()) {
@ -48,6 +43,14 @@ Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const {
return export_preset;
}
Ref<EditorExportPlatform> EditorExportPlugin::get_export_platform() const {
if (export_preset.is_valid()) {
return export_preset->get_platform();
} else {
return Ref<EditorExportPlatform>();
}
}
void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) {
ExtraFile ef;
ef.data = p_file;
@ -132,7 +135,7 @@ Vector<String> EditorExportPlugin::get_ios_project_static_libs() const {
}
Variant EditorExportPlugin::get_option(const StringName &p_name) const {
ERR_FAIL_NULL_V(export_preset, Variant());
ERR_FAIL_COND_V(export_preset.is_null(), Variant());
return export_preset->get(p_name);
}
@ -179,7 +182,7 @@ bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatfo
Ref<Resource> EditorExportPlugin::_customize_resource(const Ref<Resource> &p_resource, const String &p_path) {
Ref<Resource> ret;
GDVIRTUAL_REQUIRED_CALL(_customize_resource, p_resource, p_path, ret);
GDVIRTUAL_CALL(_customize_resource, p_resource, p_path, ret);
return ret;
}
@ -191,13 +194,13 @@ bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform>
Node *EditorExportPlugin::_customize_scene(Node *p_root, const String &p_path) {
Node *ret = nullptr;
GDVIRTUAL_REQUIRED_CALL(_customize_scene, p_root, p_path, ret);
GDVIRTUAL_CALL(_customize_scene, p_root, p_path, ret);
return ret;
}
uint64_t EditorExportPlugin::_get_customization_configuration_hash() const {
uint64_t ret = 0;
GDVIRTUAL_REQUIRED_CALL(_get_customization_configuration_hash, ret);
GDVIRTUAL_CALL(_get_customization_configuration_hash, ret);
return ret;
}
@ -211,7 +214,7 @@ void EditorExportPlugin::_end_customize_resources() {
String EditorExportPlugin::get_name() const {
String ret;
GDVIRTUAL_REQUIRED_CALL(_get_name, ret);
GDVIRTUAL_CALL(_get_name, ret);
return ret;
}
@ -221,6 +224,10 @@ bool EditorExportPlugin::supports_platform(const Ref<EditorExportPlatform> &p_ex
return ret;
}
PackedStringArray EditorExportPlugin::get_export_features(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
return _get_export_features(p_export_platform, p_debug);
}
PackedStringArray EditorExportPlugin::get_android_dependencies(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_android_dependencies, p_export_platform, p_debug, ret);
@ -283,6 +290,12 @@ bool EditorExportPlugin::_should_update_export_options(const Ref<EditorExportPla
return ret;
}
bool EditorExportPlugin::_get_export_option_visibility(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const {
bool ret = true;
GDVIRTUAL_CALL(_get_export_option_visibility, p_export_platform, p_option_name, ret);
return ret;
}
String EditorExportPlugin::_get_export_option_warning(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const {
String ret;
GDVIRTUAL_CALL(_get_export_option_warning, p_export_platform, p_option_name, ret);
@ -321,6 +334,9 @@ void EditorExportPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
ClassDB::bind_method(D_METHOD("get_option", "name"), &EditorExportPlugin::get_option);
ClassDB::bind_method(D_METHOD("get_export_preset"), &EditorExportPlugin::get_export_preset);
ClassDB::bind_method(D_METHOD("get_export_platform"), &EditorExportPlugin::get_export_platform);
GDVIRTUAL_BIND(_export_file, "path", "type", "features");
GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags");
GDVIRTUAL_BIND(_export_end);
@ -339,6 +355,7 @@ void EditorExportPlugin::_bind_methods() {
GDVIRTUAL_BIND(_get_export_options, "platform");
GDVIRTUAL_BIND(_get_export_options_overrides, "platform");
GDVIRTUAL_BIND(_should_update_export_options, "platform");
GDVIRTUAL_BIND(_get_export_option_visibility, "platform", "option");
GDVIRTUAL_BIND(_get_export_option_warning, "platform", "option");
GDVIRTUAL_BIND(_get_export_features, "platform", "debug");
@ -353,8 +370,3 @@ void EditorExportPlugin::_bind_methods() {
GDVIRTUAL_BIND(_get_android_manifest_application_element_contents, "platform", "debug");
GDVIRTUAL_BIND(_get_android_manifest_element_contents, "platform", "debug");
}
EditorExportPlugin::EditorExportPlugin() {
EDITOR_DEF("export/ssh/ssh", "");
EDITOR_DEF("export/ssh/scp", "");
}

View file

@ -31,7 +31,6 @@
#ifndef EDITOR_EXPORT_PLUGIN_H
#define EDITOR_EXPORT_PLUGIN_H
#include "core/extension/gdextension.h"
#include "core/os/shared_object.h"
#include "editor_export_platform.h"
#include "editor_export_preset.h"
@ -91,6 +90,7 @@ class EditorExportPlugin : public RefCounted {
protected:
void set_export_preset(const Ref<EditorExportPreset> &p_preset);
Ref<EditorExportPreset> get_export_preset() const;
Ref<EditorExportPlatform> get_export_platform() const;
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
@ -118,11 +118,11 @@ protected:
GDVIRTUAL0(_export_end)
GDVIRTUAL2RC(bool, _begin_customize_resources, const Ref<EditorExportPlatform> &, const Vector<String> &)
GDVIRTUAL2R(Ref<Resource>, _customize_resource, const Ref<Resource> &, String)
GDVIRTUAL2R_REQUIRED(Ref<Resource>, _customize_resource, const Ref<Resource> &, String)
GDVIRTUAL2RC(bool, _begin_customize_scenes, const Ref<EditorExportPlatform> &, const Vector<String> &)
GDVIRTUAL2R(Node *, _customize_scene, Node *, String)
GDVIRTUAL0RC(uint64_t, _get_customization_configuration_hash)
GDVIRTUAL2R_REQUIRED(Node *, _customize_scene, Node *, String)
GDVIRTUAL0RC_REQUIRED(uint64_t, _get_customization_configuration_hash)
GDVIRTUAL0(_end_customize_scenes)
GDVIRTUAL0(_end_customize_resources)
@ -131,9 +131,10 @@ protected:
GDVIRTUAL1RC(TypedArray<Dictionary>, _get_export_options, const Ref<EditorExportPlatform> &);
GDVIRTUAL1RC(Dictionary, _get_export_options_overrides, const Ref<EditorExportPlatform> &);
GDVIRTUAL1RC(bool, _should_update_export_options, const Ref<EditorExportPlatform> &);
GDVIRTUAL2RC(bool, _get_export_option_visibility, const Ref<EditorExportPlatform> &, String);
GDVIRTUAL2RC(String, _get_export_option_warning, const Ref<EditorExportPlatform> &, String);
GDVIRTUAL0RC(String, _get_name)
GDVIRTUAL0RC_REQUIRED(String, _get_name)
GDVIRTUAL1RC(bool, _supports_platform, const Ref<EditorExportPlatform> &);
@ -159,12 +160,14 @@ protected:
virtual void _get_export_options(const Ref<EditorExportPlatform> &p_export_platform, List<EditorExportPlatform::ExportOption> *r_options) const;
virtual Dictionary _get_export_options_overrides(const Ref<EditorExportPlatform> &p_export_platform) const;
virtual bool _should_update_export_options(const Ref<EditorExportPlatform> &p_export_platform) const;
virtual bool _get_export_option_visibility(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const;
virtual String _get_export_option_warning(const Ref<EditorExportPlatform> &p_export_platform, const String &p_option_name) const;
public:
virtual String get_name() const;
virtual bool supports_platform(const Ref<EditorExportPlatform> &p_export_platform) const;
PackedStringArray get_export_features(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual PackedStringArray get_android_dependencies(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual PackedStringArray get_android_dependencies_maven_repos(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
@ -182,8 +185,6 @@ public:
String get_ios_cpp_code() const;
const Vector<String> &get_macos_plugin_files() const;
Variant get_option(const StringName &p_name) const;
EditorExportPlugin();
};
#endif // EDITOR_EXPORT_PLUGIN_H

View file

@ -62,6 +62,49 @@ bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
void EditorExportPreset::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_property_warning", "name"), &EditorExportPreset::_get_property_warning);
ClassDB::bind_method(D_METHOD("has", "property"), &EditorExportPreset::has);
ClassDB::bind_method(D_METHOD("get_files_to_export"), &EditorExportPreset::get_files_to_export);
ClassDB::bind_method(D_METHOD("get_customized_files"), &EditorExportPreset::get_customized_files);
ClassDB::bind_method(D_METHOD("get_customized_files_count"), &EditorExportPreset::get_customized_files_count);
ClassDB::bind_method(D_METHOD("has_export_file", "path"), &EditorExportPreset::has_export_file);
ClassDB::bind_method(D_METHOD("get_file_export_mode", "path", "default"), &EditorExportPreset::get_file_export_mode, DEFVAL(MODE_FILE_NOT_CUSTOMIZED));
ClassDB::bind_method(D_METHOD("get_preset_name"), &EditorExportPreset::get_name);
ClassDB::bind_method(D_METHOD("is_runnable"), &EditorExportPreset::is_runnable);
ClassDB::bind_method(D_METHOD("are_advanced_options_enabled"), &EditorExportPreset::are_advanced_options_enabled);
ClassDB::bind_method(D_METHOD("is_dedicated_server"), &EditorExportPreset::is_dedicated_server);
ClassDB::bind_method(D_METHOD("get_export_filter"), &EditorExportPreset::get_export_filter);
ClassDB::bind_method(D_METHOD("get_include_filter"), &EditorExportPreset::get_include_filter);
ClassDB::bind_method(D_METHOD("get_exclude_filter"), &EditorExportPreset::get_exclude_filter);
ClassDB::bind_method(D_METHOD("get_custom_features"), &EditorExportPreset::get_custom_features);
ClassDB::bind_method(D_METHOD("get_patches"), &EditorExportPreset::get_patches);
ClassDB::bind_method(D_METHOD("get_export_path"), &EditorExportPreset::get_export_path);
ClassDB::bind_method(D_METHOD("get_encryption_in_filter"), &EditorExportPreset::get_enc_in_filter);
ClassDB::bind_method(D_METHOD("get_encryption_ex_filter"), &EditorExportPreset::get_enc_ex_filter);
ClassDB::bind_method(D_METHOD("get_encrypt_pck"), &EditorExportPreset::get_enc_pck);
ClassDB::bind_method(D_METHOD("get_encrypt_directory"), &EditorExportPreset::get_enc_directory);
ClassDB::bind_method(D_METHOD("get_encryption_key"), &EditorExportPreset::get_script_encryption_key);
ClassDB::bind_method(D_METHOD("get_script_export_mode"), &EditorExportPreset::get_script_export_mode);
ClassDB::bind_method(D_METHOD("get_or_env", "name", "env_var"), &EditorExportPreset::_get_or_env);
ClassDB::bind_method(D_METHOD("get_version", "name", "windows_version"), &EditorExportPreset::get_version);
BIND_ENUM_CONSTANT(EXPORT_ALL_RESOURCES);
BIND_ENUM_CONSTANT(EXPORT_SELECTED_SCENES);
BIND_ENUM_CONSTANT(EXPORT_SELECTED_RESOURCES);
BIND_ENUM_CONSTANT(EXCLUDE_SELECTED_RESOURCES);
BIND_ENUM_CONSTANT(EXPORT_CUSTOMIZED);
BIND_ENUM_CONSTANT(MODE_FILE_NOT_CUSTOMIZED);
BIND_ENUM_CONSTANT(MODE_FILE_STRIP);
BIND_ENUM_CONSTANT(MODE_FILE_KEEP);
BIND_ENUM_CONSTANT(MODE_FILE_REMOVE);
BIND_ENUM_CONSTANT(MODE_SCRIPT_TEXT);
BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS);
BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS_COMPRESSED);
}
String EditorExportPreset::_get_property_warning(const StringName &p_name) const {
@ -93,8 +136,29 @@ String EditorExportPreset::_get_property_warning(const StringName &p_name) const
void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
for (const KeyValue<StringName, PropertyInfo> &E : properties) {
if (!value_overrides.has(E.key) && platform->get_export_option_visibility(this, E.key)) {
p_list->push_back(E.value);
if (!value_overrides.has(E.key)) {
bool property_visible = platform->get_export_option_visibility(this, E.key);
if (!property_visible) {
continue;
}
// Get option visibility from editor export plugins.
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
if (!export_plugins[i]->supports_platform(platform)) {
continue;
}
export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));
property_visible = export_plugins[i]->_get_export_option_visibility(platform, E.key);
if (!property_visible) {
break;
}
}
if (property_visible) {
p_list->push_back(E.value);
}
}
}
}
@ -324,6 +388,42 @@ EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(cons
return p_default;
}
void EditorExportPreset::add_patch(const String &p_path, int p_at_pos) {
ERR_FAIL_COND_EDMSG(patches.has(p_path), vformat("Failed to add patch \"%s\". Patches must be unique.", p_path));
if (p_at_pos < 0) {
patches.push_back(p_path);
} else {
patches.insert(p_at_pos, p_path);
}
EditorExport::singleton->save_presets();
}
void EditorExportPreset::set_patch(int p_index, const String &p_path) {
remove_patch(p_index);
add_patch(p_path, p_index);
}
String EditorExportPreset::get_patch(int p_index) {
ERR_FAIL_INDEX_V(p_index, patches.size(), String());
return patches[p_index];
}
void EditorExportPreset::remove_patch(int p_index) {
ERR_FAIL_INDEX(p_index, patches.size());
patches.remove_at(p_index);
EditorExport::singleton->save_presets();
}
void EditorExportPreset::set_patches(const Vector<String> &p_patches) {
patches = p_patches;
}
Vector<String> EditorExportPreset::get_patches() const {
return patches;
}
void EditorExportPreset::set_custom_features(const String &p_custom_features) {
custom_features = p_custom_features;
EditorExport::singleton->save_presets();
@ -351,6 +451,15 @@ String EditorExportPreset::get_enc_ex_filter() const {
return enc_ex_filters;
}
void EditorExportPreset::set_seed(uint64_t p_seed) {
seed = p_seed;
EditorExport::singleton->save_presets();
}
uint64_t EditorExportPreset::get_seed() const {
return seed;
}
void EditorExportPreset::set_enc_pck(bool p_enabled) {
enc_pck = p_enabled;
EditorExport::singleton->save_presets();

View file

@ -74,6 +74,8 @@ private:
bool advanced_options_enabled = false;
bool dedicated_server = false;
Vector<String> patches;
friend class EditorExport;
friend class EditorExportPlatform;
@ -90,6 +92,7 @@ private:
String enc_ex_filters;
bool enc_pck = false;
bool enc_directory = false;
uint64_t seed = 0;
String script_key;
int script_mode = MODE_SCRIPT_BINARY_TOKENS_COMPRESSED;
@ -144,6 +147,13 @@ public:
void set_exclude_filter(const String &p_exclude);
String get_exclude_filter() const;
void add_patch(const String &p_path, int p_at_pos = -1);
void set_patch(int p_index, const String &p_path);
String get_patch(int p_index);
void remove_patch(int p_index);
void set_patches(const Vector<String> &p_patches);
Vector<String> get_patches() const;
void set_custom_features(const String &p_custom_features);
String get_custom_features() const;
@ -156,6 +166,9 @@ public:
void set_enc_ex_filter(const String &p_filter);
String get_enc_ex_filter() const;
void set_seed(uint64_t p_seed);
uint64_t get_seed() const;
void set_enc_pck(bool p_enabled);
bool get_enc_pck() const;
@ -168,6 +181,9 @@ public:
void set_script_export_mode(int p_mode);
int get_script_export_mode() const;
Variant _get_or_env(const StringName &p_name, const String &p_env_var) const {
return get_or_env(p_name, p_env_var);
}
Variant get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid = nullptr) const;
// Return the preset's version number, or fall back to the
@ -183,4 +199,8 @@ public:
EditorExportPreset();
};
VARIANT_ENUM_CAST(EditorExportPreset::ExportFilter);
VARIANT_ENUM_CAST(EditorExportPreset::FileExportMode);
VARIANT_ENUM_CAST(EditorExportPreset::ScriptExportMode);
#endif // EDITOR_EXPORT_PRESET_H

View file

@ -34,11 +34,12 @@
#include "core/io/json.h"
#include "core/io/zip_io.h"
#include "core/version.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "editor/export/editor_export_preset.h"
#include "editor/progress_dialog.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/file_dialog.h"
@ -47,6 +48,32 @@
#include "scene/gui/tree.h"
#include "scene/main/http_request.h"
enum DownloadsAvailability {
DOWNLOADS_AVAILABLE,
DOWNLOADS_NOT_AVAILABLE_IN_OFFLINE_MODE,
DOWNLOADS_NOT_AVAILABLE_FOR_DEV_BUILDS,
};
static DownloadsAvailability _get_downloads_availability() {
const int network_mode = EDITOR_GET("network/connection/network_mode");
if (network_mode == EditorSettings::NETWORK_OFFLINE) {
return DOWNLOADS_NOT_AVAILABLE_IN_OFFLINE_MODE;
}
// Downloadable export templates are only available for stable and official alpha/beta/RC builds
// (which always have a number following their status, e.g. "alpha1").
// Therefore, don't display download-related features when using a development version
// (whose builds aren't numbered).
if (String(VERSION_STATUS) == String("dev") ||
String(VERSION_STATUS) == String("alpha") ||
String(VERSION_STATUS) == String("beta") ||
String(VERSION_STATUS) == String("rc")) {
return DOWNLOADS_NOT_AVAILABLE_FOR_DEV_BUILDS;
}
return DOWNLOADS_AVAILABLE;
}
void ExportTemplateManager::_update_template_status() {
// Fetch installed templates from the file system.
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@ -111,7 +138,9 @@ void ExportTemplateManager::_update_template_status() {
TreeItem *ti = installed_table->create_item(installed_root);
ti->set_text(0, version_string);
#ifndef ANDROID_ENABLED
ti->add_button(0, get_editor_theme_icon(SNAME("Folder")), OPEN_TEMPLATE_FOLDER, false, TTR("Open the folder containing these templates."));
#endif
ti->add_button(0, get_editor_theme_icon(SNAME("Remove")), UNINSTALL_TEMPLATE, false, TTR("Uninstall these templates."));
}
}
@ -408,6 +437,13 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
}
String file = String::utf8(fname);
// Skip the __MACOSX directory created by macOS's built-in file zipper.
if (file.begins_with("__MACOSX")) {
ret = unzGoToNextFile(pkg);
continue;
}
if (file.ends_with("version.txt")) {
Vector<uint8_t> uncomp_data;
uncomp_data.resize(info.uncompressed_size);
@ -483,7 +519,8 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
String file = file_path.get_file();
if (file.size() == 0) {
// Skip the __MACOSX directory created by macOS's built-in file zipper.
if (file.is_empty() || file.begins_with("__MACOSX")) {
ret = unzGoToNextFile(pkg);
continue;
}
@ -543,7 +580,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
unzClose(pkg);
_update_template_status();
EditorSettings::get_singleton()->set_meta("export_template_download_directory", p_file.get_base_dir());
EditorSettings::get_singleton()->set("_export_template_download_directory", p_file.get_base_dir());
return true;
}
@ -639,9 +676,55 @@ void ExportTemplateManager::_open_template_folder(const String &p_version) {
void ExportTemplateManager::popup_manager() {
_update_template_status();
if (downloads_available && !is_downloading_templates) {
_refresh_mirrors();
switch (_get_downloads_availability()) {
case DOWNLOADS_AVAILABLE: {
current_missing_label->set_text(TTR("Export templates are missing. Download them or install from a file."));
mirrors_list->clear();
mirrors_list->add_item(TTR("Best available mirror"), 0);
mirrors_list->set_disabled(false);
mirrors_list->set_tooltip_text("");
mirror_options_button->set_disabled(false);
download_current_button->set_disabled(false);
download_current_button->set_tooltip_text("");
if (!is_downloading_templates) {
_refresh_mirrors();
}
} break;
case DOWNLOADS_NOT_AVAILABLE_IN_OFFLINE_MODE: {
current_missing_label->set_text(TTR("Export templates are missing. Install them from a file."));
mirrors_list->clear();
mirrors_list->add_item(TTR("Not available in offline mode"), 0);
mirrors_list->set_disabled(true);
mirrors_list->set_tooltip_text(TTR("Template downloading is disabled in offline mode."));
mirror_options_button->set_disabled(true);
download_current_button->set_disabled(true);
download_current_button->set_tooltip_text(TTR("Template downloading is disabled in offline mode."));
} break;
case DOWNLOADS_NOT_AVAILABLE_FOR_DEV_BUILDS: {
current_missing_label->set_text(TTR("Export templates are missing. Install them from a file."));
mirrors_list->clear();
mirrors_list->add_item(TTR("No templates for development builds"), 0);
mirrors_list->set_disabled(true);
mirrors_list->set_tooltip_text(TTR("Official export templates aren't available for development builds."));
mirror_options_button->set_disabled(true);
download_current_button->set_disabled(true);
download_current_button->set_tooltip_text(TTR("Official export templates aren't available for development builds."));
} break;
}
popup_centered(Size2(720, 280) * EDSCALE);
}
@ -802,7 +885,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
ProgressDialog::get_singleton()->end_task("uncompress_src");
unzClose(pkg);
EditorFileSystem::get_singleton()->scan_changes();
return OK;
}
@ -814,7 +897,7 @@ void ExportTemplateManager::_notification(int p_what) {
current_missing_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
current_installed_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
mirror_options_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
mirror_options_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@ -859,24 +942,11 @@ void ExportTemplateManager::_notification(int p_what) {
}
}
void ExportTemplateManager::_bind_methods() {
}
ExportTemplateManager::ExportTemplateManager() {
set_title(TTR("Export Template Manager"));
set_hide_on_ok(false);
set_ok_button_text(TTR("Close"));
// Downloadable export templates are only available for stable and official alpha/beta/RC builds
// (which always have a number following their status, e.g. "alpha1").
// Therefore, don't display download-related features when using a development version
// (whose builds aren't numbered).
downloads_available =
String(VERSION_STATUS) != String("dev") &&
String(VERSION_STATUS) != String("alpha") &&
String(VERSION_STATUS) != String("beta") &&
String(VERSION_STATUS) != String("rc");
VBoxContainer *main_vb = memnew(VBoxContainer);
add_child(main_vb);
@ -899,11 +969,6 @@ ExportTemplateManager::ExportTemplateManager() {
current_missing_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_missing_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
if (downloads_available) {
current_missing_label->set_text(TTR("Export templates are missing. Download them or install from a file."));
} else {
current_missing_label->set_text(TTR("Export templates are missing. Install them from a file."));
}
current_hb->add_child(current_missing_label);
// Status: Current version is installed.
@ -924,11 +989,13 @@ ExportTemplateManager::ExportTemplateManager() {
current_installed_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
current_installed_hb->add_child(current_installed_path);
current_open_button = memnew(Button);
#ifndef ANDROID_ENABLED
Button *current_open_button = memnew(Button);
current_open_button->set_text(TTR("Open Folder"));
current_open_button->set_tooltip_text(TTR("Open the folder containing installed templates for the current version."));
current_installed_hb->add_child(current_open_button);
current_open_button->connect(SceneStringName(pressed), callable_mp(this, &ExportTemplateManager::_open_template_folder).bind(VERSION_FULL_CONFIG));
#endif
current_uninstall_button = memnew(Button);
current_uninstall_button->set_text(TTR("Uninstall"));
@ -956,12 +1023,6 @@ ExportTemplateManager::ExportTemplateManager() {
mirrors_list = memnew(OptionButton);
mirrors_list->set_custom_minimum_size(Size2(280, 0) * EDSCALE);
if (downloads_available) {
mirrors_list->add_item(TTR("Best available mirror"), 0);
} else {
mirrors_list->add_item(TTR("(no templates for development builds)"), 0);
mirrors_list->set_disabled(true);
}
download_install_hb->add_child(mirrors_list);
request_mirrors = memnew(HTTPRequest);
@ -971,24 +1032,17 @@ ExportTemplateManager::ExportTemplateManager() {
mirror_options_button = memnew(MenuButton);
mirror_options_button->get_popup()->add_item(TTR("Open in Web Browser"), VISIT_WEB_MIRROR);
mirror_options_button->get_popup()->add_item(TTR("Copy Mirror URL"), COPY_MIRROR_URL);
mirror_options_button->set_disabled(!downloads_available);
download_install_hb->add_child(mirror_options_button);
mirror_options_button->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &ExportTemplateManager::_mirror_options_button_cbk));
download_install_hb->add_spacer();
Button *download_current_button = memnew(Button);
download_current_button = memnew(Button);
download_current_button->set_text(TTR("Download and Install"));
download_current_button->set_tooltip_text(TTR("Download and install templates for the current version from the best possible mirror."));
download_install_hb->add_child(download_current_button);
download_current_button->connect(SceneStringName(pressed), callable_mp(this, &ExportTemplateManager::_download_current));
// Update downloads buttons to prevent unsupported downloads.
if (!downloads_available) {
download_current_button->set_disabled(true);
download_current_button->set_tooltip_text(TTR("Official export templates aren't available for development builds."));
}
HBoxContainer *install_file_hb = memnew(HBoxContainer);
install_file_hb->set_alignment(BoxContainer::ALIGNMENT_END);
install_options_vb->add_child(install_file_hb);
@ -1057,7 +1111,7 @@ ExportTemplateManager::ExportTemplateManager() {
install_file_dialog->set_title(TTR("Select Template File"));
install_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
install_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
install_file_dialog->set_current_dir(EditorSettings::get_singleton()->get_meta("export_template_download_directory", ""));
install_file_dialog->set_current_dir(EDITOR_DEF("_export_template_download_directory", ""));
install_file_dialog->add_filter("*.tpz", TTR("Godot Export Templates"));
install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected).bind(false));
add_child(install_file_dialog);

View file

@ -46,7 +46,6 @@ class ExportTemplateManager : public AcceptDialog {
GDCLASS(ExportTemplateManager, AcceptDialog);
bool current_version_exists = false;
bool downloads_available = true;
bool mirrors_available = false;
bool is_refreshing_mirrors = false;
bool is_downloading_templates = false;
@ -58,7 +57,6 @@ class ExportTemplateManager : public AcceptDialog {
HBoxContainer *current_installed_hb = nullptr;
LineEdit *current_installed_path = nullptr;
Button *current_open_button = nullptr;
Button *current_uninstall_button = nullptr;
VBoxContainer *install_options_vb = nullptr;
@ -75,6 +73,7 @@ class ExportTemplateManager : public AcceptDialog {
Label *download_progress_label = nullptr;
HTTPRequest *download_templates = nullptr;
Button *install_file_button = nullptr;
Button *download_current_button = nullptr;
HTTPRequest *request_mirrors = nullptr;
enum TemplatesAction {
@ -119,7 +118,6 @@ class ExportTemplateManager : public AcceptDialog {
protected:
void _notification(int p_what);
static void _bind_methods();
public:
static String get_android_build_directory(const Ref<EditorExportPreset> &p_preset);

View file

@ -30,6 +30,8 @@
#include "lipo.h"
#include "macho.h"
bool LipO::is_lipo(const String &p_path) {
Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_path));

View file

@ -33,8 +33,6 @@
// Universal / Universal 2 fat binary file creator and extractor.
#include "macho.h"
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"

View file

@ -30,6 +30,8 @@
#include "macho.h"
#include "core/crypto/crypto_core.h"
uint32_t MachO::seg_align(uint64_t p_vmaddr, uint32_t p_min, uint32_t p_max) {
uint32_t salign = p_max;
if (p_vmaddr != 0) {

View file

@ -33,8 +33,6 @@
// Mach-O binary object file format parser and editor.
#include "core/crypto/crypto.h"
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"

View file

@ -41,7 +41,6 @@
#include "editor/gui/editor_file_dialog.h"
#include "editor/import/resource_importer_texture_settings.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
#include "scene/gui/item_list.h"
#include "scene/gui/link_button.h"
@ -100,13 +99,15 @@ void ProjectExportDialog::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
duplicate_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Remove")));
patch_add_btn->set_button_icon(get_editor_theme_icon(SNAME("Add")));
} break;
case NOTIFICATION_READY: {
duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
duplicate_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_button_icon(presets->get_editor_theme_icon(SNAME("Remove")));
patch_add_btn->set_button_icon(get_editor_theme_icon(SNAME("Add")));
connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_export_pck_zip));
_update_export_all();
} break;
@ -137,7 +138,7 @@ void ProjectExportDialog::popup_export() {
void ProjectExportDialog::_add_preset(int p_platform) {
Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_platform(p_platform)->create_preset();
ERR_FAIL_COND(!preset.is_valid());
ERR_FAIL_COND(preset.is_null());
String preset_name = EditorExport::get_singleton()->get_export_platform(p_platform)->get_name();
bool make_runnable = true;
@ -248,6 +249,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
duplicate_preset->set_disabled(true);
delete_preset->set_disabled(true);
sections->hide();
patches->clear();
export_error->hide();
export_templates_error->hide();
return;
@ -292,6 +294,21 @@ void ProjectExportDialog::_edit_preset(int p_index) {
exclude_filters->set_text(current->get_exclude_filter());
server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED);
patches->clear();
TreeItem *patch_root = patches->create_item();
Vector<String> patch_list = current->get_patches();
for (int i = 0; i < patch_list.size(); i++) {
TreeItem *patch = patches->create_item(patch_root);
const String &patch_path = patch_list[i];
patch->set_cell_mode(0, TreeItem::CELL_MODE_STRING);
patch->set_editable(0, true);
patch->set_text(0, patch_path.get_file());
patch->set_tooltip_text(0, patch_path);
patch->set_metadata(0, i);
patch->add_button(0, get_editor_theme_icon(SNAME("Remove")), 0);
patch->add_button(0, get_editor_theme_icon(SNAME("FileBrowse")), 1);
}
_fill_resource_tree();
bool needs_templates;
@ -364,10 +381,16 @@ void ProjectExportDialog::_edit_preset(int p_index) {
bool enc_pck_mode = current->get_enc_pck();
enc_pck->set_pressed(enc_pck_mode);
uint64_t seed = current->get_seed();
if (!updating_seed) {
seed_input->set_text(itos(seed));
}
enc_directory->set_disabled(!enc_pck_mode);
enc_in_filters->set_editable(enc_pck_mode);
enc_ex_filters->set_editable(enc_pck_mode);
script_key->set_editable(enc_pck_mode);
seed_input->set_editable(enc_pck_mode);
bool enc_directory_mode = current->get_enc_directory();
enc_directory->set_pressed(enc_directory_mode);
@ -573,6 +596,21 @@ void ProjectExportDialog::_enc_pck_changed(bool p_pressed) {
_update_current_preset();
}
void ProjectExportDialog::_seed_input_changed(const String &p_text) {
if (updating) {
return;
}
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
current->set_seed(seed_input->get_text().to_int());
updating_seed = true;
_update_current_preset();
updating_seed = false;
}
void ProjectExportDialog::_enc_directory_changed(bool p_pressed) {
if (updating) {
return;
@ -630,7 +668,7 @@ void ProjectExportDialog::_duplicate_preset() {
}
Ref<EditorExportPreset> preset = current->get_platform()->create_preset();
ERR_FAIL_COND(!preset.is_valid());
ERR_FAIL_COND(preset.is_null());
String preset_name = current->get_name() + " (copy)";
bool make_runnable = true;
@ -664,7 +702,14 @@ void ProjectExportDialog::_duplicate_preset() {
preset->set_export_filter(current->get_export_filter());
preset->set_include_filter(current->get_include_filter());
preset->set_exclude_filter(current->get_exclude_filter());
preset->set_patches(current->get_patches());
preset->set_custom_features(current->get_custom_features());
preset->set_enc_in_filter(current->get_enc_in_filter());
preset->set_enc_ex_filter(current->get_enc_ex_filter());
preset->set_enc_pck(current->get_enc_pck());
preset->set_enc_directory(current->get_enc_directory());
preset->set_script_encryption_key(current->get_script_encryption_key());
preset->set_script_export_mode(current->get_script_export_mode());
for (const KeyValue<StringName, Variant> &E : current->get_values()) {
preset->set(E.key, E.value);
@ -713,14 +758,29 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_
drag->add_child(tr);
Label *label = memnew(Label);
label->set_text(presets->get_item_text(pos));
label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); // Don't translate user input.
drag->add_child(label);
presets->set_drag_preview(drag);
return d;
}
}
} else if (p_from == patches) {
TreeItem *item = patches->get_item_at_position(p_point);
if (item) {
int item_metadata = item->get_metadata(0);
Dictionary d;
d["type"] = "export_patch";
d["patch"] = item_metadata;
Label *label = memnew(Label);
label->set_text(item->get_text(0));
patches->set_drag_preview(label);
return d;
}
}
return Variant();
}
@ -734,6 +794,18 @@ bool ProjectExportDialog::can_drop_data_fw(const Point2 &p_point, const Variant
if (presets->get_item_at_position(p_point, true) < 0 && !presets->is_pos_at_end_of_items(p_point)) {
return false;
}
} else if (p_from == patches) {
Dictionary d = p_data;
if (d.get("type", "") != "export_patch") {
return false;
}
TreeItem *item = patches->get_item_at_position(p_point);
if (!item) {
return false;
}
patches->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
}
return true;
@ -770,6 +842,31 @@ void ProjectExportDialog::drop_data_fw(const Point2 &p_point, const Variant &p_d
} else {
_edit_preset(presets->get_item_count() - 1);
}
} else if (p_from == patches) {
Dictionary d = p_data;
int from_pos = d["patch"];
TreeItem *item = patches->get_item_at_position(p_point);
if (!item) {
return;
}
int to_pos = item->get_metadata(0);
if (patches->get_drop_section_at_position(p_point) > 0) {
to_pos++;
}
if (to_pos > from_pos) {
to_pos--;
}
Ref<EditorExportPreset> preset = get_current_preset();
String patch = preset->get_patch(from_pos);
preset->remove_patch(from_pos);
preset->add_patch(patch, to_pos);
_update_current_preset();
}
}
@ -903,7 +1000,7 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem
if (p_export_filter == EditorExportPreset::EXPORT_SELECTED_SCENES && type != "PackedScene") {
continue;
}
if (type == "TextFile") {
if (type == "TextFile" || type == "OtherFile") {
continue;
}
@ -1025,6 +1122,75 @@ void ProjectExportDialog::_set_file_export_mode(int p_id) {
_propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED);
}
void ProjectExportDialog::_patch_tree_button_clicked(Object *p_item, int p_column, int p_id, int p_mouse_button_index) {
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
patch_index = ti->get_metadata(0);
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
if (p_id == 0) {
Vector<String> preset_patches = current->get_patches();
ERR_FAIL_INDEX(patch_index, preset_patches.size());
patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), preset_patches[patch_index].get_file()));
patch_erase->popup_centered();
} else {
patch_dialog->popup_file_dialog();
}
}
void ProjectExportDialog::_patch_tree_item_edited() {
TreeItem *item = patches->get_edited();
if (!item) {
return;
}
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
int index = item->get_metadata(0);
String patch_path = item->get_text(0);
current->set_patch(index, patch_path);
item->set_tooltip_text(0, patch_path);
}
void ProjectExportDialog::_patch_file_selected(const String &p_path) {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
String relative_path = ProjectSettings::get_singleton()->get_resource_path().path_to_file(p_path);
Vector<String> preset_patches = current->get_patches();
if (patch_index >= preset_patches.size()) {
current->add_patch(relative_path);
} else {
current->set_patch(patch_index, relative_path);
}
_update_current_preset();
}
void ProjectExportDialog::_patch_delete_confirmed() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
Vector<String> preset_patches = current->get_patches();
if (patch_index < preset_patches.size()) {
current->remove_patch(patch_index);
_update_current_preset();
}
}
void ProjectExportDialog::_patch_add_pack_pressed() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
patch_index = current->get_patches().size();
patch_dialog->popup_file_dialog();
}
void ProjectExportDialog::_export_pck_zip() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
@ -1043,11 +1209,23 @@ void ProjectExportDialog::_export_pck_zip_selected(const String &p_path) {
const Dictionary &fd_option = export_pck_zip->get_selected_options();
bool export_debug = fd_option.get(TTR("Export With Debug"), true);
bool export_as_patch = fd_option.get(TTR("Export As Patch"), true);
EditorSettings::get_singleton()->set_project_metadata("export_options", "export_debug", export_debug);
EditorSettings::get_singleton()->set_project_metadata("export_options", "export_as_patch", export_as_patch);
if (p_path.ends_with(".zip")) {
platform->export_zip(current, export_debug, p_path);
if (export_as_patch) {
platform->export_zip_patch(current, export_debug, p_path);
} else {
platform->export_zip(current, export_debug, p_path);
}
} else if (p_path.ends_with(".pck")) {
platform->export_pack(current, export_debug, p_path);
if (export_as_patch) {
platform->export_pack_patch(current, export_debug, p_path);
} else {
platform->export_pack(current, export_debug, p_path);
}
} else {
ERR_FAIL_MSG("Path must end with .pck or .zip");
}
@ -1072,10 +1250,10 @@ void ProjectExportDialog::_validate_export_path(const String &p_path) {
if (invalid_path) {
export_project->get_ok_button()->set_disabled(true);
export_project->get_line_edit()->disconnect("text_submitted", callable_mp(export_project, &EditorFileDialog::_file_submitted));
export_project->get_line_edit()->disconnect(SceneStringName(text_submitted), callable_mp(export_project, &EditorFileDialog::_file_submitted));
} else {
export_project->get_ok_button()->set_disabled(false);
export_project->get_line_edit()->connect("text_submitted", callable_mp(export_project, &EditorFileDialog::_file_submitted));
export_project->get_line_edit()->connect(SceneStringName(text_submitted), callable_mp(export_project, &EditorFileDialog::_file_submitted));
}
}
@ -1108,9 +1286,9 @@ void ProjectExportDialog::_export_project() {
// with _validate_export_path.
// FIXME: This is a hack, we should instead change EditorFileDialog to allow
// disabling validation by the "text_submitted" signal.
if (!export_project->get_line_edit()->is_connected("text_submitted", callable_mp(export_project, &EditorFileDialog::_file_submitted))) {
if (!export_project->get_line_edit()->is_connected(SceneStringName(text_submitted), callable_mp(export_project, &EditorFileDialog::_file_submitted))) {
export_project->get_ok_button()->set_disabled(false);
export_project->get_line_edit()->connect("text_submitted", callable_mp(export_project, &EditorFileDialog::_file_submitted));
export_project->get_line_edit()->connect(SceneStringName(text_submitted), callable_mp(export_project, &EditorFileDialog::_file_submitted));
}
export_project->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
@ -1135,6 +1313,8 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) {
Dictionary fd_option = export_project->get_selected_options();
bool export_debug = fd_option.get(TTR("Export With Debug"), true);
EditorSettings::get_singleton()->set_project_metadata("export_options", "export_debug", export_debug);
Error err = platform->export_project(current, export_debug, current->get_export_path(), 0);
result_dialog_log->clear();
if (err != ERR_SKIP) {
@ -1147,10 +1327,8 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) {
}
void ProjectExportDialog::_export_all_dialog() {
#ifndef ANDROID_ENABLED
export_all_dialog->show();
export_all_dialog->popup_centered(Size2(300, 80));
#endif
}
void ProjectExportDialog::_export_all_dialog_action(const String &p_str) {
@ -1243,6 +1421,7 @@ ProjectExportDialog::ProjectExportDialog() {
preset_vb->add_child(mc);
mc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
presets = memnew(ItemList);
presets->set_theme_type_variation("ItemListSecondary");
presets->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
SET_DRAG_FORWARDING_GCD(presets, ProjectExportDialog);
mc->add_child(presets);
@ -1387,6 +1566,40 @@ ProjectExportDialog::ProjectExportDialog() {
exclude_filters);
exclude_filters->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_filter_changed));
// Patch packages.
VBoxContainer *patch_vb = memnew(VBoxContainer);
sections->add_child(patch_vb);
patch_vb->set_name(TTR("Patches"));
patches = memnew(Tree);
patches->set_v_size_flags(Control::SIZE_EXPAND_FILL);
patches->set_hide_root(true);
patches->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
patches->connect("button_clicked", callable_mp(this, &ProjectExportDialog::_patch_tree_button_clicked));
patches->connect("item_edited", callable_mp(this, &ProjectExportDialog::_patch_tree_item_edited));
SET_DRAG_FORWARDING_GCD(patches, ProjectExportDialog);
patches->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
patch_vb->add_margin_child(TTR("Base Packs:"), patches, true);
patch_dialog = memnew(EditorFileDialog);
patch_dialog->add_filter("*.pck", TTR("Godot Project Pack"));
patch_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
patch_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
patch_dialog->connect("file_selected", callable_mp(this, &ProjectExportDialog::_patch_file_selected));
add_child(patch_dialog);
patch_erase = memnew(ConfirmationDialog);
patch_erase->set_ok_button_text(TTR("Delete"));
patch_erase->connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_patch_delete_confirmed));
add_child(patch_erase);
patch_add_btn = memnew(Button);
patch_add_btn->set_text(TTR("Add Pack"));
patch_add_btn->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
patch_add_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectExportDialog::_patch_add_pack_pressed));
patch_vb->add_child(patch_add_btn);
// Feature tags.
VBoxContainer *feature_vb = memnew(VBoxContainer);
@ -1412,12 +1625,12 @@ ProjectExportDialog::ProjectExportDialog() {
sec_scroll_container->add_child(sec_vb);
enc_pck = memnew(CheckButton);
enc_pck->connect("toggled", callable_mp(this, &ProjectExportDialog::_enc_pck_changed));
enc_pck->connect(SceneStringName(toggled), callable_mp(this, &ProjectExportDialog::_enc_pck_changed));
enc_pck->set_text(TTR("Encrypt Exported PCK"));
sec_vb->add_child(enc_pck);
enc_directory = memnew(CheckButton);
enc_directory->connect("toggled", callable_mp(this, &ProjectExportDialog::_enc_directory_changed));
enc_directory->connect(SceneStringName(toggled), callable_mp(this, &ProjectExportDialog::_enc_directory_changed));
enc_directory->set_text(TTR("Encrypt Index (File Names and Info)"));
sec_vb->add_child(enc_directory);
@ -1442,6 +1655,10 @@ ProjectExportDialog::ProjectExportDialog() {
sec_vb->add_child(script_key_error);
sections->add_child(sec_scroll_container);
seed_input = memnew(LineEdit);
seed_input->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_seed_input_changed));
sec_vb->add_margin_child(TTR("Initialization vector seed"), seed_input);
Label *sec_info = memnew(Label);
sec_info->set_text(TTR("Note: Encryption key needs to be stored in the binary,\nyou need to build the export templates from source."));
sec_vb->add_child(sec_info);
@ -1491,13 +1708,9 @@ ProjectExportDialog::ProjectExportDialog() {
set_ok_button_text(TTR("Export PCK/ZIP..."));
get_ok_button()->set_tooltip_text(TTR("Export the project resources as a PCK or ZIP package. This is not a playable build, only the project data without a Godot executable."));
get_ok_button()->set_disabled(true);
#ifdef ANDROID_ENABLED
export_button = memnew(Button);
export_button->hide();
#else
export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
export_button->set_tooltip_text(TTR("Export the project as a playable build (Godot executable and project data) for the selected preset."));
#endif
export_button->connect(SceneStringName(pressed), callable_mp(this, &ProjectExportDialog::_export_project));
// Disable initially before we select a valid preset
export_button->set_disabled(true);
@ -1510,14 +1723,8 @@ ProjectExportDialog::ProjectExportDialog() {
export_all_dialog->add_button(TTR("Debug"), true, "debug");
export_all_dialog->add_button(TTR("Release"), true, "release");
export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action));
#ifdef ANDROID_ENABLED
export_all_dialog->hide();
export_all_button = memnew(Button);
export_all_button->hide();
#else
export_all_button = add_button(TTR("Export All..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
#endif
export_all_button->connect(SceneStringName(pressed), callable_mp(this, &ProjectExportDialog::_export_all_dialog));
export_all_button->set_disabled(true);
@ -1578,8 +1785,9 @@ ProjectExportDialog::ProjectExportDialog() {
export_project->connect("file_selected", callable_mp(this, &ProjectExportDialog::_export_project_to_path));
export_project->get_line_edit()->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_validate_export_path));
export_project->add_option(TTR("Export With Debug"), Vector<String>(), true);
export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), true);
export_project->add_option(TTR("Export With Debug"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_debug", true));
export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_debug", true));
export_pck_zip->add_option(TTR("Export As Patch"), Vector<String>(), EditorSettings::get_singleton()->get_project_metadata("export_options", "export_as_patch", true));
set_hide_on_ok(false);

View file

@ -105,6 +105,13 @@ class ProjectExportDialog : public ConfirmationDialog {
AcceptDialog *export_all_dialog = nullptr;
RBSet<String> feature_set;
Tree *patches = nullptr;
int patch_index = -1;
EditorFileDialog *patch_dialog = nullptr;
ConfirmationDialog *patch_erase = nullptr;
Button *patch_add_btn = nullptr;
LineEdit *custom_features = nullptr;
RichTextLabel *custom_feature_display = nullptr;
@ -148,6 +155,12 @@ class ProjectExportDialog : public ConfirmationDialog {
void _tree_popup_edited(bool p_arrow_clicked);
void _set_file_export_mode(int p_id);
void _patch_tree_button_clicked(Object *p_item, int p_column, int p_id, int p_mouse_button_index);
void _patch_tree_item_edited();
void _patch_file_selected(const String &p_path);
void _patch_delete_confirmed();
void _patch_add_pack_pressed();
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
@ -159,6 +172,7 @@ class ProjectExportDialog : public ConfirmationDialog {
CheckButton *enc_directory = nullptr;
LineEdit *enc_in_filters = nullptr;
LineEdit *enc_ex_filters = nullptr;
LineEdit *seed_input = nullptr;
OptionButton *script_mode = nullptr;
@ -179,9 +193,11 @@ class ProjectExportDialog : public ConfirmationDialog {
bool updating_script_key = false;
bool updating_enc_filters = false;
bool updating_seed = false;
void _enc_pck_changed(bool p_pressed);
void _enc_directory_changed(bool p_pressed);
void _enc_filters_changed(const String &p_text);
void _seed_input_changed(const String &p_text);
void _script_encryption_key_changed(const String &p_key);
bool _validate_script_encryption_key(const String &p_key);
@ -203,7 +219,7 @@ public:
Ref<EditorExportPreset> get_current_preset() const;
bool is_exporting() const { return exporting; };
bool is_exporting() const { return exporting; }
ProjectExportDialog();
~ProjectExportDialog();

View file

@ -0,0 +1,122 @@
/**************************************************************************/
/* project_zip_packer.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "project_zip_packer.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/os/os.h"
#include "core/os/time.h"
String ProjectZIPPacker::get_project_zip_safe_name() {
// Name the downloaded ZIP file to contain the project name and download date for easier organization.
// Replace characters not allowed (or risky) in Windows file names with safe characters.
// In the project name, all invalid characters become an empty string so that a name
// like "Platformer 2: Godette's Revenge" becomes "platformer_2-_godette-s_revenge".
const String project_name = GLOBAL_GET("application/config/name");
const String project_name_safe = project_name.to_lower().replace(" ", "_");
const String datetime_safe =
Time::get_singleton()->get_datetime_string_from_system(false, true).replace(" ", "_");
const String output_name = OS::get_singleton()->get_safe_dir_name(vformat("%s_%s.zip", project_name_safe, datetime_safe));
return output_name;
}
void ProjectZIPPacker::pack_project_zip(const String &p_path) {
Ref<FileAccess> io_fa;
zlib_filefunc_def io = zipio_create_io(&io_fa);
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
const String base_path = resource_path.substr(0, resource_path.rfind_char('/')) + "/";
zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io);
_zip_recursive(resource_path, base_path, zip);
zipClose(zip, nullptr);
}
void ProjectZIPPacker::_zip_file(const String &p_path, const String &p_base_path, zipFile p_zip) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
WARN_PRINT("Unable to open file for zipping: " + p_path);
return;
}
Vector<uint8_t> data;
uint64_t len = f->get_length();
data.resize(len);
f->get_buffer(data.ptrw(), len);
String path = p_path.replace_first(p_base_path, "");
zipOpenNewFileInZip(p_zip,
path.utf8().get_data(),
nullptr,
nullptr,
0,
nullptr,
0,
nullptr,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
zipWriteInFileInZip(p_zip, data.ptr(), data.size());
zipCloseFileInZip(p_zip);
}
void ProjectZIPPacker::_zip_recursive(const String &p_path, const String &p_base_path, zipFile p_zip) {
Ref<DirAccess> dir = DirAccess::open(p_path);
if (dir.is_null()) {
WARN_PRINT("Unable to open directory for zipping: " + p_path);
return;
}
dir->list_dir_begin();
String cur = dir->get_next();
String project_data_dir_name = ProjectSettings::get_singleton()->get_project_data_dir_name();
while (!cur.is_empty()) {
String cs = p_path.path_join(cur);
if (cur == "." || cur == ".." || cur == project_data_dir_name) {
// Skip
} else if (dir->current_is_dir()) {
String path = cs.replace_first(p_base_path, "") + "/";
zipOpenNewFileInZip(p_zip,
path.utf8().get_data(),
nullptr,
nullptr,
0,
nullptr,
0,
nullptr,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
zipCloseFileInZip(p_zip);
_zip_recursive(cs, p_base_path, p_zip);
} else {
_zip_file(cs, p_base_path, p_zip);
}
cur = dir->get_next();
}
}

View file

@ -0,0 +1,46 @@
/**************************************************************************/
/* project_zip_packer.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PROJECT_ZIP_PACKER_H
#define PROJECT_ZIP_PACKER_H
#include "core/io/zip_io.h"
#include "core/variant/variant.h"
class ProjectZIPPacker {
static void _zip_file(const String &p_path, const String &p_base_path, zipFile p_zip);
static void _zip_recursive(const String &p_path, const String &p_base_path, zipFile p_zip);
public:
static String get_project_zip_safe_name();
static void pack_project_zip(const String &p_path);
};
#endif // PROJECT_ZIP_PACKER_H