Specify plate index for the 3mf workflow (#14404)

feat: forward plateindex for index-coded .gcode.3mf uploads

Gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode) and a
bundle may carry several, so the upload must name which plate to print —
even a single-plate bundle, since its entry is still indexed.

A 1-based plate index is stored in PrintHostUpload::extended_info when use_3mf
is set; the OctoPrint and Moonraker hosts forward it as a `plateindex` form
field. Servers that don't use it ignore the unknown field, so the plain G-code
path is unchanged.
This commit is contained in:
SoftFever
2026-06-25 22:02:19 +08:00
committed by GitHub
parent 0c5d85e516
commit 688127af5b
4 changed files with 54 additions and 16 deletions

View File

@@ -16117,6 +16117,8 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
const bool use_3mf = use_3mf_opt != nullptr && use_3mf_opt->value;
upload_job.upload_data.use_3mf = use_3mf;
// Orca: the concrete plate to export/send (PLATE_CURRENT_IDX resolves to the current plate).
const int resolved_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
// Obtain default output path
fs::path default_output_file;
@@ -16206,7 +16208,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config();
const auto* filament_color = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_colour"));
const auto* filament_id_opt = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_ids"));
const int resolved_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
auto enrich_project_filaments = [&](std::vector<FilamentInfo>& filaments) {
for (auto& filament : filaments) {
if (filament.id < 0)
@@ -16272,6 +16273,15 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
upload_job.upload_data.group = pDlg->group();
upload_job.upload_data.storage = pDlg->storage();
upload_job.upload_data.extended_info = pDlg->extendedInfo();
// Orca: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode) and a bundle may
// carry several of them, so the upload must name which plate to print via a 1-based plateindex.
// Even a single-plate bundle needs it, since its gcode entry is still indexed. The host upload
// forwards the field and servers that don't use it ignore it. "All plates" points at the
// current plate — the bundle still carries every plate's gcode.
if (use_3mf) {
const int plateindex = (plate_idx == PLATE_ALL_IDX ? get_partplate_list().get_curr_plate_index() : resolved_plate_idx) + 1;
upload_job.upload_data.extended_info["plateindex"] = std::to_string(plateindex);
}
}
// Show "Is printer clean" dialog for PrusaConnect - Upload and print.
@@ -16283,8 +16293,7 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
if (use_3mf) {
// Process gcode
const int export_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
const int result = send_gcode(export_plate_idx, nullptr);
const int result = send_gcode(resolved_plate_idx, nullptr);
if (result < 0) {
wxString msg = _L("Abnormal print file data. Please slice again");