mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-15 13:07:33 +00:00
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.
This commit is contained in:
@@ -3846,9 +3846,94 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
//ORCA: settings passed on the command line (--sparse-infill-density 25% ...) override the loaded
|
||||
// presets right here, so they belong in different_settings_to_system just as a preset
|
||||
// override does. Without them re-opening the exported project in the GUI shows nothing
|
||||
// modified and reverts those values to the system presets'.
|
||||
//
|
||||
// The keys come from m_config, not m_extra_config: read_cli() puts only what the user typed
|
||||
// into m_config (setup() adds nothing but CLI-own defaults), whereas the CLI writes its own
|
||||
// values into m_extra_config. Only keys whose value the override actually changed are
|
||||
// recorded -- a typed value equal to the loaded one modifies nothing -- and each lands in
|
||||
// the column(s) whose preset type owns it: [0] process, [1..n-2] filaments, [n-1] printer.
|
||||
//
|
||||
// "Changed" is judged the way the value is read: a list is compared entry by entry with a
|
||||
// missing entry read as the first, as get_at() does -- so --nozzle-temperature 245 against
|
||||
// 245,245,245 is no change, although the two serialize differently.
|
||||
//
|
||||
// A key the loaded config does not carry at all is always recorded, even if the typed value
|
||||
// equals the built-in default. On reopen the GUI restores an unlisted key from the SYSTEM
|
||||
// preset, which need not match that default: a 3MF written before an option existed leaves
|
||||
// it absent here, and --sparse-infill-density 20% (the default) against a Prusa system 15%
|
||||
// would otherwise go unrecorded and be reverted. Over-recording is cosmetic; under-recording
|
||||
// loses the value.
|
||||
std::map<std::string, std::unique_ptr<ConfigOption>> cli_override_before;
|
||||
for (const std::string &key : m_config.keys()) {
|
||||
if (!m_extra_config.has(key))
|
||||
continue;
|
||||
const ConfigOption *loaded = m_print_config.option(key);
|
||||
cli_override_before[key].reset(loaded != nullptr ? loaded->clone() : nullptr); // null: always recorded
|
||||
}
|
||||
|
||||
// Apply command line options to a more specific DynamicPrintConfig which provides normalize()
|
||||
// (command line options override --load files)
|
||||
m_print_config.apply(m_extra_config, true);
|
||||
|
||||
if (!cli_override_before.empty()) {
|
||||
std::vector<std::string> &columns = m_print_config.option<ConfigOptionStrings>("different_settings_to_system", true)->values;
|
||||
auto owned_by = [](const std::vector<std::string> &options, const std::string &key) {
|
||||
return std::find(options.begin(), options.end(), key) != options.end();
|
||||
};
|
||||
auto add_to_column = [&columns](size_t index, const std::string &key) {
|
||||
std::vector<std::string> keys;
|
||||
Slic3r::unescape_strings_cstyle(columns[index], keys);
|
||||
if (std::find(keys.begin(), keys.end(), key) == keys.end()) {
|
||||
keys.push_back(key);
|
||||
columns[index] = Slic3r::escape_strings_cstyle(keys);
|
||||
}
|
||||
};
|
||||
auto same_value = [](const ConfigOption *a, const ConfigOption *b) {
|
||||
if (a == nullptr || b == nullptr)
|
||||
return false;
|
||||
const auto *va = dynamic_cast<const ConfigOptionVectorBase *>(a);
|
||||
const auto *vb = dynamic_cast<const ConfigOptionVectorBase *>(b);
|
||||
if (va == nullptr || vb == nullptr)
|
||||
return va == vb && a->serialize() == b->serialize();
|
||||
const std::vector<std::string> ea = va->vserialize(), eb = vb->vserialize();
|
||||
if (ea.empty() || eb.empty())
|
||||
return ea.empty() && eb.empty();
|
||||
for (size_t i = 0; i < std::max(ea.size(), eb.size()); ++i)
|
||||
if (ea[i < ea.size() ? i : 0] != eb[i < eb.size() ? i : 0])
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
//ORCA: always true after the resize to filament_count + 2 above, and nothing in between can
|
||||
// shrink the column vector -- different_settings_to_system is not a CLI option. Kept as
|
||||
// a check rather than an assert: release builds compile asserts out, so an assert would
|
||||
// protect nothing, while a build with _GLIBCXX_ASSERTIONS would abort on columns[0].
|
||||
if (columns.size() >= 2) {
|
||||
for (const auto &[key, before] : cli_override_before) {
|
||||
if (same_value(before.get(), m_print_config.option(key)))
|
||||
continue;
|
||||
bool recorded = false;
|
||||
if (owned_by(Preset::print_options(), key)) {
|
||||
add_to_column(0, key);
|
||||
recorded = true;
|
||||
}
|
||||
if (owned_by(Preset::filament_options(), key)) {
|
||||
for (size_t i = 1; i + 1 < columns.size(); ++i)
|
||||
add_to_column(i, key);
|
||||
recorded = true;
|
||||
}
|
||||
if (owned_by(Preset::printer_options(), key)) {
|
||||
add_to_column(columns.size() - 1, key);
|
||||
recorded = true;
|
||||
}
|
||||
if (recorded)
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("CLI: override %1% recorded in different_settings_to_system") % key;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Normalizing after importing the 3MFs / AMFs
|
||||
m_print_config.normalize_fdm();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user