Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 50 additions & 31 deletions src/libslic3r/GCode/PostProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,18 @@ void gcode_add_line_number(const std::string& path, const DynamicPrintConfig& co
// The post-processing script may change the output_name.
bool run_post_process_scripts(std::string &src_path, bool make_copy, const std::string &host, std::string &output_name, const DynamicPrintConfig &config)
{
// Get both print-level and printer-level post-processing scripts
const auto *post_process = config.opt<ConfigOptionStrings>("post_process");
if (// likely running in SLA mode
post_process == nullptr ||
// no post-processing script
post_process->values.empty())
const auto *printer_post_process = config.opt<ConfigOptionStrings>("printer_post_process");

// Check if we have any post-processing scripts to run
bool has_print_scripts = (post_process != nullptr && !post_process->values.empty());
bool has_printer_scripts = (printer_post_process != nullptr && !printer_post_process->values.empty());

if (!has_print_scripts && !has_printer_scripts) {
// No post-processing scripts defined
return false;
}

std::string path;
if (make_copy) {
Expand Down Expand Up @@ -301,35 +307,48 @@ bool run_post_process_scripts(std::string &src_path, bool make_copy, const std::
remove_output_name_file();

try {
for (const std::string &scripts : post_process->values) {
std::vector<std::string> lines;
boost::split(lines, scripts, boost::is_any_of("\r\n"));
for (std::string script : lines) {
// Ignore empty post processing script lines.
boost::trim(script);
if (script.empty())
continue;
BOOST_LOG_TRIVIAL(info) << "Executing script " << script << " on file " << path;
std::string std_err;
const int result = run_script(script, gcode_file.string(), std_err);
if (result != 0) {
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
BOOST_LOG_TRIVIAL(error) << msg;
delete_copy();
throw Slic3r::RuntimeError(msg);
}
if (! boost::filesystem::exists(gcode_file)) {
const std::string msg = (boost::format(_(L(
"Post-processing script %1% failed.\n\n"
"The post-processing script is expected to change the G-code file %2% in place, but the G-code file was deleted and likely saved under a new name.\n"
"Please adjust the post-processing script to change the G-code in place and consult the manual on how to optionally rename the post-processed G-code file.\n")))
% script % path).str();
BOOST_LOG_TRIVIAL(error) << msg;
throw Slic3r::RuntimeError(msg);
// Helper function to execute a set of post-processing scripts
auto execute_scripts = [&](const ConfigOptionStrings* scripts_config, const std::string& script_type) {
if (scripts_config == nullptr || scripts_config->values.empty()) {
return;
}

for (const std::string &scripts : scripts_config->values) {
std::vector<std::string> lines;
boost::split(lines, scripts, boost::is_any_of("\r\n"));
for (std::string script : lines) {
// Ignore empty post processing script lines.
boost::trim(script);
if (script.empty())
continue;
BOOST_LOG_TRIVIAL(info) << "Executing " << script_type << " script " << script << " on file " << path;
std::string std_err;
const int result = run_script(script, gcode_file.string(), std_err);
if (result != 0) {
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
BOOST_LOG_TRIVIAL(error) << msg;
delete_copy();
throw Slic3r::RuntimeError(msg);
}
if (! boost::filesystem::exists(gcode_file)) {
const std::string msg = (boost::format(_(L(
"Post-processing script %1% failed.\n\n"
"The post-processing script is expected to change the G-code file %2% in place, but the G-code file was deleted and likely saved under a new name.\n"
"Please adjust the post-processing script to change the G-code in place and consult the manual on how to optionally rename the post-processed G-code file.\n")))
% script % path).str();
BOOST_LOG_TRIVIAL(error) << msg;
throw Slic3r::RuntimeError(msg);
}
}
}
}
};

// Execute printer-level post-processing scripts first
execute_scripts(printer_post_process, "printer-level");

// Then execute print-level post-processing scripts
execute_scripts(post_process, "print-level");
if (boost::filesystem::exists(path_output_name)) {
try {
// Read a single line from path_output_name, which should contain the new output name of the post-processed G-code.
Expand Down
14 changes: 14 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2704,6 +2704,20 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(0));

def = this->add("printer_post_process", coStrings);
def->label = L("Printer Post-processing Scripts");
def->tooltip = L("If you want to process the output G-code through custom scripts specific to this printer, "
"just list their absolute paths here. Separate multiple scripts with a semicolon. "
"Scripts will be passed the absolute path to the G-code file as the first argument, "
"and they can access the Orca Slicer config settings by reading environment variables. "
"These scripts will run in addition to any print-level post-processing scripts.");
def->gui_flags = "serialized";
def->multiline = true;
def->full_width = true;
def->height = 6;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings());

//BBS
def = this->add("infill_combination", coBool);
def->label = L("Infill combination");
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionPoint, bed_mesh_max))
((ConfigOptionPoint, bed_mesh_probe_distance))
((ConfigOptionFloat, adaptive_bed_mesh_margin))
((ConfigOptionStrings, printer_post_process))


)
Expand Down
7 changes: 7 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3864,6 +3864,13 @@ void TabPrinter::build_fff()
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);

optgroup = page->new_optgroup(L("Post-processing Scripts"), L"param_gcode", 0);
option = optgroup->get_option("printer_post_process");
option.opt.full_width = true;
option.opt.is_code = true;
option.opt.height = 15;
optgroup->append_single_option_line(option);

page = add_options_page(L("Notes"), "custom-gcode_note"); // ORCA: icon only visible on placeholders
optgroup = page->new_optgroup(L("Notes"), "note", 0);
option = optgroup->get_option("printer_notes");
Expand Down
Loading