mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-03 05:41:10 +00:00
Refresh a CLI Project's Filament Settings From Their System Presets
The CLI loads a project's printer and process settings as the GUI does, taking every key the project does not list as changed from the current system preset, but it kept the stored filament values. A project saved before a profile update then sliced with old filament values on the command line and with the current ones in the GUI. Every project filament that no loaded filament replaces is now resolved by its system preset name and fed to the filament merge the up-to-date path already uses, which keeps the keys listed in different_settings_to_system and maps per-variant values onto the preset's variants. This covers a plain run, --uptodate without --uptodate-filaments, and the slots --load-filaments leaves empty. The merge tells refreshed entries from loaded ones per entry instead of by the global loaded-filament count, and the entries are kept in slot order. A project filament saved under a name the presets have since split per nozzle is resolved through the name conversion the GUI uses, which PresetBundle now exposes.
This commit is contained in:
+37
-4
@@ -2779,6 +2779,37 @@ int CLI::run(int argc, char **argv)
|
||||
fetch_compatible_values = true;
|
||||
}
|
||||
|
||||
// Refresh every project filament no loaded filament replaces from its current system preset, as the GUI
|
||||
// does when it loads the project; the filament merge below keeps the keys the project lists as changed.
|
||||
// Entries stay in slot order, which the merge's variant bookkeeping relies on.
|
||||
std::vector<bool> load_filaments_refresh(load_filaments_config.size(), false);
|
||||
if (is_bbl_3mf && new_printer_name.empty()) {
|
||||
const ConfigOptionStrings *project_filament_ids = m_print_config.option<ConfigOptionStrings>("filament_ids");
|
||||
for (size_t index = 0; index < current_filaments_system_name.size(); index++) {
|
||||
const int slot = static_cast<int>(index) + 1;
|
||||
if (std::find(load_filaments_index.begin(), load_filaments_index.end(), slot) != load_filaments_index.end())
|
||||
continue;
|
||||
std::string system_name = current_filaments_system_name[index];
|
||||
if (system_name.empty())
|
||||
continue;
|
||||
PresetBundle::convert_filament_preset_name(current_printer_name, system_name);
|
||||
DynamicPrintConfig config;
|
||||
std::string error;
|
||||
if (!ensure_system_preset_resolver().resolve_system_preset(config, Preset::TYPE_FILAMENT, system_name, config_substitution_rule, error)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("CLI: system filament preset '%1%' not resolved (%2%); filament %3% keeps its values") % system_name % error % slot;
|
||||
continue;
|
||||
}
|
||||
const size_t at = std::upper_bound(load_filaments_index.begin(), load_filaments_index.end(), slot) - load_filaments_index.begin();
|
||||
load_filaments_id.insert(load_filaments_id.begin() + at,
|
||||
project_filament_ids != nullptr && index < project_filament_ids->size() ? project_filament_ids->values[index] : std::string());
|
||||
load_filaments_name.insert(load_filaments_name.begin() + at, system_name);
|
||||
load_filaments_config.insert(load_filaments_config.begin() + at, std::move(config));
|
||||
load_filaments_index.insert(load_filaments_index.begin() + at, slot);
|
||||
load_filaments_inherit.insert(load_filaments_inherit.begin() + at, system_name);
|
||||
load_filaments_refresh.insert(load_filaments_refresh.begin() + at, true);
|
||||
}
|
||||
}
|
||||
|
||||
//fetch upward_compatible_machine
|
||||
if (fetch_upward_values) {
|
||||
if (!current_printer_system_name.empty()) {
|
||||
@@ -3469,7 +3500,7 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
|
||||
//set the filament settings into print config
|
||||
if ((load_filament_count > 0) || (up_config_to_date))
|
||||
if ((load_filament_count > 0) || (up_config_to_date) || !load_filaments_config.empty())
|
||||
{
|
||||
//std::vector<int> filament_variant_count(filament_count, 1);
|
||||
std::vector<int> old_start_indice(filament_count, 0);
|
||||
@@ -3528,6 +3559,8 @@ int CLI::run(int argc, char **argv)
|
||||
for (int index = 0; index < load_filaments_config.size(); index++) {
|
||||
DynamicPrintConfig& config = load_filaments_config[index];
|
||||
int filament_index = load_filaments_index[index];
|
||||
// A filament given with --load-filaments replaces the slot; a refreshed one keeps the project's changed keys.
|
||||
const bool loaded = load_filament_count > 0 && !load_filaments_refresh[index];
|
||||
std::vector<std::string> different_keys;
|
||||
|
||||
//ORCA: diff before load_default_gcodes_to_config, the way the process and machine
|
||||
@@ -3537,12 +3570,12 @@ int CLI::run(int argc, char **argv)
|
||||
// compared" to "compared as empty against the parent" and land in the column
|
||||
// as an override the user never made.
|
||||
std::string filament_different_settings;
|
||||
if (load_filament_count > 0)
|
||||
if (loaded)
|
||||
filament_different_settings = cli_different_settings(config, load_filaments_inherit[index], Preset::TYPE_FILAMENT);
|
||||
|
||||
load_default_gcodes_to_config(config, Preset::TYPE_FILAMENT);
|
||||
|
||||
if (load_filament_count > 0) {
|
||||
if (loaded) {
|
||||
ConfigOptionStrings *opt_filament_settings = static_cast<ConfigOptionStrings *> (m_print_config.option("filament_settings_id", true));
|
||||
std::string& filament_name = load_filaments_name[index];
|
||||
ConfigOptionString* filament_name_setting = new ConfigOptionString(filament_name);
|
||||
@@ -3614,7 +3647,7 @@ int CLI::run(int argc, char **argv)
|
||||
flush_and_exit(CLI_CONFIG_FILE_ERROR);
|
||||
}
|
||||
|
||||
if ((load_filament_count == 0) && !different_keys_set.empty())
|
||||
if (!loaded && !different_keys_set.empty())
|
||||
{
|
||||
std::set<std::string>::iterator iter = different_keys_set.find(opt_key);
|
||||
if ( iter != different_keys_set.end()) {
|
||||
|
||||
@@ -5251,7 +5251,7 @@ static void apply_receiver_mix_relocations(DynamicPrintConfig&
|
||||
|
||||
|
||||
//convert the old filament preset to new one after split
|
||||
static void convert_filament_preset_name(std::string& machine_name, std::string& filament_name)
|
||||
void PresetBundle::convert_filament_preset_name(const std::string& machine_name, std::string& filament_name)
|
||||
{
|
||||
auto machine_iter = filament_preset_convert.find(machine_name);
|
||||
if (machine_iter != filament_preset_convert.end())
|
||||
|
||||
@@ -238,6 +238,9 @@ public:
|
||||
// Keys a project keeps when its presets are loaded: those listed in its escaped
|
||||
// "different_settings_to_system" entry for the preset, plus the preset bookkeeping keys.
|
||||
static std::set<std::string> project_different_keys(const std::string &different_settings);
|
||||
// A project filament saved under a name the current presets split per nozzle (e.g. H2D 0.6) is loaded from
|
||||
// the preset that now holds its values.
|
||||
static void convert_filament_preset_name(const std::string& machine_name, std::string& filament_name);
|
||||
|
||||
PresetBundle();
|
||||
PresetBundle(const PresetBundle &rhs);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# End-to-end check that the CLI loads a project's printer and process settings as the GUI does.
|
||||
# End-to-end check that the CLI loads a project's printer, process and filament settings as the GUI does.
|
||||
#
|
||||
# The GUI takes every key a project does not list as changed from the project's current system preset:
|
||||
# keys saved before an option existed, and keys holding an older system value. Keys the project lists
|
||||
# in different_settings_to_system keep the project's value. A project is exported from the shipped
|
||||
# Bambu Lab P1S presets; one printer key and one process key are removed, one printer key and one
|
||||
# process key are changed without being listed, one key is changed and listed, and it is sliced again.
|
||||
# Bambu Lab P1S presets with two filaments; one printer key and one process key are removed, one printer
|
||||
# key, one process key and two filament keys (one per filament, one per extruder variant) are changed
|
||||
# without being listed, one process key and the first filament's density are changed and listed, and it
|
||||
# is sliced again: as is, with --uptodate, and with --load-filaments replacing only the second filament.
|
||||
#
|
||||
# usage: test_cli_project_missing_keys.sh <orca-slicer binary> <python3> <resources/profiles/BBL>
|
||||
set -u
|
||||
@@ -45,7 +47,7 @@ slice() {
|
||||
|
||||
slice base "$WORK/cube.stl" \
|
||||
--load-settings "$PROFILES/machine/Bambu Lab P1S 0.4 nozzle.json;$PROFILES/process/0.20mm Standard @BBL X1C.json" \
|
||||
--load-filaments "$PROFILES/filament/Bambu PLA Basic @BBL P1S 0.4 nozzle.json"
|
||||
--load-filaments "$PROFILES/filament/Bambu PLA Basic @BBL P1S 0.4 nozzle.json;$PROFILES/filament/Bambu PLA Basic @BBL P1S 0.4 nozzle.json"
|
||||
|
||||
# The removed keys, with their option defaults from PrintConfig.cpp; stale keys changed without being
|
||||
# listed as different, which must come back with the system value; and a listed key the project keeps.
|
||||
@@ -67,30 +69,44 @@ with zipfile.ZipFile(src) as zin, zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED
|
||||
for key in ("top_shell_layers", "extruder_clearance_height_to_rod"):
|
||||
expected[key] = config[key]
|
||||
config[key] = str(int(float(config[key])) + 1)
|
||||
for key in ("filament_cost", "filament_max_volumetric_speed"):
|
||||
expected[key] = config[key]
|
||||
config[key] = [str(float(v) + 1) for v in config[key]]
|
||||
expected["wall_loops"] = str(int(config["wall_loops"]) + 1)
|
||||
config["wall_loops"] = expected["wall_loops"]
|
||||
expected["filament_density"] = [str(float(config["filament_density"][0]) + 1)] + config["filament_density"][1:]
|
||||
config["filament_density"] = [expected["filament_density"][0]] + [str(float(v) + 1) for v in config["filament_density"][1:]]
|
||||
# One entry for the process, one per filament, one for the printer.
|
||||
different = config["different_settings_to_system"]
|
||||
different[0] = ";".join([k for k in different[0].split(";") if k] + ["wall_loops"])
|
||||
different[1] = ";".join([k for k in different[1].split(";") if k] + ["filament_density"])
|
||||
data = json.dumps(config, indent=4)
|
||||
zout.writestr(item, data)
|
||||
with open(dst + ".expected.json", "w") as f:
|
||||
json.dump(expected, f)
|
||||
EOF
|
||||
|
||||
slice project "$WORK/old.3mf"
|
||||
|
||||
"$PY" - "$WORK/project/out.3mf" "$WORK/old.3mf.expected.json" <<'EOF'
|
||||
check() {
|
||||
"$PY" - "$WORK/$1/out.3mf" "$WORK/old.3mf.expected.json" "$1" <<'EOF'
|
||||
import json, sys, zipfile
|
||||
|
||||
with zipfile.ZipFile(sys.argv[1]) as z:
|
||||
config = json.loads(z.read("Metadata/project_settings.config"))
|
||||
with open(sys.argv[2]) as f:
|
||||
expected = json.load(f)
|
||||
errors = ["%s is %r, want %r" % (key, config.get(key), want) for key, want in expected.items() if config.get(key) != want]
|
||||
errors = ["%s: %s is %r, want %r" % (sys.argv[3], key, config.get(key), want) for key, want in expected.items() if config.get(key) != want]
|
||||
for e in errors:
|
||||
print("FAIL: " + e)
|
||||
sys.exit(1 if errors else 0)
|
||||
EOF
|
||||
status=$?
|
||||
[ "$status" -eq 0 ] || { tail -n 40 "$WORK/project/log"; exit 1; }
|
||||
[ $? -eq 0 ] || { tail -n 40 "$WORK/$1/log"; exit 1; }
|
||||
}
|
||||
|
||||
slice project "$WORK/old.3mf"
|
||||
check project
|
||||
slice uptodate "$WORK/old.3mf" --uptodate
|
||||
check uptodate
|
||||
# The replaced second filament takes the system values the refresh would have given it.
|
||||
slice partial "$WORK/old.3mf" --load-filaments ";$PROFILES/filament/Bambu PLA Basic @BBL P1S 0.4 nozzle.json"
|
||||
check partial
|
||||
echo "PASS"
|
||||
|
||||
Reference in New Issue
Block a user