1 | /**************************************************************************/ |
2 | /* editor_export_platform.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef EDITOR_EXPORT_PLATFORM_H |
32 | #define EDITOR_EXPORT_PLATFORM_H |
33 | |
34 | class EditorFileSystemDirectory; |
35 | struct EditorProgress; |
36 | |
37 | #include "core/io/dir_access.h" |
38 | #include "core/io/zip_io.h" |
39 | #include "editor_export_preset.h" |
40 | #include "editor_export_shared_object.h" |
41 | #include "scene/gui/rich_text_label.h" |
42 | #include "scene/main/node.h" |
43 | #include "scene/resources/image_texture.h" |
44 | |
45 | class EditorExportPlugin; |
46 | |
47 | const String ENV_SCRIPT_ENCRYPTION_KEY = "GODOT_SCRIPT_ENCRYPTION_KEY" ; |
48 | |
49 | class EditorExportPlatform : public RefCounted { |
50 | GDCLASS(EditorExportPlatform, RefCounted); |
51 | |
52 | protected: |
53 | static void _bind_methods(); |
54 | |
55 | public: |
56 | 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); |
57 | typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so); |
58 | |
59 | enum ExportMessageType { |
60 | EXPORT_MESSAGE_NONE, |
61 | EXPORT_MESSAGE_INFO, |
62 | EXPORT_MESSAGE_WARNING, |
63 | EXPORT_MESSAGE_ERROR, |
64 | }; |
65 | |
66 | struct ExportMessage { |
67 | ExportMessageType msg_type; |
68 | String category; |
69 | String text; |
70 | }; |
71 | |
72 | private: |
73 | struct SavedData { |
74 | uint64_t ofs = 0; |
75 | uint64_t size = 0; |
76 | bool encrypted = false; |
77 | Vector<uint8_t> md5; |
78 | CharString path_utf8; |
79 | |
80 | bool operator<(const SavedData &p_data) const { |
81 | return path_utf8 < p_data.path_utf8; |
82 | } |
83 | }; |
84 | |
85 | struct PackData { |
86 | Ref<FileAccess> f; |
87 | Vector<SavedData> file_ofs; |
88 | EditorProgress *ep = nullptr; |
89 | Vector<SharedObject> *so_files = nullptr; |
90 | }; |
91 | |
92 | struct ZipData { |
93 | void *zip = nullptr; |
94 | EditorProgress *ep = nullptr; |
95 | }; |
96 | |
97 | Vector<ExportMessage> messages; |
98 | |
99 | void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths); |
100 | void _export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths); |
101 | void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths); |
102 | |
103 | 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); |
104 | 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); |
105 | |
106 | void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude); |
107 | void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude); |
108 | |
109 | static Error _add_shared_object(void *p_userdata, const SharedObject &p_so); |
110 | |
111 | struct FileExportCache { |
112 | uint64_t source_modified_time = 0; |
113 | String source_md5; |
114 | String saved_path; |
115 | bool used = false; |
116 | }; |
117 | |
118 | bool _export_customize_dictionary(Dictionary &dict, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); |
119 | bool _export_customize_array(Array &array, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); |
120 | bool _export_customize_object(Object *p_object, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); |
121 | bool _export_customize_scene_resources(Node *p_root, Node *p_node, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); |
122 | bool _is_editable_ancestor(Node *p_root, Node *p_node); |
123 | |
124 | String _export_customize(const String &p_path, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins, LocalVector<Ref<EditorExportPlugin>> &customize_scenes_plugins, HashMap<String, FileExportCache> &export_cache, const String &export_base_path, bool p_force_save); |
125 | String _get_script_encryption_key(const Ref<EditorExportPreset> &p_preset) const; |
126 | |
127 | protected: |
128 | struct ExportNotifier { |
129 | ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags); |
130 | ~ExportNotifier(); |
131 | }; |
132 | |
133 | HashSet<String> get_features(const Ref<EditorExportPreset> &p_preset, bool p_debug) const; |
134 | |
135 | bool exists_export_template(String template_file_name, String *err) const; |
136 | String find_export_template(String template_file_name, String *err = nullptr) const; |
137 | void gen_export_flags(Vector<String> &r_flags, int p_flags); |
138 | void gen_debug_flags(Vector<String> &r_flags, int p_flags); |
139 | |
140 | virtual void zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name); |
141 | |
142 | Error ssh_run_on_remote(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, String *r_out = nullptr, int p_port_fwd = -1) const; |
143 | Error ssh_run_on_remote_no_wait(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, OS::ProcessID *r_pid = nullptr, int p_port_fwd = -1) const; |
144 | Error ssh_push_to_remote(const String &p_host, const String &p_port, const Vector<String> &p_scp_args, const String &p_src_file, const String &p_dst_file) const; |
145 | |
146 | public: |
147 | virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0; |
148 | |
149 | struct ExportOption { |
150 | PropertyInfo option; |
151 | Variant default_value; |
152 | bool update_visibility = false; |
153 | bool required = false; |
154 | |
155 | ExportOption(const PropertyInfo &p_info, const Variant &p_default, bool p_update_visibility = false, bool p_required = false) : |
156 | option(p_info), |
157 | default_value(p_default), |
158 | update_visibility(p_update_visibility), |
159 | required(p_required) { |
160 | } |
161 | ExportOption() {} |
162 | }; |
163 | |
164 | virtual Ref<EditorExportPreset> create_preset(); |
165 | virtual bool is_executable(const String &p_path) const { return false; } |
166 | |
167 | virtual void clear_messages() { messages.clear(); } |
168 | virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) { |
169 | ExportMessage msg; |
170 | msg.category = p_category; |
171 | msg.text = p_message; |
172 | msg.msg_type = p_type; |
173 | messages.push_back(msg); |
174 | switch (p_type) { |
175 | case EXPORT_MESSAGE_INFO: { |
176 | print_line(vformat("%s: %s" , msg.category, msg.text)); |
177 | } break; |
178 | case EXPORT_MESSAGE_WARNING: { |
179 | WARN_PRINT(vformat("%s: %s" , msg.category, msg.text)); |
180 | } break; |
181 | case EXPORT_MESSAGE_ERROR: { |
182 | ERR_PRINT(vformat("%s: %s" , msg.category, msg.text)); |
183 | } break; |
184 | default: |
185 | break; |
186 | } |
187 | } |
188 | |
189 | virtual int get_message_count() const { |
190 | return messages.size(); |
191 | } |
192 | |
193 | virtual ExportMessage get_message(int p_index) const { |
194 | ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage()); |
195 | return messages[p_index]; |
196 | } |
197 | |
198 | virtual ExportMessageType get_worst_message_type() const { |
199 | ExportMessageType worst_type = EXPORT_MESSAGE_NONE; |
200 | for (int i = 0; i < messages.size(); i++) { |
201 | worst_type = MAX(worst_type, messages[i].msg_type); |
202 | } |
203 | return worst_type; |
204 | } |
205 | |
206 | static Vector<String> get_forced_export_files(); |
207 | |
208 | virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err); |
209 | |
210 | virtual void get_export_options(List<ExportOption> *r_options) const = 0; |
211 | virtual bool should_update_export_options() { return false; } |
212 | virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const { return true; } |
213 | virtual String get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const { return String(); } |
214 | |
215 | virtual String get_os_name() const = 0; |
216 | virtual String get_name() const = 0; |
217 | virtual Ref<Texture2D> get_logo() const = 0; |
218 | |
219 | Error export_project_files(const Ref<EditorExportPreset> &p_preset, bool p_debug, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = nullptr); |
220 | |
221 | 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); |
222 | Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); |
223 | |
224 | virtual bool poll_export() { return false; } |
225 | virtual int get_options_count() const { return 0; } |
226 | virtual String get_options_tooltip() const { return "" ; } |
227 | virtual Ref<ImageTexture> get_option_icon(int p_index) const; |
228 | virtual String get_option_label(int p_device) const { return "" ; } |
229 | virtual String get_option_tooltip(int p_device) const { return "" ; } |
230 | |
231 | enum DebugFlags { |
232 | DEBUG_FLAG_DUMB_CLIENT = 1, |
233 | DEBUG_FLAG_REMOTE_DEBUG = 2, |
234 | DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST = 4, |
235 | DEBUG_FLAG_VIEW_COLLISIONS = 8, |
236 | DEBUG_FLAG_VIEW_NAVIGATION = 16, |
237 | }; |
238 | |
239 | virtual void cleanup() {} |
240 | virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; } |
241 | virtual Ref<Texture2D> get_run_icon() const { return get_logo(); } |
242 | |
243 | bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const; |
244 | virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const = 0; |
245 | virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const = 0; |
246 | |
247 | virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0; |
248 | virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) = 0; |
249 | virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); |
250 | virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); |
251 | virtual void get_platform_features(List<String> *r_features) const = 0; |
252 | virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) = 0; |
253 | virtual String get_debug_protocol() const { return "tcp://" ; } |
254 | |
255 | EditorExportPlatform(); |
256 | }; |
257 | |
258 | #endif // EDITOR_EXPORT_PLATFORM_H |
259 | |