diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3262d3fe021..c6019e51f4c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -16114,6 +16114,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; @@ -16203,7 +16205,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn) DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config(); const auto* filament_color = dynamic_cast(cfg.option("filament_colour")); const auto* filament_id_opt = dynamic_cast(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& filaments) { for (auto& filament : filaments) { if (filament.id < 0) @@ -16269,6 +16270,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_.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. @@ -16280,8 +16290,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"); diff --git a/src/slic3r/Utils/Moonraker.cpp b/src/slic3r/Utils/Moonraker.cpp index 33a0960426f..f1ca4323901 100644 --- a/src/slic3r/Utils/Moonraker.cpp +++ b/src/slic3r/Utils/Moonraker.cpp @@ -237,18 +237,26 @@ bool Moonraker::upload(PrintHostUpload upload_data, ProgressFn progress_fn, Erro bool result = true; std::string uploaded_path; - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% to %3% (root=%4%, filename=%5%, start_print=%6%)") + //ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_.gcode), so the upload names the + // plate via a 1-based `plateindex` (set only in the .3mf path, see Plater::send_gcode_legacy); + // servers that don't use it ignore the unknown form field. + const std::string plateindex = upload_data.extended("plateindex"); + + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% to %3% (root=%4%, filename=%5%, plateindex=%6%, start_print=%7%)") % name % upload_data.source_path % url % root % upload_filename.string() + % (plateindex.empty() ? "-" : plateindex) % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); auto http = Http::post(std::move(url)); set_auth(http); - http.form_add("root", root) - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) + http.form_add("root", root); + if (!plateindex.empty()) + http.form_add("plateindex", plateindex); + http.form_add_file("file", upload_data.source_path.string(), upload_filename.string()) .on_complete([&](std::string body, unsigned status) { BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: upload HTTP %2%: %3%") % name % status % body; try { diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index cfae9babdce..fa57b7b5275 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -345,13 +345,15 @@ bool OctoPrint::upload_inner_with_resolved_ip(PrintHostUpload upload_data, Progr info_fn(L"resolve", boost::nowide::widen(url)); - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") + const std::string plateindex = upload_data.extended("plateindex"); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, plateindex: %7%") % name % upload_data.source_path % url % upload_filename.string() % upload_parent_path.string() - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") + % (plateindex.empty() ? "-" : plateindex); auto http = Http::post(url);//std::move(url)); // "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable. @@ -362,8 +364,13 @@ bool OctoPrint::upload_inner_with_resolved_ip(PrintHostUpload upload_data, Progr http.header("Host", Http::get_host_header_value(m_host)); set_auth(http); http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") - .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) + .form_add("path", upload_parent_path.string()); // XXX: slashes on windows ??? + //ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_.gcode), so the upload names the + // plate via a 1-based `plateindex` (see Plater::send_gcode_legacy); servers that don't use it + // ignore the unknown form field. + if (!plateindex.empty()) + http.form_add("plateindex", plateindex); + http.form_add_file("file", upload_data.source_path.string(), upload_filename.string()) .on_complete([&](std::string body, unsigned status) { BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; @@ -429,13 +436,15 @@ bool OctoPrint::upload_inner_with_host(PrintHostUpload upload_data, ProgressFn p } #endif // _WIN32 - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") + const std::string plateindex = upload_data.extended("plateindex"); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, plateindex: %7%") % name % upload_data.source_path % url % upload_filename.string() % upload_parent_path.string() - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); + % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") + % (plateindex.empty() ? "-" : plateindex); auto http = Http::post(std::move(url)); #ifdef WIN32 @@ -449,8 +458,13 @@ bool OctoPrint::upload_inner_with_host(PrintHostUpload upload_data, ProgressFn p #endif // _WIN32 set_auth(http); http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") - .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) + .form_add("path", upload_parent_path.string()); // XXX: slashes on windows ??? + //ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_.gcode), so the upload names the + // plate via a 1-based `plateindex` (see Plater::send_gcode_legacy); servers that don't use it + // ignore the unknown form field. + if (!plateindex.empty()) + http.form_add("plateindex", plateindex); + http.form_add_file("file", upload_data.source_path.string(), upload_filename.string()) .on_complete([&](std::string body, unsigned status) { BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; }) diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp index 2b0611849d2..87a8df89349 100644 --- a/src/slic3r/Utils/PrintHost.hpp +++ b/src/slic3r/Utils/PrintHost.hpp @@ -29,10 +29,10 @@ ENABLE_ENUM_BITMASK_OPERATORS(PrintHostPostUploadAction); struct PrintHostUpload { - bool use_3mf; + bool use_3mf { false }; boost::filesystem::path source_path; boost::filesystem::path upload_path; - + std::string group; std::string storage; @@ -40,6 +40,13 @@ struct PrintHostUpload // Some extended parameters for different upload methods. std::map extended_info; + + // Safe accessor for an extended_info entry; returns `def` when the key is absent. + std::string extended(const std::string &key, const std::string &def = {}) const + { + auto it = extended_info.find(key); + return it != extended_info.end() ? it->second : def; + } }; class PrintHost