mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 13:32:44 +00:00
173706750d9ddf49fe07f9feaae49352bcdd4439
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
31eb8a2bd1 |
CLI: let --export-settings - write the merged config to stdout
--export-settings already writes the merged config as JSON at the right point in the CLI flow. Passing - writes the same document to stdout. - ConfigBase::save_to_json gains a stream overload. The file overload serializes through it before opening the file, so the format is unchanged and a config that cannot be serialized leaves an existing file untouched instead of truncating it. - On stdout, invalid UTF-8 in string values is written as U+FFFD instead of ending the process with an uncaught type_error; files keep the strict behaviour. - - is rejected up front when combined with an action or transform that can write to stdout or does real work, so stdout carries only the JSON. - The unconditional "skip locked instance" stdout write during arrange now goes to the log. - Tests in tests/libslic3r/test_config.cpp. |
||
|
|
c5b152b722 |
CLI: record command-line overrides in different_settings_to_system (#15642)
* CLI: record command-line overrides in different_settings_to_system Settings passed on the command line (--sparse-infill-density 25% ...) override the loaded presets when m_extra_config is applied to m_print_config, but nothing recorded them in different_settings_to_system. The exported project therefore carried the new value with no mark that it was modified, and re-opening it in the GUI reverted it to the system preset's value -- the same failure the preset-leaf diff fixes for user presets, via a different source of override. The key set comes from m_config, not m_extra_config. read_cli() puts only what the user typed into m_config and setup() adds nothing but CLI-own defaults (none of the keys run() materialises there is a preset option), whereas the CLI writes its own values into m_extra_config (has_filament_switcher, filament_colour, filament_map ...), which must not be reported as user overrides. Values are snapshotted just before the apply and only keys the override actually changed are recorded: a typed value equal to the loaded one modifies nothing, and listing it would read as a spurious difference against what the GUI writes. Each key lands in the column(s) whose preset type owns it -- process, every filament, printer -- and a key already present is not duplicated. Keys no preset owns (curr_bed_type, a project setting) land nowhere, as in the GUI. Follow-up to #15595, split out at review. * CLI: judge command-line overrides the way the value is read Review follow-ups on the override recording: - Lists were compared as whole serialized strings. read_cli() builds a fresh one-entry list, so --nozzle-temperature 245 against 245,245,245 on a three-filament project was recorded in every filament column although nothing changed. Lists are now compared entry by entry with a missing entry read as the first, as get_at() reads it (and as resize() pads). - The log line fired for every changed key, including ones no preset owns (curr_bed_type) and which therefore land in no column. It now fires only when a column took the key. - m_print_config.has(key) straight after apply(m_extra_config, true) was always true, both configs sharing print_config_def; removed. columns.size() >= 2 also always holds after the resize to filament_count + 2 -- different_settings_to_system is not a CLI option, so nothing in between can shrink it -- but that rests on code far away, so it stays a plain check rather than an assert: release builds compile asserts out, and a _GLIBCXX_ASSERTIONS build would abort on columns[0]. Deliberately NOT done: comparing a key the loaded config lacks against its built-in default. On reopen the GUI restores an unlisted key from the SYSTEM preset, not the default. A 3MF written before an option existed leaves it absent here, so --sparse-infill-density 20% (the default) against a Prusa system 15% would go unrecorded and be reverted to 15%. Absent keys stay always-recorded: over-recording is cosmetic, under-recording loses the value. Verified that such a key really is absent at this point, rather than filled from the system preset. Reported by HanifKoh and raistlin7447 in review of #15642. |
||
|
|
ccd6086787 |
CLI: evaluate compatible_printers_condition in the compat checks (#15449)
* CLI: evaluate compatible_printers_condition in the compat checks
Slicing from the CLI with --load-settings exits with
CLI_PROCESS_NOT_COMPATIBLE (-17), "The selected printer is not compatible
with the process preset in the 3mf.", for process/printer pairs the GUI
accepts. Reproducible with stock, unmodified Prusa system profiles:
orca-slicer --datadir <datadir> \
--load-settings "<datadir>/system/Prusa/process/0.20mm SPEED @CORE One HF 0.4.json;<datadir>/system/Prusa/machine/Prusa CORE One HF 0.4 nozzle.json" \
--load-filaments "<datadir>/system/Prusa/filament/Prusament PETG @CORE One HF 0.4.json" \
--slice 0 --outputdir /tmp/out model.stl
The four compat checks in CLI::run did a literal name match against the
`compatible_printers` list only:
for (index ...) if (new_print_compatible_printers[index] == new_printer_system_name)
process_compatible = true;
Process profiles that declare compatibility through
`compatible_printers_condition` and leave `compatible_printers` empty are
therefore always reported incompatible -- the condition is never consulted.
For 0.20mm SPEED @CORE One HF 0.4 that condition is:
printer_notes=~/.*PRINTER_MODEL_COREONE[^_a-zA-Z0-9].*/ and
nozzle_diameter[0]==0.4 and printer_notes=~/.*HF_NOZZLE.*/
The GUI does not have this bug: is_compatible_with_printer() in Preset.cpp
treats an empty list as "no explicit constraint" and evaluates the
condition in that case.
Fix: replace the four loops with a check_compat lambda that calls
is_compatible_with_printer() -- the same helper the GUI uses -- wrapping
the already-loaded DynamicPrintConfigs in lightweight Preset /
PresetWithVendorProfile shells. The 3MF-embedded process/printer full
configs are kept in current_process_full_config /
current_printer_full_config so the condition can be evaluated for the
reprocess paths too; those fall back to the previous literal match when
the full config was not preserved.
Behaviour is unchanged where an explicit compatible_printers list exists:
is_compatible_with_printer() performs the same name match, and returns
true when both list and condition are empty, matching the existing
"old 3mf, no compatible printers, set to compatible" path.
Split out of #13731 (section 1) as a standalone, single-purpose change.
Orthogonal to the inherits-chain resolution work in #14718 / #15302 /
#15438; those decide which values a preset resolves to, this decides
whether the resulting pair is considered compatible.
* CLI: translate the 3MF's renamed compatibility keys before the compat check
The 3MF fallback fed the project config to is_compatible_with_printer() as-is,
but a project config does not carry compatible_printers or
compatible_printers_condition. PresetBundle::construct_full_config() erases both
and re-emits them as print_compatible_printers and
compatible_machine_expression_group; they are renamed back only on the
PresetBundle load path, which the CLI does not take. The check therefore saw no
list and no condition, read that as 'no constraint' and accepted every printer.
That is not just a wrong accept. An early true skips the !process_compatible
block that sets machine_switch, so the new printer is never appended to
print_compatible_printers and the exported 3MF stays marked compatible only with
the printer it came from -- which is exactly what that block exists to prevent.
Translate the two keys back before the check. Index 0 of the expression group is
the print preset; the group is filled print, filaments, printer.
Also note in the comment that profiles/BBL/{process,machine}_full/ are gitignored
and generated by nothing in-tree, so current_*_full_config is always empty and
this fallback is the only live path -- not the rare non-BBL case the original
comment implied.
Reported with measurements by HanifKoh in review of #15449.
Preset: add a config-level is_compatible_with_printer() overload
The CLI holds resolved DynamicPrintConfigs, not Presets, so it wrapped them in
throwaway Preset shells at the call site. Moving that into Preset.cpp puts the
compatibility policy -- including the documented fail-open on a malformed
compatible_printers_condition -- in one place for the GUI and the CLI, rather
than leaving a second copy of the plumbing in OrcaSlicer.cpp to drift.
Purely additive: neither existing overload changes, so no GUI behaviour moves.
Requested by HanifKoh in review of #15449.
(cherry picked from commit 14ca1972ef4d3c7d90935d159423013a40a6bd70)
* CLI: never overwrite a real compat key with an empty renamed one
|
||
|
|
1e76e733b7 |
CLI: record user overrides in different_settings_to_system for 3MF export (#15595)
* CLI: record user overrides in different_settings_to_system for 3MF export
Three sites in CLI::run wrote an empty `different_settings_to_system` column
and left a //todo:
//todo: support user machine preset's different settings
different_settings[filament_count+1] = "";
//todo: support system process preset
different_settings[0] = "";
//todo: update different settings of filaments
different_settings[filament_index] = "";
So a 3MF exported by the CLI does not record which keys the user actually
overrode relative to the system parent. Re-opening such a project in the GUI
then shows spurious "unsaved changes", and accepting that dialog can revert
inherited process/filament/machine values to system defaults.
The column could not be filled before because the CLI had no resolved view of
the parent preset. It does now: #15438 builds a PresetBundle for inherits
resolution, so the parent can be looked up by name and diffed against the
resolved leaf. This adds no extra loading -- the bundle is the one already
built, and the helper returns "" whenever it is unavailable or the parent
cannot be found, which is the previous behaviour.
Preset metadata is filtered out of the diff: `inherits`, the three
`*_settings_id` keys, and `compatible_printers` / `compatible_prints` and
their `_condition` variants, which have their own tracking columns
(`inherits_group`, per-slot lists) and would otherwise double-count.
A value already carried by the loaded JSON still wins for the process slot, so
presets saved with a `different_settings_to_system` field behave as before;
the computed value only fills the gap where that field is absent, which is the
case for every user preset in my datadir (0 of 47 carry it).
System presets keep an empty column: there are no user overrides to record.
* CLI: diff the filament slot before load_default_gcodes_to_config
The process and machine slots compute their different_settings_to_system column
before load_default_gcodes_to_config(); the filament slot did it after. That
call materialises absent gcode keys via option(..., true), and
DynamicConfig::diff only compares keys present in both configs -- so a gcode key
the resolved leaf did not carry would go from 'not compared' to 'compared as
empty against the parent' and land in the column as an override the user never
made.
Hoisted into a local above the call, guarded by load_filament_count > 0 so the
work is skipped exactly where it was before, and assigned at the original site.
The diff now also runs before config.erase("filament_settings_id"), which is
immaterial: cli_different_settings already filters filament_settings_id along
with the other *_settings_id keys.
This is a consistency fix rather than a demonstrated defect -- resolve_preset
merges the parent config, so in practice the gcode keys are already present on
both sides and the diff is unaffected. It removes the dependence on that
invariant, which the other two slots never had.
Reported by HanifKoh in review of #15595.
|
||
|
|
705c82688e | PartPlate::check_outside: guard m_plater null deref (fix CLI rotate SIGSEGV) (#14415) | ||
|
|
ae0193899d | calib: default-init Calib_Params scalar fields (#14413) | ||
|
|
88262ee504 |
CLI: guard 4 null derefs when loading a 3mf without preset ids (#14580)
CLI: guard 4 null derefs when loading a 3mf with no preset ids
At OrcaSlicer.cpp:1700-1704 the post-load block reads printer_settings_id,
print_settings_id, filament_settings_id, and nozzle_diameter from the
config that the 3mf carries. If the 3mf is a BBL/BBS-flavored 3mf but
was produced by a non-GUI writer (e.g. CLI --export-3mf without a
loaded preset) any of those keys can be absent, and config.option<T>(...)
returns nullptr — the ->value / ->values deref then SIGSEGVs.
Wrap each optional lookup in an if-let. printer_model, printer_extruder_variant,
and print_extruder_variant already pass create_if_missing=true and are safe.
Repro (BEFORE this patch):
orca-slicer --export-3mf out.3mf in.stl # produces preset-less 3mf
orca-slicer --info out.3mf # SIGSEGV at :1700
bt: __cxx11::basic_string::_M_assign
-> Slic3r::CLI::run @ OrcaSlicer.cpp:1700
AFTER: --info out.3mf returns exit 0 with the mesh summary.
The same failure mode affected --inspect-mesh, --inspect-paint, and
every other action that has to walk the loaded model's config; --slice
would only survive because it always injects a printer via
--load-settings.
|
||
|
|
a529f8c473 |
Print Host: add Moonraker (Klipper) host type (#13991)
OrcaSlicer currently ships an "Octo/Klipper" host type that maps to the
OctoPrint REST endpoints (api/version, api/files/local). It works for
Klipper setups that run Moonraker with the OctoPrint-emulation plugin,
but native Moonraker — and Moonraker-compatible firmwares like the
Prusa-Firmware-Buddy buddy-klipper fork — speak a different shape:
distinct paths, JSON body for /printer/print/start, {"result":...}
envelope. There's no host type for that today.
Add a new Moonraker class deriving from PrintHost. Endpoints used,
matching the Moonraker spec:
- GET /server/info — connection test, reads
result.klippy_state
- GET /server/files/roots — storage-picker dropdown
(returns roots with 'w'
permission); gracefully
degrades if absent
- POST /server/files/upload (multipart) — upload (form fields:
file, root)
- POST /printer/print/start (json) — {"filename":"<path>"}; the
filename is whatever the
upload response returned
in result.item.path, so any
server-side rename
(collision suffix etc.) is
respected. JSON body is
built via property_tree
write_json so exotic
characters in the path are
properly escaped.
Auth: X-Api-Key header, only when printhost_apikey is non-empty
(Moonraker can be configured to require it but doesn't by default).
HTTP Basic / Digest are not part of the Moonraker spec and are not
sent.
Storage root is read from upload_data.storage with "gcodes" as the
fallback default, so the existing storage-picker plumbing in
PrintHostDialogs lights up automatically once enumerable roots are
returned.
UI: registers as the "Moonraker (Klipper)" entry under host_type;
selectable via the existing Physical Printer dialog (sidebar's
connection button on the printer card).
Verified against a Prusa-Firmware-Buddy buddy-klipper fork (firmware
identifies as moonraker_version "0.8.0-prusalink-shim"): /server/info
test, multipart upload to /server/files/upload, and JSON
/printer/print/start all work end-to-end. The existing "Octo/Klipper"
entry is left untouched so users currently relying on Moonraker's
OctoPrint-emulation plugin keep working.
|
||
|
|
f760f4e462 |
Fix Flow Ratio dialog shrinking after main window minimize (#13545)
FlowRateCalibrationDialog was missing the SetSizeHints call that every other calibration dialog in calib_dlg.cpp uses (Cornering, Pa, Pa Pattern, Max Volumetric Speed, Temperature, Retraction, VFA, Input Shaping). Without it, the dialog has no enforced minimum size: on wxGTK, iconizing the main window while the dialog is open triggers a layout/refresh that re-runs Fit() with transient zero-sized children, collapsing the dialog to ~222x249 px with the OK button clipped and unreachable. The window manager then honors the (incorrect) small geometry hint, so the user cannot resize it back manually. Two changes: * Add v_sizer->SetSizeHints(this) after Fit() in the constructor, matching the pattern used by all other dialogs in this file. This locks in the correct minimum the first time Fit() runs, before any iconize event. * Remove the redundant Fit() from on_dpi_changed. With SetSizeHints in place the WM enforces the minimum, but the unconditional Fit() on every DPI/refresh signal was the trigger for the shrink path; Refresh() alone is sufficient here. Co-authored-by: Packerlschupfer <packerl@schupfer.at> |