mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-13 12:07:41 +00:00
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)
This commit is contained in:
@@ -2611,13 +2611,25 @@ int CLI::run(int argc, char **argv)
|
|||||||
auto check_compat = [](const DynamicPrintConfig &process_cfg,
|
auto check_compat = [](const DynamicPrintConfig &process_cfg,
|
||||||
const DynamicPrintConfig &printer_cfg,
|
const DynamicPrintConfig &printer_cfg,
|
||||||
const std::string &printer_name) -> bool {
|
const std::string &printer_name) -> bool {
|
||||||
Preset process_preset(Preset::TYPE_PRINT, std::string("__cli_process_check"));
|
return is_compatible_with_printer(process_cfg, Preset::TYPE_PRINT, printer_cfg, printer_name);
|
||||||
process_preset.config = process_cfg;
|
};
|
||||||
Preset printer_preset(Preset::TYPE_PRINTER, printer_name);
|
|
||||||
printer_preset.config = printer_cfg;
|
//ORCA: a 3MF's project config does not carry compatible_printers / compatible_printers_condition.
|
||||||
PresetWithVendorProfile process_pwvp(process_preset, nullptr);
|
// PresetBundle::construct_full_config() erases both and re-emits them as
|
||||||
PresetWithVendorProfile printer_pwvp(printer_preset, nullptr);
|
// print_compatible_printers and compatible_machine_expression_group; they are renamed back
|
||||||
return is_compatible_with_printer(process_pwvp, printer_pwvp);
|
// only on the PresetBundle load path, which the CLI does not take. Feeding the project config
|
||||||
|
// to the check as-is therefore presents no list and no condition, and
|
||||||
|
// is_compatible_with_printer() reads that as "no constraint" and accepts every printer.
|
||||||
|
// Translate the two keys back. Index 0 of the expression group is the print preset -- the
|
||||||
|
// group is filled print, filaments, printer (PresetBundle.cpp).
|
||||||
|
auto cli_process_compat_config = [](const DynamicPrintConfig &project_cfg) -> DynamicPrintConfig {
|
||||||
|
DynamicPrintConfig cfg = project_cfg;
|
||||||
|
if (const auto *list = project_cfg.option<ConfigOptionStrings>("print_compatible_printers"))
|
||||||
|
cfg.set_key_value("compatible_printers", new ConfigOptionStrings(list->values));
|
||||||
|
const auto *group = project_cfg.option<ConfigOptionStrings>("compatible_machine_expression_group");
|
||||||
|
if (group != nullptr && !group->values.empty())
|
||||||
|
cfg.set_key_value("compatible_printers_condition", new ConfigOptionString(group->values.front()));
|
||||||
|
return cfg;
|
||||||
};
|
};
|
||||||
if (!new_printer_name.empty()) {
|
if (!new_printer_name.empty()) {
|
||||||
if (!new_process_name.empty()) {
|
if (!new_process_name.empty()) {
|
||||||
@@ -2628,12 +2640,16 @@ int CLI::run(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//3MF-embedded process vs new printer. current_process_full_config is only populated from
|
//3MF-embedded process vs new printer. current_process_full_config is only populated from
|
||||||
//profiles/BBL/process_full/, i.e. for BBL profiles; for every other vendor fall back to the
|
//profiles/BBL/process_full/, so for every other vendor fall back to the 3MF's own project
|
||||||
//3MF's own project config, which is already merged into m_print_config above and carries
|
//config in m_print_config, with its renamed compatibility keys translated back (see
|
||||||
//compatible_printers_condition. Without this a 3MF built from a condition-only process is
|
//cli_process_compat_config above). Without this a 3MF built from a condition-only process
|
||||||
//rejected when re-sliced with the very printer it was made for.
|
//is rejected when re-sliced with the very printer it was made for.
|
||||||
{
|
{
|
||||||
const DynamicPrintConfig &process_cfg = current_process_full_config.empty() ? m_print_config : current_process_full_config;
|
//ORCA: profiles/BBL/{process,machine}_full/ are gitignored and not generated in-tree,
|
||||||
|
// so current_*_full_config is always empty and this fallback is the only live path.
|
||||||
|
const DynamicPrintConfig process_cfg = current_process_full_config.empty()
|
||||||
|
? cli_process_compat_config(m_print_config)
|
||||||
|
: current_process_full_config;
|
||||||
process_compatible = check_compat(process_cfg, load_machine_config, new_printer_system_name);
|
process_compatible = check_compat(process_cfg, load_machine_config, new_printer_system_name);
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, old process %3%, inherited from %4% ,compatible %5%")
|
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, old process %3%, inherited from %4% ,compatible %5%")
|
||||||
|
|||||||
@@ -867,6 +867,20 @@ bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const Pre
|
|||||||
return is_compatible_with_printer(preset, active_printer, &config);
|
return is_compatible_with_printer(preset, active_printer, &config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ORCA: see the header. The CLI resolves --load-settings into bare DynamicPrintConfigs and has no
|
||||||
|
// Preset objects to hand; without this it would have to reimplement the policy or build the shells
|
||||||
|
// at every call site.
|
||||||
|
bool is_compatible_with_printer(const DynamicPrintConfig &preset_config, Preset::Type preset_type,
|
||||||
|
const DynamicPrintConfig &printer_config, const std::string &printer_name)
|
||||||
|
{
|
||||||
|
Preset preset(preset_type, std::string("__compat_check"));
|
||||||
|
preset.config = preset_config;
|
||||||
|
Preset printer(Preset::TYPE_PRINTER, printer_name);
|
||||||
|
printer.config = printer_config;
|
||||||
|
return is_compatible_with_printer(PresetWithVendorProfile(preset, nullptr),
|
||||||
|
PresetWithVendorProfile(printer, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
||||||
{
|
{
|
||||||
//BBS: add config related log
|
//BBS: add config related log
|
||||||
|
|||||||
@@ -459,6 +459,11 @@ protected:
|
|||||||
bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print, const PresetWithVendorProfile &active_printer);
|
bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print, const PresetWithVendorProfile &active_printer);
|
||||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config);
|
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config);
|
||||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer);
|
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer);
|
||||||
|
// ORCA: same check for callers that hold raw configs rather than Presets (the CLI). Wraps them in
|
||||||
|
// throwaway Preset shells and delegates, so the compatibility policy -- including the fail-open on a
|
||||||
|
// malformed compatible_printers_condition -- lives in one place for the GUI and the CLI alike.
|
||||||
|
bool is_compatible_with_printer(const DynamicPrintConfig &preset_config, Preset::Type preset_type,
|
||||||
|
const DynamicPrintConfig &printer_config, const std::string &printer_name);
|
||||||
|
|
||||||
// Where a preset is being loaded from. `Auto` lets load_presets() infer from the directory path.
|
// Where a preset is being loaded from. `Auto` lets load_presets() infer from the directory path.
|
||||||
struct PresetOrigin {
|
struct PresetOrigin {
|
||||||
|
|||||||
Reference in New Issue
Block a user