Read BambuStudio Nil Slots as Not Set Instead of Aborting the Load

BambuStudio and its forks save a nozzle variant that matches the parent
preset as "nil", including in keys OrcaSlicer can't leave empty, such as
retraction, z-hop and nozzle temperature. Reading one threw, which ended
the rest of the settings file: a project kept only the keys before it
alphabetically, and an embedded or user preset was dropped.

load_from_json now reads such a slot as not set when the caller opts in
(project settings, embedded presets, user presets). If every slot is nil,
the key is left out. Otherwise the slot holds the option default and is
recorded, and update_diff_values_to_child_config gives it the parent
preset's value. Other loaders still reject nil.
This commit is contained in:
Hanif Koh
2026-10-02 18:00:54 +08:00
parent 0bc8912667
commit 5ecb596b1c
8 changed files with 168 additions and 15 deletions
+8 -5
View File
@@ -1726,9 +1726,11 @@ PresetCollection::UserPresetLoad PresetCollection::resolve_user_preset(
//ConfigSubstitutions config_substitutions = config.load_from_ini(preset.file, substitution_rule);
std::map<std::string, std::string> key_values;
std::string reason;
ConfigSubstitutions config_substitutions = config.load_from_json(preset.file, substitution_rule, key_values, reason);
if (! config_substitutions.empty())
out.substitutions.push_back({ preset.name, m_type, PresetConfigSubstitutions::Source::UserFile, preset.file, std::move(config_substitutions) });
ConfigSubstitutionContext load_context(substitution_rule);
load_context.accept_nil = true;
config.load_from_json(preset.file, load_context, true, key_values, reason);
if (! load_context.substitutions.empty())
out.substitutions.push_back({ preset.name, m_type, PresetConfigSubstitutions::Source::UserFile, preset.file, std::move(load_context.substitutions) });
if (!reason.empty()) {
out.discard_file = true;
out.errors.push_back((boost::format("parse config %1% failed") % preset.file).str());
@@ -1764,7 +1766,7 @@ PresetCollection::UserPresetLoad PresetCollection::resolve_user_preset(
preset.config = inherit_preset->config;
preset.filament_id = inherit_preset->filament_id;
extend_default_config_length(config, false, {});
preset.config.update_diff_values_to_child_config(config, extruder_id_name, extruder_variant_name, *key_set1, *key_set2);
preset.config.update_diff_values_to_child_config(config, extruder_id_name, extruder_variant_name, *key_set1, *key_set2, &load_context.nil_slots);
}
else {
auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config);
@@ -2137,7 +2139,8 @@ void PresetCollection::load_project_embedded_presets(std::vector<Preset*>& proje
BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset->file;
continue;
}
preset->config.update_diff_values_to_child_config(config, extruder_id_name, extruder_variant_name, *key_set1, *key_set2);
preset->config.update_diff_values_to_child_config(config, extruder_id_name, extruder_variant_name, *key_set1, *key_set2, &preset->nil_slots);
preset->nil_slots.clear();
//preset->config.apply(std::move(config));
Preset::normalize(preset->config);
// Report configuration fields, which are misplaced into a wrong group.