From f0c59208e7a31e628a9b84567754e22a0bedac73 Mon Sep 17 00:00:00 2001 From: Sergei <119299827+ghzserg@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:47:03 +0500 Subject: [PATCH] Apply post-processing scripts to G-code packed into .gcode.3mf (non-BBL) (#16464) Post-processing scripts now run on a copy of each sliced plate's G-code before it is packed into a .gcode.3mf. This covers Export plate sliced file, sending a .3mf to a print host, and the print dialog for non-BBL printers. BBL printers are skipped, because their G-code is post-processed in place after slicing. Backups are skipped too. Export plate sliced file no longer reports success when export_3mf() fails. --- src/slic3r/GUI/Plater.cpp | 46 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d395fe104c..058eae58ba 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -228,6 +228,7 @@ #include "Jobs/PlaterWorker.hpp" #include "Jobs/BoostThreadWorker.hpp" #include "BackgroundSlicingProcess.hpp" +#include "PostProcessor.hpp" #include "SelectMachine.hpp" #include "SendMultiMachinePage.hpp" #include "SendToPrinter.hpp" @@ -19572,7 +19573,11 @@ void Plater::export_gcode_3mf(bool export_all) SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SplitModel | SaveStrategy::WithGcode | SaveStrategy::SkipModel; // BBS: silence if (wxGetApp().app_config->get_bool("export_statistics")) strategy = strategy | SaveStrategy::WithStatistics; - export_3mf(output_path, strategy, plate_idx); + if (export_3mf(output_path, strategy, plate_idx) < 0) { + // No file was written (e.g. a post-processing script failed), don't report a successful export. + p->exporting_status = ExportingStatus::NOT_EXPORTING; + return; + } RemovableDriveManager& removable_drive_manager = *wxGetApp().removable_drive_manager(); @@ -20429,6 +20434,45 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy p->partplate_list.store_to_3mf_structure(plate_data_list, (strategy & SaveStrategy::WithGcode || strategy & SaveStrategy::WithSliceInfo), export_plate_idx, strategy & SaveStrategy::WithStatistics); + // Orca: non-BBL G-code isn't post-processed in place, so run the scripts on a copy before packing it. + std::vector pp_tmp_files; + ScopeGuard remove_pp_tmp_files([&pp_tmp_files]() { + for (const std::string& f : pp_tmp_files) { + boost::system::error_code ec; + boost::filesystem::remove(f, ec); + } + }); + + // Backups (SkipStatic) don't pack G-code, so don't run user scripts for them. + if ((strategy & SaveStrategy::WithGcode) && !(strategy & SaveStrategy::SkipStatic) && + p->printer_technology == ptFFF && !wxGetApp().preset_bundle->is_bbl_vendor()) { + try { + for (PlateData* pd : plate_data_list) { + if (pd == nullptr || pd->gcode_file.empty()) + continue; + PartPlate* plate = p->partplate_list.get_plate(pd->plate_index); + if (plate == nullptr) + continue; + PrintBase* print = nullptr; + plate->get_print(&print, nullptr, nullptr); + Print* fff_print = dynamic_cast(print); + if (fff_print == nullptr) + continue; + + std::string src_path = pd->gcode_file; // in/out: becomes the post-processed copy if a script ran + std::string output_name = path_u8; // scripts see the real target; a rename is ignored for 3mf + if (run_post_process_scripts(src_path, true, "File", output_name, fff_print->full_print_config())) { + pp_tmp_files.push_back(src_path); + pd->gcode_file = src_path; + } + } + } catch (const std::exception& ex) { + release_PlateData_list(plate_data_list); + show_error(this, ex.what(), false); + return -1; + } + } + // BBS: backup PresetBundle& preset_bundle = *wxGetApp().preset_bundle; std::vector project_presets = preset_bundle.get_current_project_embedded_presets();