1 | /**************************************************************************/ |
2 | /* editor_export_preset.cpp */ |
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 | #include "editor_export.h" |
32 | |
33 | #include "core/config/project_settings.h" |
34 | |
35 | bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) { |
36 | values[p_name] = p_value; |
37 | EditorExport::singleton->save_presets(); |
38 | if (update_visibility.has(p_name)) { |
39 | if (update_visibility[p_name]) { |
40 | notify_property_list_changed(); |
41 | } |
42 | return true; |
43 | } |
44 | |
45 | return false; |
46 | } |
47 | |
48 | bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { |
49 | if (values.has(p_name)) { |
50 | r_ret = values[p_name]; |
51 | return true; |
52 | } |
53 | |
54 | return false; |
55 | } |
56 | |
57 | void EditorExportPreset::_bind_methods() { |
58 | ClassDB::bind_method(D_METHOD("_get_property_warning" , "name" ), &EditorExportPreset::_get_property_warning); |
59 | } |
60 | |
61 | String EditorExportPreset::_get_property_warning(const StringName &p_name) const { |
62 | String warning = platform->get_export_option_warning(this, p_name); |
63 | if (!warning.is_empty()) { |
64 | warning += "\n" ; |
65 | } |
66 | |
67 | // Get property warning from editor export plugins. |
68 | Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); |
69 | for (int i = 0; i < export_plugins.size(); i++) { |
70 | if (!export_plugins[i]->supports_platform(platform)) { |
71 | continue; |
72 | } |
73 | |
74 | export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this)); |
75 | String plugin_warning = export_plugins[i]->_get_export_option_warning(platform, p_name); |
76 | if (!plugin_warning.is_empty()) { |
77 | warning += plugin_warning + "\n" ; |
78 | } |
79 | } |
80 | |
81 | return warning; |
82 | } |
83 | |
84 | void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { |
85 | for (const KeyValue<StringName, PropertyInfo> &E : properties) { |
86 | if (platform->get_export_option_visibility(this, E.key)) { |
87 | p_list->push_back(E.value); |
88 | } |
89 | } |
90 | } |
91 | |
92 | Ref<EditorExportPlatform> EditorExportPreset::get_platform() const { |
93 | return platform; |
94 | } |
95 | |
96 | void EditorExportPreset::update_files() { |
97 | { |
98 | Vector<String> to_remove; |
99 | for (const String &E : selected_files) { |
100 | if (!FileAccess::exists(E)) { |
101 | to_remove.push_back(E); |
102 | } |
103 | } |
104 | for (int i = 0; i < to_remove.size(); ++i) { |
105 | selected_files.erase(to_remove[i]); |
106 | } |
107 | } |
108 | |
109 | { |
110 | Vector<String> to_remove; |
111 | for (const KeyValue<String, FileExportMode> &E : customized_files) { |
112 | if (!FileAccess::exists(E.key) && !DirAccess::exists(E.key)) { |
113 | to_remove.push_back(E.key); |
114 | } |
115 | } |
116 | for (int i = 0; i < to_remove.size(); ++i) { |
117 | customized_files.erase(to_remove[i]); |
118 | } |
119 | } |
120 | } |
121 | |
122 | Vector<String> EditorExportPreset::get_files_to_export() const { |
123 | Vector<String> files; |
124 | for (const String &E : selected_files) { |
125 | files.push_back(E); |
126 | } |
127 | return files; |
128 | } |
129 | |
130 | Dictionary EditorExportPreset::get_customized_files() const { |
131 | Dictionary files; |
132 | for (const KeyValue<String, FileExportMode> &E : customized_files) { |
133 | String mode; |
134 | switch (E.value) { |
135 | case MODE_FILE_NOT_CUSTOMIZED: { |
136 | continue; |
137 | } break; |
138 | case MODE_FILE_STRIP: { |
139 | mode = "strip" ; |
140 | } break; |
141 | case MODE_FILE_KEEP: { |
142 | mode = "keep" ; |
143 | } break; |
144 | case MODE_FILE_REMOVE: { |
145 | mode = "remove" ; |
146 | } |
147 | } |
148 | files[E.key] = mode; |
149 | } |
150 | return files; |
151 | } |
152 | |
153 | int EditorExportPreset::get_customized_files_count() const { |
154 | return customized_files.size(); |
155 | } |
156 | |
157 | void EditorExportPreset::set_customized_files(const Dictionary &p_files) { |
158 | for (const Variant *key = p_files.next(nullptr); key; key = p_files.next(key)) { |
159 | EditorExportPreset::FileExportMode mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; |
160 | String value = p_files[*key]; |
161 | if (value == "strip" ) { |
162 | mode = EditorExportPreset::MODE_FILE_STRIP; |
163 | } else if (value == "keep" ) { |
164 | mode = EditorExportPreset::MODE_FILE_KEEP; |
165 | } else if (value == "remove" ) { |
166 | mode = EditorExportPreset::MODE_FILE_REMOVE; |
167 | } |
168 | set_file_export_mode(*key, mode); |
169 | } |
170 | } |
171 | |
172 | void EditorExportPreset::set_name(const String &p_name) { |
173 | name = p_name; |
174 | EditorExport::singleton->save_presets(); |
175 | } |
176 | |
177 | String EditorExportPreset::get_name() const { |
178 | return name; |
179 | } |
180 | |
181 | void EditorExportPreset::set_runnable(bool p_enable) { |
182 | runnable = p_enable; |
183 | EditorExport::singleton->save_presets(); |
184 | } |
185 | |
186 | bool EditorExportPreset::is_runnable() const { |
187 | return runnable; |
188 | } |
189 | |
190 | void EditorExportPreset::set_dedicated_server(bool p_enable) { |
191 | dedicated_server = p_enable; |
192 | EditorExport::singleton->save_presets(); |
193 | } |
194 | |
195 | bool EditorExportPreset::is_dedicated_server() const { |
196 | return dedicated_server; |
197 | } |
198 | |
199 | void EditorExportPreset::set_export_filter(ExportFilter p_filter) { |
200 | export_filter = p_filter; |
201 | EditorExport::singleton->save_presets(); |
202 | } |
203 | |
204 | EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const { |
205 | return export_filter; |
206 | } |
207 | |
208 | void EditorExportPreset::set_include_filter(const String &p_include) { |
209 | include_filter = p_include; |
210 | EditorExport::singleton->save_presets(); |
211 | } |
212 | |
213 | String EditorExportPreset::get_include_filter() const { |
214 | return include_filter; |
215 | } |
216 | |
217 | void EditorExportPreset::set_export_path(const String &p_path) { |
218 | export_path = p_path; |
219 | /* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path, |
220 | * this should be removed. */ |
221 | if (export_path.is_absolute_path()) { |
222 | String res_path = OS::get_singleton()->get_resource_dir(); |
223 | export_path = res_path.path_to_file(export_path); |
224 | } |
225 | EditorExport::singleton->save_presets(); |
226 | } |
227 | |
228 | String EditorExportPreset::get_export_path() const { |
229 | return export_path; |
230 | } |
231 | |
232 | void EditorExportPreset::set_exclude_filter(const String &p_exclude) { |
233 | exclude_filter = p_exclude; |
234 | EditorExport::singleton->save_presets(); |
235 | } |
236 | |
237 | String EditorExportPreset::get_exclude_filter() const { |
238 | return exclude_filter; |
239 | } |
240 | |
241 | void EditorExportPreset::add_export_file(const String &p_path) { |
242 | selected_files.insert(p_path); |
243 | EditorExport::singleton->save_presets(); |
244 | } |
245 | |
246 | void EditorExportPreset::remove_export_file(const String &p_path) { |
247 | selected_files.erase(p_path); |
248 | EditorExport::singleton->save_presets(); |
249 | } |
250 | |
251 | bool EditorExportPreset::has_export_file(const String &p_path) { |
252 | return selected_files.has(p_path); |
253 | } |
254 | |
255 | void EditorExportPreset::set_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_mode) { |
256 | if (p_mode == FileExportMode::MODE_FILE_NOT_CUSTOMIZED) { |
257 | customized_files.erase(p_path); |
258 | } else { |
259 | customized_files.insert(p_path, p_mode); |
260 | } |
261 | EditorExport::singleton->save_presets(); |
262 | } |
263 | |
264 | EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_default) const { |
265 | HashMap<String, FileExportMode>::ConstIterator i = customized_files.find(p_path); |
266 | if (i) { |
267 | return i->value; |
268 | } |
269 | return p_default; |
270 | } |
271 | |
272 | void EditorExportPreset::set_custom_features(const String &p_custom_features) { |
273 | custom_features = p_custom_features; |
274 | EditorExport::singleton->save_presets(); |
275 | } |
276 | |
277 | String EditorExportPreset::get_custom_features() const { |
278 | return custom_features; |
279 | } |
280 | |
281 | void EditorExportPreset::set_enc_in_filter(const String &p_filter) { |
282 | enc_in_filters = p_filter; |
283 | EditorExport::singleton->save_presets(); |
284 | } |
285 | |
286 | String EditorExportPreset::get_enc_in_filter() const { |
287 | return enc_in_filters; |
288 | } |
289 | |
290 | void EditorExportPreset::set_enc_ex_filter(const String &p_filter) { |
291 | enc_ex_filters = p_filter; |
292 | EditorExport::singleton->save_presets(); |
293 | } |
294 | |
295 | String EditorExportPreset::get_enc_ex_filter() const { |
296 | return enc_ex_filters; |
297 | } |
298 | |
299 | void EditorExportPreset::set_enc_pck(bool p_enabled) { |
300 | enc_pck = p_enabled; |
301 | EditorExport::singleton->save_presets(); |
302 | } |
303 | |
304 | bool EditorExportPreset::get_enc_pck() const { |
305 | return enc_pck; |
306 | } |
307 | |
308 | void EditorExportPreset::set_enc_directory(bool p_enabled) { |
309 | enc_directory = p_enabled; |
310 | EditorExport::singleton->save_presets(); |
311 | } |
312 | |
313 | bool EditorExportPreset::get_enc_directory() const { |
314 | return enc_directory; |
315 | } |
316 | |
317 | void EditorExportPreset::set_script_encryption_key(const String &p_key) { |
318 | script_key = p_key; |
319 | EditorExport::singleton->save_presets(); |
320 | } |
321 | |
322 | String EditorExportPreset::get_script_encryption_key() const { |
323 | return script_key; |
324 | } |
325 | |
326 | Variant EditorExportPreset::get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid) const { |
327 | const String from_env = OS::get_singleton()->get_environment(p_env_var); |
328 | if (!from_env.is_empty()) { |
329 | if (r_valid) { |
330 | *r_valid = true; |
331 | } |
332 | return from_env; |
333 | } |
334 | return get(p_name, r_valid); |
335 | } |
336 | |
337 | String EditorExportPreset::get_version(const StringName &p_preset_string, bool p_windows_version) const { |
338 | String result = get(p_preset_string); |
339 | if (result.is_empty()) { |
340 | result = GLOBAL_GET("application/config/version" ); |
341 | |
342 | if (p_windows_version) { |
343 | // Modify version number to match Windows constraints (version numbers must have 4 components). |
344 | const PackedStringArray result_split = result.split("." ); |
345 | String windows_version; |
346 | if (result_split.is_empty()) { |
347 | // Use a valid fallback if the version string is empty, as a version number must be specified. |
348 | result = "1.0.0.0" ; |
349 | } else if (result_split.size() == 1) { |
350 | result = result + ".0.0.0" ; |
351 | } else if (result_split.size() == 2) { |
352 | result = result + ".0.0" ; |
353 | } else if (result_split.size() == 3) { |
354 | result = result + ".0" ; |
355 | } else { |
356 | // 4 components or more in the version string. Trim to contain only the first 4 components. |
357 | result = vformat("%s.%s.%s.%s" , result_split[0] + result_split[1] + result_split[2] + result_split[3]); |
358 | } |
359 | } else if (result.is_empty()) { |
360 | // Use a valid fallback if the version string is empty, as a version number must be specified. |
361 | result = "1.0.0" ; |
362 | } |
363 | } |
364 | |
365 | return result; |
366 | } |
367 | |
368 | EditorExportPreset::EditorExportPreset() {} |
369 | |