mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-25 03:42:05 +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:
@@ -410,14 +410,14 @@ TEST_CASE("save_to_json round-trips plugin capability references as strings", "[
|
||||
namespace fs = boost::filesystem;
|
||||
const fs::path tmp = fs::temp_directory_path() / fs::unique_path("orca_plugins_%%%%-%%%%.json");
|
||||
const std::vector<std::string> refs = {
|
||||
"local_plugin;;post_process",
|
||||
"cloud_plugin;550e8400-e29b-41d4-a716-446655440000;post_process"
|
||||
"local_plugin;;inset",
|
||||
"cloud_plugin;550e8400-e29b-41d4-a716-446655440000;inset"
|
||||
};
|
||||
|
||||
std::unique_ptr<DynamicPrintConfig> config_ptr(
|
||||
DynamicPrintConfig::new_from_defaults_keys({"post_process_plugin"}));
|
||||
DynamicPrintConfig::new_from_defaults_keys({"slicing_pipeline_plugin"}));
|
||||
DynamicPrintConfig config = std::move(*config_ptr);
|
||||
config.option<ConfigOptionStrings>("post_process_plugin", true)->values = refs;
|
||||
config.option<ConfigOptionStrings>("slicing_pipeline_plugin", true)->values = refs;
|
||||
config.save_to_json(tmp.string(), "test_preset", "User", "1.0.0.0");
|
||||
|
||||
nlohmann::json j;
|
||||
@@ -425,7 +425,7 @@ TEST_CASE("save_to_json round-trips plugin capability references as strings", "[
|
||||
boost::nowide::ifstream ifs(tmp.string());
|
||||
ifs >> j;
|
||||
}
|
||||
REQUIRE(j["post_process_plugin"] == nlohmann::json(refs));
|
||||
REQUIRE(j["slicing_pipeline_plugin"] == nlohmann::json(refs));
|
||||
CHECK_FALSE(j.contains("plugins"));
|
||||
|
||||
DynamicPrintConfig reloaded = DynamicPrintConfig::full_print_config();
|
||||
@@ -434,7 +434,7 @@ TEST_CASE("save_to_json round-trips plugin capability references as strings", "[
|
||||
std::string reason;
|
||||
REQUIRE(reloaded.load_from_json(tmp.string(), substitutions, true, key_values, reason) == 0);
|
||||
CHECK(reason.empty());
|
||||
CHECK(reloaded.option<ConfigOptionStrings>("post_process_plugin")->values == refs);
|
||||
CHECK(reloaded.option<ConfigOptionStrings>("slicing_pipeline_plugin")->values == refs);
|
||||
|
||||
fs::remove(tmp);
|
||||
}
|
||||
@@ -446,17 +446,17 @@ TEST_CASE("plugin capability references survive string-map serialization", "[Con
|
||||
};
|
||||
|
||||
DynamicPrintConfig original = DynamicPrintConfig::full_print_config();
|
||||
original.option<ConfigOptionStrings>("post_process_plugin", true)->values = refs;
|
||||
original.option<ConfigOptionStrings>("slicing_pipeline_plugin", true)->values = refs;
|
||||
|
||||
std::map<std::string, std::string> serialized{
|
||||
{"post_process_plugin", original.option<ConfigOptionStrings>("post_process_plugin")->serialize()}
|
||||
{"slicing_pipeline_plugin", original.option<ConfigOptionStrings>("slicing_pipeline_plugin")->serialize()}
|
||||
};
|
||||
CHECK(serialized["post_process_plugin"].find("\"master_plugin;;header-stamp\"") != std::string::npos);
|
||||
CHECK(serialized["slicing_pipeline_plugin"].find("\"master_plugin;;header-stamp\"") != std::string::npos);
|
||||
|
||||
DynamicPrintConfig reloaded = DynamicPrintConfig::full_print_config();
|
||||
reloaded.load_string_map(serialized, ForwardCompatibilitySubstitutionRule::Disable);
|
||||
|
||||
CHECK(reloaded.option<ConfigOptionStrings>("post_process_plugin")->values == refs);
|
||||
CHECK(reloaded.option<ConfigOptionStrings>("slicing_pipeline_plugin")->values == refs);
|
||||
}
|
||||
|
||||
TEST_CASE("parse_capability_ref parses local and cloud references", "[Config][plugin]") {
|
||||
@@ -502,14 +502,13 @@ struct PluginResolverFixture {
|
||||
TEST_CASE_METHOD(PluginResolverFixture,
|
||||
"update_plugin_manifest derives references generically from plugin-backed options",
|
||||
"[Config][plugins]") {
|
||||
// Both scalar (printer_agent) and vector (post_process_plugin, slicing_pipeline_plugin) options
|
||||
// opt in via a non-empty ConfigOptionDef::plugin_type (is_plugin_backed) and are resolved with it
|
||||
// -- there is no hardcoded per-option switch. printer_agent in particular relies on its plugin_type
|
||||
// metadata being wired up (it is edited via a dedicated widget, not the plugin_picker).
|
||||
// Both scalar (printer_agent) and vector (slicing_pipeline_plugin) options opt in via a non-empty
|
||||
// ConfigOptionDef::plugin_type (is_plugin_backed) and are resolved with it -- there is no hardcoded
|
||||
// per-option switch. printer_agent in particular relies on its plugin_type metadata being wired up
|
||||
// (it is edited via a dedicated widget, not the plugin_picker).
|
||||
std::unique_ptr<DynamicPrintConfig> config_ptr(DynamicPrintConfig::new_from_defaults_keys(
|
||||
{"post_process_plugin", "slicing_pipeline_plugin", "printer_agent"}));
|
||||
{"slicing_pipeline_plugin", "printer_agent"}));
|
||||
DynamicPrintConfig config = std::move(*config_ptr);
|
||||
config.option<ConfigOptionStrings>("post_process_plugin", true)->values = {"pp"};
|
||||
config.option<ConfigOptionStrings>("slicing_pipeline_plugin", true)->values = {"sp"};
|
||||
config.option<ConfigOptionString>("printer_agent", true)->value = "agent";
|
||||
|
||||
@@ -517,23 +516,22 @@ TEST_CASE_METHOD(PluginResolverFixture,
|
||||
const std::vector<std::string> manifest = config.option<ConfigOptionStrings>("plugins")->values;
|
||||
|
||||
using Catch::Matchers::VectorContains;
|
||||
REQUIRE_THAT(manifest, VectorContains(std::string("pp;;post-processing")));
|
||||
REQUIRE_THAT(manifest, VectorContains(std::string("sp;;slicing-pipeline")));
|
||||
REQUIRE_THAT(manifest, VectorContains(std::string("agent;;printer-connection")));
|
||||
CHECK(manifest.size() == 3);
|
||||
CHECK(manifest.size() == 2);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(PluginResolverFixture,
|
||||
"update_plugin_manifest de-duplicates references and skips unset options",
|
||||
"[Config][plugins]") {
|
||||
std::unique_ptr<DynamicPrintConfig> config_ptr(DynamicPrintConfig::new_from_defaults_keys(
|
||||
{"post_process_plugin", "printer_agent"}));
|
||||
{"slicing_pipeline_plugin", "printer_agent"}));
|
||||
DynamicPrintConfig config = std::move(*config_ptr);
|
||||
config.option<ConfigOptionStrings>("post_process_plugin", true)->values = {"x", "x"}; // duplicate
|
||||
config.option<ConfigOptionStrings>("slicing_pipeline_plugin", true)->values = {"x", "x"}; // duplicate
|
||||
// printer_agent stays at its default empty value -> contributes nothing to the manifest.
|
||||
|
||||
config.update_plugin_manifest();
|
||||
const std::vector<std::string> manifest = config.option<ConfigOptionStrings>("plugins")->values;
|
||||
|
||||
CHECK(manifest == std::vector<std::string>{"x;;post-processing"});
|
||||
CHECK(manifest == std::vector<std::string>{"x;;slicing-pipeline"});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user