Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/export/editor_export_preset.cpp
9896 views
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
update_value_overrides();
41
notify_property_list_changed();
42
}
43
return true;
44
}
45
46
return false;
47
}
48
49
bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
50
if (value_overrides.has(p_name)) {
51
r_ret = value_overrides[p_name];
52
return true;
53
}
54
55
if (values.has(p_name)) {
56
r_ret = values[p_name];
57
return true;
58
}
59
60
return false;
61
}
62
63
Variant EditorExportPreset::get_project_setting(const StringName &p_name) {
64
List<String> ftr_list;
65
platform->get_platform_features(&ftr_list);
66
platform->get_preset_features(this, &ftr_list);
67
68
Vector<String> features;
69
for (const String &E : ftr_list) {
70
features.push_back(E);
71
}
72
73
if (!get_custom_features().is_empty()) {
74
Vector<String> tmp_custom_list = get_custom_features().split(",");
75
76
for (int i = 0; i < tmp_custom_list.size(); i++) {
77
String f = tmp_custom_list[i].strip_edges();
78
if (!f.is_empty()) {
79
features.push_back(f);
80
}
81
}
82
}
83
return ProjectSettings::get_singleton()->get_setting_with_override_and_custom_features(p_name, features);
84
}
85
86
void EditorExportPreset::_bind_methods() {
87
ClassDB::bind_method(D_METHOD("_get_property_warning", "name"), &EditorExportPreset::_get_property_warning);
88
89
ClassDB::bind_method(D_METHOD("has", "property"), &EditorExportPreset::has);
90
91
ClassDB::bind_method(D_METHOD("get_files_to_export"), &EditorExportPreset::get_files_to_export);
92
ClassDB::bind_method(D_METHOD("get_customized_files"), &EditorExportPreset::get_customized_files);
93
ClassDB::bind_method(D_METHOD("get_customized_files_count"), &EditorExportPreset::get_customized_files_count);
94
ClassDB::bind_method(D_METHOD("has_export_file", "path"), &EditorExportPreset::has_export_file);
95
ClassDB::bind_method(D_METHOD("get_file_export_mode", "path", "default"), &EditorExportPreset::get_file_export_mode, DEFVAL(MODE_FILE_NOT_CUSTOMIZED));
96
ClassDB::bind_method(D_METHOD("get_project_setting", "name"), &EditorExportPreset::get_project_setting);
97
98
ClassDB::bind_method(D_METHOD("get_preset_name"), &EditorExportPreset::get_name);
99
ClassDB::bind_method(D_METHOD("is_runnable"), &EditorExportPreset::is_runnable);
100
ClassDB::bind_method(D_METHOD("are_advanced_options_enabled"), &EditorExportPreset::are_advanced_options_enabled);
101
ClassDB::bind_method(D_METHOD("is_dedicated_server"), &EditorExportPreset::is_dedicated_server);
102
ClassDB::bind_method(D_METHOD("get_export_filter"), &EditorExportPreset::get_export_filter);
103
ClassDB::bind_method(D_METHOD("get_include_filter"), &EditorExportPreset::get_include_filter);
104
ClassDB::bind_method(D_METHOD("get_exclude_filter"), &EditorExportPreset::get_exclude_filter);
105
ClassDB::bind_method(D_METHOD("get_custom_features"), &EditorExportPreset::get_custom_features);
106
ClassDB::bind_method(D_METHOD("get_patches"), &EditorExportPreset::get_patches);
107
ClassDB::bind_method(D_METHOD("get_export_path"), &EditorExportPreset::get_export_path);
108
ClassDB::bind_method(D_METHOD("get_encryption_in_filter"), &EditorExportPreset::get_enc_in_filter);
109
ClassDB::bind_method(D_METHOD("get_encryption_ex_filter"), &EditorExportPreset::get_enc_ex_filter);
110
ClassDB::bind_method(D_METHOD("get_encrypt_pck"), &EditorExportPreset::get_enc_pck);
111
ClassDB::bind_method(D_METHOD("get_encrypt_directory"), &EditorExportPreset::get_enc_directory);
112
ClassDB::bind_method(D_METHOD("get_encryption_key"), &EditorExportPreset::get_script_encryption_key);
113
ClassDB::bind_method(D_METHOD("get_script_export_mode"), &EditorExportPreset::get_script_export_mode);
114
115
ClassDB::bind_method(D_METHOD("get_or_env", "name", "env_var"), &EditorExportPreset::_get_or_env);
116
ClassDB::bind_method(D_METHOD("get_version", "name", "windows_version"), &EditorExportPreset::get_version);
117
118
BIND_ENUM_CONSTANT(EXPORT_ALL_RESOURCES);
119
BIND_ENUM_CONSTANT(EXPORT_SELECTED_SCENES);
120
BIND_ENUM_CONSTANT(EXPORT_SELECTED_RESOURCES);
121
BIND_ENUM_CONSTANT(EXCLUDE_SELECTED_RESOURCES);
122
BIND_ENUM_CONSTANT(EXPORT_CUSTOMIZED);
123
124
BIND_ENUM_CONSTANT(MODE_FILE_NOT_CUSTOMIZED);
125
BIND_ENUM_CONSTANT(MODE_FILE_STRIP);
126
BIND_ENUM_CONSTANT(MODE_FILE_KEEP);
127
BIND_ENUM_CONSTANT(MODE_FILE_REMOVE);
128
129
BIND_ENUM_CONSTANT(MODE_SCRIPT_TEXT);
130
BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS);
131
BIND_ENUM_CONSTANT(MODE_SCRIPT_BINARY_TOKENS_COMPRESSED);
132
}
133
134
String EditorExportPreset::_get_property_warning(const StringName &p_name) const {
135
if (value_overrides.has(p_name)) {
136
return String();
137
}
138
139
String warning = platform->get_export_option_warning(this, p_name);
140
if (!warning.is_empty()) {
141
warning += "\n";
142
}
143
144
// Get property warning from editor export plugins.
145
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
146
for (int i = 0; i < export_plugins.size(); i++) {
147
if (!export_plugins[i]->supports_platform(platform)) {
148
continue;
149
}
150
151
export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));
152
String plugin_warning = export_plugins[i]->_get_export_option_warning(platform, p_name);
153
if (!plugin_warning.is_empty()) {
154
warning += plugin_warning + "\n";
155
}
156
}
157
158
return warning;
159
}
160
161
void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
162
for (const KeyValue<StringName, PropertyInfo> &E : properties) {
163
if (!value_overrides.has(E.key)) {
164
bool property_visible = platform->get_export_option_visibility(this, E.key);
165
if (!property_visible) {
166
continue;
167
}
168
169
// Get option visibility from editor export plugins.
170
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
171
for (int i = 0; i < export_plugins.size(); i++) {
172
if (!export_plugins[i]->supports_platform(platform)) {
173
continue;
174
}
175
176
export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));
177
property_visible = export_plugins[i]->_get_export_option_visibility(platform, E.key);
178
if (!property_visible) {
179
break;
180
}
181
}
182
183
if (property_visible) {
184
p_list->push_back(E.value);
185
}
186
}
187
}
188
}
189
190
Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
191
return platform;
192
}
193
194
void EditorExportPreset::update_files() {
195
{
196
Vector<String> to_remove;
197
for (const String &E : selected_files) {
198
if (!FileAccess::exists(E)) {
199
to_remove.push_back(E);
200
}
201
}
202
for (int i = 0; i < to_remove.size(); ++i) {
203
selected_files.erase(to_remove[i]);
204
}
205
}
206
207
{
208
Vector<String> to_remove;
209
for (const KeyValue<String, FileExportMode> &E : customized_files) {
210
if (!FileAccess::exists(E.key) && !DirAccess::exists(E.key)) {
211
to_remove.push_back(E.key);
212
}
213
}
214
for (int i = 0; i < to_remove.size(); ++i) {
215
customized_files.erase(to_remove[i]);
216
}
217
}
218
}
219
220
void EditorExportPreset::update_value_overrides() {
221
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
222
HashMap<StringName, Variant> new_value_overrides;
223
224
value_overrides.clear();
225
226
for (int i = 0; i < export_plugins.size(); i++) {
227
if (!export_plugins[i]->supports_platform(platform)) {
228
continue;
229
}
230
231
export_plugins.write[i]->set_export_preset(Ref<EditorExportPreset>(this));
232
233
Dictionary plugin_overrides = export_plugins[i]->_get_export_options_overrides(platform);
234
if (!plugin_overrides.is_empty()) {
235
for (const KeyValue<Variant, Variant> &kv : plugin_overrides) {
236
const StringName &key = kv.key;
237
const Variant &value = kv.value;
238
if (new_value_overrides.has(key) && new_value_overrides[key] != value) {
239
WARN_PRINT_ED(vformat("Editor export plugin '%s' overrides pre-existing export option override '%s' with new value.", export_plugins[i]->get_name(), key));
240
}
241
new_value_overrides[key] = value;
242
}
243
}
244
}
245
246
value_overrides = new_value_overrides;
247
notify_property_list_changed();
248
}
249
250
Vector<String> EditorExportPreset::get_files_to_export() const {
251
Vector<String> files;
252
for (const String &E : selected_files) {
253
files.push_back(E);
254
}
255
return files;
256
}
257
258
Dictionary EditorExportPreset::get_customized_files() const {
259
Dictionary files;
260
for (const KeyValue<String, FileExportMode> &E : customized_files) {
261
String mode;
262
switch (E.value) {
263
case MODE_FILE_NOT_CUSTOMIZED: {
264
continue;
265
} break;
266
case MODE_FILE_STRIP: {
267
mode = "strip";
268
} break;
269
case MODE_FILE_KEEP: {
270
mode = "keep";
271
} break;
272
case MODE_FILE_REMOVE: {
273
mode = "remove";
274
}
275
}
276
files[E.key] = mode;
277
}
278
return files;
279
}
280
281
int EditorExportPreset::get_customized_files_count() const {
282
return customized_files.size();
283
}
284
285
void EditorExportPreset::set_customized_files(const Dictionary &p_files) {
286
for (const Variant *key = p_files.next(nullptr); key; key = p_files.next(key)) {
287
EditorExportPreset::FileExportMode mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
288
String value = p_files[*key];
289
if (value == "strip") {
290
mode = EditorExportPreset::MODE_FILE_STRIP;
291
} else if (value == "keep") {
292
mode = EditorExportPreset::MODE_FILE_KEEP;
293
} else if (value == "remove") {
294
mode = EditorExportPreset::MODE_FILE_REMOVE;
295
}
296
set_file_export_mode(*key, mode);
297
}
298
}
299
300
void EditorExportPreset::set_name(const String &p_name) {
301
name = p_name;
302
EditorExport::singleton->save_presets();
303
}
304
305
String EditorExportPreset::get_name() const {
306
return name;
307
}
308
309
void EditorExportPreset::set_runnable(bool p_enable) {
310
runnable = p_enable;
311
EditorExport::singleton->emit_presets_runnable_changed();
312
EditorExport::singleton->save_presets();
313
}
314
315
bool EditorExportPreset::is_runnable() const {
316
return runnable;
317
}
318
319
void EditorExportPreset::set_advanced_options_enabled(bool p_enabled) {
320
if (advanced_options_enabled == p_enabled) {
321
return;
322
}
323
advanced_options_enabled = p_enabled;
324
EditorExport::singleton->save_presets();
325
notify_property_list_changed();
326
}
327
328
bool EditorExportPreset::are_advanced_options_enabled() const {
329
return advanced_options_enabled;
330
}
331
332
void EditorExportPreset::set_dedicated_server(bool p_enable) {
333
dedicated_server = p_enable;
334
EditorExport::singleton->save_presets();
335
}
336
337
bool EditorExportPreset::is_dedicated_server() const {
338
return dedicated_server;
339
}
340
341
void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
342
export_filter = p_filter;
343
EditorExport::singleton->save_presets();
344
}
345
346
EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
347
return export_filter;
348
}
349
350
void EditorExportPreset::set_include_filter(const String &p_include) {
351
include_filter = p_include;
352
EditorExport::singleton->save_presets();
353
}
354
355
String EditorExportPreset::get_include_filter() const {
356
return include_filter;
357
}
358
359
void EditorExportPreset::set_export_path(const String &p_path) {
360
export_path = p_path;
361
/* NOTE(SonerSound): if there is a need to implement a PropertyHint that specifically indicates a relative path,
362
* this should be removed. */
363
if (export_path.is_absolute_path()) {
364
String res_path = OS::get_singleton()->get_resource_dir();
365
export_path = res_path.path_to_file(export_path);
366
}
367
EditorExport::singleton->save_presets();
368
}
369
370
String EditorExportPreset::get_export_path() const {
371
return export_path;
372
}
373
374
void EditorExportPreset::set_exclude_filter(const String &p_exclude) {
375
exclude_filter = p_exclude;
376
EditorExport::singleton->save_presets();
377
}
378
379
String EditorExportPreset::get_exclude_filter() const {
380
return exclude_filter;
381
}
382
383
void EditorExportPreset::add_export_file(const String &p_path) {
384
selected_files.insert(p_path);
385
EditorExport::singleton->save_presets();
386
}
387
388
void EditorExportPreset::remove_export_file(const String &p_path) {
389
selected_files.erase(p_path);
390
EditorExport::singleton->save_presets();
391
}
392
393
bool EditorExportPreset::has_export_file(const String &p_path) {
394
return selected_files.has(p_path);
395
}
396
397
void EditorExportPreset::set_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_mode) {
398
if (p_mode == FileExportMode::MODE_FILE_NOT_CUSTOMIZED) {
399
customized_files.erase(p_path);
400
} else {
401
customized_files.insert(p_path, p_mode);
402
}
403
EditorExport::singleton->save_presets();
404
}
405
406
EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_default) const {
407
HashMap<String, FileExportMode>::ConstIterator i = customized_files.find(p_path);
408
if (i) {
409
return i->value;
410
}
411
return p_default;
412
}
413
414
void EditorExportPreset::add_patch(const String &p_path, int p_at_pos) {
415
ERR_FAIL_COND_EDMSG(patches.has(p_path), vformat("Failed to add patch \"%s\". Patches must be unique.", p_path));
416
417
if (p_at_pos < 0) {
418
patches.push_back(p_path);
419
} else {
420
patches.insert(p_at_pos, p_path);
421
}
422
423
EditorExport::singleton->save_presets();
424
}
425
426
void EditorExportPreset::set_patch(int p_index, const String &p_path) {
427
remove_patch(p_index);
428
add_patch(p_path, p_index);
429
}
430
431
String EditorExportPreset::get_patch(int p_index) {
432
ERR_FAIL_INDEX_V(p_index, patches.size(), String());
433
return patches[p_index];
434
}
435
436
void EditorExportPreset::remove_patch(int p_index) {
437
ERR_FAIL_INDEX(p_index, patches.size());
438
patches.remove_at(p_index);
439
EditorExport::singleton->save_presets();
440
}
441
442
void EditorExportPreset::set_patches(const Vector<String> &p_patches) {
443
patches = p_patches;
444
}
445
446
Vector<String> EditorExportPreset::get_patches() const {
447
return patches;
448
}
449
450
void EditorExportPreset::set_custom_features(const String &p_custom_features) {
451
custom_features = p_custom_features;
452
EditorExport::singleton->save_presets();
453
}
454
455
String EditorExportPreset::get_custom_features() const {
456
return custom_features;
457
}
458
459
void EditorExportPreset::set_enc_in_filter(const String &p_filter) {
460
enc_in_filters = p_filter;
461
EditorExport::singleton->save_presets();
462
}
463
464
String EditorExportPreset::get_enc_in_filter() const {
465
return enc_in_filters;
466
}
467
468
void EditorExportPreset::set_enc_ex_filter(const String &p_filter) {
469
enc_ex_filters = p_filter;
470
EditorExport::singleton->save_presets();
471
}
472
473
String EditorExportPreset::get_enc_ex_filter() const {
474
return enc_ex_filters;
475
}
476
477
void EditorExportPreset::set_seed(uint64_t p_seed) {
478
seed = p_seed;
479
EditorExport::singleton->save_presets();
480
}
481
482
uint64_t EditorExportPreset::get_seed() const {
483
return seed;
484
}
485
486
void EditorExportPreset::set_enc_pck(bool p_enabled) {
487
enc_pck = p_enabled;
488
EditorExport::singleton->save_presets();
489
}
490
491
bool EditorExportPreset::get_enc_pck() const {
492
return enc_pck;
493
}
494
495
void EditorExportPreset::set_enc_directory(bool p_enabled) {
496
enc_directory = p_enabled;
497
EditorExport::singleton->save_presets();
498
}
499
500
bool EditorExportPreset::get_enc_directory() const {
501
return enc_directory;
502
}
503
504
void EditorExportPreset::set_script_encryption_key(const String &p_key) {
505
script_key = p_key;
506
EditorExport::singleton->save_presets();
507
}
508
509
String EditorExportPreset::get_script_encryption_key() const {
510
return script_key;
511
}
512
513
void EditorExportPreset::set_script_export_mode(int p_mode) {
514
script_mode = p_mode;
515
EditorExport::singleton->save_presets();
516
}
517
518
int EditorExportPreset::get_script_export_mode() const {
519
return script_mode;
520
}
521
522
Variant EditorExportPreset::get_or_env(const StringName &p_name, const String &p_env_var, bool *r_valid) const {
523
const String from_env = OS::get_singleton()->get_environment(p_env_var);
524
if (!from_env.is_empty()) {
525
if (r_valid) {
526
*r_valid = true;
527
}
528
return from_env;
529
}
530
return get(p_name, r_valid);
531
}
532
533
_FORCE_INLINE_ bool _check_digits(const String &p_str) {
534
for (int i = 0; i < p_str.length(); i++) {
535
char32_t c = p_str.operator[](i);
536
if (!is_digit(c)) {
537
return false;
538
}
539
}
540
return true;
541
}
542
543
String EditorExportPreset::get_version(const StringName &p_preset_string, bool p_windows_version) const {
544
String result = get(p_preset_string);
545
if (result.is_empty()) {
546
result = GLOBAL_GET("application/config/version");
547
548
// Split and validate version number components.
549
const PackedStringArray result_split = result.split(".", false);
550
bool valid_version = !result_split.is_empty();
551
for (const String &E : result_split) {
552
if (!_check_digits(E)) {
553
valid_version = false;
554
break;
555
}
556
}
557
558
if (valid_version) {
559
if (p_windows_version) {
560
// Modify version number to match Windows constraints (version numbers must have 4 components).
561
if (result_split.size() == 1) {
562
result = result + ".0.0.0";
563
} else if (result_split.size() == 2) {
564
result = result + ".0.0";
565
} else if (result_split.size() == 3) {
566
result = result + ".0";
567
} else {
568
result = vformat("%s.%s.%s.%s", result_split[0], result_split[1], result_split[2], result_split[3]);
569
}
570
} else {
571
result = String(".").join(result_split);
572
}
573
} else {
574
if (!result.is_empty()) {
575
WARN_PRINT(vformat("Invalid version number \"%s\". The version number can only contain numeric characters (0-9) and non-consecutive periods (.).", result));
576
}
577
if (p_windows_version) {
578
result = "1.0.0.0";
579
} else {
580
result = "1.0.0";
581
}
582
}
583
}
584
585
return result;
586
}
587
588