Add ability to export patch packs

Co-authored-by: Poq Xert <poqxert@poqxert.ru>
This commit is contained in:
Mikael Hermansson
2024-09-17 12:48:10 +02:00
parent 4254946de9
commit d3be030ea6
18 changed files with 619 additions and 20 deletions

View File

@@ -102,11 +102,13 @@ void ProjectExportDialog::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add")));
} break;
case NOTIFICATION_READY: {
duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add")));
connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_export_pck_zip));
_update_export_all();
} break;
@@ -248,6 +250,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
duplicate_preset->set_disabled(true);
delete_preset->set_disabled(true);
sections->hide();
patches->clear();
export_error->hide();
export_templates_error->hide();
return;
@@ -292,6 +295,21 @@ void ProjectExportDialog::_edit_preset(int p_index) {
exclude_filters->set_text(current->get_exclude_filter());
server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED);
patches->clear();
TreeItem *patch_root = patches->create_item();
Vector<String> patch_list = current->get_patches();
for (int i = 0; i < patch_list.size(); i++) {
TreeItem *patch = patches->create_item(patch_root);
const String &patch_path = patch_list[i];
patch->set_cell_mode(0, TreeItem::CELL_MODE_STRING);
patch->set_editable(0, true);
patch->set_text(0, patch_path.get_file());
patch->set_tooltip_text(0, patch_path);
patch->set_metadata(0, i);
patch->add_button(0, get_editor_theme_icon(SNAME("Remove")), 0);
patch->add_button(0, get_editor_theme_icon(SNAME("FileBrowse")), 1);
}
_fill_resource_tree();
bool needs_templates;
@@ -664,6 +682,7 @@ void ProjectExportDialog::_duplicate_preset() {
preset->set_export_filter(current->get_export_filter());
preset->set_include_filter(current->get_include_filter());
preset->set_exclude_filter(current->get_exclude_filter());
preset->set_patches(current->get_patches());
preset->set_custom_features(current->get_custom_features());
for (const KeyValue<StringName, Variant> &E : current->get_values()) {
@@ -720,8 +739,22 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_
return d;
}
}
} else if (p_from == patches) {
TreeItem *item = patches->get_item_at_position(p_point);
if (item) {
int item_metadata = item->get_metadata(0);
Dictionary d;
d["type"] = "export_patch";
d["patch"] = item_metadata;
Label *label = memnew(Label);
label->set_text(item->get_text(0));
patches->set_drag_preview(label);
return d;
}
}
return Variant();
}
@@ -735,6 +768,18 @@ bool ProjectExportDialog::can_drop_data_fw(const Point2 &p_point, const Variant
if (presets->get_item_at_position(p_point, true) < 0 && !presets->is_pos_at_end_of_items(p_point)) {
return false;
}
} else if (p_from == patches) {
Dictionary d = p_data;
if (d.get("type", "") != "export_patch") {
return false;
}
TreeItem *item = patches->get_item_at_position(p_point);
if (!item) {
return false;
}
patches->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
}
return true;
@@ -771,6 +816,31 @@ void ProjectExportDialog::drop_data_fw(const Point2 &p_point, const Variant &p_d
} else {
_edit_preset(presets->get_item_count() - 1);
}
} else if (p_from == patches) {
Dictionary d = p_data;
int from_pos = d["patch"];
TreeItem *item = patches->get_item_at_position(p_point);
if (!item) {
return;
}
int to_pos = item->get_metadata(0);
if (patches->get_drop_section_at_position(p_point) > 0) {
to_pos++;
}
if (to_pos > from_pos) {
to_pos--;
}
Ref<EditorExportPreset> preset = get_current_preset();
String patch = preset->get_patch(from_pos);
preset->remove_patch(from_pos);
preset->add_patch(patch, to_pos);
_update_current_preset();
}
}
@@ -1026,6 +1096,75 @@ void ProjectExportDialog::_set_file_export_mode(int p_id) {
_propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED);
}
void ProjectExportDialog::_patch_tree_button_clicked(Object *p_item, int p_column, int p_id, int p_mouse_button_index) {
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
patch_index = ti->get_metadata(0);
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
if (p_id == 0) {
Vector<String> preset_patches = current->get_patches();
ERR_FAIL_INDEX(patch_index, preset_patches.size());
patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), preset_patches[patch_index].get_file()));
patch_erase->popup_centered();
} else {
patch_dialog->popup_file_dialog();
}
}
void ProjectExportDialog::_patch_tree_item_edited() {
TreeItem *item = patches->get_edited();
if (!item) {
return;
}
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
int index = item->get_metadata(0);
String patch_path = item->get_text(0);
current->set_patch(index, patch_path);
item->set_tooltip_text(0, patch_path);
}
void ProjectExportDialog::_patch_file_selected(const String &p_path) {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
String relative_path = ProjectSettings::get_singleton()->get_resource_path().path_to_file(p_path);
Vector<String> preset_patches = current->get_patches();
if (patch_index >= preset_patches.size()) {
current->add_patch(relative_path);
} else {
current->set_patch(patch_index, relative_path);
}
_update_current_preset();
}
void ProjectExportDialog::_patch_delete_confirmed() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
Vector<String> preset_patches = current->get_patches();
if (patch_index < preset_patches.size()) {
current->remove_patch(patch_index);
_update_current_preset();
}
}
void ProjectExportDialog::_patch_add_pack_pressed() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
patch_index = current->get_patches().size();
patch_dialog->popup_file_dialog();
}
void ProjectExportDialog::_export_pck_zip() {
Ref<EditorExportPreset> current = get_current_preset();
ERR_FAIL_COND(current.is_null());
@@ -1044,11 +1183,20 @@ void ProjectExportDialog::_export_pck_zip_selected(const String &p_path) {
const Dictionary &fd_option = export_pck_zip->get_selected_options();
bool export_debug = fd_option.get(TTR("Export With Debug"), true);
bool export_as_patch = fd_option.get(TTR("Export As Patch"), true);
if (p_path.ends_with(".zip")) {
platform->export_zip(current, export_debug, p_path);
if (export_as_patch) {
platform->export_zip_patch(current, export_debug, p_path);
} else {
platform->export_zip(current, export_debug, p_path);
}
} else if (p_path.ends_with(".pck")) {
platform->export_pack(current, export_debug, p_path);
if (export_as_patch) {
platform->export_pack_patch(current, export_debug, p_path);
} else {
platform->export_pack(current, export_debug, p_path);
}
} else {
ERR_FAIL_MSG("Path must end with .pck or .zip");
}
@@ -1386,6 +1534,40 @@ ProjectExportDialog::ProjectExportDialog() {
exclude_filters);
exclude_filters->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_filter_changed));
// Patch packages.
VBoxContainer *patch_vb = memnew(VBoxContainer);
sections->add_child(patch_vb);
patch_vb->set_name(TTR("Patches"));
patches = memnew(Tree);
patches->set_v_size_flags(Control::SIZE_EXPAND_FILL);
patches->set_hide_root(true);
patches->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
patches->connect("button_clicked", callable_mp(this, &ProjectExportDialog::_patch_tree_button_clicked));
patches->connect("item_edited", callable_mp(this, &ProjectExportDialog::_patch_tree_item_edited));
SET_DRAG_FORWARDING_GCD(patches, ProjectExportDialog);
patches->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
patch_vb->add_margin_child(TTR("Base Packs:"), patches, true);
patch_dialog = memnew(EditorFileDialog);
patch_dialog->add_filter("*.pck", TTR("Godot Project Pack"));
patch_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
patch_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
patch_dialog->connect("file_selected", callable_mp(this, &ProjectExportDialog::_patch_file_selected));
add_child(patch_dialog);
patch_erase = memnew(ConfirmationDialog);
patch_erase->set_ok_button_text(TTR("Delete"));
patch_erase->connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_patch_delete_confirmed));
add_child(patch_erase);
patch_add_btn = memnew(Button);
patch_add_btn->set_text(TTR("Add Pack"));
patch_add_btn->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
patch_add_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectExportDialog::_patch_add_pack_pressed));
patch_vb->add_child(patch_add_btn);
// Feature tags.
VBoxContainer *feature_vb = memnew(VBoxContainer);
@@ -1569,6 +1751,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_project->add_option(TTR("Export With Debug"), Vector<String>(), true);
export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), true);
export_pck_zip->add_option(TTR("Export As Patch"), Vector<String>(), true);
set_hide_on_ok(false);