Extend Publish workflow with full-filament and type/color requirements

Per material slot, the Publish dialog can now embed the entire filament preset ("Full Publish") and require a curated filament type and/or colour:

- On export, full-publish vector options are masked to the author's slot so unrelated slot data never leaks into the published file.

- On load, slots are matched by the published type: a match keeps the receiver's material (full dumps ignored, partial keys applied); a mismatch replaces the slot with the first visible same-type library filament, falling back to a temporary embedded preset or skipped keys when none exists. Required colours apply regardless of the type match.

- The receiver's slot count grows only to the highest published slot.

- Published 3MFs load as a new project: the file's path is not adopted as the project filename, published metadata is stripped from the model, and the file is added to recent projects.

- Notifications list replaced slots, and the edited filament preset is refreshed so applied values surface in the GUI.

- Dialog: "Full Publish" toggle replaces the material opt-in and select-all headers; new Color/Type requirement rows with swatches.

- Add Ctrl+Shift+E shortcut for the Publish dialog (menu, key handling, and the keyboard shortcuts dialog).

- Tests for export slot masking, metadata round-trip, replacement semantics, slot growth, and skipped-key reporting.
This commit is contained in:
Lam Wei Lun
2026-08-18 13:49:10 +08:00
parent 2b18744cc2
commit 6c429059e0
13 changed files with 1037 additions and 135 deletions
+17 -8
View File
@@ -741,6 +741,10 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
if (m_plater) { m_plater->add_file(); }
return;
}
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'E') {
if (can_export_model()) publish_project();
return;
}
evt.Skip();
});
@@ -1728,6 +1732,16 @@ bool MainFrame::save_project_as(const wxString& filename)
return ret;
}
void MainFrame::publish_project()
{
if (m_plater == nullptr)
return;
PublishSettingsDialog dlg(this);
if (dlg.ShowModal() != wxID_OK)
return;
m_plater->export_published_3mf(dlg.GetPublishedKeys(), dlg.GetPublishedMaterialKeys());
}
bool MainFrame::can_upload() const
{
return true;
@@ -2820,19 +2834,14 @@ void MainFrame::init_menubar_as_editor()
// BBS: publish
fileMenu->AppendSeparator();
auto publish_handler = [this](wxCommandEvent&) {
if (!m_plater) return;
PublishSettingsDialog dlg(this);
if (dlg.ShowModal() != wxID_OK) return;
m_plater->export_published_3mf(dlg.GetPublishedKeys(), dlg.GetPublishedMaterialKeys());
};
auto publish_handler = [this](wxCommandEvent&) { publish_project(); };
#ifndef __APPLE__
append_menu_item(fileMenu, wxID_ANY, _L("Publish") + dots, _L("Export a 3MF file with the selected settings embedded"),
append_menu_item(fileMenu, wxID_ANY, _L("Publish") + dots + "\t" + ctrl + shift + "E", _L("Export a 3MF file with the selected settings embedded"),
publish_handler, "menu_publish", nullptr,
[this](){return can_export_model(); }, this);
#else
append_menu_item(fileMenu, wxID_ANY, _L("Publish") + dots, _L("Export a 3MF file with the selected settings embedded"),
append_menu_item(fileMenu, wxID_ANY, _L("Publish") + dots + "\t" + ctrl + shift + "E", _L("Export a 3MF file with the selected settings embedded"),
publish_handler, "", nullptr,
[this](){return can_export_model(); }, this);
#endif