mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-27 04:42:33 +00:00
feat(plugin)!: merge G-code post-processing into the slicing pipeline as psGCodePostProcess
G-code post-processing is now a step of the slicing-pipeline plugin rather than a separate capability type. One capability class can transform slices at the geometry seams AND edit the final G-code, behind a single picker/option. - Add SlicingPipelineStepPlugin::psGCodePostProcess (bound as orca.slicing.Step.psGCodePostProcess). Unlike the geometry steps it fires from the GUI export path in PostProcessor.cpp, not from Print::process(): ctx.print/ctx.object are None and the plugin edits the file at ctx.gcode_path in place. It may run more than once per slice (file export and/or upload) and its output is not shown in the preview. - Extend SlicingPipelineContext with gcode_path/host/output_name and a C++-only full_config; config_value() falls back to it when there is no live Print. - PostProcessor.cpp dispatches SlicingPipelinePluginCapability at psGCodePostProcess, driven by the existing slicing_pipeline_plugin option. - The exported G-code lives outside data_dir(), so the plugin audit sandbox would block the write; the trampoline's audit setup grants ctx.gcode_path's folder as a scoped allowed root, gated on a non-empty gcode_path so the geometry-step hooks gain no extra filesystem access. BREAKING CHANGE: the separate G-code post-processing capability type is removed. - orca.gcode.GCodePluginCapabilityBase and orca.PluginType.PostProcessing are gone; post-processing plugins migrate to orca.slicing.SlicingPipelineCapabilityBase + Step.psGCodePostProcess (and gain ctx.params / ctx.config_value()). - The post_process_plugin config option is removed; use slicing_pipeline_plugin. Presets carrying the old key degrade to the standard unknown-key warning. - Manifest type = "post-processing" now maps to Unknown (advisory only; the loader dispatches on the C++ get_type()). Also repairs two latent build breaks the branch carried: stale Step enum value usages in test_slicing_pipeline_hook.cpp and a reference to the removed ConfigOptionDef::PluginType::None in Tab::on_value_change (now is_plugin_backed()). Adds the orca_gcode_stamp sample plugin and a psGCodePostProcess binding test.
This commit is contained in:
@@ -44,20 +44,22 @@ TEST_CASE("SlicingPipeline hook fires once per step per object in order", "[slic
|
||||
|
||||
using S = Slic3r::SlicingPipelineStepPlugin;
|
||||
auto count = [&](S s){ return std::count_if(calls.begin(), calls.end(), [&](const Call& c){ return c.step == s; }); };
|
||||
CHECK(count(S::Slice) == 1);
|
||||
CHECK(count(S::Perimeters) == 1);
|
||||
CHECK(count(S::PrepareInfill) == 1); // the prepare-infill seam fires once per object
|
||||
CHECK(count(S::Infill) == 1);
|
||||
CHECK(count(S::WipeTower) == 1);
|
||||
CHECK(count(S::SkirtBrim) == 1);
|
||||
CHECK(count(S::posSlice) == 1);
|
||||
CHECK(count(S::posPerimeters) == 1);
|
||||
CHECK(count(S::posPrepareInfill) == 1); // the prepare-infill seam fires once per object
|
||||
CHECK(count(S::posInfill) == 1);
|
||||
CHECK(count(S::psWipeTower) == 1);
|
||||
CHECK(count(S::psSkirtBrim) == 1);
|
||||
// psGCodePostProcess fires from the GUI export path, never from process():
|
||||
CHECK(count(S::psGCodePostProcess) == 0);
|
||||
// print-wide steps carry a null object:
|
||||
for (const auto& c : calls)
|
||||
if (c.step == S::WipeTower || c.step == S::SkirtBrim) CHECK(c.obj == nullptr);
|
||||
if (c.step == S::psWipeTower || c.step == S::psSkirtBrim) CHECK(c.obj == nullptr);
|
||||
// Slice must fire before Perimeters for the same object:
|
||||
auto idx = [&](S s){ for (size_t i=0;i<calls.size();++i) if (calls[i].step==s) return (int)i; return -1; };
|
||||
CHECK(idx(S::Slice) < idx(S::Perimeters));
|
||||
CHECK(idx(S::Perimeters) < idx(S::PrepareInfill)); // prepare-infill fires after perimeters...
|
||||
CHECK(idx(S::PrepareInfill) < idx(S::Infill)); // ...and before the fills are built
|
||||
CHECK(idx(S::posSlice) < idx(S::posPerimeters));
|
||||
CHECK(idx(S::posPerimeters) < idx(S::posPrepareInfill)); // prepare-infill fires after perimeters...
|
||||
CHECK(idx(S::posPrepareInfill) < idx(S::posInfill)); // ...and before the fills are built
|
||||
}
|
||||
|
||||
#include <sstream>
|
||||
@@ -418,10 +420,10 @@ TEST_CASE("fill_surfaces mutation cascades at PrepareInfill but not at Infill",
|
||||
return n;
|
||||
};
|
||||
using S = Slic3r::SlicingPipelineStepPlugin;
|
||||
const size_t base = fill_paths(false, S::PrepareInfill); // active hook, no mutation
|
||||
const size_t base = fill_paths(false, S::posPrepareInfill); // active hook, no mutation
|
||||
CHECK(base > 0);
|
||||
CHECK(fill_paths(true, S::PrepareInfill) < base); // mutation before make_fills cascades
|
||||
CHECK(fill_paths(true, S::Infill) == base); // mutation after make_fills is a no-op (v1)
|
||||
CHECK(fill_paths(true, S::posPrepareInfill) < base); // mutation before make_fills cascades
|
||||
CHECK(fill_paths(true, S::posInfill) == base); // mutation after make_fills is a no-op (v1)
|
||||
}
|
||||
|
||||
// lslices (the layer's merged islands) are built once in slice() and never rebuilt by
|
||||
|
||||
Reference in New Issue
Block a user