summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp6
-rw-r--r--editor/export/editor_export.cpp11
-rw-r--r--editor/export/editor_export_platform.cpp45
-rw-r--r--editor/export/editor_export_platform.h2
-rw-r--r--editor/export/editor_export_plugin.cpp10
-rw-r--r--editor/export/editor_export_plugin.h18
-rw-r--r--editor/export/editor_export_preset.cpp96
-rw-r--r--editor/export/editor_export_preset.h21
-rw-r--r--editor/export/project_export.cpp132
-rw-r--r--editor/export/project_export.h10
-rw-r--r--editor/plugins/dedicated_server_export_plugin.cpp139
-rw-r--r--editor/plugins/dedicated_server_export_plugin.h58
12 files changed, 513 insertions, 35 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index c344812065..bbae6e5389 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -125,6 +125,7 @@
#include "editor/plugins/asset_library_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/debugger_editor_plugin.h"
+#include "editor/plugins/dedicated_server_export_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "editor/plugins/gdextension_export_plugin.h"
@@ -7878,6 +7879,11 @@ EditorNode::EditorNode() {
EditorExport::get_singleton()->add_export_plugin(gdextension_export_plugin);
+ Ref<DedicatedServerExportPlugin> dedicated_server_export_plugin;
+ dedicated_server_export_plugin.instantiate();
+
+ EditorExport::get_singleton()->add_export_plugin(dedicated_server_export_plugin);
+
Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin;
packed_scene_translation_parser_plugin.instantiate();
EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD);
diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp
index 1d147cc5b9..4900ced2e4 100644
--- a/editor/export/editor_export.cpp
+++ b/editor/export/editor_export.cpp
@@ -45,6 +45,7 @@ void EditorExport::_save() {
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, "dedicated_server", preset->is_dedicated_server());
config->set_value(section, "custom_features", preset->get_custom_features());
bool save_files = false;
@@ -64,6 +65,11 @@ void EditorExport::_save() {
config->set_value(section, "export_filter", "exclude");
save_files = true;
} break;
+ case EditorExportPreset::EXPORT_CUSTOMIZED: {
+ config->set_value(section, "export_filter", "customized");
+ config->set_value(section, "customized_files", preset->get_customized_files());
+ save_files = false;
+ };
}
if (save_files) {
@@ -213,6 +219,7 @@ void EditorExport::load_config() {
preset->set_name(config->get_value(section, "name"));
preset->set_runnable(config->get_value(section, "runnable"));
+ preset->set_dedicated_server(config->get_value(section, "dedicated_server", false));
if (config->has_section_key(section, "custom_features")) {
preset->set_custom_features(config->get_value(section, "custom_features"));
@@ -233,6 +240,10 @@ void EditorExport::load_config() {
} else if (export_filter == "exclude") {
preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES);
get_files = true;
+ } else if (export_filter == "customized") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_CUSTOMIZED);
+ preset->set_customized_files(config->get_value(section, "customized_files", Dictionary()));
+ get_files = false;
}
if (get_files) {
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 27ca0b84a1..9f79eecfb7 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -343,6 +343,24 @@ void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_d
}
}
+void EditorExportPlatform::_export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths) {
+ for (int i = 0; i < p_dir->get_subdir_count(); i++) {
+ EditorFileSystemDirectory *subdir = p_dir->get_subdir(i);
+ _export_find_customized_resources(p_preset, subdir, p_preset->get_file_export_mode(subdir->get_path(), p_mode), p_paths);
+ }
+
+ for (int i = 0; i < p_dir->get_file_count(); i++) {
+ if (p_dir->get_file_type(i) == "TextFile") {
+ continue;
+ }
+ String path = p_dir->get_file_path(i);
+ EditorExportPreset::FileExportMode file_mode = p_preset->get_file_export_mode(path, p_mode);
+ if (file_mode != EditorExportPreset::MODE_FILE_REMOVE) {
+ p_paths.insert(path);
+ }
+ }
+}
+
void EditorExportPlatform::_export_find_dependencies(const String &p_path, HashSet<String> &p_paths) {
if (p_paths.has(p_path)) {
return;
@@ -639,10 +657,20 @@ bool EditorExportPlatform::_export_customize_object(Object *p_object, LocalVecto
return changed;
}
+bool EditorExportPlatform::_is_editable_ancestor(Node *p_root, Node *p_node) {
+ while (p_node != nullptr && p_node != p_root) {
+ if (p_root->is_editable_instance(p_node)) {
+ return true;
+ }
+ p_node = p_node->get_owner();
+ }
+ return false;
+}
+
bool EditorExportPlatform::_export_customize_scene_resources(Node *p_root, Node *p_node, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins) {
bool changed = false;
- if (p_node == p_root || p_node->get_owner() == p_root) {
+ if (p_root == p_node || p_node->get_owner() == p_root || _is_editable_ancestor(p_root, p_node)) {
if (_export_customize_object(p_node, customize_resources_plugins)) {
changed = true;
}
@@ -757,10 +785,10 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector
break;
}
}
+ }
- if (_export_customize_object(res.ptr(), customize_resources_plugins)) {
- modified = true;
- }
+ if (_export_customize_object(res.ptr(), customize_resources_plugins)) {
+ modified = true;
}
if (modified || p_force_save) {
@@ -796,6 +824,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
for (int i = 0; i < files.size(); i++) {
paths.erase(files[i]);
}
+ } else if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED) {
+ _export_find_customized_resources(p_preset, EditorFileSystem::get_singleton()->get_filesystem(), p_preset->get_file_export_mode("res://"), paths);
} else {
bool scenes_only = p_preset->get_export_filter() == EditorExportPreset::EXPORT_SELECTED_SCENES;
@@ -939,14 +969,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
LocalVector<Ref<EditorExportPlugin>> customize_scenes_plugins;
for (int i = 0; i < export_plugins.size(); i++) {
- if (export_plugins[i]->_begin_customize_resources(Ref<EditorExportPlatform>(this), features_psa)) {
+ if (export_plugins.write[i]->_begin_customize_resources(Ref<EditorExportPlatform>(this), features_psa)) {
customize_resources_plugins.push_back(export_plugins[i]);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash);
uint64_t hash = export_plugins[i]->_get_customization_configuration_hash();
custom_resources_hash = hash_murmur3_one_64(hash, custom_resources_hash);
}
- if (export_plugins[i]->_begin_customize_scenes(Ref<EditorExportPlatform>(this), features_psa)) {
+ if (export_plugins.write[i]->_begin_customize_scenes(Ref<EditorExportPlatform>(this), features_psa)) {
customize_scenes_plugins.push_back(export_plugins[i]);
custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash);
@@ -1218,6 +1248,9 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
}
}
}
+ for (int i = 0; i < export_plugins.size(); i++) {
+ custom_list.append_array(export_plugins[i]->_get_export_features(Ref<EditorExportPlatform>(this), p_debug));
+ }
ProjectSettings::CustomMap custom_map;
if (path_remaps.size()) {
diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h
index 1fb35759ac..3b4e92c9bd 100644
--- a/editor/export/editor_export_platform.h
+++ b/editor/export/editor_export_platform.h
@@ -91,6 +91,7 @@ private:
Vector<ExportMessage> messages;
void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths);
+ void _export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths);
void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths);
static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
@@ -112,6 +113,7 @@ private:
bool _export_customize_array(Array &array, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins);
bool _export_customize_object(Object *p_object, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins);
bool _export_customize_scene_resources(Node *p_root, Node *p_node, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins);
+ bool _is_editable_ancestor(Node *p_root, Node *p_node);
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);
diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp
index dfd4520eec..0add55820f 100644
--- a/editor/export/editor_export_plugin.cpp
+++ b/editor/export/editor_export_plugin.cpp
@@ -141,7 +141,7 @@ void EditorExportPlugin::_export_end_script() {
// Customization
-bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const {
+bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) {
bool ret = false;
GDVIRTUAL_CALL(_begin_customize_resources, p_platform, p_features, ret);
return ret;
@@ -153,7 +153,7 @@ Ref<Resource> EditorExportPlugin::_customize_resource(const Ref<Resource> &p_res
return ret;
}
-bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const {
+bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) {
bool ret = false;
GDVIRTUAL_CALL(_begin_customize_scenes, p_platform, p_features, ret);
return ret;
@@ -185,6 +185,12 @@ String EditorExportPlugin::_get_name() const {
return ret;
}
+PackedStringArray EditorExportPlugin::_get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const {
+ PackedStringArray ret;
+ GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret);
+ return ret;
+}
+
void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {
}
diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h
index 5ac0a70c3e..fad647a67b 100644
--- a/editor/export/editor_export_plugin.h
+++ b/editor/export/editor_export_plugin.h
@@ -120,18 +120,22 @@ protected:
GDVIRTUAL0(_end_customize_scenes)
GDVIRTUAL0(_end_customize_resources)
+ GDVIRTUAL2RC(PackedStringArray, _get_export_features, const Ref<EditorExportPlatform> &, bool);
+
GDVIRTUAL0RC(String, _get_name)
- bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const; // Return true if this plugin does property export customization
- Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made.
+ virtual bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features); // Return true if this plugin does property export customization
+ virtual Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made.
+
+ virtual bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features); // Return true if this plugin does property export customization
+ virtual Node *_customize_scene(Node *p_root, const String &p_path); // Return true if a change was made
- bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const; // Return true if this plugin does property export customization
- Node *_customize_scene(Node *p_root, const String &p_path); // Return true if a change was made
+ virtual uint64_t _get_customization_configuration_hash() const; // Hash used for caching customized resources and scenes.
- uint64_t _get_customization_configuration_hash() const; // Hash used for caching customized resources and scenes.
+ virtual void _end_customize_scenes();
+ virtual void _end_customize_resources();
- void _end_customize_scenes();
- void _end_customize_resources();
+ virtual PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const;
virtual String _get_name() const;
diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp
index c6365806b3..6beef623bc 100644
--- a/editor/export/editor_export_preset.cpp
+++ b/editor/export/editor_export_preset.cpp
@@ -64,15 +64,29 @@ 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);
+void EditorExportPreset::update_files() {
+ {
+ 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]);
}
}
- for (int i = 0; i < to_remove.size(); ++i) {
- selected_files.erase(to_remove[i]);
+
+ {
+ Vector<String> to_remove;
+ for (const KeyValue<String, FileExportMode> &E : customized_files) {
+ if (!FileAccess::exists(E.key) && !DirAccess::exists(E.key)) {
+ to_remove.push_back(E.key);
+ }
+ }
+ for (int i = 0; i < to_remove.size(); ++i) {
+ customized_files.erase(to_remove[i]);
+ }
}
}
@@ -84,6 +98,48 @@ Vector<String> EditorExportPreset::get_files_to_export() const {
return files;
}
+Dictionary EditorExportPreset::get_customized_files() const {
+ Dictionary files;
+ for (const KeyValue<String, FileExportMode> &E : customized_files) {
+ String mode;
+ switch (E.value) {
+ case MODE_FILE_NOT_CUSTOMIZED: {
+ continue;
+ } break;
+ case MODE_FILE_STRIP: {
+ mode = "strip";
+ } break;
+ case MODE_FILE_KEEP: {
+ mode = "keep";
+ } break;
+ case MODE_FILE_REMOVE: {
+ mode = "remove";
+ }
+ }
+ files[E.key] = mode;
+ }
+ return files;
+}
+
+int EditorExportPreset::get_customized_files_count() const {
+ return customized_files.size();
+}
+
+void EditorExportPreset::set_customized_files(const Dictionary &p_files) {
+ for (const Variant *key = p_files.next(nullptr); key; key = p_files.next(key)) {
+ EditorExportPreset::FileExportMode mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+ String value = p_files[*key];
+ if (value == "strip") {
+ mode = EditorExportPreset::MODE_FILE_STRIP;
+ } else if (value == "keep") {
+ mode = EditorExportPreset::MODE_FILE_KEEP;
+ } else if (value == "remove") {
+ mode = EditorExportPreset::MODE_FILE_REMOVE;
+ }
+ set_file_export_mode(*key, mode);
+ }
+}
+
void EditorExportPreset::set_name(const String &p_name) {
name = p_name;
EditorExport::singleton->save_presets();
@@ -102,6 +158,15 @@ bool EditorExportPreset::is_runnable() const {
return runnable;
}
+void EditorExportPreset::set_dedicated_server(bool p_enable) {
+ dedicated_server = p_enable;
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::is_dedicated_server() const {
+ return dedicated_server;
+}
+
void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
export_filter = p_filter;
EditorExport::singleton->save_presets();
@@ -158,6 +223,23 @@ bool EditorExportPreset::has_export_file(const String &p_path) {
return selected_files.has(p_path);
}
+void EditorExportPreset::set_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_mode) {
+ if (p_mode == FileExportMode::MODE_FILE_NOT_CUSTOMIZED) {
+ customized_files.erase(p_path);
+ } else {
+ customized_files.insert(p_path, p_mode);
+ }
+ EditorExport::singleton->save_presets();
+}
+
+EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_default) const {
+ HashMap<String, FileExportMode>::ConstIterator i = customized_files.find(p_path);
+ if (i) {
+ return i->value;
+ }
+ return p_default;
+}
+
void EditorExportPreset::set_custom_features(const String &p_custom_features) {
custom_features = p_custom_features;
EditorExport::singleton->save_presets();
diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h
index de208f410e..db139d8860 100644
--- a/editor/export/editor_export_preset.h
+++ b/editor/export/editor_export_preset.h
@@ -44,6 +44,14 @@ public:
EXPORT_SELECTED_SCENES,
EXPORT_SELECTED_RESOURCES,
EXCLUDE_SELECTED_RESOURCES,
+ EXPORT_CUSTOMIZED,
+ };
+
+ enum FileExportMode {
+ MODE_FILE_NOT_CUSTOMIZED,
+ MODE_FILE_STRIP,
+ MODE_FILE_KEEP,
+ MODE_FILE_REMOVE,
};
private:
@@ -55,7 +63,9 @@ private:
String exporter;
HashSet<String> selected_files;
+ HashMap<String, FileExportMode> customized_files;
bool runnable = false;
+ bool dedicated_server = false;
friend class EditorExport;
friend class EditorExportPlatform;
@@ -85,20 +95,29 @@ public:
bool has(const StringName &p_property) const { return values.has(p_property); }
- void update_files_to_export();
+ void update_files();
Vector<String> get_files_to_export() const;
+ Dictionary get_customized_files() const;
+ int get_customized_files_count() const;
+ void set_customized_files(const Dictionary &p_files);
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_file_export_mode(const String &p_path, FileExportMode p_mode);
+ FileExportMode get_file_export_mode(const String &p_path, FileExportMode p_default = MODE_FILE_NOT_CUSTOMIZED) const;
+
void set_name(const String &p_name);
String get_name() const;
void set_runnable(bool p_enable);
bool is_runnable() const;
+ void set_dedicated_server(bool p_enable);
+ bool is_dedicated_server() const;
+
void set_export_filter(ExportFilter p_filter);
ExportFilter get_export_filter() const;
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 2caebc6f04..52c192164f 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -45,6 +45,7 @@
#include "scene/gui/link_button.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
+#include "scene/gui/popup_menu.h"
#include "scene/gui/split_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tree.h"
@@ -165,7 +166,7 @@ void ProjectExportDialog::_update_presets() {
if (preset->is_runnable()) {
preset_name += " (" + TTR("Runnable") + ")";
}
- preset->update_files_to_export();
+ preset->update_files();
presets->add_item(preset_name, preset->get_platform()->get_logo());
}
@@ -244,6 +245,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
export_filter->select(current->get_export_filter());
include_filters->set_text(current->get_include_filter());
exclude_filters->set_text(current->get_exclude_filter());
+ server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED);
_fill_resource_tree();
@@ -570,6 +572,7 @@ void ProjectExportDialog::_duplicate_preset() {
if (make_runnable) {
preset->set_runnable(make_runnable);
}
+ preset->set_dedicated_server(current->is_dedicated_server());
preset->set_export_filter(current->get_export_filter());
preset->set_include_filter(current->get_include_filter());
preset->set_exclude_filter(current->get_exclude_filter());
@@ -692,7 +695,16 @@ void ProjectExportDialog::_export_type_changed(int p_which) {
return;
}
- current->set_export_filter(EditorExportPreset::ExportFilter(p_which));
+ EditorExportPreset::ExportFilter filter_type = (EditorExportPreset::ExportFilter)p_which;
+ current->set_export_filter(filter_type);
+ current->set_dedicated_server(filter_type == EditorExportPreset::EXPORT_CUSTOMIZED);
+ server_strip_message->set_visible(filter_type == EditorExportPreset::EXPORT_CUSTOMIZED);
+
+ // Default to stripping everything when first switching to server build.
+ if (filter_type == EditorExportPreset::EXPORT_CUSTOMIZED && current->get_customized_files_count() == 0) {
+ current->set_file_export_mode("res://", EditorExportPreset::MODE_FILE_STRIP);
+ }
+
updating = true;
_fill_resource_tree();
updating = false;
@@ -728,25 +740,53 @@ void ProjectExportDialog::_fill_resource_tree() {
return;
}
+ TreeItem *root = include_files->create_item();
+
+ if (f == EditorExportPreset::EXPORT_CUSTOMIZED) {
+ include_files->set_columns(2);
+ include_files->set_column_expand(1, false);
+ include_files->set_column_custom_minimum_width(1, 250 * EDSCALE);
+ } else {
+ include_files->set_columns(1);
+ }
+
include_label->show();
include_margin->show();
- TreeItem *root = include_files->create_item();
+ _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(), root, current, f);
+}
- _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(), root, current, f == EditorExportPreset::EXPORT_SELECTED_SCENES);
+void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode) {
+ if (p_mode == EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) {
+ p_item->set_checked(0, false);
+ p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
+ p_item->set_text(1, "");
+ p_item->set_editable(1, false);
+ p_item->set_selectable(1, false);
+ } else {
+ p_item->set_checked(0, true);
+ p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM);
+ p_item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_mode)));
+ p_item->set_editable(1, true);
+ p_item->set_selectable(1, true);
+ }
}
-bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, bool p_only_scenes) {
+bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, EditorExportPreset::ExportFilter p_export_filter) {
p_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
p_item->set_icon(0, presets->get_theme_icon(SNAME("folder"), SNAME("FileDialog")));
p_item->set_text(0, p_dir->get_name() + "/");
p_item->set_editable(0, true);
p_item->set_metadata(0, p_dir->get_path());
+ if (p_export_filter == EditorExportPreset::EXPORT_CUSTOMIZED) {
+ _setup_item_for_file_mode(p_item, current->get_file_export_mode(p_dir->get_path()));
+ }
+
bool used = false;
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
TreeItem *subdir = include_files->create_item(p_item);
- if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) {
+ if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_export_filter)) {
used = true;
} else {
memdelete(subdir);
@@ -755,7 +795,7 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem
for (int i = 0; i < p_dir->get_file_count(); i++) {
String type = p_dir->get_file_type(i);
- if (p_only_scenes && type != "PackedScene") {
+ if (p_export_filter == EditorExportPreset::EXPORT_SELECTED_SCENES && type != "PackedScene") {
continue;
}
if (type == "TextFile") {
@@ -770,9 +810,14 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem
file->set_icon(0, EditorNode::get_singleton()->get_class_icon(type));
file->set_editable(0, true);
- file->set_checked(0, current->has_export_file(path));
file->set_metadata(0, path);
- file->propagate_check(0);
+
+ if (p_export_filter == EditorExportPreset::EXPORT_CUSTOMIZED) {
+ _setup_item_for_file_mode(file, current->get_file_export_mode(path));
+ } else {
+ file->set_checked(0, current->has_export_file(path));
+ file->propagate_check(0);
+ }
used = true;
}
@@ -794,7 +839,19 @@ void ProjectExportDialog::_tree_changed() {
return;
}
- item->propagate_check(0);
+ if (current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED) {
+ EditorExportPreset::FileExportMode file_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+ String path = item->get_metadata(0);
+
+ if (item->is_checked(0)) {
+ file_mode = current->get_file_export_mode(path, EditorExportPreset::MODE_FILE_STRIP);
+ }
+
+ _setup_item_for_file_mode(item, file_mode);
+ current->set_file_export_mode(path, file_mode);
+ } else {
+ item->propagate_check(0);
+ }
}
void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) {
@@ -814,6 +871,30 @@ void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) {
}
}
+void ProjectExportDialog::_tree_popup_edited(bool p_arrow_clicked) {
+ Rect2 bounds = include_files->get_custom_popup_rect();
+ bounds.position += get_global_canvas_transform().get_origin();
+ bounds.size *= get_global_canvas_transform().get_scale();
+ if (!is_embedding_subwindows()) {
+ bounds.position += get_position();
+ }
+ file_mode_popup->popup(bounds);
+}
+
+void ProjectExportDialog::_set_file_export_mode(int p_id) {
+ Ref<EditorExportPreset> current = get_current_preset();
+ if (current.is_null()) {
+ return;
+ }
+
+ TreeItem *item = include_files->get_edited();
+ String path = item->get_metadata(0);
+
+ current->set_file_export_mode(path, (EditorExportPreset::FileExportMode)p_id);
+
+ item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_id)));
+}
+
void ProjectExportDialog::_export_pck_zip() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
@@ -1068,6 +1149,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_filter->add_item(TTR("Export selected scenes (and dependencies)"));
export_filter->add_item(TTR("Export selected resources (and dependencies)"));
export_filter->add_item(TTR("Export all resources in the project except resources checked below"));
+ export_filter->add_item(TTR("Export as dedicated server"));
resources_vb->add_margin_child(TTR("Export Mode:"), export_filter);
export_filter->connect("item_selected", callable_mp(this, &ProjectExportDialog::_export_type_changed));
@@ -1082,6 +1164,36 @@ ProjectExportDialog::ProjectExportDialog() {
include_margin->add_child(include_files);
include_files->connect("item_edited", callable_mp(this, &ProjectExportDialog::_tree_changed));
include_files->connect("check_propagated_to_item", callable_mp(this, &ProjectExportDialog::_check_propagated_to_item));
+ include_files->connect("custom_popup_edited", callable_mp(this, &ProjectExportDialog::_tree_popup_edited));
+
+ server_strip_message = memnew(Label);
+ server_strip_message->set_visible(false);
+ server_strip_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ resources_vb->add_child(server_strip_message);
+
+ {
+ List<StringName> resource_names;
+ ClassDB::get_inheriters_from_class("Resource", &resource_names);
+
+ PackedStringArray strippable;
+ for (StringName resource_name : resource_names) {
+ if (ClassDB::has_method(resource_name, "create_placeholder", true)) {
+ strippable.push_back(resource_name);
+ }
+ }
+ strippable.sort();
+
+ String message = TTR("\"Strip Visuals\" will replace the following resources with placeholders:") + " ";
+ message += String(", ").join(strippable);
+ server_strip_message->set_text(message);
+ }
+
+ file_mode_popup = memnew(PopupMenu);
+ add_child(file_mode_popup);
+ file_mode_popup->add_item(TTR("Strip Visuals"), EditorExportPreset::MODE_FILE_STRIP);
+ file_mode_popup->add_item(TTR("Keep"), EditorExportPreset::MODE_FILE_KEEP);
+ file_mode_popup->add_item(TTR("Remove"), EditorExportPreset::MODE_FILE_REMOVE);
+ file_mode_popup->connect("id_pressed", callable_mp(this, &ProjectExportDialog::_set_file_export_mode));
include_filters = memnew(LineEdit);
resources_vb->add_margin_child(
diff --git a/editor/export/project_export.h b/editor/export/project_export.h
index d392dba2a4..63f8fc4a2e 100644
--- a/editor/export/project_export.h
+++ b/editor/export/project_export.h
@@ -31,11 +31,11 @@
#ifndef PROJECT_EXPORT_H
#define PROJECT_EXPORT_H
+#include "editor/export/editor_export_preset.h"
#include "scene/gui/dialogs.h"
class CheckBox;
class CheckButton;
-class EditorExportPreset;
class EditorFileDialog;
class EditorFileSystemDirectory;
class EditorInspector;
@@ -43,6 +43,7 @@ class EditorPropertyPath;
class ItemList;
class MenuButton;
class OptionButton;
+class PopupMenu;
class RichTextLabel;
class TabContainer;
class Tree;
@@ -75,6 +76,8 @@ private:
LineEdit *include_filters = nullptr;
LineEdit *exclude_filters = nullptr;
Tree *include_files = nullptr;
+ Label *server_strip_message = nullptr;
+ PopupMenu *file_mode_popup = nullptr;
Label *include_label = nullptr;
MarginContainer *include_margin = nullptr;
@@ -113,9 +116,12 @@ private:
void _export_type_changed(int p_which);
void _filter_changed(const String &p_filter);
void _fill_resource_tree();
- bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, bool p_only_scenes);
+ void _setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode);
+ bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, EditorExportPreset::ExportFilter p_export_filter);
void _tree_changed();
void _check_propagated_to_item(Object *p_obj, int column);
+ void _tree_popup_edited(bool p_arrow_clicked);
+ void _set_file_export_mode(int p_id);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
diff --git a/editor/plugins/dedicated_server_export_plugin.cpp b/editor/plugins/dedicated_server_export_plugin.cpp
new file mode 100644
index 0000000000..013706034e
--- /dev/null
+++ b/editor/plugins/dedicated_server_export_plugin.cpp
@@ -0,0 +1,139 @@
+/**************************************************************************/
+/* dedicated_server_export_plugin.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "dedicated_server_export_plugin.h"
+
+EditorExportPreset::FileExportMode DedicatedServerExportPlugin::_get_export_mode_for_path(const String &p_path) {
+ Ref<EditorExportPreset> preset = get_export_preset();
+ ERR_FAIL_COND_V(preset.is_null(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED);
+
+ EditorExportPreset::FileExportMode mode = preset->get_file_export_mode(p_path);
+ if (mode != EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) {
+ return mode;
+ }
+
+ String path = p_path;
+ if (path.begins_with("res://")) {
+ path = path.substr(6);
+ }
+
+ Vector<String> parts = path.split("/");
+
+ while (parts.size() > 0) {
+ parts.resize(parts.size() - 1);
+
+ String test_path = "res://";
+ if (parts.size() > 0) {
+ test_path += String("/").join(parts) + "/";
+ }
+
+ mode = preset->get_file_export_mode(test_path);
+ if (mode != EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) {
+ break;
+ }
+ }
+
+ return mode;
+}
+
+PackedStringArray DedicatedServerExportPlugin::_get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const {
+ PackedStringArray ret;
+
+ Ref<EditorExportPreset> preset = get_export_preset();
+ ERR_FAIL_COND_V(preset.is_null(), ret);
+
+ if (preset->is_dedicated_server()) {
+ ret.append("dedicated_server");
+ }
+ return ret;
+}
+
+uint64_t DedicatedServerExportPlugin::_get_customization_configuration_hash() const {
+ Ref<EditorExportPreset> preset = get_export_preset();
+ ERR_FAIL_COND_V(preset.is_null(), 0);
+
+ if (preset->get_export_filter() != EditorExportPreset::EXPORT_CUSTOMIZED) {
+ return 0;
+ }
+
+ return preset->get_customized_files().hash();
+}
+
+bool DedicatedServerExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) {
+ Ref<EditorExportPreset> preset = get_export_preset();
+ ERR_FAIL_COND_V(preset.is_null(), false);
+
+ current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+
+ return preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED;
+}
+
+bool DedicatedServerExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) {
+ Ref<EditorExportPreset> preset = get_export_preset();
+ ERR_FAIL_COND_V(preset.is_null(), false);
+
+ current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+
+ return preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED;
+}
+
+Node *DedicatedServerExportPlugin::_customize_scene(Node *p_root, const String &p_path) {
+ // Simply set the export mode based on the scene path. All the real
+ // customization happens in _customize_resource().
+ current_export_mode = _get_export_mode_for_path(p_path);
+ return nullptr;
+}
+
+Ref<Resource> DedicatedServerExportPlugin::_customize_resource(const Ref<Resource> &p_resource, const String &p_path) {
+ // If the resource has a path, we use that to get our export mode. But if it
+ // doesn't, we assume that this resource is embedded in the last resource with
+ // a path.
+ if (p_path != "") {
+ current_export_mode = _get_export_mode_for_path(p_path);
+ }
+
+ if (p_resource.is_valid() && current_export_mode == EditorExportPreset::MODE_FILE_STRIP && p_resource->has_method("create_placeholder")) {
+ Callable::CallError err;
+ Ref<Resource> result = const_cast<Resource *>(p_resource.ptr())->callp("create_placeholder", nullptr, 0, err);
+ if (err.error == Callable::CallError::CALL_OK) {
+ return result;
+ }
+ }
+
+ return Ref<Resource>();
+}
+
+void DedicatedServerExportPlugin::_end_customize_scenes() {
+ current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+}
+
+void DedicatedServerExportPlugin::_end_customize_resources() {
+ current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED;
+}
diff --git a/editor/plugins/dedicated_server_export_plugin.h b/editor/plugins/dedicated_server_export_plugin.h
new file mode 100644
index 0000000000..cb014ae52d
--- /dev/null
+++ b/editor/plugins/dedicated_server_export_plugin.h
@@ -0,0 +1,58 @@
+/**************************************************************************/
+/* dedicated_server_export_plugin.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef DEDICATED_SERVER_EXPORT_PLUGIN_H
+#define DEDICATED_SERVER_EXPORT_PLUGIN_H
+
+#include "editor/export/editor_export.h"
+
+class DedicatedServerExportPlugin : public EditorExportPlugin {
+private:
+ EditorExportPreset::FileExportMode current_export_mode;
+
+ EditorExportPreset::FileExportMode _get_export_mode_for_path(const String &p_path);
+
+protected:
+ String _get_name() const override { return "DedicatedServer"; }
+
+ PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const override;
+ uint64_t _get_customization_configuration_hash() const override;
+
+ bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) override;
+ bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) override;
+
+ Node *_customize_scene(Node *p_root, const String &p_path) override;
+ Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path) override;
+
+ void _end_customize_scenes() override;
+ void _end_customize_resources() override;
+};
+
+#endif // DEDICATED_SERVER_EXPORT_PLUGIN_H