* fix(GUI): honor "Ignore" when layer height exceeds the configured maximum
Entering a layer height above the printer's max_layer_height on the Print
Settings tab fired two guards in sequence. Tab::on_value_change prompts
"...Adjust to the set range automatically?" with an Adjust/Ignore choice, and
ConfigManipulation::update_print_fff_config then showed an OK-only "Too large
layer height. Reset to X" dialog whose result was never checked, so it always
reset the value. The second guard overrode the user's "Ignore", resetting the
layer height regardless.
Changes:
- Extract the shared Adjust/Ignore dialog into
ConfigManipulation::layer_height_out_of_range_dialog, reused by the tab
(Tab::on_value_change) and the per-object/part settings panels. The dialog now
names the value it will clamp to and reads correctly for too-low as well as
too-high.
- The tab/plate path is already covered by Tab::on_value_change, so the
duplicate reset is dropped from update_print_fff_config.
- The per-object/part panels have no on_value_change hook, so add
ConfigManipulation::check_object_layer_height and call it from the object
settings update paths, gated on the edited option (changed_opt_key ==
"layer_height"). It prompts once per layer-height edit and does not re-prompt
when unrelated object settings change after the user chose "Ignore".
Fixes#14214
* refactor(GUI): unify the layer-height range check across tab and object panels
Copilot review of #14369 noted that the per-object check only guarded the
max at extruder 0 and skipped the too-low case, diverging from the tab.
Move the whole range check into ConfigManipulation::check_layer_height,
used by both Tab::on_value_change and the per-object/part panels. It takes
the widest [min, max] window across the printer's extruders, offers
Adjust/Ignore in both directions, and resets a near-zero value. The tab's
inline block collapses to one call, dropping the duplicated limit logic.
* fix(GUI): only enforce layer-height limits that are actually set
max_layer_height defaults to 0 (unset), so the unconditional range check
offered to clamp any layer height to 0 on presets that don't define it.
Guard each branch (near-zero, too-high, too-low) so an unset limit disables
that direction; the slice-time nozzle-diameter check still applies.
Also run check_layer_height before update_print_fff_config in the object
panels so a near-zero per-object value prompts the same way the tab does,
with update_print_fff_config's fallback still covering the no-minimum case.
Adds a printer option that picks up the new tool without a blocking temperature
wait, travels to the wipe tower, and waits there right before purging, parked
beside the tower so the ooze from the heat-up lands next to it rather than on the
model. The incoming filament's target is raised ahead of the tool change, so the
heat-up overlaps both the change itself and the travel to the tower.
Off by default, and only offered for multi-extruder printers using a Type 2 wipe
tower; the generic toolchanger profile enables it.
* update snapmaker profiles. largely ported for Snapmaker Orca fork
* update prime volume
* set precise_outer_wall to 1
* Update per-material multi-tool ramming to the filament library
* Add per-filament overrides for toolchange retraction
* Set toolchange retraction per filament for Snapmaker U1
* set default support type to tree
* format snapmaker profiles
set_live_printer_agent centralizes
the swap: deselect the machine,
clear stale sidebar state and the
previous agent's Other Devices, then
install the new agent (or null when
its provider vanished). Plugin
load/unload callbacks refresh the
dropdown and re-run agent selection.
load_last_machine no longer falls
back to the first available machine.
A dedicated PrinterAgentChoice field
reads rows straight from the live
agent registry and stores the agent
id string, replacing the fake-coEnum
index mapping. The field moves to
TabPrinter and registers with the
searcher so UnsavedChanges renders
it; the PhysicalPrinterDialog copy
and its update hook are removed
(#125). switch_printer_agent now
resolves ids via
resolve_printer_agent_id.
# 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)
The preset option was plugin_preference_overrides while the GUI field type
that renders it was GUIType::plugin_config, for one and the same thing.
Settle on "config": the store, the dialog and the Python hooks all say config
already, so renaming that way touches 4 files instead of the whole plugin
subsystem and the public plugin API.
Keep the _overrides suffix — the option is the preset's override layer over
the base PluginConfig store, a distinction EffectiveCapabilityConfig tracks.
Also wrap the printer tab's group heading in L(); it was the only one of the
three missing it, and was therefore untranslatable.
Resolve five conflicts, all of which needed both sides rather than a pick:
- BackgroundSlicingProcess: ours was a pure tabs->spaces reformat of base, so
keep main's per-filament volume/nozzle map read-back (its only change here).
- GUI_App: main's #12506 else-if attached to an `if` this branch deleted;
re-expressed onto the same-agent early-return path (the agent factory caches
per id, so pointer equality is the same predicate).
- MainFrame: both sides relocated Sync Presets independently; keep main's
push_notification plus the branch's Plugins menu items.
- Tab: the "TODO: Orca: Support hybrid" blocks were unchanged base, not a branch
decision; take main's enabled Hybrid to match the already auto-merged siblings.
- test_config: union of both sides' cases (6 plugin + 9 multi-nozzle).
* ENH: config: add logic to apply params to object/region config with multi-extruder
JIRA: no-jira
Change-Id: Ieab98cd8d031e5ca82a3aad2d0b89d8ae4a794f1
(cherry picked from commit 3179fd416e68ca8bc2d746f859508d07db18fe5b)
* FIX: X1C switch to H2D lose Highflow parameter
Jira: STUDIO-15272
Change-Id: Id8cf5d93a49d5542ac82f9554974b458e15c1193
(cherry picked from commit 15d9f072ff658a3beb4f916d978dfea12c2d9f16)
* Fix mishandling of `stride` param and add unit test for it
* Fix modified multi-variant per-obj option highlight
* Fix issue that per-obj FloatsOrPercents options are marked as dirty incorrectly when lost focus
---------
Co-authored-by: lane.wei <lane.wei@bambulab.com>
Co-authored-by: weiting.ji <weiting.ji@bambulab.com>
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.
The sidebar extruder cards get an interactive title row — "<name> ( <count> )"
with an edit button — showing the extruder's physical nozzle count on
multi-nozzle printers (hidden elsewhere). Clicking it opens the existing
"Set nozzle count" dialog, which now also handles a Hybrid extruder by
offering both Standard and High Flow counts (an empty mix is rejected) and
shows a hotend thumbnail.
Because `extruder_nozzle_stats` is session-only (saved presets never carry
it, so preset switches rebuild the edited config without it), the stats are
re-baselined whenever they are missing: each extruder starts with
extruder_max_nozzle_count nozzles of its selected volume type. Switching an
extruder's flow type carries its total count over to the new type, except
when the stats came from a device sync — the machine-reported per-type
breakdown must survive a manual flow switch.
The badge refreshes on preset load, flow-type change, manual edit, device
sync, and project load. Single-extruder cards keep the title row but never
enable editing.
An extruder with more than one physical sub-nozzle can hold a mix of
Standard and High Flow nozzles. The Flow dropdown now offers Hybrid for
such extruders (extruder_max_nozzle_count > 1, nil-guarded); grouping
already expands a Hybrid extruder into per-volume nozzle groups from
extruder_nozzle_stats.
- sidebar Flow combo offers Hybrid only for multi-sub-nozzle extruders
- preset lookup treats Hybrid as Standard (presets define no Hybrid
variant); variant strings are never fabricated for it
- printer tab splits a Hybrid extruder into Standard + High Flow rows,
with matching selection-index arithmetic and sync-enable rules
- syncing from a printer whose extruder holds mixed nozzle flows now
selects Hybrid instead of collapsing to the dominant flow type
- send-to-printer flow check: a nozzle-rack extruder validates its
nozzle inventory (mounted + rack) against every needed flow instead
of comparing only the mounted nozzle; mounted-flow lookup is now
per-extruder, fixing an index shift when a nozzle reports no flow
- Hybrid is session-only in app config (stored as Standard), so a
fresh session starts from concrete flow types
Printers whose extruders have a single sub-nozzle (including all
dual-extruder machines without a rack) see no new option and identical
check behavior.