mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-14 20:47:33 +00:00
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.
This commit is contained in:
@@ -53,6 +53,7 @@ using namespace nlohmann;
|
|||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/Config.hpp"
|
#include "libslic3r/Config.hpp"
|
||||||
|
#include "libslic3r/Preset.hpp"
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include "libslic3r/GCode.hpp"
|
#include "libslic3r/GCode.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
@@ -1462,6 +1463,10 @@ int CLI::run(int argc, char **argv)
|
|||||||
std::vector<std::string> upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings;
|
std::vector<std::string> upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings;
|
||||||
std::vector<std::string> current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants, new_extruder_variants, current_print_extruder_variants, new_printer_extruder_variants;
|
std::vector<std::string> current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants, new_extruder_variants, current_print_extruder_variants, new_printer_extruder_variants;
|
||||||
DynamicPrintConfig load_process_config, load_machine_config;
|
DynamicPrintConfig load_process_config, load_machine_config;
|
||||||
|
//ORCA: full configs of the "current" (3MF-embedded) process/printer presets, kept so that
|
||||||
|
// compatible_printers_condition can be evaluated for them below. Previously only the
|
||||||
|
// literal compatible_printers list was extracted.
|
||||||
|
DynamicPrintConfig current_process_full_config, current_printer_full_config;
|
||||||
bool new_process_config_is_system = true, new_printer_config_is_system = true;
|
bool new_process_config_is_system = true, new_printer_config_is_system = true;
|
||||||
std::string pipe_name, makerlab_name, makerlab_version, different_process_setting;
|
std::string pipe_name, makerlab_name, makerlab_version, different_process_setting;
|
||||||
const std::vector<std::string> &metadata_name = m_config.option<ConfigOptionStrings>("metadata_name", true)->values;
|
const std::vector<std::string> &metadata_name = m_config.option<ConfigOptionStrings>("metadata_name", true)->values;
|
||||||
@@ -2551,6 +2556,8 @@ int CLI::run(int argc, char **argv)
|
|||||||
flush_and_exit(ret);
|
flush_and_exit(ret);
|
||||||
}
|
}
|
||||||
upward_compatible_printers = config.option<ConfigOptionStrings>("upward_compatible_machine", true)->values;
|
upward_compatible_printers = config.option<ConfigOptionStrings>("upward_compatible_machine", true)->values;
|
||||||
|
//ORCA: keep the full config so compatible_printers_condition can be evaluated against it below
|
||||||
|
current_printer_full_config = std::move(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2573,6 +2580,8 @@ int CLI::run(int argc, char **argv)
|
|||||||
flush_and_exit(ret);
|
flush_and_exit(ret);
|
||||||
}
|
}
|
||||||
current_print_compatible_printers = config.option<ConfigOptionStrings>("compatible_printers", true)->values;
|
current_print_compatible_printers = config.option<ConfigOptionStrings>("compatible_printers", true)->values;
|
||||||
|
//ORCA: keep the full config so compatible_printers_condition can be evaluated against it below
|
||||||
|
current_process_full_config = std::move(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2591,46 +2600,63 @@ int CLI::run(int argc, char **argv)
|
|||||||
for (int index = 0; index < upward_compatible_printers.size(); index++) {
|
for (int index = 0; index < upward_compatible_printers.size(); index++) {
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("index %1%, upward_compatible_printers %2%")%index %upward_compatible_printers[index];
|
BOOST_LOG_TRIVIAL(info) << boost::format("index %1%, upward_compatible_printers %2%")%index %upward_compatible_printers[index];
|
||||||
}
|
}
|
||||||
|
//ORCA: Replace the four manual equality-loop checks below with is_compatible_with_printer(), the
|
||||||
|
// same helper the GUI uses, which also evaluates compatible_printers_condition. Process
|
||||||
|
// profiles that declare compatibility via condition only -- leaving compatible_printers
|
||||||
|
// empty -- were always reported incompatible by the literal-name match, so a CLI slice with
|
||||||
|
// such a preset exited with CLI_PROCESS_NOT_COMPATIBLE (-17) even though the GUI accepts the
|
||||||
|
// same pair. Behaviour is unchanged where an explicit list exists: is_compatible_with_printer
|
||||||
|
// does the same name match, and returns true when both list and condition are empty (which
|
||||||
|
// matches the "old 3mf, no compatible printers" path below).
|
||||||
|
auto check_compat = [](const DynamicPrintConfig &process_cfg,
|
||||||
|
const DynamicPrintConfig &printer_cfg,
|
||||||
|
const std::string &printer_name) -> bool {
|
||||||
|
Preset process_preset(Preset::TYPE_PRINT, std::string("__cli_process_check"));
|
||||||
|
process_preset.config = process_cfg;
|
||||||
|
Preset printer_preset(Preset::TYPE_PRINTER, printer_name);
|
||||||
|
printer_preset.config = printer_cfg;
|
||||||
|
PresetWithVendorProfile process_pwvp(process_preset, nullptr);
|
||||||
|
PresetWithVendorProfile printer_pwvp(printer_preset, nullptr);
|
||||||
|
return is_compatible_with_printer(process_pwvp, printer_pwvp);
|
||||||
|
};
|
||||||
if (!new_printer_name.empty()) {
|
if (!new_printer_name.empty()) {
|
||||||
if (!new_process_name.empty()) {
|
if (!new_process_name.empty()) {
|
||||||
for (int index = 0; index < new_print_compatible_printers.size(); index++) {
|
//new process + new printer: both configs came from --load-settings
|
||||||
if (new_print_compatible_printers[index] == new_printer_system_name) {
|
process_compatible = check_compat(load_process_config, load_machine_config, new_printer_system_name);
|
||||||
process_compatible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
||||||
%new_printer_name %new_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
%new_printer_name %new_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int index = 0; index < current_print_compatible_printers.size(); index++) {
|
//3MF-embedded process vs new printer. current_process_full_config is only populated from
|
||||||
if (current_print_compatible_printers[index] == new_printer_system_name) {
|
//profiles/BBL/process_full/, i.e. for BBL profiles; for every other vendor fall back to the
|
||||||
process_compatible = true;
|
//3MF's own project config, which is already merged into m_print_config above and carries
|
||||||
break;
|
//compatible_printers_condition. Without this a 3MF built from a condition-only process 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;
|
||||||
|
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%")
|
||||||
%new_printer_name %new_printer_system_name %current_process_name %current_process_system_name %process_compatible;
|
%new_printer_name %new_printer_system_name %current_process_name %current_process_system_name %process_compatible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!new_process_name.empty()) {
|
else if (!new_process_name.empty()) {
|
||||||
for (int index = 0; index < new_print_compatible_printers.size(); index++) {
|
//new process vs 3MF-embedded printer. As above, current_printer_full_config only resolves for
|
||||||
if (new_print_compatible_printers[index] == current_printer_system_name) {
|
//BBL profiles; otherwise evaluate against the 3MF's own project config in m_print_config, which
|
||||||
process_compatible = true;
|
//holds the embedded printer's printer_notes / nozzle_diameter.
|
||||||
break;
|
{
|
||||||
}
|
const DynamicPrintConfig &printer_cfg = current_printer_full_config.empty() ? m_print_config : current_printer_full_config;
|
||||||
|
process_compatible = check_compat(load_process_config, printer_cfg, current_printer_system_name);
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("old printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
BOOST_LOG_TRIVIAL(info) << boost::format("old printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
||||||
%current_printer_name %current_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
%current_printer_name %current_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//check the compatible of old printer&&process
|
//both sides 3MF-embedded (pure reprocess)
|
||||||
for (int index = 0; index < current_print_compatible_printers.size(); index++) {
|
if (!current_process_full_config.empty() && !current_printer_full_config.empty())
|
||||||
if (current_print_compatible_printers[index] == current_printer_system_name) {
|
process_compatible = check_compat(current_process_full_config, current_printer_full_config, current_printer_system_name);
|
||||||
process_compatible = true;
|
else
|
||||||
break;
|
process_compatible = std::find(current_print_compatible_printers.begin(), current_print_compatible_printers.end(), current_printer_system_name) != current_print_compatible_printers.end();
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!process_compatible && current_print_compatible_printers.empty())
|
if (!process_compatible && current_print_compatible_printers.empty())
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf, no compatible printers, set to compatible");
|
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf, no compatible printers, set to compatible");
|
||||||
|
|||||||
Reference in New Issue
Block a user