mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-18 22:31:13 -06:00
NEW: add custom printer config wizard
Change-Id: I48f34039635803c3f1cee4cc2c853a0ffa5b451a Signed-off-by: Stone Li <stone.li@bambulab.com> (cherry picked from commit 387ba2a5aac05d3b3af0923f88415188ae8cb44e) Signed-off-by: Stone Li <stone.li@bambulab.com>
This commit is contained in:
parent
5c82ec410e
commit
0b84ca62bf
19 changed files with 711 additions and 303 deletions
|
@ -757,6 +757,9 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
if (boost::iequals(it.key(),BBL_JSON_KEY_VERSION)) {
|
||||
key_values.emplace(BBL_JSON_KEY_VERSION, it.value());
|
||||
}
|
||||
if (boost::iequals(it.key(), BBL_JSON_KEY_IS_CUSTOM)) {
|
||||
key_values.emplace(BBL_JSON_KEY_IS_CUSTOM, it.value());
|
||||
}
|
||||
else if (boost::iequals(it.key(), BBL_JSON_KEY_NAME)) {
|
||||
key_values.emplace(BBL_JSON_KEY_NAME, it.value());
|
||||
}
|
||||
|
@ -1209,14 +1212,15 @@ ConfigSubstitutions ConfigBase::load_from_gcode_file(const std::string &file, Fo
|
|||
}
|
||||
|
||||
//BBS: add json support
|
||||
void ConfigBase::save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version) const
|
||||
void ConfigBase::save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version, const std::string is_custom) const
|
||||
{
|
||||
json j;
|
||||
|
||||
//record the headers
|
||||
j[BBL_JSON_KEY_VERSION] = version;
|
||||
j[BBL_JSON_KEY_NAME] = name;
|
||||
j[BBL_JSON_KEY_FROM] = from;
|
||||
if (!is_custom.empty())
|
||||
j[BBL_JSON_KEY_IS_CUSTOM] = is_custom;
|
||||
|
||||
//record all the key-values
|
||||
for (const std::string &opt_key : this->keys())
|
||||
|
|
|
@ -2139,7 +2139,7 @@ public:
|
|||
void save(const std::string &file) const;
|
||||
|
||||
//BBS: add json support
|
||||
void save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version) const;
|
||||
void save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version, const std::string is_custom = "") const;
|
||||
|
||||
// Set all the nullable values to nils.
|
||||
void null_nullables();
|
||||
|
|
|
@ -520,10 +520,10 @@ void Preset::save(DynamicPrintConfig* parent_config)
|
|||
ConfigOption *opt_dst = temp_config.option(option, true);
|
||||
opt_dst->set(opt_src);
|
||||
}
|
||||
temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string());
|
||||
temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined);
|
||||
}
|
||||
else
|
||||
this->config.save_to_json(this->file, this->name, from_str, this->version.to_string());
|
||||
this->config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined);
|
||||
|
||||
fs::path idx_file(this->file);
|
||||
idx_file.replace_extension(".info");
|
||||
|
@ -682,6 +682,13 @@ bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
|
|||
return is_bbl_vendor_preset;
|
||||
}
|
||||
|
||||
bool Preset::is_custom_defined()
|
||||
{
|
||||
if (custom_defined == "1")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::vector<std::string> s_Preset_print_options {
|
||||
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode",
|
||||
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
|
||||
|
@ -757,7 +764,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
|||
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "bed_exclude_area", "gcode_flavor",
|
||||
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
|
||||
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"default_print_profile", "inherits",
|
||||
|
@ -841,7 +848,7 @@ static std::vector<std::string> s_Preset_sla_material_options {
|
|||
|
||||
static std::vector<std::string> s_Preset_sla_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "printable_height",
|
||||
"printable_area","bed_custom_texture", "bed_custom_model", "printable_height",
|
||||
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
|
||||
"display_mirror_x", "display_mirror_y",
|
||||
"display_orientation",
|
||||
|
@ -1017,14 +1024,20 @@ void PresetCollection::load_presets(
|
|||
}
|
||||
preset.version = *version;
|
||||
|
||||
if (key_values.find(BBL_JSON_KEY_IS_CUSTOM) != key_values.end())
|
||||
preset.custom_defined = key_values[BBL_JSON_KEY_IS_CUSTOM];
|
||||
|
||||
//BBS: use inherit config as the base
|
||||
Preset* inherit_preset = nullptr;
|
||||
ConfigOption* inherits_config = config.option(BBL_JSON_KEY_INHERITS);
|
||||
|
||||
// check inherits_config
|
||||
if (inherits_config) {
|
||||
ConfigOptionString * option_str = dynamic_cast<ConfigOptionString *> (inherits_config);
|
||||
std::string inherits_value = option_str->value;
|
||||
|
||||
inherit_preset = this->find_preset(inherits_value, false, true);
|
||||
} else {
|
||||
;
|
||||
}
|
||||
const Preset& default_preset = this->default_preset_for(config);
|
||||
if (inherit_preset) {
|
||||
|
@ -1032,19 +1045,22 @@ void PresetCollection::load_presets(
|
|||
preset.filament_id = inherit_preset->filament_id;
|
||||
}
|
||||
else {
|
||||
if (!preset.is_custom_defined()) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
|
||||
continue;
|
||||
}
|
||||
//should not happen
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
|
||||
//BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
|
||||
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
|
||||
//preset.config = default_preset.config;
|
||||
continue;
|
||||
preset.config = default_preset.config;
|
||||
}
|
||||
preset.config.apply(std::move(config));
|
||||
Preset::normalize(preset.config);
|
||||
// Report configuration fields, which are misplaced into a wrong group.
|
||||
std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config);
|
||||
if (! incorrect_keys.empty())
|
||||
if (!incorrect_keys.empty())
|
||||
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" <<
|
||||
preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
|
||||
preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
|
||||
preset.loaded = true;
|
||||
//BBS: add some workaround for previous incorrect settings
|
||||
if ((!preset.setting_id.empty())&&(preset.setting_id == preset.base_id))
|
||||
|
@ -1352,25 +1368,29 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std:
|
|||
if (!preset->is_user()) continue;
|
||||
preset->file = path_from_name(preset->name);
|
||||
|
||||
//BBS: only save difference for user preset
|
||||
std::string inherits = Preset::inherits(preset->config);
|
||||
if (inherits.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name;
|
||||
// BBS add sync info
|
||||
preset->sync_info = "delete";
|
||||
need_to_delete_list.push_back(preset->setting_id);
|
||||
delete_name_list.push_back(preset->name);
|
||||
continue;
|
||||
}
|
||||
Preset* parent_preset = this->find_preset(inherits, false, true);
|
||||
if (!parent_preset) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits;
|
||||
continue;
|
||||
}
|
||||
if (preset->is_custom_defined()) {
|
||||
preset->save(nullptr);
|
||||
} else {
|
||||
//BBS: only save difference for user preset
|
||||
std::string inherits = Preset::inherits(preset->config);
|
||||
if (inherits.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name;
|
||||
// BBS add sync info
|
||||
preset->sync_info = "delete";
|
||||
need_to_delete_list.push_back(preset->setting_id);
|
||||
delete_name_list.push_back(preset->name);
|
||||
continue;
|
||||
}
|
||||
Preset* parent_preset = this->find_preset(inherits, false, true);
|
||||
if (!parent_preset) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preset->base_id.empty())
|
||||
preset->base_id = parent_preset->setting_id;
|
||||
preset->save(&(parent_preset->config));
|
||||
if (preset->base_id.empty())
|
||||
preset->base_id = parent_preset->setting_id;
|
||||
preset->save(&(parent_preset->config));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto delete_name: delete_name_list)
|
||||
|
@ -1596,11 +1616,11 @@ bool PresetCollection::validate_printers(const std::string &name, DynamicPrintCo
|
|||
|
||||
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
|
||||
// and select it, losing previous modifications.
|
||||
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select)
|
||||
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select, Semver file_version, bool is_custom_defined)
|
||||
{
|
||||
DynamicPrintConfig cfg(this->default_preset().config);
|
||||
cfg.apply_only(config, cfg.keys(), true);
|
||||
return this->load_preset(path, name, std::move(cfg), select);
|
||||
return this->load_preset(path, name, std::move(cfg), select, file_version, is_custom_defined);
|
||||
}
|
||||
|
||||
static bool profile_print_params_same(const DynamicPrintConfig &cfg_old, const DynamicPrintConfig &cfg_new)
|
||||
|
@ -1867,7 +1887,7 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
|
|||
return std::make_pair(&preset, false);
|
||||
}
|
||||
|
||||
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select)
|
||||
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select, Semver file_version, bool is_custom_defined)
|
||||
{
|
||||
lock();
|
||||
auto it = this->find_preset_internal(name);
|
||||
|
@ -1882,6 +1902,10 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string
|
|||
preset.config = std::move(config);
|
||||
preset.loaded = true;
|
||||
preset.is_dirty = false;
|
||||
preset.custom_defined = is_custom_defined ? "1": "0";
|
||||
//BBS
|
||||
if (file_version.valid())
|
||||
preset.version = file_version;
|
||||
if (select)
|
||||
this->select_preset_by_name(name, true);
|
||||
unlock();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
//BBS: add json support
|
||||
#define BBL_JSON_KEY_VERSION "version"
|
||||
#define BBL_JSON_KEY_IS_CUSTOM "is_custom_defined"
|
||||
#define BBL_JSON_KEY_URL "url"
|
||||
#define BBL_JSON_KEY_NAME "name"
|
||||
#define BBL_JSON_KEY_DESCRIPTION "description"
|
||||
|
@ -229,6 +230,7 @@ public:
|
|||
std::string user_id; // preset user_id
|
||||
std::string base_id; // base id of preset
|
||||
std::string sync_info; // enum: "delete", "create", "update", ""
|
||||
std::string custom_defined; // enum: "1", "0", ""
|
||||
long long updated_time{0}; //last updated time
|
||||
std::map<std::string, std::string> key_values;
|
||||
|
||||
|
@ -300,6 +302,8 @@ public:
|
|||
|
||||
bool is_bbl_vendor_preset(PresetBundle *preset_bundle);
|
||||
|
||||
bool is_custom_defined();
|
||||
|
||||
static const std::vector<std::string>& print_options();
|
||||
static const std::vector<std::string>& filament_options();
|
||||
// Printer options contain the nozzle options.
|
||||
|
@ -434,8 +438,8 @@ public:
|
|||
|
||||
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
|
||||
// and select it, losing previous modifications.
|
||||
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true);
|
||||
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true);
|
||||
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
|
||||
// Returns a loaded preset, returns true if an existing preset was selected AND modified from config.
|
||||
// In that case the successive filament loaded for a multi material printer should not be modified, but
|
||||
|
|
|
@ -1756,7 +1756,7 @@ ConfigSubstitutions PresetBundle::load_config_file(const std::string &path, Forw
|
|||
|
||||
// Load a config file from a boost property_tree. This is a private method called from load_config_file.
|
||||
// is_external == false on if called from ConfigWizard
|
||||
void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version)
|
||||
void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version, bool selected, bool is_custom_defined)
|
||||
{
|
||||
PrinterTechnology printer_technology = Preset::printer_technology(config);
|
||||
|
||||
|
@ -1826,7 +1826,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
[&config, &inherits, &inherits_values,
|
||||
&compatible_printers_condition, &compatible_printers_condition_values,
|
||||
&compatible_prints_condition, &compatible_prints_condition_values,
|
||||
is_external, &name, &name_or_path, file_version]
|
||||
is_external, &name, &name_or_path, file_version, selected, is_custom_defined]
|
||||
(PresetCollection &presets, size_t idx, const std::string &key, const std::set<std::string> &different_keys, std::string filament_id) {
|
||||
// Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles.
|
||||
inherits = inherits_values[idx];
|
||||
|
@ -1838,7 +1838,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
if (is_external)
|
||||
presets.load_external_preset(name_or_path, name, config.opt_string(key, true), config, different_keys, PresetCollection::LoadAndSelect::Always, file_version, filament_id);
|
||||
else
|
||||
presets.load_preset(presets.path_from_name(name), name, config).save(nullptr);
|
||||
presets.load_preset(presets.path_from_name(name), name, config, selected, file_version, is_custom_defined).save(nullptr);
|
||||
};
|
||||
|
||||
switch (Preset::printer_technology(config)) {
|
||||
|
@ -1899,7 +1899,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
loaded = this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config, filament_different_keys_set, PresetCollection::LoadAndSelect::Always, file_version, filament_id).first;
|
||||
else {
|
||||
// called from Config Wizard.
|
||||
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config);
|
||||
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config, true, file_version, is_custom_defined);
|
||||
loaded->save(nullptr);
|
||||
}
|
||||
this->filament_presets.clear();
|
||||
|
|
|
@ -126,8 +126,8 @@ public:
|
|||
|
||||
// Load user configuration and store it into the user profiles.
|
||||
// This method is called by the configuration wizard.
|
||||
void load_config_from_wizard(const std::string &name, DynamicPrintConfig config)
|
||||
{ this->load_config_file_config(name, false, std::move(config)); }
|
||||
void load_config_from_wizard(const std::string &name, DynamicPrintConfig config, Semver file_version, bool is_custom_defined = false)
|
||||
{ this->load_config_file_config(name, false, std::move(config), file_version, true, is_custom_defined); }
|
||||
|
||||
// Load configuration that comes from a model file containing configuration, such as 3MF et al.
|
||||
// This method is called by the Plater.
|
||||
|
@ -225,7 +225,7 @@ private:
|
|||
// Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path.
|
||||
// and the external config is just referenced, not stored into user profile directory.
|
||||
// If it is not an external config, then the config will be stored into the user profile directory.
|
||||
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version = Semver());
|
||||
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version = Semver(), bool selected = false, bool is_custom_defined = false);
|
||||
/*ConfigSubstitutions load_config_file_config_bundle(
|
||||
const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule);*/
|
||||
|
||||
|
|
|
@ -329,6 +329,16 @@ void PrintConfigDef::init_common_params()
|
|||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) });
|
||||
|
||||
def = this->add("bed_custom_texture", coString);
|
||||
def->label = L("Bed custom texture");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("bed_custom_model", coString);
|
||||
def->label = L("Bed custom model");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("elefant_foot_compensation", coFloat);
|
||||
def->label = L("Elephant foot compensation");
|
||||
def->category = L("Quality");
|
||||
|
@ -1408,29 +1418,29 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("What kind of gcode the printer is compatible with");
|
||||
def->enum_keys_map = &ConfigOptionEnum<GCodeFlavor>::get_enum_values();
|
||||
def->enum_values.push_back("marlin");
|
||||
//def->enum_values.push_back("reprap");
|
||||
//def->enum_values.push_back("reprapfirmware");
|
||||
//def->enum_values.push_back("repetier");
|
||||
//def->enum_values.push_back("teacup");
|
||||
//def->enum_values.push_back("makerware");
|
||||
//def->enum_values.push_back("marlin2");
|
||||
//def->enum_values.push_back("sailfish");
|
||||
//def->enum_values.push_back("mach3");
|
||||
//def->enum_values.push_back("machinekit");
|
||||
//def->enum_values.push_back("smoothie");
|
||||
//def->enum_values.push_back("no-extrusion");
|
||||
/*def->enum_values.push_back("reprap");
|
||||
def->enum_values.push_back("reprapfirmware");
|
||||
def->enum_values.push_back("repetier");
|
||||
def->enum_values.push_back("teacup");
|
||||
def->enum_values.push_back("makerware");
|
||||
def->enum_values.push_back("marlin2");
|
||||
def->enum_values.push_back("sailfish");
|
||||
def->enum_values.push_back("mach3");
|
||||
def->enum_values.push_back("machinekit");
|
||||
def->enum_values.push_back("smoothie");
|
||||
def->enum_values.push_back("no-extrusion");*/
|
||||
def->enum_labels.push_back("Marlin(legacy)");
|
||||
//def->enum_labels.push_back("RepRap/Sprinter");
|
||||
//def->enum_labels.push_back("RepRapFirmware");
|
||||
//def->enum_labels.push_back("Repetier");
|
||||
//def->enum_labels.push_back("Teacup");
|
||||
//def->enum_labels.push_back("MakerWare (MakerBot)");
|
||||
//def->enum_labels.push_back("Marlin 2");
|
||||
//def->enum_labels.push_back("Sailfish (MakerBot)");
|
||||
//def->enum_labels.push_back("Mach3/LinuxCNC");
|
||||
//def->enum_labels.push_back("Machinekit");
|
||||
//def->enum_labels.push_back("Smoothie");
|
||||
//def->enum_labels.push_back(L("No extrusion"));
|
||||
/*def->enum_labels.push_back("RepRap/Sprinter");
|
||||
def->enum_labels.push_back("RepRapFirmware");
|
||||
def->enum_labels.push_back("Repetier");
|
||||
def->enum_labels.push_back("Teacup");
|
||||
def->enum_labels.push_back("MakerWare (MakerBot)");
|
||||
def->enum_labels.push_back("Marlin 2");
|
||||
def->enum_labels.push_back("Sailfish (MakerBot)");
|
||||
def->enum_labels.push_back("Mach3/LinuxCNC");
|
||||
def->enum_labels.push_back("Machinekit");
|
||||
def->enum_labels.push_back("Smoothie");
|
||||
def->enum_labels.push_back(L("No extrusion"));*/
|
||||
def->mode = comAdvanced;
|
||||
def->readonly = false;
|
||||
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfMarlinLegacy));
|
||||
|
@ -3894,6 +3904,16 @@ std::string DynamicPrintConfig::get_filament_type(std::string &displayed_filamen
|
|||
return "PLA";
|
||||
}
|
||||
|
||||
bool DynamicPrintConfig::is_custom_defined()
|
||||
{
|
||||
auto* is_custom_defined = dynamic_cast<const ConfigOptionStrings*>(this->option("is_custom_defined"));
|
||||
if (!is_custom_defined || is_custom_defined->empty())
|
||||
return false;
|
||||
if (is_custom_defined->get_at(0) == "1")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//FIXME localize this function.
|
||||
std::string validate(const FullPrintConfig &cfg)
|
||||
{
|
||||
|
|
|
@ -357,6 +357,8 @@ public:
|
|||
|
||||
//BBS special case Support G/ Support W
|
||||
std::string get_filament_type(std::string &displayed_filament_type, int id = 0);
|
||||
|
||||
bool is_custom_defined();
|
||||
};
|
||||
|
||||
void handle_legacy_sla(DynamicPrintConfig &config);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue