Fix plugin configuration not taking effect, and improve the plugin config UI (#14944)

# Description

Changing a slicing plugin's configuration had no effect on the sliced
result until you forced a re-slice some other way; it now applies
immediately. Print, printer and filament presets also keep their plugin
configuration separately, so configuring a plugin on one no longer wipes
out what you set on another.

A plugin's custom configuration page gets the same round of improvements
in both the Plugins dialog and the per-preset dialog: it follows the
app's light/dark theme, keeps its state while you edit instead of
resetting under the cursor, and can tell whether it is being edited
globally or for a preset, so "Restore defaults" can be labeled for what
it will actually do. The two bundled examples show this off — Twistify
now ships a custom configuration UI, and Inspector is themed, groups

# Screenshots/Recordings/Graphs



https://github.com/user-attachments/assets/02ca062a-5143-49a3-abe0-a2a040b3a928



## Tests

<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->

<!--
> A guide for users on how to download the artifacts from this PR.
-->

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
This commit is contained in:
SoftFever
2026-07-25 20:00:56 +08:00
committed by GitHub
parent d6cb667b89
commit 9a72dda79a
18 changed files with 1202 additions and 408 deletions

View File

@@ -218,10 +218,24 @@ TEST_CASE("Changing slicing_pipeline_plugin invalidates posSlice", "[slicing_pip
CHECK_FALSE(print.objects().front()->is_step_done(posSlice)); // re-slice required
}
// Editing a slicing plugin's config (print_plugin_config_overrides) must re-run posSlice, where the
// plugin transforms each layer's geometry; otherwise the cached slice keeps the old config's result.
TEST_CASE("Changing print_plugin_config_overrides invalidates posSlice", "[slicing_pipeline]") {
Slic3r::Print print; Slic3r::Model model;
auto config = Slic3r::DynamicPrintConfig::full_print_config();
init_print({cube(20)}, print, model, config);
print.process();
REQUIRE(print.objects().front()->is_step_done(posSlice));
config.set_key_value("print_plugin_config_overrides",
new Slic3r::ConfigOptionString("[{\"type\":\"slicing-pipeline\",\"name\":\"Twistify\",\"config\":{\"twist_deg_per_mm\":2.0}}]"));
print.apply(model, config);
CHECK_FALSE(print.objects().front()->is_step_done(posSlice)); // re-slice required
}
#include <catch2/matchers/catch_matchers_floating_point.hpp>
// A similarity transform (rotate + uniform scale) applied to slices at Step.posSlice, matching
// what the Twistify sample (sandboxes/orca_twistify_plugin_example_any.py) does. This C++ analogue
// what the Twistify plugin (sandboxes/orca_twistify_plugin_any.py) does. This C++ analogue
// rotates every region's slices a fixed 45 deg about the object's base-footprint center -- the same
// seam and cascade the sample drives through the slices.set() + Layer::make_slices() path. Two
// end-to-end invariants after process() confirm the approach: