浏览代码

Split up editor export code into multiple files

Aaron Franke 3 年之前
父节点
当前提交
e53ae13178
共有 38 个文件被更改,包括 1771 次插入1456 次删除
  1. 1 0
      editor/SCsub
  2. 1 0
      editor/debugger/debug_adapter/debug_adapter_parser.cpp
  3. 0 532
      editor/editor_export.h
  4. 1 1
      editor/editor_node.cpp
  5. 1 1
      editor/editor_node.h
  6. 1 1
      editor/editor_plugin.cpp
  7. 1 1
      editor/editor_run_native.cpp
  8. 5 0
      editor/export/SCsub
  9. 355 0
      editor/export/editor_export.cpp
  10. 84 0
      editor/export/editor_export.h
  11. 4 903
      editor/export/editor_export_platform.cpp
  12. 221 0
      editor/export/editor_export_platform.h
  13. 247 0
      editor/export/editor_export_platform_pc.cpp
  14. 82 0
      editor/export/editor_export_platform_pc.h
  15. 201 0
      editor/export/editor_export_plugin.cpp
  16. 132 0
      editor/export/editor_export_plugin.h
  17. 221 0
      editor/export/editor_export_preset.cpp
  18. 145 0
      editor/export/editor_export_preset.h
  19. 51 0
      editor/export/editor_export_shared_object.h
  20. 1 1
      editor/plugins/gdextension_export_plugin.h
  21. 1 1
      editor/project_export.h
  22. 0 1
      editor/project_settings_editor.cpp
  23. 0 1
      editor/property_editor.cpp
  24. 1 1
      modules/gdscript/register_types.cpp
  25. 2 2
      platform/android/export/export.cpp
  26. 1 1
      platform/android/export/export_plugin.h
  27. 1 1
      platform/android/export/gradle_export_util.h
  28. 1 0
      platform/ios/export/export.cpp
  29. 1 1
      platform/ios/export/export_plugin.h
  30. 1 1
      platform/javascript/export/export_plugin.h
  31. 0 1
      platform/javascript/export/export_server.h
  32. 1 0
      platform/linuxbsd/export/export.cpp
  33. 1 1
      platform/linuxbsd/export/export_plugin.h
  34. 1 1
      platform/macos/export/export_plugin.h
  35. 1 1
      platform/uwp/export/app_packager.h
  36. 1 1
      platform/uwp/export/export_plugin.h
  37. 1 0
      platform/windows/export/export.cpp
  38. 1 1
      platform/windows/export/export_plugin.h

+ 1 - 0
editor/SCsub

@@ -113,6 +113,7 @@ if env["tools"]:
     env.add_source_files(env.editor_sources, "register_exporters.gen.cpp")
 
     SConscript("debugger/SCsub")
+    SConscript("export/SCsub")
     SConscript("fileserver/SCsub")
     SConscript("icons/SCsub")
     SConscript("import/SCsub")

+ 1 - 0
editor/debugger/debug_adapter/debug_adapter_parser.cpp

@@ -34,6 +34,7 @@
 #include "editor/debugger/script_editor_debugger.h"
 #include "editor/editor_node.h"
 #include "editor/editor_run_native.h"
+#include "editor/export/editor_export_platform.h"
 #include "editor/plugins/script_editor_plugin.h"
 
 void DebugAdapterParser::_bind_methods() {

+ 0 - 532
editor/editor_export.h

@@ -1,532 +0,0 @@
-/*************************************************************************/
-/*  editor_export.h                                                      */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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_H
-#define EDITOR_EXPORT_H
-
-#include "core/io/dir_access.h"
-#include "core/io/resource.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/main/node.h"
-#include "scene/main/timer.h"
-#include "scene/resources/texture.h"
-
-class FileAccess;
-class EditorExportPlatform;
-class EditorFileSystemDirectory;
-struct EditorProgress;
-
-class EditorExportPreset : public RefCounted {
-	GDCLASS(EditorExportPreset, RefCounted);
-
-public:
-	enum ExportFilter {
-		EXPORT_ALL_RESOURCES,
-		EXPORT_SELECTED_SCENES,
-		EXPORT_SELECTED_RESOURCES,
-		EXCLUDE_SELECTED_RESOURCES,
-	};
-
-	enum ScriptExportMode {
-		MODE_SCRIPT_TEXT,
-		MODE_SCRIPT_COMPILED,
-	};
-
-private:
-	Ref<EditorExportPlatform> platform;
-	ExportFilter export_filter = EXPORT_ALL_RESOURCES;
-	String include_filter;
-	String exclude_filter;
-	String export_path;
-
-	String exporter;
-	HashSet<String> selected_files;
-	bool runnable = false;
-
-	friend class EditorExport;
-	friend class EditorExportPlatform;
-
-	List<PropertyInfo> properties;
-	HashMap<StringName, Variant> values;
-
-	String name;
-
-	String custom_features;
-
-	String enc_in_filters;
-	String enc_ex_filters;
-	bool enc_pck = false;
-	bool enc_directory = false;
-
-	int script_mode = MODE_SCRIPT_COMPILED;
-	String script_key;
-
-protected:
-	bool _set(const StringName &p_name, const Variant &p_value);
-	bool _get(const StringName &p_name, Variant &r_ret) const;
-	void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
-	Ref<EditorExportPlatform> get_platform() const;
-
-	bool has(const StringName &p_property) const { return values.has(p_property); }
-
-	void update_files_to_export();
-
-	Vector<String> get_files_to_export() const;
-
-	void add_export_file(const String &p_path);
-	void remove_export_file(const String &p_path);
-	bool has_export_file(const String &p_path);
-
-	void set_name(const String &p_name);
-	String get_name() const;
-
-	void set_runnable(bool p_enable);
-	bool is_runnable() const;
-
-	void set_export_filter(ExportFilter p_filter);
-	ExportFilter get_export_filter() const;
-
-	void set_include_filter(const String &p_include);
-	String get_include_filter() const;
-
-	void set_exclude_filter(const String &p_exclude);
-	String get_exclude_filter() const;
-
-	void set_custom_features(const String &p_custom_features);
-	String get_custom_features() const;
-
-	void set_export_path(const String &p_path);
-	String get_export_path() const;
-
-	void set_enc_in_filter(const String &p_filter);
-	String get_enc_in_filter() const;
-
-	void set_enc_ex_filter(const String &p_filter);
-	String get_enc_ex_filter() const;
-
-	void set_enc_pck(bool p_enabled);
-	bool get_enc_pck() const;
-
-	void set_enc_directory(bool p_enabled);
-	bool get_enc_directory() const;
-
-	void set_script_export_mode(int p_mode);
-	int get_script_export_mode() const;
-
-	void set_script_encryption_key(const String &p_key);
-	String get_script_encryption_key() const;
-
-	const List<PropertyInfo> &get_properties() const { return properties; }
-
-	EditorExportPreset() {}
-};
-
-struct SharedObject {
-	String path;
-	Vector<String> tags;
-	String target;
-
-	SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) :
-			path(p_path),
-			tags(p_tags),
-			target(p_target) {
-	}
-
-	SharedObject() {}
-};
-
-class EditorExportPlatform : public RefCounted {
-	GDCLASS(EditorExportPlatform, RefCounted);
-
-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 (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
-
-	enum ExportMessageType {
-		EXPORT_MESSAGE_NONE,
-		EXPORT_MESSAGE_INFO,
-		EXPORT_MESSAGE_WARNING,
-		EXPORT_MESSAGE_ERROR,
-	};
-
-	struct ExportMessage {
-		ExportMessageType msg_type;
-		String category;
-		String text;
-	};
-
-private:
-	struct SavedData {
-		uint64_t ofs = 0;
-		uint64_t size = 0;
-		bool encrypted = false;
-		Vector<uint8_t> md5;
-		CharString path_utf8;
-
-		bool operator<(const SavedData &p_data) const {
-			return path_utf8 < p_data.path_utf8;
-		}
-	};
-
-	struct PackData {
-		Ref<FileAccess> f;
-		Vector<SavedData> file_ofs;
-		EditorProgress *ep = nullptr;
-		Vector<SharedObject> *so_files = nullptr;
-	};
-
-	struct ZipData {
-		void *zip = nullptr;
-		EditorProgress *ep = nullptr;
-	};
-
-	struct FeatureContainers {
-		HashSet<String> features;
-		Vector<String> features_pv;
-	};
-
-	Vector<ExportMessage> messages;
-
-	void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths);
-	void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
-
-	void gen_debug_flags(Vector<String> &r_flags, int p_flags);
-	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);
-
-	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);
-
-protected:
-	struct ExportNotifier {
-		ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
-		~ExportNotifier();
-	};
-
-	FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug);
-
-	bool exists_export_template(String template_file_name, String *err) const;
-	String find_export_template(String template_file_name, String *err = nullptr) const;
-	void gen_export_flags(Vector<String> &r_flags, int p_flags);
-
-public:
-	virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) = 0;
-
-	struct ExportOption {
-		PropertyInfo option;
-		Variant default_value;
-
-		ExportOption(const PropertyInfo &p_info, const Variant &p_default) :
-				option(p_info),
-				default_value(p_default) {
-		}
-		ExportOption() {}
-	};
-
-	virtual Ref<EditorExportPreset> create_preset();
-
-	virtual void clear_messages() { messages.clear(); }
-	virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) {
-		ExportMessage msg;
-		msg.category = p_category;
-		msg.text = p_message;
-		msg.msg_type = p_type;
-		messages.push_back(msg);
-		switch (p_type) {
-			case EXPORT_MESSAGE_INFO: {
-				print_line(vformat("%s: %s\n", msg.category, msg.text));
-			} break;
-			case EXPORT_MESSAGE_WARNING: {
-				WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text));
-			} break;
-			case EXPORT_MESSAGE_ERROR: {
-				ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text));
-			} break;
-			default:
-				break;
-		}
-	}
-
-	virtual int get_message_count() const {
-		return messages.size();
-	}
-
-	virtual ExportMessage get_message(int p_index) const {
-		ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage());
-		return messages[p_index];
-	}
-
-	virtual ExportMessageType get_worst_message_type() const {
-		ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
-		for (int i = 0; i < messages.size(); i++) {
-			worst_type = MAX(worst_type, messages[i].msg_type);
-		}
-		return worst_type;
-	}
-
-	virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);
-
-	virtual void get_export_options(List<ExportOption> *r_options) = 0;
-	virtual bool should_update_export_options() { return false; }
-	virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; }
-
-	virtual String get_os_name() const = 0;
-	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);
-
-	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);
-
-	virtual bool poll_export() { return false; }
-	virtual int get_options_count() const { return 0; }
-	virtual String get_options_tooltip() const { return ""; }
-	virtual Ref<ImageTexture> get_option_icon(int p_index) const;
-	virtual String get_option_label(int p_device) const { return ""; }
-	virtual String get_option_tooltip(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_COLLISONS = 8,
-		DEBUG_FLAG_VIEW_NAVIGATION = 16,
-	};
-
-	virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
-	virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
-
-	String test_etc2() const;
-	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) 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 void get_platform_features(List<String> *r_features) = 0;
-	virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0;
-	virtual String get_debug_protocol() const { return "tcp://"; }
-
-	EditorExportPlatform();
-};
-
-class EditorExportPlugin : public RefCounted {
-	GDCLASS(EditorExportPlugin, RefCounted);
-
-	friend class EditorExportPlatform;
-
-	Ref<EditorExportPreset> export_preset;
-
-	Vector<SharedObject> shared_objects;
-	struct ExtraFile {
-		String path;
-		Vector<uint8_t> data;
-		bool remap = false;
-	};
-	Vector<ExtraFile> extra_files;
-	bool skipped = false;
-
-	Vector<String> ios_frameworks;
-	Vector<String> ios_embedded_frameworks;
-	Vector<String> ios_project_static_libs;
-	String ios_plist_content;
-	String ios_linker_flags;
-	Vector<String> ios_bundle_files;
-	String ios_cpp_code;
-
-	Vector<String> macos_plugin_files;
-
-	_FORCE_INLINE_ void _clear() {
-		shared_objects.clear();
-		extra_files.clear();
-		skipped = false;
-	}
-
-	_FORCE_INLINE_ void _export_end() {
-		ios_frameworks.clear();
-		ios_embedded_frameworks.clear();
-		ios_bundle_files.clear();
-		ios_plist_content = "";
-		ios_linker_flags = "";
-		ios_cpp_code = "";
-		macos_plugin_files.clear();
-	}
-
-	void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features);
-	void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
-	void _export_end_script();
-
-protected:
-	void set_export_preset(const Ref<EditorExportPreset> &p_preset);
-	Ref<EditorExportPreset> get_export_preset() 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());
-
-	void add_ios_framework(const String &p_path);
-	void add_ios_embedded_framework(const String &p_path);
-	void add_ios_project_static_lib(const String &p_path);
-	void add_ios_plist_content(const String &p_plist_content);
-	void add_ios_linker_flags(const String &p_flags);
-	void add_ios_bundle_file(const String &p_path);
-	void add_ios_cpp_code(const String &p_code);
-	void add_macos_plugin_file(const String &p_path);
-
-	void skip();
-
-	virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);
-	virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags);
-
-	static void _bind_methods();
-
-	GDVIRTUAL3(_export_file, String, String, Vector<String>)
-	GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t)
-	GDVIRTUAL0(_export_end)
-
-public:
-	Vector<String> get_ios_frameworks() const;
-	Vector<String> get_ios_embedded_frameworks() const;
-	Vector<String> get_ios_project_static_libs() const;
-	String get_ios_plist_content() const;
-	String get_ios_linker_flags() const;
-	Vector<String> get_ios_bundle_files() const;
-	String get_ios_cpp_code() const;
-	const Vector<String> &get_macos_plugin_files() const;
-
-	EditorExportPlugin();
-};
-
-class EditorExport : public Node {
-	GDCLASS(EditorExport, Node);
-
-	Vector<Ref<EditorExportPlatform>> export_platforms;
-	Vector<Ref<EditorExportPreset>> export_presets;
-	Vector<Ref<EditorExportPlugin>> export_plugins;
-
-	StringName _export_presets_updated;
-
-	Timer *save_timer = nullptr;
-	bool block_save = false;
-
-	static EditorExport *singleton;
-
-	void _save();
-
-protected:
-	friend class EditorExportPreset;
-	void save_presets();
-
-	void _notification(int p_what);
-	static void _bind_methods();
-
-public:
-	static EditorExport *get_singleton() { return singleton; }
-
-	void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
-	int get_export_platform_count();
-	Ref<EditorExportPlatform> get_export_platform(int p_idx);
-
-	void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1);
-	int get_export_preset_count() const;
-	Ref<EditorExportPreset> get_export_preset(int p_idx);
-	void remove_export_preset(int p_idx);
-
-	void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
-	void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
-	Vector<Ref<EditorExportPlugin>> get_export_plugins();
-
-	void load_config();
-	void update_export_presets();
-	bool poll_export_platforms();
-
-	EditorExport();
-	~EditorExport();
-};
-
-class EditorExportPlatformPC : public EditorExportPlatform {
-	GDCLASS(EditorExportPlatformPC, EditorExportPlatform);
-
-private:
-	Ref<ImageTexture> logo;
-	String name;
-	String os_name;
-
-	int chmod_flags = -1;
-
-public:
-	virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
-
-	virtual void get_export_options(List<ExportOption> *r_options) override;
-
-	virtual String get_name() const override;
-	virtual String get_os_name() const override;
-	virtual Ref<Texture2D> get_logo() const override;
-
-	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) 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 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);
-
-	void set_extension(const String &p_extension, const String &p_feature_key = "default");
-	void set_name(const String &p_name);
-	void set_os_name(const String &p_name);
-
-	void set_logo(const Ref<Texture2D> &p_logo);
-
-	void add_platform_feature(const String &p_feature);
-	virtual void get_platform_features(List<String> *r_features) override;
-	virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
-
-	int get_chmod_flags() const;
-	void set_chmod_flags(int p_flags);
-
-	virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
-		return Error::OK;
-	}
-};
-
-class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
-	GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin);
-
-public:
-	virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override;
-	EditorExportTextSceneToBinaryPlugin();
-};
-
-#endif // EDITOR_EXPORT_H

+ 1 - 1
editor/editor_node.cpp

@@ -78,7 +78,6 @@
 #include "editor/editor_build_profile.h"
 #include "editor/editor_command_palette.h"
 #include "editor/editor_data.h"
-#include "editor/editor_export.h"
 #include "editor/editor_feature_profile.h"
 #include "editor/editor_file_dialog.h"
 #include "editor/editor_file_system.h"
@@ -104,6 +103,7 @@
 #include "editor/editor_themes.h"
 #include "editor/editor_toaster.h"
 #include "editor/editor_translation_parser.h"
+#include "editor/export/editor_export.h"
 #include "editor/export_template_manager.h"
 #include "editor/filesystem_dock.h"
 #include "editor/import/audio_stream_import_settings.h"

+ 1 - 1
editor/editor_node.h

@@ -32,10 +32,10 @@
 #define EDITOR_NODE_H
 
 #include "core/templates/safe_refcount.h"
-#include "editor/editor_export.h"
 #include "editor/editor_folding.h"
 #include "editor/editor_native_shader_source_visualizer.h"
 #include "editor/editor_run.h"
+#include "editor/export/editor_export.h"
 #include "editor/inspector_dock.h"
 #include "editor/property_editor.h"
 

+ 1 - 1
editor/editor_plugin.cpp

@@ -31,11 +31,11 @@
 #include "editor_plugin.h"
 
 #include "editor/editor_command_palette.h"
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
 #include "editor/editor_paths.h"
 #include "editor/editor_resource_preview.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
 #include "editor/filesystem_dock.h"
 #include "editor/plugins/canvas_item_editor_plugin.h"
 #include "editor/plugins/node_3d_editor_plugin.h"

+ 1 - 1
editor/editor_run_native.cpp

@@ -30,9 +30,9 @@
 
 #include "editor_run_native.h"
 
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"
+#include "editor/export/editor_export_platform.h"
 
 void EditorRunNative::_notification(int p_what) {
 	switch (p_what) {

+ 5 - 0
editor/export/SCsub

@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.editor_sources, "*.cpp")

+ 355 - 0
editor/export/editor_export.cpp

@@ -0,0 +1,355 @@
+/*************************************************************************/
+/*  editor_export.cpp                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.h"
+
+#include "core/config/project_settings.h"
+#include "core/io/config_file.h"
+
+EditorExport *EditorExport::singleton = nullptr;
+
+void EditorExport::_save() {
+	Ref<ConfigFile> config;
+	config.instantiate();
+	for (int i = 0; i < export_presets.size(); i++) {
+		Ref<EditorExportPreset> preset = export_presets[i];
+		String section = "preset." + itos(i);
+
+		config->set_value(section, "name", preset->get_name());
+		config->set_value(section, "platform", preset->get_platform()->get_name());
+		config->set_value(section, "runnable", preset->is_runnable());
+		config->set_value(section, "custom_features", preset->get_custom_features());
+
+		bool save_files = false;
+		switch (preset->get_export_filter()) {
+			case EditorExportPreset::EXPORT_ALL_RESOURCES: {
+				config->set_value(section, "export_filter", "all_resources");
+			} break;
+			case EditorExportPreset::EXPORT_SELECTED_SCENES: {
+				config->set_value(section, "export_filter", "scenes");
+				save_files = true;
+			} break;
+			case EditorExportPreset::EXPORT_SELECTED_RESOURCES: {
+				config->set_value(section, "export_filter", "resources");
+				save_files = true;
+			} break;
+			case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: {
+				config->set_value(section, "export_filter", "exclude");
+				save_files = true;
+			} break;
+		}
+
+		if (save_files) {
+			Vector<String> export_files = preset->get_files_to_export();
+			config->set_value(section, "export_files", export_files);
+		}
+		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, "encryption_include_filters", preset->get_enc_in_filter());
+		config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
+		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());
+		config->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
+
+		String option_section = "preset." + itos(i) + ".options";
+
+		for (const PropertyInfo &E : preset->get_properties()) {
+			config->set_value(option_section, E.name, preset->get(E.name));
+		}
+	}
+
+	config->save("res://export_presets.cfg");
+}
+
+void EditorExport::save_presets() {
+	if (block_save) {
+		return;
+	}
+	save_timer->start();
+}
+
+void EditorExport::_bind_methods() {
+	ADD_SIGNAL(MethodInfo("export_presets_updated"));
+}
+
+void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
+	export_platforms.push_back(p_platform);
+}
+
+int EditorExport::get_export_platform_count() {
+	return export_platforms.size();
+}
+
+Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) {
+	ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>());
+
+	return export_platforms[p_idx];
+}
+
+void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) {
+	if (p_at_pos < 0) {
+		export_presets.push_back(p_preset);
+	} else {
+		export_presets.insert(p_at_pos, p_preset);
+	}
+}
+
+String EditorExportPlatform::test_etc2() const {
+	const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
+
+	if (!etc2_supported) {
+		return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
+	}
+
+	return String();
+}
+
+int EditorExport::get_export_preset_count() const {
+	return export_presets.size();
+}
+
+Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) {
+	ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>());
+	return export_presets[p_idx];
+}
+
+void EditorExport::remove_export_preset(int p_idx) {
+	export_presets.remove_at(p_idx);
+	save_presets();
+}
+
+void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
+	if (!export_plugins.has(p_plugin)) {
+		export_plugins.push_back(p_plugin);
+	}
+}
+
+void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
+	export_plugins.erase(p_plugin);
+}
+
+Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() {
+	return export_plugins;
+}
+
+void EditorExport::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_ENTER_TREE: {
+			load_config();
+		} break;
+
+		case NOTIFICATION_PROCESS: {
+			update_export_presets();
+		} break;
+	}
+}
+
+void EditorExport::load_config() {
+	Ref<ConfigFile> config;
+	config.instantiate();
+	Error err = config->load("res://export_presets.cfg");
+	if (err != OK) {
+		return;
+	}
+
+	block_save = true;
+
+	int index = 0;
+	while (true) {
+		String section = "preset." + itos(index);
+		if (!config->has_section(section)) {
+			break;
+		}
+
+		String platform = config->get_value(section, "platform");
+
+		Ref<EditorExportPreset> preset;
+
+		for (int i = 0; i < export_platforms.size(); i++) {
+			if (export_platforms[i]->get_name() == platform) {
+				preset = export_platforms.write[i]->create_preset();
+				break;
+			}
+		}
+
+		if (!preset.is_valid()) {
+			index++;
+			ERR_CONTINUE(!preset.is_valid());
+		}
+
+		preset->set_name(config->get_value(section, "name"));
+		preset->set_runnable(config->get_value(section, "runnable"));
+
+		if (config->has_section_key(section, "custom_features")) {
+			preset->set_custom_features(config->get_value(section, "custom_features"));
+		}
+
+		String export_filter = config->get_value(section, "export_filter");
+
+		bool get_files = false;
+
+		if (export_filter == "all_resources") {
+			preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES);
+		} else if (export_filter == "scenes") {
+			preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES);
+			get_files = true;
+		} else if (export_filter == "resources") {
+			preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES);
+			get_files = true;
+		} else if (export_filter == "exclude") {
+			preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES);
+			get_files = true;
+		}
+
+		if (get_files) {
+			Vector<String> files = config->get_value(section, "export_files");
+
+			for (int i = 0; i < files.size(); i++) {
+				if (!FileAccess::exists(files[i])) {
+					preset->remove_export_file(files[i]);
+				} else {
+					preset->add_export_file(files[i]);
+				}
+			}
+		}
+
+		preset->set_include_filter(config->get_value(section, "include_filter"));
+		preset->set_exclude_filter(config->get_value(section, "exclude_filter"));
+		preset->set_export_path(config->get_value(section, "export_path", ""));
+
+		if (config->has_section_key(section, "encrypt_pck")) {
+			preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
+		}
+		if (config->has_section_key(section, "encrypt_directory")) {
+			preset->set_enc_directory(config->get_value(section, "encrypt_directory"));
+		}
+		if (config->has_section_key(section, "encryption_include_filters")) {
+			preset->set_enc_in_filter(config->get_value(section, "encryption_include_filters"));
+		}
+		if (config->has_section_key(section, "encryption_exclude_filters")) {
+			preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters"));
+		}
+		if (config->has_section_key(section, "script_export_mode")) {
+			preset->set_script_export_mode(config->get_value(section, "script_export_mode"));
+		}
+		if (config->has_section_key(section, "script_encryption_key")) {
+			preset->set_script_encryption_key(config->get_value(section, "script_encryption_key"));
+		}
+
+		String option_section = "preset." + itos(index) + ".options";
+
+		List<String> options;
+
+		config->get_section_keys(option_section, &options);
+
+		for (const String &E : options) {
+			Variant value = config->get_value(option_section, E);
+
+			preset->set(E, value);
+		}
+
+		add_export_preset(preset);
+		index++;
+	}
+
+	block_save = false;
+}
+
+void EditorExport::update_export_presets() {
+	HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
+
+	for (int i = 0; i < export_platforms.size(); i++) {
+		Ref<EditorExportPlatform> platform = export_platforms[i];
+
+		if (platform->should_update_export_options()) {
+			List<EditorExportPlatform::ExportOption> options;
+			platform->get_export_options(&options);
+
+			platform_options[platform->get_name()] = options;
+		}
+	}
+
+	bool export_presets_updated = false;
+	for (int i = 0; i < export_presets.size(); i++) {
+		Ref<EditorExportPreset> preset = export_presets[i];
+		if (platform_options.has(preset->get_platform()->get_name())) {
+			export_presets_updated = true;
+
+			List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()];
+
+			// Copy the previous preset values
+			HashMap<StringName, Variant> previous_values = preset->values;
+
+			// Clear the preset properties and values prior to reloading
+			preset->properties.clear();
+			preset->values.clear();
+
+			for (const EditorExportPlatform::ExportOption &E : options) {
+				preset->properties.push_back(E.option);
+
+				StringName option_name = E.option.name;
+				preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value;
+			}
+		}
+	}
+
+	if (export_presets_updated) {
+		emit_signal(_export_presets_updated);
+	}
+}
+
+bool EditorExport::poll_export_platforms() {
+	bool changed = false;
+	for (int i = 0; i < export_platforms.size(); i++) {
+		if (export_platforms.write[i]->poll_export()) {
+			changed = true;
+		}
+	}
+
+	return changed;
+}
+
+EditorExport::EditorExport() {
+	save_timer = memnew(Timer);
+	add_child(save_timer);
+	save_timer->set_wait_time(0.8);
+	save_timer->set_one_shot(true);
+	save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
+
+	_export_presets_updated = "export_presets_updated";
+
+	singleton = this;
+	set_process(true);
+}
+
+EditorExport::~EditorExport() {
+}

+ 84 - 0
editor/export/editor_export.h

@@ -0,0 +1,84 @@
+/*************************************************************************/
+/*  editor_export.h                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_H
+#define EDITOR_EXPORT_H
+
+#include "editor_export_platform.h"
+#include "editor_export_plugin.h"
+
+class EditorExport : public Node {
+	GDCLASS(EditorExport, Node);
+
+	Vector<Ref<EditorExportPlatform>> export_platforms;
+	Vector<Ref<EditorExportPreset>> export_presets;
+	Vector<Ref<EditorExportPlugin>> export_plugins;
+
+	StringName _export_presets_updated;
+
+	Timer *save_timer = nullptr;
+	bool block_save = false;
+
+	static EditorExport *singleton;
+
+	void _save();
+
+protected:
+	friend class EditorExportPreset;
+	void save_presets();
+
+	void _notification(int p_what);
+	static void _bind_methods();
+
+public:
+	static EditorExport *get_singleton() { return singleton; }
+
+	void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
+	int get_export_platform_count();
+	Ref<EditorExportPlatform> get_export_platform(int p_idx);
+
+	void add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos = -1);
+	int get_export_preset_count() const;
+	Ref<EditorExportPreset> get_export_preset(int p_idx);
+	void remove_export_preset(int p_idx);
+
+	void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
+	void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin);
+	Vector<Ref<EditorExportPlugin>> get_export_plugins();
+
+	void load_config();
+	void update_export_presets();
+	bool poll_export_platforms();
+
+	EditorExport();
+	~EditorExport();
+};
+
+#endif // EDITOR_EXPORT_H

+ 4 - 903
editor/editor_export.cpp → editor/export/editor_export_platform.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  editor_export.cpp                                                    */
+/*  editor_export_platform.cpp                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,28 +28,21 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "editor_export.h"
+#include "editor_export_platform.h"
 
 #include "core/config/project_settings.h"
 #include "core/crypto/crypto_core.h"
 #include "core/extension/native_extension.h"
-#include "core/io/config_file.h"
-#include "core/io/dir_access.h"
-#include "core/io/file_access.h"
 #include "core/io/file_access_encrypted.h"
 #include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
-#include "core/io/resource_loader.h"
-#include "core/io/resource_saver.h"
 #include "core/io/zip_io.h"
-#include "core/object/script_language.h"
 #include "core/version.h"
 #include "editor/editor_file_system.h"
 #include "editor/editor_node.h"
 #include "editor/editor_paths.h"
 #include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
 #include "editor/plugins/script_editor_plugin.h"
-#include "scene/resources/resource_format_text.h"
+#include "editor_export_plugin.h"
 
 static int _get_pad(int p_alignment, int p_n) {
 	int rest = p_n % p_alignment;
@@ -63,196 +56,6 @@ static int _get_pad(int p_alignment, int p_n) {
 
 #define PCK_PADDING 16
 
-bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) {
-	if (values.has(p_name)) {
-		values[p_name] = p_value;
-		EditorExport::singleton->save_presets();
-		return true;
-	}
-
-	return false;
-}
-
-bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
-	if (values.has(p_name)) {
-		r_ret = values[p_name];
-		return true;
-	}
-
-	return false;
-}
-
-void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
-	for (const PropertyInfo &E : properties) {
-		if (platform->get_export_option_visibility(E.name, values)) {
-			p_list->push_back(E);
-		}
-	}
-}
-
-Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
-	return platform;
-}
-
-void EditorExportPreset::update_files_to_export() {
-	Vector<String> to_remove;
-	for (const String &E : selected_files) {
-		if (!FileAccess::exists(E)) {
-			to_remove.push_back(E);
-		}
-	}
-	for (int i = 0; i < to_remove.size(); ++i) {
-		selected_files.erase(to_remove[i]);
-	}
-}
-
-Vector<String> EditorExportPreset::get_files_to_export() const {
-	Vector<String> files;
-	for (const String &E : selected_files) {
-		files.push_back(E);
-	}
-	return files;
-}
-
-void EditorExportPreset::set_name(const String &p_name) {
-	name = p_name;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_name() const {
-	return name;
-}
-
-void EditorExportPreset::set_runnable(bool p_enable) {
-	runnable = p_enable;
-	EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::is_runnable() const {
-	return runnable;
-}
-
-void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
-	export_filter = p_filter;
-	EditorExport::singleton->save_presets();
-}
-
-EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
-	return export_filter;
-}
-
-void EditorExportPreset::set_include_filter(const String &p_include) {
-	include_filter = p_include;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_include_filter() const {
-	return include_filter;
-}
-
-void EditorExportPreset::set_export_path(const String &p_path) {
-	export_path = p_path;
-	/* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
-	 * this should be removed. */
-	if (export_path.is_absolute_path()) {
-		String res_path = OS::get_singleton()->get_resource_dir();
-		export_path = res_path.path_to_file(export_path);
-	}
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_export_path() const {
-	return export_path;
-}
-
-void EditorExportPreset::set_exclude_filter(const String &p_exclude) {
-	exclude_filter = p_exclude;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_exclude_filter() const {
-	return exclude_filter;
-}
-
-void EditorExportPreset::add_export_file(const String &p_path) {
-	selected_files.insert(p_path);
-	EditorExport::singleton->save_presets();
-}
-
-void EditorExportPreset::remove_export_file(const String &p_path) {
-	selected_files.erase(p_path);
-	EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::has_export_file(const String &p_path) {
-	return selected_files.has(p_path);
-}
-
-void EditorExportPreset::set_custom_features(const String &p_custom_features) {
-	custom_features = p_custom_features;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_custom_features() const {
-	return custom_features;
-}
-
-void EditorExportPreset::set_enc_in_filter(const String &p_filter) {
-	enc_in_filters = p_filter;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_enc_in_filter() const {
-	return enc_in_filters;
-}
-
-void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {
-	enc_ex_filters = p_filter;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_enc_ex_filter() const {
-	return enc_ex_filters;
-}
-
-void EditorExportPreset::set_enc_pck(bool p_enabled) {
-	enc_pck = p_enabled;
-	EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::get_enc_pck() const {
-	return enc_pck;
-}
-
-void EditorExportPreset::set_enc_directory(bool p_enabled) {
-	enc_directory = p_enabled;
-	EditorExport::singleton->save_presets();
-}
-
-bool EditorExportPreset::get_enc_directory() const {
-	return enc_directory;
-}
-
-void EditorExportPreset::set_script_export_mode(int p_mode) {
-	script_mode = p_mode;
-	EditorExport::singleton->save_presets();
-}
-
-int EditorExportPreset::get_script_export_mode() const {
-	return script_mode;
-}
-
-void EditorExportPreset::set_script_encryption_key(const String &p_key) {
-	script_key = p_key;
-	EditorExport::singleton->save_presets();
-}
-
-String EditorExportPreset::get_script_encryption_key() const {
-	return script_key;
-}
-
-///////////////////////////////////
-
 bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) {
 	bool has_messages = false;
 
@@ -272,7 +75,7 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err)
 		} else {
 			p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons")), 16 * EDSCALE, 16 * EDSCALE, Color(1.0, 1.0, 1.0), INLINE_ALIGNMENT_CENTER);
 			p_log->add_text(" ");
-			p_log->add_text(TTR("Completed successfully."));
+			p_log->add_text(TTR("Completed sucessfully."));
 			if (msg_count > 0) {
 				has_messages = true;
 			}
@@ -625,138 +428,6 @@ void EditorExportPlatform::_edit_filter_list(HashSet<String> &r_list, const Stri
 	_edit_files_with_filter(da, filters, r_list, exclude);
 }
 
-void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
-	if (p_preset.is_valid()) {
-		export_preset = p_preset;
-	}
-}
-
-Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const {
-	return export_preset;
-}
-
-void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) {
-	ExtraFile ef;
-	ef.data = p_file;
-	ef.path = p_path;
-	ef.remap = p_remap;
-	extra_files.push_back(ef);
-}
-
-void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) {
-	shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
-}
-
-void EditorExportPlugin::add_ios_framework(const String &p_path) {
-	ios_frameworks.push_back(p_path);
-}
-
-void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) {
-	ios_embedded_frameworks.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_frameworks() const {
-	return ios_frameworks;
-}
-
-Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const {
-	return ios_embedded_frameworks;
-}
-
-void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
-	ios_plist_content += p_plist_content + "\n";
-}
-
-String EditorExportPlugin::get_ios_plist_content() const {
-	return ios_plist_content;
-}
-
-void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
-	if (ios_linker_flags.length() > 0) {
-		ios_linker_flags += ' ';
-	}
-	ios_linker_flags += p_flags;
-}
-
-String EditorExportPlugin::get_ios_linker_flags() const {
-	return ios_linker_flags;
-}
-
-void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
-	ios_bundle_files.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
-	return ios_bundle_files;
-}
-
-void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
-	ios_cpp_code += p_code;
-}
-
-String EditorExportPlugin::get_ios_cpp_code() const {
-	return ios_cpp_code;
-}
-
-void EditorExportPlugin::add_macos_plugin_file(const String &p_path) {
-	macos_plugin_files.push_back(p_path);
-}
-
-const Vector<String> &EditorExportPlugin::get_macos_plugin_files() const {
-	return macos_plugin_files;
-}
-
-void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) {
-	ios_project_static_libs.push_back(p_path);
-}
-
-Vector<String> EditorExportPlugin::get_ios_project_static_libs() const {
-	return ios_project_static_libs;
-}
-
-void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) {
-	GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
-}
-
-void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
-	GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags);
-}
-
-void EditorExportPlugin::_export_end_script() {
-	GDVIRTUAL_CALL(_export_end);
-}
-
-void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
-}
-
-void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
-}
-
-void EditorExportPlugin::skip() {
-	skipped = true;
-}
-
-void EditorExportPlugin::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object);
-	ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib);
-	ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
-	ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
-	ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework);
-	ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
-	ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
-	ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
-	ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
-	ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file);
-	ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
-
-	GDVIRTUAL_BIND(_export_file, "path", "type", "features");
-	GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags");
-	GDVIRTUAL_BIND(_export_end);
-}
-
-EditorExportPlugin::EditorExportPlugin() {
-}
-
 EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug) {
 	Ref<EditorExportPlatform> platform = p_preset->get_platform();
 	List<String> feature_list;
@@ -1504,573 +1175,3 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
 
 EditorExportPlatform::EditorExportPlatform() {
 }
-
-////
-
-EditorExport *EditorExport::singleton = nullptr;
-
-void EditorExport::_save() {
-	Ref<ConfigFile> config;
-	config.instantiate();
-	for (int i = 0; i < export_presets.size(); i++) {
-		Ref<EditorExportPreset> preset = export_presets[i];
-		String section = "preset." + itos(i);
-
-		config->set_value(section, "name", preset->get_name());
-		config->set_value(section, "platform", preset->get_platform()->get_name());
-		config->set_value(section, "runnable", preset->is_runnable());
-		config->set_value(section, "custom_features", preset->get_custom_features());
-
-		bool save_files = false;
-		switch (preset->get_export_filter()) {
-			case EditorExportPreset::EXPORT_ALL_RESOURCES: {
-				config->set_value(section, "export_filter", "all_resources");
-			} break;
-			case EditorExportPreset::EXPORT_SELECTED_SCENES: {
-				config->set_value(section, "export_filter", "scenes");
-				save_files = true;
-			} break;
-			case EditorExportPreset::EXPORT_SELECTED_RESOURCES: {
-				config->set_value(section, "export_filter", "resources");
-				save_files = true;
-			} break;
-			case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES: {
-				config->set_value(section, "export_filter", "exclude");
-				save_files = true;
-			} break;
-		}
-
-		if (save_files) {
-			Vector<String> export_files = preset->get_files_to_export();
-			config->set_value(section, "export_files", export_files);
-		}
-		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, "encryption_include_filters", preset->get_enc_in_filter());
-		config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter());
-		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());
-		config->set_value(section, "script_encryption_key", preset->get_script_encryption_key());
-
-		String option_section = "preset." + itos(i) + ".options";
-
-		for (const PropertyInfo &E : preset->get_properties()) {
-			config->set_value(option_section, E.name, preset->get(E.name));
-		}
-	}
-
-	config->save("res://export_presets.cfg");
-}
-
-void EditorExport::save_presets() {
-	if (block_save) {
-		return;
-	}
-	save_timer->start();
-}
-
-void EditorExport::_bind_methods() {
-	ADD_SIGNAL(MethodInfo("export_presets_updated"));
-}
-
-void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
-	export_platforms.push_back(p_platform);
-}
-
-int EditorExport::get_export_platform_count() {
-	return export_platforms.size();
-}
-
-Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) {
-	ERR_FAIL_INDEX_V(p_idx, export_platforms.size(), Ref<EditorExportPlatform>());
-
-	return export_platforms[p_idx];
-}
-
-void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, int p_at_pos) {
-	if (p_at_pos < 0) {
-		export_presets.push_back(p_preset);
-	} else {
-		export_presets.insert(p_at_pos, p_preset);
-	}
-}
-
-String EditorExportPlatform::test_etc2() const {
-	const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
-
-	if (!etc2_supported) {
-		return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
-	}
-
-	return String();
-}
-
-int EditorExport::get_export_preset_count() const {
-	return export_presets.size();
-}
-
-Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) {
-	ERR_FAIL_INDEX_V(p_idx, export_presets.size(), Ref<EditorExportPreset>());
-	return export_presets[p_idx];
-}
-
-void EditorExport::remove_export_preset(int p_idx) {
-	export_presets.remove_at(p_idx);
-	save_presets();
-}
-
-void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
-	if (!export_plugins.has(p_plugin)) {
-		export_plugins.push_back(p_plugin);
-	}
-}
-
-void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) {
-	export_plugins.erase(p_plugin);
-}
-
-Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() {
-	return export_plugins;
-}
-
-void EditorExport::_notification(int p_what) {
-	switch (p_what) {
-		case NOTIFICATION_ENTER_TREE: {
-			load_config();
-		} break;
-
-		case NOTIFICATION_PROCESS: {
-			update_export_presets();
-		} break;
-	}
-}
-
-void EditorExport::load_config() {
-	Ref<ConfigFile> config;
-	config.instantiate();
-	Error err = config->load("res://export_presets.cfg");
-	if (err != OK) {
-		return;
-	}
-
-	block_save = true;
-
-	int index = 0;
-	while (true) {
-		String section = "preset." + itos(index);
-		if (!config->has_section(section)) {
-			break;
-		}
-
-		String platform = config->get_value(section, "platform");
-
-		Ref<EditorExportPreset> preset;
-
-		for (int i = 0; i < export_platforms.size(); i++) {
-			if (export_platforms[i]->get_name() == platform) {
-				preset = export_platforms.write[i]->create_preset();
-				break;
-			}
-		}
-
-		if (!preset.is_valid()) {
-			index++;
-			ERR_CONTINUE(!preset.is_valid());
-		}
-
-		preset->set_name(config->get_value(section, "name"));
-		preset->set_runnable(config->get_value(section, "runnable"));
-
-		if (config->has_section_key(section, "custom_features")) {
-			preset->set_custom_features(config->get_value(section, "custom_features"));
-		}
-
-		String export_filter = config->get_value(section, "export_filter");
-
-		bool get_files = false;
-
-		if (export_filter == "all_resources") {
-			preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES);
-		} else if (export_filter == "scenes") {
-			preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES);
-			get_files = true;
-		} else if (export_filter == "resources") {
-			preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES);
-			get_files = true;
-		} else if (export_filter == "exclude") {
-			preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES);
-			get_files = true;
-		}
-
-		if (get_files) {
-			Vector<String> files = config->get_value(section, "export_files");
-
-			for (int i = 0; i < files.size(); i++) {
-				if (!FileAccess::exists(files[i])) {
-					preset->remove_export_file(files[i]);
-				} else {
-					preset->add_export_file(files[i]);
-				}
-			}
-		}
-
-		preset->set_include_filter(config->get_value(section, "include_filter"));
-		preset->set_exclude_filter(config->get_value(section, "exclude_filter"));
-		preset->set_export_path(config->get_value(section, "export_path", ""));
-
-		if (config->has_section_key(section, "encrypt_pck")) {
-			preset->set_enc_pck(config->get_value(section, "encrypt_pck"));
-		}
-		if (config->has_section_key(section, "encrypt_directory")) {
-			preset->set_enc_directory(config->get_value(section, "encrypt_directory"));
-		}
-		if (config->has_section_key(section, "encryption_include_filters")) {
-			preset->set_enc_in_filter(config->get_value(section, "encryption_include_filters"));
-		}
-		if (config->has_section_key(section, "encryption_exclude_filters")) {
-			preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters"));
-		}
-		if (config->has_section_key(section, "script_export_mode")) {
-			preset->set_script_export_mode(config->get_value(section, "script_export_mode"));
-		}
-		if (config->has_section_key(section, "script_encryption_key")) {
-			preset->set_script_encryption_key(config->get_value(section, "script_encryption_key"));
-		}
-
-		String option_section = "preset." + itos(index) + ".options";
-
-		List<String> options;
-
-		config->get_section_keys(option_section, &options);
-
-		for (const String &E : options) {
-			Variant value = config->get_value(option_section, E);
-
-			preset->set(E, value);
-		}
-
-		add_export_preset(preset);
-		index++;
-	}
-
-	block_save = false;
-}
-
-void EditorExport::update_export_presets() {
-	HashMap<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
-
-	for (int i = 0; i < export_platforms.size(); i++) {
-		Ref<EditorExportPlatform> platform = export_platforms[i];
-
-		if (platform->should_update_export_options()) {
-			List<EditorExportPlatform::ExportOption> options;
-			platform->get_export_options(&options);
-
-			platform_options[platform->get_name()] = options;
-		}
-	}
-
-	bool export_presets_updated = false;
-	for (int i = 0; i < export_presets.size(); i++) {
-		Ref<EditorExportPreset> preset = export_presets[i];
-		if (platform_options.has(preset->get_platform()->get_name())) {
-			export_presets_updated = true;
-
-			List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()];
-
-			// Copy the previous preset values
-			HashMap<StringName, Variant> previous_values = preset->values;
-
-			// Clear the preset properties and values prior to reloading
-			preset->properties.clear();
-			preset->values.clear();
-
-			for (const EditorExportPlatform::ExportOption &E : options) {
-				preset->properties.push_back(E.option);
-
-				StringName option_name = E.option.name;
-				preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value;
-			}
-		}
-	}
-
-	if (export_presets_updated) {
-		emit_signal(_export_presets_updated);
-	}
-}
-
-bool EditorExport::poll_export_platforms() {
-	bool changed = false;
-	for (int i = 0; i < export_platforms.size(); i++) {
-		if (export_platforms.write[i]->poll_export()) {
-			changed = true;
-		}
-	}
-
-	return changed;
-}
-
-EditorExport::EditorExport() {
-	save_timer = memnew(Timer);
-	add_child(save_timer);
-	save_timer->set_wait_time(0.8);
-	save_timer->set_one_shot(true);
-	save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
-
-	_export_presets_updated = "export_presets_updated";
-
-	singleton = this;
-	set_process(true);
-}
-
-EditorExport::~EditorExport() {
-}
-
-//////////
-
-void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
-	if (p_preset->get("texture_format/s3tc")) {
-		r_features->push_back("s3tc");
-	}
-	if (p_preset->get("texture_format/etc")) {
-		r_features->push_back("etc");
-	}
-	if (p_preset->get("texture_format/etc2")) {
-		r_features->push_back("etc2");
-	}
-
-	if (p_preset->get("binary_format/64_bits")) {
-		r_features->push_back("64");
-	} else {
-		r_features->push_back("32");
-	}
-}
-
-void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
-	String ext_filter = (get_os_name() == "Windows") ? "*.exe" : "";
-	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
-
-	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1));
-
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/64_bits"), true));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false));
-
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
-	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true));
-}
-
-String EditorExportPlatformPC::get_name() const {
-	return name;
-}
-
-String EditorExportPlatformPC::get_os_name() const {
-	return os_name;
-}
-
-Ref<Texture2D> EditorExportPlatformPC::get_logo() const {
-	return logo;
-}
-
-bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
-	String err;
-	bool valid = false;
-
-	// Look for export templates (first official, and if defined custom templates).
-
-	bool use64 = p_preset->get("binary_format/64_bits");
-	bool dvalid = exists_export_template(get_template_file_name("debug", use64 ? "x86_64" : "x86_32"), &err);
-	bool rvalid = exists_export_template(get_template_file_name("release", use64 ? "x86_64" : "x86_32"), &err);
-
-	if (p_preset->get("custom_template/debug") != "") {
-		dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
-		if (!dvalid) {
-			err += TTR("Custom debug template not found.") + "\n";
-		}
-	}
-	if (p_preset->get("custom_template/release") != "") {
-		rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
-		if (!rvalid) {
-			err += TTR("Custom release template not found.") + "\n";
-		}
-	}
-
-	valid = dvalid || rvalid;
-	r_missing_templates = !valid;
-
-	if (!err.is_empty()) {
-		r_error = err;
-	}
-	return valid;
-}
-
-Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int 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);
-	if (err == OK) {
-		err = modify_template(p_preset, p_debug, p_path, p_flags);
-	}
-	if (err == OK) {
-		err = export_project_data(p_preset, p_debug, p_path, p_flags);
-	}
-
-	return err;
-}
-
-Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int 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;
-	}
-
-	String custom_debug = p_preset->get("custom_template/debug");
-	String custom_release = p_preset->get("custom_template/release");
-
-	String template_path = p_debug ? custom_debug : custom_release;
-
-	template_path = template_path.strip_edges();
-
-	if (template_path.is_empty()) {
-		template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/64_bits") ? "64" : "32"));
-	}
-
-	if (!template_path.is_empty() && !FileAccess::exists(template_path)) {
-		add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path));
-		return ERR_FILE_NOT_FOUND;
-	}
-
-	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	da->make_dir_recursive(p_path.get_base_dir());
-	Error err = da->copy(template_path, p_path, get_chmod_flags());
-	if (err != OK) {
-		add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
-	}
-
-	return err;
-}
-
-Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
-	String pck_path;
-	if (p_preset->get("binary_format/embed_pck")) {
-		pck_path = p_path;
-	} else {
-		pck_path = p_path.get_basename() + ".pck";
-	}
-
-	Vector<SharedObject> so_files;
-
-	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);
-	if (err == OK && p_preset->get("binary_format/embed_pck")) {
-		if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) {
-			add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
-			return ERR_INVALID_PARAMETER;
-		}
-
-		err = fixup_embedded_pck(p_path, embedded_pos, embedded_size);
-	}
-
-	if (err == OK && !so_files.is_empty()) {
-		// If shared object files, copy them.
-		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-		for (int i = 0; i < so_files.size() && err == OK; i++) {
-			String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path);
-			String target_path;
-			if (so_files[i].target.is_empty()) {
-				target_path = p_path.get_base_dir().plus_file(src_path.get_file());
-			} else {
-				target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file());
-			}
-
-			if (da->dir_exists(src_path)) {
-				err = da->make_dir_recursive(target_path);
-				if (err == OK) {
-					err = da->copy_dir(src_path, target_path, -1, true);
-				}
-			} else {
-				err = da->copy(src_path, target_path);
-				if (err == OK) {
-					err = sign_shared_object(p_preset, p_debug, target_path);
-				}
-			}
-		}
-	}
-
-	return err;
-}
-
-Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
-	return OK;
-}
-
-void EditorExportPlatformPC::set_name(const String &p_name) {
-	name = p_name;
-}
-
-void EditorExportPlatformPC::set_os_name(const String &p_name) {
-	os_name = p_name;
-}
-
-void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) {
-	logo = p_logo;
-}
-
-void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
-	r_features->push_back("pc"); //all pcs support "pc"
-	r_features->push_back("s3tc"); //all pcs support "s3tc" compression
-	r_features->push_back(get_os_name().to_lower()); //OS name is a feature
-}
-
-void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {
-	if (p_features.has("bptc")) {
-		if (p_preset->has("texture_format/no_bptc_fallbacks")) {
-			p_features.erase("s3tc");
-		}
-	}
-}
-
-int EditorExportPlatformPC::get_chmod_flags() const {
-	return chmod_flags;
-}
-
-void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
-	chmod_flags = p_flags;
-}
-
-///////////////////////
-
-void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
-	String extension = p_path.get_extension().to_lower();
-	if (extension != "tres" && extension != "tscn") {
-		return;
-	}
-
-	bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary");
-	if (!convert) {
-		return;
-	}
-	String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
-	Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
-	if (err != OK) {
-		DirAccess::remove_file_or_error(tmp_path);
-		ERR_FAIL();
-	}
-	Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
-	if (data.size() == 0) {
-		DirAccess::remove_file_or_error(tmp_path);
-		ERR_FAIL();
-	}
-	DirAccess::remove_file_or_error(tmp_path);
-	add_file(p_path + ".converted.res", data, true);
-}
-
-EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
-	GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false);
-}

+ 221 - 0
editor/export/editor_export_platform.h

@@ -0,0 +1,221 @@
+/*************************************************************************/
+/*  editor_export_platform.h                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_H
+#define EDITOR_EXPORT_PLATFORM_H
+
+class EditorFileSystemDirectory;
+struct EditorProgress;
+
+#include "core/io/dir_access.h"
+#include "editor_export_preset.h"
+#include "editor_export_shared_object.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/main/node.h"
+
+class EditorExportPlatform : public RefCounted {
+	GDCLASS(EditorExportPlatform, RefCounted);
+
+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 (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);
+
+	enum ExportMessageType {
+		EXPORT_MESSAGE_NONE,
+		EXPORT_MESSAGE_INFO,
+		EXPORT_MESSAGE_WARNING,
+		EXPORT_MESSAGE_ERROR,
+	};
+
+	struct ExportMessage {
+		ExportMessageType msg_type;
+		String category;
+		String text;
+	};
+
+private:
+	struct SavedData {
+		uint64_t ofs = 0;
+		uint64_t size = 0;
+		bool encrypted = false;
+		Vector<uint8_t> md5;
+		CharString path_utf8;
+
+		bool operator<(const SavedData &p_data) const {
+			return path_utf8 < p_data.path_utf8;
+		}
+	};
+
+	struct PackData {
+		Ref<FileAccess> f;
+		Vector<SavedData> file_ofs;
+		EditorProgress *ep = nullptr;
+		Vector<SharedObject> *so_files = nullptr;
+	};
+
+	struct ZipData {
+		void *zip = nullptr;
+		EditorProgress *ep = nullptr;
+	};
+
+	struct FeatureContainers {
+		HashSet<String> features;
+		Vector<String> features_pv;
+	};
+
+	Vector<ExportMessage> messages;
+
+	void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths);
+	void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
+
+	void gen_debug_flags(Vector<String> &r_flags, int p_flags);
+	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);
+
+	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);
+
+protected:
+	struct ExportNotifier {
+		ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
+		~ExportNotifier();
+	};
+
+	FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &p_preset, bool p_debug);
+
+	bool exists_export_template(String template_file_name, String *err) const;
+	String find_export_template(String template_file_name, String *err = nullptr) const;
+	void gen_export_flags(Vector<String> &r_flags, int p_flags);
+
+public:
+	virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) = 0;
+
+	struct ExportOption {
+		PropertyInfo option;
+		Variant default_value;
+
+		ExportOption(const PropertyInfo &p_info, const Variant &p_default) :
+				option(p_info),
+				default_value(p_default) {
+		}
+		ExportOption() {}
+	};
+
+	virtual Ref<EditorExportPreset> create_preset();
+
+	virtual void clear_messages() { messages.clear(); }
+	virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) {
+		ExportMessage msg;
+		msg.category = p_category;
+		msg.text = p_message;
+		msg.msg_type = p_type;
+		messages.push_back(msg);
+		switch (p_type) {
+			case EXPORT_MESSAGE_INFO: {
+				print_line(vformat("%s: %s\n", msg.category, msg.text));
+			} break;
+			case EXPORT_MESSAGE_WARNING: {
+				WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text));
+			} break;
+			case EXPORT_MESSAGE_ERROR: {
+				ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text));
+			} break;
+			default:
+				break;
+		}
+	}
+
+	virtual int get_message_count() const {
+		return messages.size();
+	}
+
+	virtual ExportMessage get_message(int p_index) const {
+		ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage());
+		return messages[p_index];
+	}
+
+	virtual ExportMessageType get_worst_message_type() const {
+		ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
+		for (int i = 0; i < messages.size(); i++) {
+			worst_type = MAX(worst_type, messages[i].msg_type);
+		}
+		return worst_type;
+	}
+
+	virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);
+
+	virtual void get_export_options(List<ExportOption> *r_options) = 0;
+	virtual bool should_update_export_options() { return false; }
+	virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; }
+
+	virtual String get_os_name() const = 0;
+	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);
+
+	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);
+
+	virtual bool poll_export() { return false; }
+	virtual int get_options_count() const { return 0; }
+	virtual String get_options_tooltip() const { return ""; }
+	virtual Ref<ImageTexture> get_option_icon(int p_index) const;
+	virtual String get_option_label(int p_device) const { return ""; }
+	virtual String get_option_tooltip(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_COLLISONS = 8,
+		DEBUG_FLAG_VIEW_NAVIGATION = 16,
+	};
+
+	virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
+	virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
+
+	String test_etc2() const;
+	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) 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 void get_platform_features(List<String> *r_features) = 0;
+	virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0;
+	virtual String get_debug_protocol() const { return "tcp://"; }
+
+	EditorExportPlatform();
+};
+
+#endif // EDITOR_EXPORT_PLATFORM_H

+ 247 - 0
editor/export/editor_export_platform_pc.cpp

@@ -0,0 +1,247 @@
+/*************************************************************************/
+/*  editor_export_platform_pc.cpp                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_pc.h"
+
+#include "core/config/project_settings.h"
+
+void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+	if (p_preset->get("texture_format/s3tc")) {
+		r_features->push_back("s3tc");
+	}
+	if (p_preset->get("texture_format/etc")) {
+		r_features->push_back("etc");
+	}
+	if (p_preset->get("texture_format/etc2")) {
+		r_features->push_back("etc2");
+	}
+
+	if (p_preset->get("binary_format/64_bits")) {
+		r_features->push_back("64");
+	} else {
+		r_features->push_back("32");
+	}
+}
+
+void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
+	String ext_filter = (get_os_name() == "Windows") ? "*.exe" : "";
+	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), ""));
+
+	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1));
+
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/64_bits"), true));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "binary_format/embed_pck"), false));
+
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/bptc"), false));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/no_bptc_fallbacks"), true));
+}
+
+String EditorExportPlatformPC::get_name() const {
+	return name;
+}
+
+String EditorExportPlatformPC::get_os_name() const {
+	return os_name;
+}
+
+Ref<Texture2D> EditorExportPlatformPC::get_logo() const {
+	return logo;
+}
+
+bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+	String err;
+	bool valid = false;
+
+	// Look for export templates (first official, and if defined custom templates).
+
+	bool use64 = p_preset->get("binary_format/64_bits");
+	bool dvalid = exists_export_template(get_template_file_name("debug", use64 ? "x86_64" : "x86_32"), &err);
+	bool rvalid = exists_export_template(get_template_file_name("release", use64 ? "x86_64" : "x86_32"), &err);
+
+	if (p_preset->get("custom_template/debug") != "") {
+		dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+		if (!dvalid) {
+			err += TTR("Custom debug template not found.") + "\n";
+		}
+	}
+	if (p_preset->get("custom_template/release") != "") {
+		rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+		if (!rvalid) {
+			err += TTR("Custom release template not found.") + "\n";
+		}
+	}
+
+	valid = dvalid || rvalid;
+	r_missing_templates = !valid;
+
+	if (!err.is_empty()) {
+		r_error = err;
+	}
+	return valid;
+}
+
+Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int 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);
+	if (err == OK) {
+		err = modify_template(p_preset, p_debug, p_path, p_flags);
+	}
+	if (err == OK) {
+		err = export_project_data(p_preset, p_debug, p_path, p_flags);
+	}
+
+	return err;
+}
+
+Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int 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;
+	}
+
+	String custom_debug = p_preset->get("custom_template/debug");
+	String custom_release = p_preset->get("custom_template/release");
+
+	String template_path = p_debug ? custom_debug : custom_release;
+
+	template_path = template_path.strip_edges();
+
+	if (template_path.is_empty()) {
+		template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/64_bits") ? "64" : "32"));
+	}
+
+	if (!template_path.is_empty() && !FileAccess::exists(template_path)) {
+		add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path));
+		return ERR_FILE_NOT_FOUND;
+	}
+
+	Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+	da->make_dir_recursive(p_path.get_base_dir());
+	Error err = da->copy(template_path, p_path, get_chmod_flags());
+	if (err != OK) {
+		add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
+	}
+
+	return err;
+}
+
+Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+	String pck_path;
+	if (p_preset->get("binary_format/embed_pck")) {
+		pck_path = p_path;
+	} else {
+		pck_path = p_path.get_basename() + ".pck";
+	}
+
+	Vector<SharedObject> so_files;
+
+	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);
+	if (err == OK && p_preset->get("binary_format/embed_pck")) {
+		if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) {
+			add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
+			return ERR_INVALID_PARAMETER;
+		}
+
+		err = fixup_embedded_pck(p_path, embedded_pos, embedded_size);
+	}
+
+	if (err == OK && !so_files.is_empty()) {
+		// If shared object files, copy them.
+		Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		for (int i = 0; i < so_files.size() && err == OK; i++) {
+			String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path);
+			String target_path;
+			if (so_files[i].target.is_empty()) {
+				target_path = p_path.get_base_dir().plus_file(src_path.get_file());
+			} else {
+				target_path = p_path.get_base_dir().plus_file(so_files[i].target).plus_file(src_path.get_file());
+			}
+
+			if (da->dir_exists(src_path)) {
+				err = da->make_dir_recursive(target_path);
+				if (err == OK) {
+					err = da->copy_dir(src_path, target_path, -1, true);
+				}
+			} else {
+				err = da->copy(src_path, target_path);
+				if (err == OK) {
+					err = sign_shared_object(p_preset, p_debug, target_path);
+				}
+			}
+		}
+	}
+
+	return err;
+}
+
+Error EditorExportPlatformPC::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
+	return OK;
+}
+
+void EditorExportPlatformPC::set_name(const String &p_name) {
+	name = p_name;
+}
+
+void EditorExportPlatformPC::set_os_name(const String &p_name) {
+	os_name = p_name;
+}
+
+void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) {
+	logo = p_logo;
+}
+
+void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
+	r_features->push_back("pc"); //all pcs support "pc"
+	r_features->push_back("s3tc"); //all pcs support "s3tc" compression
+	r_features->push_back(get_os_name().to_lower()); //OS name is a feature
+}
+
+void EditorExportPlatformPC::resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {
+	if (p_features.has("bptc")) {
+		if (p_preset->has("texture_format/no_bptc_fallbacks")) {
+			p_features.erase("s3tc");
+		}
+	}
+}
+
+int EditorExportPlatformPC::get_chmod_flags() const {
+	return chmod_flags;
+}
+
+void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
+	chmod_flags = p_flags;
+}

+ 82 - 0
editor/export/editor_export_platform_pc.h

@@ -0,0 +1,82 @@
+/*************************************************************************/
+/*  editor_export_platform_pc.h                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_PC_H
+#define EDITOR_EXPORT_PLATFORM_PC_H
+
+#include "editor_export_platform.h"
+
+class EditorExportPlatformPC : public EditorExportPlatform {
+	GDCLASS(EditorExportPlatformPC, EditorExportPlatform);
+
+private:
+	Ref<ImageTexture> logo;
+	String name;
+	String os_name;
+
+	int chmod_flags = -1;
+
+public:
+	virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+
+	virtual void get_export_options(List<ExportOption> *r_options) override;
+
+	virtual String get_name() const override;
+	virtual String get_os_name() const override;
+	virtual Ref<Texture2D> get_logo() const override;
+
+	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) 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 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);
+
+	void set_extension(const String &p_extension, const String &p_feature_key = "default");
+	void set_name(const String &p_name);
+	void set_os_name(const String &p_name);
+
+	void set_logo(const Ref<Texture2D> &p_logo);
+
+	void add_platform_feature(const String &p_feature);
+	virtual void get_platform_features(List<String> *r_features) override;
+	virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
+
+	int get_chmod_flags() const;
+	void set_chmod_flags(int p_flags);
+
+	virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
+		return Error::OK;
+	}
+};
+
+#endif // EDITOR_EXPORT_PLATFORM_PC_H

+ 201 - 0
editor/export/editor_export_plugin.cpp

@@ -0,0 +1,201 @@
+/*************************************************************************/
+/*  editor_export_plugin.cpp                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_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/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()) {
+		export_preset = p_preset;
+	}
+}
+
+Ref<EditorExportPreset> EditorExportPlugin::get_export_preset() const {
+	return export_preset;
+}
+
+void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) {
+	ExtraFile ef;
+	ef.data = p_file;
+	ef.path = p_path;
+	ef.remap = p_remap;
+	extra_files.push_back(ef);
+}
+
+void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<String> &p_tags, const String &p_target) {
+	shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
+}
+
+void EditorExportPlugin::add_ios_framework(const String &p_path) {
+	ios_frameworks.push_back(p_path);
+}
+
+void EditorExportPlugin::add_ios_embedded_framework(const String &p_path) {
+	ios_embedded_frameworks.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_frameworks() const {
+	return ios_frameworks;
+}
+
+Vector<String> EditorExportPlugin::get_ios_embedded_frameworks() const {
+	return ios_embedded_frameworks;
+}
+
+void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) {
+	ios_plist_content += p_plist_content + "\n";
+}
+
+String EditorExportPlugin::get_ios_plist_content() const {
+	return ios_plist_content;
+}
+
+void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) {
+	if (ios_linker_flags.length() > 0) {
+		ios_linker_flags += ' ';
+	}
+	ios_linker_flags += p_flags;
+}
+
+String EditorExportPlugin::get_ios_linker_flags() const {
+	return ios_linker_flags;
+}
+
+void EditorExportPlugin::add_ios_bundle_file(const String &p_path) {
+	ios_bundle_files.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_bundle_files() const {
+	return ios_bundle_files;
+}
+
+void EditorExportPlugin::add_ios_cpp_code(const String &p_code) {
+	ios_cpp_code += p_code;
+}
+
+String EditorExportPlugin::get_ios_cpp_code() const {
+	return ios_cpp_code;
+}
+
+void EditorExportPlugin::add_macos_plugin_file(const String &p_path) {
+	macos_plugin_files.push_back(p_path);
+}
+
+const Vector<String> &EditorExportPlugin::get_macos_plugin_files() const {
+	return macos_plugin_files;
+}
+
+void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) {
+	ios_project_static_libs.push_back(p_path);
+}
+
+Vector<String> EditorExportPlugin::get_ios_project_static_libs() const {
+	return ios_project_static_libs;
+}
+
+void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features) {
+	GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
+}
+
+void EditorExportPlugin::_export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
+	GDVIRTUAL_CALL(_export_begin, p_features, p_debug, p_path, p_flags);
+}
+
+void EditorExportPlugin::_export_end_script() {
+	GDVIRTUAL_CALL(_export_end);
+}
+
+void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
+}
+
+void EditorExportPlugin::_export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags) {
+}
+
+void EditorExportPlugin::skip() {
+	skipped = true;
+}
+
+void EditorExportPlugin::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags", "target"), &EditorExportPlugin::add_shared_object);
+	ClassDB::bind_method(D_METHOD("add_ios_project_static_lib", "path"), &EditorExportPlugin::add_ios_project_static_lib);
+	ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file);
+	ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework);
+	ClassDB::bind_method(D_METHOD("add_ios_embedded_framework", "path"), &EditorExportPlugin::add_ios_embedded_framework);
+	ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content);
+	ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags);
+	ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file);
+	ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code);
+	ClassDB::bind_method(D_METHOD("add_macos_plugin_file", "path"), &EditorExportPlugin::add_macos_plugin_file);
+	ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip);
+
+	GDVIRTUAL_BIND(_export_file, "path", "type", "features");
+	GDVIRTUAL_BIND(_export_begin, "features", "is_debug", "path", "flags");
+	GDVIRTUAL_BIND(_export_end);
+}
+
+EditorExportPlugin::EditorExportPlugin() {
+}
+
+///////////////////////
+
+void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
+	String extension = p_path.get_extension().to_lower();
+	if (extension != "tres" && extension != "tscn") {
+		return;
+	}
+
+	bool convert = GLOBAL_GET("editor/export/convert_text_resources_to_binary");
+	if (!convert) {
+		return;
+	}
+	String tmp_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpfile.res");
+	Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
+	if (err != OK) {
+		DirAccess::remove_file_or_error(tmp_path);
+		ERR_FAIL();
+	}
+	Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
+	if (data.size() == 0) {
+		DirAccess::remove_file_or_error(tmp_path);
+		ERR_FAIL();
+	}
+	DirAccess::remove_file_or_error(tmp_path);
+	add_file(p_path + ".converted.res", data, true);
+}
+
+EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
+	GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false);
+}

+ 132 - 0
editor/export/editor_export_plugin.h

@@ -0,0 +1,132 @@
+/*************************************************************************/
+/*  editor_export_plugin.h                                               */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_PLUGIN_H
+#define EDITOR_EXPORT_PLUGIN_H
+
+#include "core/extension/native_extension.h"
+#include "editor_export_preset.h"
+#include "editor_export_shared_object.h"
+
+class EditorExportPlugin : public RefCounted {
+	GDCLASS(EditorExportPlugin, RefCounted);
+
+	friend class EditorExportPlatform;
+
+	Ref<EditorExportPreset> export_preset;
+
+	Vector<SharedObject> shared_objects;
+	struct ExtraFile {
+		String path;
+		Vector<uint8_t> data;
+		bool remap = false;
+	};
+	Vector<ExtraFile> extra_files;
+	bool skipped = false;
+
+	Vector<String> ios_frameworks;
+	Vector<String> ios_embedded_frameworks;
+	Vector<String> ios_project_static_libs;
+	String ios_plist_content;
+	String ios_linker_flags;
+	Vector<String> ios_bundle_files;
+	String ios_cpp_code;
+
+	Vector<String> macos_plugin_files;
+
+	_FORCE_INLINE_ void _clear() {
+		shared_objects.clear();
+		extra_files.clear();
+		skipped = false;
+	}
+
+	_FORCE_INLINE_ void _export_end() {
+		ios_frameworks.clear();
+		ios_embedded_frameworks.clear();
+		ios_bundle_files.clear();
+		ios_plist_content = "";
+		ios_linker_flags = "";
+		ios_cpp_code = "";
+		macos_plugin_files.clear();
+	}
+
+	void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features);
+	void _export_begin_script(const Vector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
+	void _export_end_script();
+
+protected:
+	void set_export_preset(const Ref<EditorExportPreset> &p_preset);
+	Ref<EditorExportPreset> get_export_preset() 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());
+
+	void add_ios_framework(const String &p_path);
+	void add_ios_embedded_framework(const String &p_path);
+	void add_ios_project_static_lib(const String &p_path);
+	void add_ios_plist_content(const String &p_plist_content);
+	void add_ios_linker_flags(const String &p_flags);
+	void add_ios_bundle_file(const String &p_path);
+	void add_ios_cpp_code(const String &p_code);
+	void add_macos_plugin_file(const String &p_path);
+
+	void skip();
+
+	virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);
+	virtual void _export_begin(const HashSet<String> &p_features, bool p_debug, const String &p_path, int p_flags);
+
+	static void _bind_methods();
+
+	GDVIRTUAL3(_export_file, String, String, Vector<String>)
+	GDVIRTUAL4(_export_begin, Vector<String>, bool, String, uint32_t)
+	GDVIRTUAL0(_export_end)
+
+public:
+	Vector<String> get_ios_frameworks() const;
+	Vector<String> get_ios_embedded_frameworks() const;
+	Vector<String> get_ios_project_static_libs() const;
+	String get_ios_plist_content() const;
+	String get_ios_linker_flags() const;
+	Vector<String> get_ios_bundle_files() const;
+	String get_ios_cpp_code() const;
+	const Vector<String> &get_macos_plugin_files() const;
+
+	EditorExportPlugin();
+};
+
+class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
+	GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin);
+
+public:
+	virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override;
+	EditorExportTextSceneToBinaryPlugin();
+};
+
+#endif // EDITOR_EXPORT_PLUGIN_H

+ 221 - 0
editor/export/editor_export_preset.cpp

@@ -0,0 +1,221 @@
+/*************************************************************************/
+/*  editor_export_preset.cpp                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.h"
+
+bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) {
+	if (values.has(p_name)) {
+		values[p_name] = p_value;
+		EditorExport::singleton->save_presets();
+		return true;
+	}
+
+	return false;
+}
+
+bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
+	if (values.has(p_name)) {
+		r_ret = values[p_name];
+		return true;
+	}
+
+	return false;
+}
+
+void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
+	for (const PropertyInfo &E : properties) {
+		if (platform->get_export_option_visibility(E.name, values)) {
+			p_list->push_back(E);
+		}
+	}
+}
+
+Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
+	return platform;
+}
+
+void EditorExportPreset::update_files_to_export() {
+	Vector<String> to_remove;
+	for (const String &E : selected_files) {
+		if (!FileAccess::exists(E)) {
+			to_remove.push_back(E);
+		}
+	}
+	for (int i = 0; i < to_remove.size(); ++i) {
+		selected_files.erase(to_remove[i]);
+	}
+}
+
+Vector<String> EditorExportPreset::get_files_to_export() const {
+	Vector<String> files;
+	for (const String &E : selected_files) {
+		files.push_back(E);
+	}
+	return files;
+}
+
+void EditorExportPreset::set_name(const String &p_name) {
+	name = p_name;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_name() const {
+	return name;
+}
+
+void EditorExportPreset::set_runnable(bool p_enable) {
+	runnable = p_enable;
+	EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::is_runnable() const {
+	return runnable;
+}
+
+void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
+	export_filter = p_filter;
+	EditorExport::singleton->save_presets();
+}
+
+EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
+	return export_filter;
+}
+
+void EditorExportPreset::set_include_filter(const String &p_include) {
+	include_filter = p_include;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_include_filter() const {
+	return include_filter;
+}
+
+void EditorExportPreset::set_export_path(const String &p_path) {
+	export_path = p_path;
+	/* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
+	 * this should be removed. */
+	if (export_path.is_absolute_path()) {
+		String res_path = OS::get_singleton()->get_resource_dir();
+		export_path = res_path.path_to_file(export_path);
+	}
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_export_path() const {
+	return export_path;
+}
+
+void EditorExportPreset::set_exclude_filter(const String &p_exclude) {
+	exclude_filter = p_exclude;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_exclude_filter() const {
+	return exclude_filter;
+}
+
+void EditorExportPreset::add_export_file(const String &p_path) {
+	selected_files.insert(p_path);
+	EditorExport::singleton->save_presets();
+}
+
+void EditorExportPreset::remove_export_file(const String &p_path) {
+	selected_files.erase(p_path);
+	EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::has_export_file(const String &p_path) {
+	return selected_files.has(p_path);
+}
+
+void EditorExportPreset::set_custom_features(const String &p_custom_features) {
+	custom_features = p_custom_features;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_custom_features() const {
+	return custom_features;
+}
+
+void EditorExportPreset::set_enc_in_filter(const String &p_filter) {
+	enc_in_filters = p_filter;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_enc_in_filter() const {
+	return enc_in_filters;
+}
+
+void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {
+	enc_ex_filters = p_filter;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_enc_ex_filter() const {
+	return enc_ex_filters;
+}
+
+void EditorExportPreset::set_enc_pck(bool p_enabled) {
+	enc_pck = p_enabled;
+	EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::get_enc_pck() const {
+	return enc_pck;
+}
+
+void EditorExportPreset::set_enc_directory(bool p_enabled) {
+	enc_directory = p_enabled;
+	EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::get_enc_directory() const {
+	return enc_directory;
+}
+
+void EditorExportPreset::set_script_export_mode(int p_mode) {
+	script_mode = p_mode;
+	EditorExport::singleton->save_presets();
+}
+
+int EditorExportPreset::get_script_export_mode() const {
+	return script_mode;
+}
+
+void EditorExportPreset::set_script_encryption_key(const String &p_key) {
+	script_key = p_key;
+	EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_script_encryption_key() const {
+	return script_key;
+}
+
+EditorExportPreset::EditorExportPreset() {}

+ 145 - 0
editor/export/editor_export_preset.h

@@ -0,0 +1,145 @@
+/*************************************************************************/
+/*  editor_export_preset.h                                               */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_PRESET_H
+#define EDITOR_EXPORT_PRESET_H
+
+class EditorExportPlatform;
+
+#include "core/object/ref_counted.h"
+
+class EditorExportPreset : public RefCounted {
+	GDCLASS(EditorExportPreset, RefCounted);
+
+public:
+	enum ExportFilter {
+		EXPORT_ALL_RESOURCES,
+		EXPORT_SELECTED_SCENES,
+		EXPORT_SELECTED_RESOURCES,
+		EXCLUDE_SELECTED_RESOURCES,
+	};
+
+	enum ScriptExportMode {
+		MODE_SCRIPT_TEXT,
+		MODE_SCRIPT_COMPILED,
+	};
+
+private:
+	Ref<EditorExportPlatform> platform;
+	ExportFilter export_filter = EXPORT_ALL_RESOURCES;
+	String include_filter;
+	String exclude_filter;
+	String export_path;
+
+	String exporter;
+	HashSet<String> selected_files;
+	bool runnable = false;
+
+	friend class EditorExport;
+	friend class EditorExportPlatform;
+
+	List<PropertyInfo> properties;
+	HashMap<StringName, Variant> values;
+
+	String name;
+
+	String custom_features;
+
+	String enc_in_filters;
+	String enc_ex_filters;
+	bool enc_pck = false;
+	bool enc_directory = false;
+
+	int script_mode = MODE_SCRIPT_COMPILED;
+	String script_key;
+
+protected:
+	bool _set(const StringName &p_name, const Variant &p_value);
+	bool _get(const StringName &p_name, Variant &r_ret) const;
+	void _get_property_list(List<PropertyInfo> *p_list) const;
+
+public:
+	Ref<EditorExportPlatform> get_platform() const;
+
+	bool has(const StringName &p_property) const { return values.has(p_property); }
+
+	void update_files_to_export();
+
+	Vector<String> get_files_to_export() const;
+
+	void add_export_file(const String &p_path);
+	void remove_export_file(const String &p_path);
+	bool has_export_file(const String &p_path);
+
+	void set_name(const String &p_name);
+	String get_name() const;
+
+	void set_runnable(bool p_enable);
+	bool is_runnable() const;
+
+	void set_export_filter(ExportFilter p_filter);
+	ExportFilter get_export_filter() const;
+
+	void set_include_filter(const String &p_include);
+	String get_include_filter() const;
+
+	void set_exclude_filter(const String &p_exclude);
+	String get_exclude_filter() const;
+
+	void set_custom_features(const String &p_custom_features);
+	String get_custom_features() const;
+
+	void set_export_path(const String &p_path);
+	String get_export_path() const;
+
+	void set_enc_in_filter(const String &p_filter);
+	String get_enc_in_filter() const;
+
+	void set_enc_ex_filter(const String &p_filter);
+	String get_enc_ex_filter() const;
+
+	void set_enc_pck(bool p_enabled);
+	bool get_enc_pck() const;
+
+	void set_enc_directory(bool p_enabled);
+	bool get_enc_directory() const;
+
+	void set_script_export_mode(int p_mode);
+	int get_script_export_mode() const;
+
+	void set_script_encryption_key(const String &p_key);
+	String get_script_encryption_key() const;
+
+	const List<PropertyInfo> &get_properties() const { return properties; }
+
+	EditorExportPreset();
+};
+
+#endif // EDITOR_EXPORT_PRESET_H

+ 51 - 0
editor/export/editor_export_shared_object.h

@@ -0,0 +1,51 @@
+/*************************************************************************/
+/*  editor_export_shared_object.h                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_SHARED_OBJECT_H
+#define EDITOR_EXPORT_SHARED_OBJECT_H
+
+#include "core/string/ustring.h"
+#include "core/templates/vector.h"
+
+struct SharedObject {
+	String path;
+	Vector<String> tags;
+	String target;
+
+	SharedObject(const String &p_path, const Vector<String> &p_tags, const String &p_target) :
+			path(p_path),
+			tags(p_tags),
+			target(p_target) {
+	}
+
+	SharedObject() {}
+};
+
+#endif // EDITOR_EXPORT_SHARED_OBJECT_H

+ 1 - 1
editor/plugins/gdextension_export_plugin.h

@@ -31,7 +31,7 @@
 #ifndef GDEXTENSION_EXPORT_PLUGIN_H
 #define GDEXTENSION_EXPORT_PLUGIN_H
 
-#include "editor/editor_export.h"
+#include "editor/export/editor_export.h"
 
 class GDExtensionExportPlugin : public EditorExportPlugin {
 protected:

+ 1 - 1
editor/project_export.h

@@ -33,10 +33,10 @@
 
 #include "core/io/dir_access.h"
 #include "core/os/thread.h"
-#include "editor/editor_export.h"
 #include "editor/editor_file_system.h"
 #include "editor/editor_inspector.h"
 #include "editor/editor_properties.h"
+#include "editor/export/editor_export.h"
 #include "scene/gui/button.h"
 #include "scene/gui/check_button.h"
 #include "scene/gui/control.h"

+ 0 - 1
editor/project_settings_editor.cpp

@@ -31,7 +31,6 @@
 #include "project_settings_editor.h"
 
 #include "core/config/project_settings.h"
-#include "editor/editor_export.h"
 #include "editor/editor_log.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"

+ 0 - 1
editor/property_editor.cpp

@@ -43,7 +43,6 @@
 #include "editor/array_property_edit.h"
 #include "editor/create_dialog.h"
 #include "editor/dictionary_property_edit.h"
-#include "editor/editor_export.h"
 #include "editor/editor_file_dialog.h"
 #include "editor/editor_file_system.h"
 #include "editor/editor_help.h"

+ 1 - 1
modules/gdscript/register_types.cpp

@@ -52,10 +52,10 @@ GDScriptCache *gdscript_cache = nullptr;
 
 #ifdef TOOLS_ENABLED
 
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
 #include "editor/editor_settings.h"
 #include "editor/editor_translation_parser.h"
+#include "editor/export/editor_export.h"
 #include "editor/gdscript_highlighter.h"
 #include "editor/gdscript_translation_parser_plugin.h"
 

+ 2 - 2
platform/android/export/export.cpp

@@ -30,10 +30,10 @@
 
 #include "export.h"
 
-#include "export_plugin.h"
-
 #include "core/os/os.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
+#include "export_plugin.h"
 
 void register_android_exporter() {
 	EDITOR_DEF("export/android/android_sdk_path", "");

+ 1 - 1
platform/android/export/export_plugin.h

@@ -35,7 +35,7 @@
 
 #include "core/io/zip_io.h"
 #include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export_platform.h"
 
 const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">

+ 1 - 1
platform/android/export/gradle_export_util.h

@@ -35,7 +35,7 @@
 #include "core/io/file_access.h"
 #include "core/io/zip_io.h"
 #include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export.h"
 
 const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="utf-8"?>
 <!--WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->

+ 1 - 0
platform/ios/export/export.cpp

@@ -30,6 +30,7 @@
 
 #include "export.h"
 
+#include "editor/export/editor_export.h"
 #include "export_plugin.h"
 
 void register_ios_exporter() {

+ 1 - 1
platform/ios/export/export_plugin.h

@@ -40,8 +40,8 @@
 #include "core/os/os.h"
 #include "core/templates/safe_refcount.h"
 #include "core/version.h"
-#include "editor/editor_export.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform.h"
 #include "main/splash.gen.h"
 #include "platform/ios/logo.gen.h"
 #include "string.h"

+ 1 - 1
platform/javascript/export/export_plugin.h

@@ -36,8 +36,8 @@
 #include "core/io/stream_peer_ssl.h"
 #include "core/io/tcp_server.h"
 #include "core/io/zip_io.h"
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
+#include "editor/export/editor_export_platform.h"
 #include "main/splash.gen.h"
 #include "platform/javascript/logo.gen.h"
 #include "platform/javascript/run_icon.gen.h"

+ 0 - 1
platform/javascript/export/export_server.h

@@ -35,7 +35,6 @@
 #include "core/io/stream_peer_ssl.h"
 #include "core/io/tcp_server.h"
 #include "core/io/zip_io.h"
-#include "editor/editor_export.h"
 #include "editor/editor_paths.h"
 
 class EditorHTTPServer : public RefCounted {

+ 1 - 0
platform/linuxbsd/export/export.cpp

@@ -30,6 +30,7 @@
 
 #include "export.h"
 
+#include "editor/export/editor_export.h"
 #include "export_plugin.h"
 
 void register_linuxbsd_exporter() {

+ 1 - 1
platform/linuxbsd/export/export_plugin.h

@@ -32,8 +32,8 @@
 #define LINUXBSD_EXPORT_PLUGIN_H
 
 #include "core/io/file_access.h"
-#include "editor/editor_export.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform_pc.h"
 #include "platform/linuxbsd/logo.gen.h"
 #include "scene/resources/texture.h"
 

+ 1 - 1
platform/macos/export/export_plugin.h

@@ -39,8 +39,8 @@
 #include "core/io/zip_io.h"
 #include "core/os/os.h"
 #include "core/version.h"
-#include "editor/editor_export.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
 #include "platform/macos/logo.gen.h"
 
 #include <sys/stat.h>

+ 1 - 1
platform/uwp/export/app_packager.h

@@ -40,7 +40,7 @@
 #include "core/io/zip_io.h"
 #include "core/object/class_db.h"
 #include "core/version.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export_platform.h"
 
 #include "thirdparty/minizip/unzip.h"
 #include "thirdparty/minizip/zip.h"

+ 1 - 1
platform/uwp/export/export_plugin.h

@@ -39,9 +39,9 @@
 #include "core/io/zip_io.h"
 #include "core/object/class_db.h"
 #include "core/version.h"
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
 #include "editor/editor_paths.h"
+#include "editor/export/editor_export_platform.h"
 
 #include "thirdparty/minizip/unzip.h"
 #include "thirdparty/minizip/zip.h"

+ 1 - 0
platform/windows/export/export.cpp

@@ -30,6 +30,7 @@
 
 #include "export.h"
 
+#include "editor/export/editor_export.h"
 #include "export_plugin.h"
 
 void register_windows_exporter() {

+ 1 - 1
platform/windows/export/export_plugin.h

@@ -33,8 +33,8 @@
 
 #include "core/io/file_access.h"
 #include "core/os/os.h"
-#include "editor/editor_export.h"
 #include "editor/editor_settings.h"
+#include "editor/export/editor_export_platform_pc.h"
 #include "platform/windows/logo.gen.h"
 
 class EditorExportPlatformWindows : public EditorExportPlatformPC {