From 6b2b970b9ae1f00b6c1fd4bcbb4e01c15860918e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Jun 2018 13:57:37 +0200 Subject: [PATCH 01/12] Added machine evelope configuration parameters (the MachineEnvelopeConfig class). Added localization support for libslic3r through a callback (the callback is not registered yet, so the localization does nothing). Localized the Print::validate() error messages. --- xs/src/libslic3r/Config.hpp | 2 + xs/src/libslic3r/GCode.cpp | 2 +- xs/src/libslic3r/I18N.hpp | 16 ++++++ xs/src/libslic3r/Print.cpp | 57 ++++++++++----------- xs/src/libslic3r/PrintConfig.cpp | 85 +++++++++++++++++++++++++++++++- xs/src/libslic3r/PrintConfig.hpp | 53 +++++++++++++++++++- xs/src/libslic3r/utils.cpp | 4 ++ xs/xsp/Config.xsp | 6 +-- xs/xsp/Print.xsp | 2 +- 9 files changed, 189 insertions(+), 38 deletions(-) create mode 100644 xs/src/libslic3r/I18N.hpp diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index bde1eb651..377bdbea4 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -291,6 +291,8 @@ public: ConfigOptionFloats() : ConfigOptionVector() {} explicit ConfigOptionFloats(size_t n, double value) : ConfigOptionVector(n, value) {} explicit ConfigOptionFloats(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} + explicit ConfigOptionFloats(const std::vector &vec) : ConfigOptionVector(vec) {} + explicit ConfigOptionFloats(std::vector &&vec) : ConfigOptionVector(std::move(vec)) {} static ConfigOptionType static_type() { return coFloats; } ConfigOptionType type() const override { return static_type(); } diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b581b3e76..479af7abe 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1411,7 +1411,7 @@ void GCode::apply_print_config(const PrintConfig &print_config) void GCode::append_full_config(const Print& print, std::string& str) { - const StaticPrintConfig *configs[] = { &print.config, &print.default_object_config, &print.default_region_config }; + const StaticPrintConfig *configs[] = { static_cast(&print.config), &print.default_object_config, &print.default_region_config }; for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) { const StaticPrintConfig *cfg = configs[i]; for (const std::string &key : cfg->keys()) diff --git a/xs/src/libslic3r/I18N.hpp b/xs/src/libslic3r/I18N.hpp new file mode 100644 index 000000000..bc9345f11 --- /dev/null +++ b/xs/src/libslic3r/I18N.hpp @@ -0,0 +1,16 @@ +#ifndef slic3r_I18N_hpp_ +#define slic3r_I18N_hpp_ + +#include + +namespace Slic3r { + +typedef std::string (*translate_fn_type)(const char*); +extern translate_fn_type translate_fn; +inline void set_translate_callback(translate_fn_type fn) { translate_fn = fn; } +inline std::string translate(const std::string &s) { return (translate_fn == nullptr) ? s : (*translate_fn)(s.c_str()); } +inline std::string translate(const char *ptr) { return (translate_fn == nullptr) ? std::string(ptr) : (*translate_fn)(ptr); } + +} // namespace Slic3r + +#endif /* slic3r_I18N_hpp_ */ diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 08802139d..c8d3ccde1 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -4,6 +4,7 @@ #include "Extruder.hpp" #include "Flow.hpp" #include "Geometry.hpp" +#include "I18N.hpp" #include "SupportMaterial.hpp" #include "GCode/WipeTowerPrusaMM.hpp" #include @@ -11,6 +12,10 @@ #include #include +//! macro used to mark string used at localization, +//! return same string +#define L(s) translate(s) + namespace Slic3r { template class PrintState; @@ -523,7 +528,7 @@ std::string Print::validate() const print_volume.min.z = -1e10; for (PrintObject *po : this->objects) { if (!print_volume.contains(po->model_object()->tight_bounding_box(false))) - return "Some objects are outside of the print volume."; + return L("Some objects are outside of the print volume."); } if (this->config.complete_objects) { @@ -550,7 +555,7 @@ std::string Print::validate() const Polygon p = convex_hull; p.translate(copy); if (! intersection(convex_hulls_other, p).empty()) - return "Some objects are too close; your extruder will collide with them."; + return L("Some objects are too close; your extruder will collide with them."); polygons_append(convex_hulls_other, p); } } @@ -565,7 +570,7 @@ std::string Print::validate() const // it will be printed as last one so its height doesn't matter. object_height.pop_back(); if (! object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value)) - return "Some objects are too tall and cannot be printed without extruder collisions."; + return L("Some objects are too tall and cannot be printed without extruder collisions."); } } // end if (this->config.complete_objects) @@ -575,27 +580,22 @@ std::string Print::validate() const total_copies_count += object->copies().size(); // #4043 if (total_copies_count > 1 && ! this->config.complete_objects.value) - return "The Spiral Vase option can only be used when printing a single object."; + return L("The Spiral Vase option can only be used when printing a single object."); if (this->regions.size() > 1) - return "The Spiral Vase option can only be used when printing single material objects."; + return L("The Spiral Vase option can only be used when printing single material objects."); } if (this->config.single_extruder_multi_material) { for (size_t i=1; iconfig.nozzle_diameter.values.size(); ++i) if (this->config.nozzle_diameter.values[i] != this->config.nozzle_diameter.values[i-1]) - return "All extruders must have the same diameter for single extruder multimaterial printer."; + return L("All extruders must have the same diameter for single extruder multimaterial printer."); } if (this->has_wipe_tower() && ! this->objects.empty()) { - #if 0 - for (auto dmr : this->config.nozzle_diameter.values) - if (std::abs(dmr - 0.4) > EPSILON) - return "The Wipe Tower is currently only supported for the 0.4mm nozzle diameter."; - #endif if (this->config.gcode_flavor != gcfRepRap && this->config.gcode_flavor != gcfMarlin) - return "The Wipe Tower is currently only supported for the Marlin and RepRap/Sprinter G-code flavors."; + return L("The Wipe Tower is currently only supported for the Marlin and RepRap/Sprinter G-code flavors."); if (! this->config.use_relative_e_distances) - return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."; + return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."); SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters(); const PrintObject* tallest_object = this->objects.front(); // let's find the tallest object @@ -607,13 +607,13 @@ std::string Print::validate() const SlicingParameters slicing_params = object->slicing_parameters(); if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON || std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON) - return "The Wipe Tower is only supported for multiple objects if they have equal layer heigths"; + return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths"); if (slicing_params.raft_layers() != slicing_params0.raft_layers()) - return "The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers"; + return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers"); if (object->config.support_material_contact_distance != this->objects.front()->config.support_material_contact_distance) - return "The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance"; + return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance"); if (! equal_layering(slicing_params, slicing_params0)) - return "The Wipe Tower is only supported for multiple objects if they are sliced equally."; + return L("The Wipe Tower is only supported for multiple objects if they are sliced equally."); bool was_layer_height_profile_valid = object->layer_height_profile_valid; object->update_layer_height_profile(); object->layer_height_profile_valid = was_layer_height_profile_valid; @@ -637,13 +637,8 @@ std::string Print::validate() const failed = true; if (failed) - return "The Wipe tower is only supported if all objects have the same layer height profile"; + return L("The Wipe tower is only supported if all objects have the same layer height profile"); } - - /*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) - if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON && - std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON) - return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";*/ } } @@ -651,7 +646,7 @@ std::string Print::validate() const // find the smallest nozzle diameter std::vector extruders = this->extruders(); if (extruders.empty()) - return "The supplied settings will cause an empty print."; + return L("The supplied settings will cause an empty print."); std::vector nozzle_diameters; for (unsigned int extruder_id : extruders) @@ -661,7 +656,7 @@ std::string Print::validate() const unsigned int total_extruders_count = this->config.nozzle_diameter.size(); for (const auto& extruder_idx : extruders) if ( extruder_idx >= total_extruders_count ) - return "One or more object were assigned an extruder that the printer does not have."; + return L("One or more object were assigned an extruder that the printer does not have."); for (PrintObject *object : this->objects) { if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) && @@ -670,13 +665,13 @@ std::string Print::validate() const // will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles // are of the same diameter. if (nozzle_diameters.size() > 1) - return "Printing with multiple extruders of differing nozzle diameters. " + return L("Printing with multiple extruders of differing nozzle diameters. " "If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), " - "all nozzles have to be of the same diameter."; + "all nozzles have to be of the same diameter."); } // validate first_layer_height - double first_layer_height = object->config.get_abs_value("first_layer_height"); + double first_layer_height = object->config.get_abs_value(L("first_layer_height")); double first_layer_min_nozzle_diameter; if (object->config.raft_layers > 0) { // if we have raft layers, only support material extruder is used on first layer @@ -691,11 +686,11 @@ std::string Print::validate() const first_layer_min_nozzle_diameter = min_nozzle_diameter; } if (first_layer_height > first_layer_min_nozzle_diameter) - return "First layer height can't be greater than nozzle diameter"; + return L("First layer height can't be greater than nozzle diameter"); // validate layer_height if (object->config.layer_height.value > min_nozzle_diameter) - return "Layer height can't be greater than nozzle diameter"; + return L("Layer height can't be greater than nozzle diameter"); } } @@ -1212,7 +1207,7 @@ std::string Print::output_filename() try { return this->placeholder_parser.process(this->config.output_filename_format.value, 0); } catch (std::runtime_error &err) { - throw std::runtime_error(std::string("Failed processing of the output_filename_format template.\n") + err.what()); + throw std::runtime_error(L("Failed processing of the output_filename_format template.") + "\n" + err.what()); } } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index b77a3a76e..c5e520b4f 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1,7 +1,10 @@ #include "PrintConfig.hpp" +#include "I18N.hpp" #include #include +#include +#include #include #include @@ -11,7 +14,7 @@ namespace Slic3r { //! macro used to mark string used at localization, //! return same string -#define L(s) s +#define L(s) translate(s) PrintConfigDef::PrintConfigDef() { @@ -853,6 +856,85 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloat(0.3); + { + struct AxisDefault { + std::string name; + std::vector max_feedrate; + std::vector max_acceleration; + std::vector max_jerk; + }; + std::vector axes { + // name, max_feedrate, max_acceleration, max_jerk + { "x", { 200., 200. }, { 1000., 1000. }, { 10., 10. } }, + { "y", { 200., 200. }, { 1000., 1000. }, { 10., 10. } }, + { "z", { 12., 12. }, { 200., 200. }, { 0.4, 0.4 } }, + { "e", { 120., 120. }, { 5000., 5000. }, { 2.5, 2.5 } } + }; + for (const AxisDefault &axis : axes) { + std::string axis_upper = boost::to_upper_copy(axis.name); + // Add the machine feedrate limits for XYZE axes. (M203) + def = this->add("machine_max_feedrate_" + axis.name, coFloats); + def->label = (boost::format(L("Maximum feedrate %1%")) % axis_upper).str(); + def->category = L("Machine limits"); + def->tooltip = (boost::format(L("Maximum feedrate of the %1% axis")) % axis_upper).str(); + def->sidetext = L("mm/s"); + def->min = 0; + def->default_value = new ConfigOptionFloats(axis.max_feedrate); + // Add the machine acceleration limits for XYZE axes (M201) + def = this->add("machine_max_acceleration_" + axis.name, coFloats); + def->label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str(); + def->category = L("Machine limits"); + def->tooltip = (boost::format(L("Maximum acceleration of the %1% axis")) % axis_upper).str(); + def->sidetext = L("mm/s²"); + def->min = 0; + def->default_value = new ConfigOptionFloats(axis.max_acceleration); + // Add the machine jerk limits for XYZE axes (M205) + def = this->add("machine_max_jerk_" + axis.name, coFloats); + def->label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str(); + def->category = L("Machine limits"); + def->tooltip = (boost::format(L("Maximum jerk of the %1% axis")) % axis_upper).str(); + def->sidetext = L("mm/s"); + def->min = 0; + def->default_value = new ConfigOptionFloats(axis.max_jerk); + } + } + + // M205 S... [mm/sec] + def = this->add("machine_min_extruding_rate", coFloats); + def->label = L("Minimum feedrate when extruding"); + def->category = L("Machine limits"); + def->tooltip = L("Minimum feedrate when extruding") + " (M205 S)"; + def->sidetext = L("mm/s"); + def->min = 0; + def->default_value = new ConfigOptionFloats(0., 0.); + + // M205 T... [mm/sec] + def = this->add("machine_min_travel_rate", coFloats); + def->label = L("Minimum travel feedrate"); + def->category = L("Machine limits"); + def->tooltip = L("Minimum travel feedrate") + " (M205 T)"; + def->sidetext = L("mm/s"); + def->min = 0; + def->default_value = new ConfigOptionFloats(0., 0.); + + // M204 S... [mm/sec^2] + def = this->add("machine_max_acceleration_extruding", coFloats); + def->label = L("Maximum acceleration when extruding"); + def->category = L("Machine limits"); + def->tooltip = L("Maximum acceleration when extruding") + " (M204 S)"; + def->sidetext = L("mm/s²"); + def->min = 0; + def->default_value = new ConfigOptionFloats(1250., 1250.); + + // M204 T... [mm/sec^2] + def = this->add("machine_max_acceleration_retracting", coFloats); + def->label = L("Maximum acceleration when retracting"); + def->category = L("Machine limits"); + def->tooltip = L("Maximum acceleration when retracting") + " (M204 T)"; + def->sidetext = L("mm/s²"); + def->min = 0; + def->default_value = new ConfigOptionFloats(1250., 1250.); + def = this->add("max_fan_speed", coInts); def->label = L("Max"); def->tooltip = L("This setting represents the maximum speed of your fan."); @@ -2198,6 +2280,7 @@ std::string FullPrintConfig::validate() // Declare the static caches for each StaticPrintConfig derived class. StaticPrintConfig::StaticCache PrintObjectConfig::s_cache_PrintObjectConfig; StaticPrintConfig::StaticCache PrintRegionConfig::s_cache_PrintRegionConfig; +StaticPrintConfig::StaticCache MachineEnvelopeConfig::s_cache_MachineEnvelopeConfig; StaticPrintConfig::StaticCache GCodeConfig::s_cache_GCodeConfig; StaticPrintConfig::StaticCache PrintConfig::s_cache_PrintConfig; StaticPrintConfig::StaticCache HostConfig::s_cache_HostConfig; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 2e36ca665..f3be03c2a 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -455,6 +455,56 @@ protected: } }; +class MachineEnvelopeConfig : public StaticPrintConfig +{ + STATIC_PRINT_CONFIG_CACHE(MachineEnvelopeConfig) +public: + // M201 X... Y... Z... E... [mm/sec^2] + ConfigOptionFloats machine_max_acceleration_x; + ConfigOptionFloats machine_max_acceleration_y; + ConfigOptionFloats machine_max_acceleration_z; + ConfigOptionFloats machine_max_acceleration_e; + // M203 X... Y... Z... E... [mm/sec] + ConfigOptionFloats machine_max_feedrate_x; + ConfigOptionFloats machine_max_feedrate_y; + ConfigOptionFloats machine_max_feedrate_z; + ConfigOptionFloats machine_max_feedrate_e; + // M204 S... [mm/sec^2] + ConfigOptionFloats machine_max_acceleration_extruding; + // M204 T... [mm/sec^2] + ConfigOptionFloats machine_max_acceleration_retracting; + // M205 X... Y... Z... E... [mm/sec] + ConfigOptionFloats machine_max_jerk_x; + ConfigOptionFloats machine_max_jerk_y; + ConfigOptionFloats machine_max_jerk_z; + ConfigOptionFloats machine_max_jerk_e; + // M205 T... [mm/sec] + ConfigOptionFloats machine_min_travel_rate; + // M205 S... [mm/sec] + ConfigOptionFloats machine_min_extruding_rate; + +protected: + void initialize(StaticCacheBase &cache, const char *base_ptr) + { + OPT_PTR(machine_max_acceleration_x); + OPT_PTR(machine_max_acceleration_y); + OPT_PTR(machine_max_acceleration_z); + OPT_PTR(machine_max_acceleration_e); + OPT_PTR(machine_max_feedrate_x); + OPT_PTR(machine_max_feedrate_y); + OPT_PTR(machine_max_feedrate_z); + OPT_PTR(machine_max_feedrate_e); + OPT_PTR(machine_max_acceleration_extruding); + OPT_PTR(machine_max_acceleration_retracting); + OPT_PTR(machine_max_jerk_x); + OPT_PTR(machine_max_jerk_y); + OPT_PTR(machine_max_jerk_z); + OPT_PTR(machine_max_jerk_e); + OPT_PTR(machine_min_travel_rate); + OPT_PTR(machine_min_extruding_rate); + } +}; + // This object is mapped to Perl as Slic3r::Config::GCode. class GCodeConfig : public StaticPrintConfig { @@ -566,7 +616,7 @@ protected: }; // This object is mapped to Perl as Slic3r::Config::Print. -class PrintConfig : public GCodeConfig +class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig { STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig) PrintConfig() : GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); } @@ -642,6 +692,7 @@ protected: PrintConfig(int) : GCodeConfig(1) {} void initialize(StaticCacheBase &cache, const char *base_ptr) { + this->MachineEnvelopeConfig::initialize(cache, base_ptr); this->GCodeConfig::initialize(cache, base_ptr); OPT_PTR(avoid_crossing_perimeters); OPT_PTR(bed_shape); diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 745d07fcd..2d177da3c 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -1,4 +1,5 @@ #include "Utils.hpp" +#include "I18N.hpp" #include #include @@ -123,6 +124,9 @@ const std::string& localization_dir() return g_local_dir; } +// Translate function callback, to call wxWidgets translate function to convert non-localized UTF8 string to a localized one. +translate_fn_type translate_fn = nullptr; + static std::string g_data_dir; void set_data_dir(const std::string &dir) diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 6adfc49a2..b8ad84ba4 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -74,13 +74,13 @@ static StaticPrintConfig* new_GCodeConfig() %code{% RETVAL = new GCodeConfig(); %}; static StaticPrintConfig* new_PrintConfig() - %code{% RETVAL = new PrintConfig(); %}; + %code{% RETVAL = static_cast(new PrintConfig()); %}; static StaticPrintConfig* new_PrintObjectConfig() %code{% RETVAL = new PrintObjectConfig(); %}; static StaticPrintConfig* new_PrintRegionConfig() %code{% RETVAL = new PrintRegionConfig(); %}; static StaticPrintConfig* new_FullPrintConfig() - %code{% RETVAL = static_cast(new FullPrintConfig()); %}; + %code{% RETVAL = static_cast(new FullPrintConfig()); %}; ~StaticPrintConfig(); bool has(t_config_option_key opt_key); SV* as_hash() @@ -119,7 +119,7 @@ auto config = new FullPrintConfig(); try { config->load(path); - RETVAL = static_cast(config); + RETVAL = static_cast(config); } catch (std::exception& e) { delete config; croak("Error extracting configuration from %s:\n%s\n", path, e.what()); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index b53b5e82d..e336131d0 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -133,7 +133,7 @@ _constant() ~Print(); Ref config() - %code%{ RETVAL = &THIS->config; %}; + %code%{ RETVAL = static_cast(&THIS->config); %}; Ref default_object_config() %code%{ RETVAL = &THIS->default_object_config; %}; Ref default_region_config() From 02d4f3e14d0347e9bddd8d7c6d8ffaa7ad19010e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Jun 2018 18:33:46 +0200 Subject: [PATCH 02/12] Provide a callback to libslic3r to translate texts. Moved the "translate" functions to namespaces to avoid clashes between the code in libslic3r and Slic3r GUI projects. --- resources/localization/list.txt | 1 + xs/src/libslic3r/I18N.hpp | 12 +++++++----- xs/src/libslic3r/PrintConfig.cpp | 2 +- xs/src/libslic3r/utils.cpp | 2 +- xs/src/slic3r/GUI/GUI.cpp | 6 +++++- xs/src/slic3r/GUI/GUI.hpp | 13 ++++++++----- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/resources/localization/list.txt b/resources/localization/list.txt index 0fd528994..bc545b1bf 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -21,6 +21,7 @@ xs/src/slic3r/GUI/UpdateDialogs.cpp xs/src/slic3r/GUI/WipeTowerDialog.cpp xs/src/slic3r/Utils/OctoPrint.cpp xs/src/slic3r/Utils/PresetUpdater.cpp +xs/src/libslic3r/Print.cpp xs/src/libslic3r/PrintConfig.cpp xs/src/libslic3r/GCode/PreviewData.cpp lib/Slic3r/GUI.pm diff --git a/xs/src/libslic3r/I18N.hpp b/xs/src/libslic3r/I18N.hpp index bc9345f11..db4fd22df 100644 --- a/xs/src/libslic3r/I18N.hpp +++ b/xs/src/libslic3r/I18N.hpp @@ -5,11 +5,13 @@ namespace Slic3r { -typedef std::string (*translate_fn_type)(const char*); -extern translate_fn_type translate_fn; -inline void set_translate_callback(translate_fn_type fn) { translate_fn = fn; } -inline std::string translate(const std::string &s) { return (translate_fn == nullptr) ? s : (*translate_fn)(s.c_str()); } -inline std::string translate(const char *ptr) { return (translate_fn == nullptr) ? std::string(ptr) : (*translate_fn)(ptr); } +namespace I18N { + typedef std::string (*translate_fn_type)(const char*); + extern translate_fn_type translate_fn; + inline void set_translate_callback(translate_fn_type fn) { translate_fn = fn; } + inline std::string translate(const std::string &s) { return (translate_fn == nullptr) ? s : (*translate_fn)(s.c_str()); } + inline std::string translate(const char *ptr) { return (translate_fn == nullptr) ? std::string(ptr) : (*translate_fn)(ptr); } +} // namespace I18N } // namespace Slic3r diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index c5e520b4f..486e6fe18 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -14,7 +14,7 @@ namespace Slic3r { //! macro used to mark string used at localization, //! return same string -#define L(s) translate(s) +#define L(s) Slic3r::I18N::translate(s) PrintConfigDef::PrintConfigDef() { diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 2d177da3c..991118c14 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -125,7 +125,7 @@ const std::string& localization_dir() } // Translate function callback, to call wxWidgets translate function to convert non-localized UTF8 string to a localized one. -translate_fn_type translate_fn = nullptr; +Slic3r::I18N::translate_fn_type Slic3r::I18N::translate_fn = nullptr; static std::string g_data_dir; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index e2f3925fc..825c37dce 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -56,7 +56,7 @@ #include "../Utils/PresetUpdater.hpp" #include "../Config/Snapshot.hpp" - +#include "libslic3r/I18N.hpp" namespace Slic3r { namespace GUI { @@ -149,9 +149,13 @@ void update_label_colours_from_appconfig() } } +static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)); } + void set_wxapp(wxApp *app) { g_wxApp = app; + // Let the libslic3r know the callback, which will translate messages on demand. + Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); init_label_colours(); } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 285354446..83052cb6e 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -33,11 +33,14 @@ class PresetUpdater; class DynamicPrintConfig; class TabIface; -#define _(s) Slic3r::translate((s)) -inline wxString translate(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)); } -inline wxString translate(const wchar_t *s) { return wxGetTranslation(s); } -inline wxString translate(const std::string &s) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)); } -inline wxString translate(const std::wstring &s) { return wxGetTranslation(s.c_str()); } +#define _(s) Slic3r::GUI::I18N::translate((s)) + +namespace GUI { namespace I18N { + inline wxString translate(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)); } + inline wxString translate(const wchar_t *s) { return wxGetTranslation(s); } + inline wxString translate(const std::string &s) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)); } + inline wxString translate(const std::wstring &s) { return wxGetTranslation(s.c_str()); } +} } // !!! If you needed to translate some wxString, // !!! please use _(L(string)) From ac011aec6dd2793b1e5590e4dccafa618f378c2d Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Jun 2018 18:55:31 +0200 Subject: [PATCH 03/12] Removed dependencies of libslic3r on Slic3r GUI library. --- xs/src/libslic3r/GCode/PreviewData.cpp | 15 ++++++++------- xs/src/libslic3r/Print.cpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/xs/src/libslic3r/GCode/PreviewData.cpp b/xs/src/libslic3r/GCode/PreviewData.cpp index 40f0747b2..3833bca06 100644 --- a/xs/src/libslic3r/GCode/PreviewData.cpp +++ b/xs/src/libslic3r/GCode/PreviewData.cpp @@ -2,7 +2,12 @@ #include "PreviewData.hpp" #include #include -#include "slic3r/GUI/GUI.hpp" +#include + +#include + +//! macro used to mark string used at localization, +#define L(s) (s) namespace Slic3r { @@ -405,7 +410,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: items.reserve(last_valid - first_valid + 1); for (unsigned int i = (unsigned int)first_valid; i <= (unsigned int)last_valid; ++i) { - items.emplace_back(_CHB(extrusion.role_names[i].c_str()).data(), extrusion.role_colors[i]); + items.emplace_back(Slic3r::I18N::translate(extrusion.role_names[i]), extrusion.role_colors[i]); } break; @@ -436,13 +441,9 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: items.reserve(tools_colors_count); for (unsigned int i = 0; i < tools_colors_count; ++i) { - char buf[MIN_BUF_LENGTH_FOR_L]; - sprintf(buf, _CHB(L("Extruder %d")), i + 1); - GCodePreviewData::Color color; ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); - - items.emplace_back(buf, color); + items.emplace_back((boost::format(Slic3r::I18N::translate(L("Extruder %d"))) % (i + 1)).str(), color); } break; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index c8d3ccde1..5dc84cc72 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -14,7 +14,7 @@ //! macro used to mark string used at localization, //! return same string -#define L(s) translate(s) +#define L(s) Slic3r::I18N::translate(s) namespace Slic3r { From 3a2b501012419b636b525b341e2c7613c97162e3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Jun 2018 19:07:55 +0200 Subject: [PATCH 04/12] Fixed compilation on OSX --- xs/src/slic3r/GUI/GUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 825c37dce..642866606 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -149,7 +149,7 @@ void update_label_colours_from_appconfig() } } -static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)); } +static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str(); } void set_wxapp(wxApp *app) { From 8abe1b3633b9fe6f304eeac2feb7aeeeae0bf8e8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 20 Jun 2018 19:26:19 +0200 Subject: [PATCH 05/12] Yet another fix for the OSX. --- xs/src/slic3r/GUI/GUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 642866606..0360d73d0 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -149,7 +149,7 @@ void update_label_colours_from_appconfig() } } -static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str(); } +static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } void set_wxapp(wxApp *app) { From 082ed95a943554d27f0bbf8815c1db76d1208515 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 22 Jun 2018 14:17:03 +0200 Subject: [PATCH 06/12] Activate existing projects after loading AMF/3MF/Config: Initial implementation. --- xs/src/libslic3r/GCode.cpp | 5 ++-- xs/src/slic3r/GUI/Preset.cpp | 45 +++++++++++++++++++++++++++++- xs/src/slic3r/GUI/Preset.hpp | 12 ++++++++ xs/src/slic3r/GUI/PresetBundle.cpp | 30 +++++++++++--------- 4 files changed, 76 insertions(+), 16 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 479af7abe..009493113 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1415,11 +1415,12 @@ void GCode::append_full_config(const Print& print, std::string& str) for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) { const StaticPrintConfig *cfg = configs[i]; for (const std::string &key : cfg->keys()) - { if (key != "compatible_printers") str += "; " + key + " = " + cfg->serialize(key) + "\n"; - } } + const DynamicConfig &full_config = print.placeholder_parser.config(); + for (const char *key : { "print_settings_id", "filament_settings_id", "printer_settings_id" }) + str += std::string("; ") + key + " = " + full_config.serialize(key) + "\n"; } void GCode::set_extruders(const std::vector &extruder_ids) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 68982185b..d9774bfc2 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -424,7 +424,50 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string { DynamicPrintConfig cfg(this->default_preset().config); cfg.apply_only(config, cfg.keys(), true); - return this->load_preset(path, name, std::move(cfg)); + return this->load_preset(path, name, std::move(cfg), select); +} + +// Load a preset from an already parsed config file, insert it into the sorted sequence of presets +// and select it, losing previous modifications. +// In case +Preset& PresetCollection::load_external_preset( + // Path to the profile source file (a G-code, an AMF or 3MF file, a config file) + const std::string &path, + // Name of the profile, derived from the source file name. + const std::string &name, + // Original name of the profile, extracted from the loaded config. Empty, if the name has not been stored. + const std::string &original_name, + // Config to initialize the preset from. + const DynamicPrintConfig &config, + // Select the preset after loading? + bool select) +{ + // Load the preset over a default preset, so that the missing fields are filled in from the default preset. + DynamicPrintConfig cfg(this->default_preset().config); + cfg.apply_only(config, cfg.keys(), true); + // Is there a preset already loaded with the name stored inside the config? + std::deque::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name); + if (it != m_presets.end()) { + t_config_option_keys diff = it->config.diff(cfg); + //FIXME Following keys are either not updated in the preset (the *_settings_id), + // or not stored into the AMF/3MF/Config file, therefore they will most likely not match. + // Ignore these differences for now. + for (const char *key : { "compatible_printers", "compatible_printers_condition", "inherits", + "print_settings_id", "filament_settings_id", "printer_settings_id", + "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" }) + diff.erase(std::remove(diff.begin(), diff.end(), key), diff.end()); + // Preset with the same name as stored inside the config exists. + if (diff.empty()) { + // The preset exists and it matches the values stored inside config. + if (select) + this->select_preset(it - m_presets.begin()); + return *it; + } + } + // The external preset does not match an internal preset, load the external preset. + Preset &preset = this->load_preset(path, name, std::move(cfg), select); + preset.is_external = true; + return preset; } Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select) diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 31fb69aa8..ee0cdc18b 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -200,6 +200,18 @@ public: 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_external_preset( + // Path to the profile source file (a G-code, an AMF or 3MF file, a config file) + const std::string &path, + // Name of the profile, derived from the source file name. + const std::string &name, + // Original name of the profile, extracted from the loaded config. Empty, if the name has not been stored. + const std::string &original_name, + // Config to initialize the preset from. + const DynamicPrintConfig &config, + // Select the preset after loading? + bool select = true); + // Save the preset under a new name. If the name is different from the old one, // a new preset is stored into the list of presets. // All presets are marked as not modified and the new preset is activated. diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index d36ef7b6f..8f417fcfe 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -416,6 +416,9 @@ DynamicPrintConfig PresetBundle::full_config() const opt->value = boost::algorithm::clamp(opt->value, 0, int(num_extruders)); } + out.option("print_settings_id", true)->value = this->prints.get_selected_preset().name; + out.option("filament_settings_id", true)->values = this->filament_presets; + out.option("printer_settings_id", true)->value = this->printers.get_selected_preset().name; return out; } @@ -502,24 +505,25 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // First load the print and printer presets. for (size_t i_group = 0; i_group < 2; ++ i_group) { PresetCollection &presets = (i_group == 0) ? this->prints : this->printers; - Preset &preset = presets.load_preset(is_external ? name_or_path : presets.path_from_name(name), name, config); - if (is_external) - preset.is_external = true; + if (is_external) + presets.load_external_preset(name_or_path, name, + config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id"), + config); else - preset.save(); + presets.load_preset(presets.path_from_name(name), name, config).save(); } // 3) Now load the filaments. If there are multiple filament presets, split them and load them. auto *nozzle_diameter = dynamic_cast(config.option("nozzle_diameter")); auto *filament_diameter = dynamic_cast(config.option("filament_diameter")); size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size()); + const ConfigOptionStrings *old_filament_profile_names = config.option("filament_settings_id", false); + assert(old_filament_profile_names != nullptr); if (num_extruders <= 1) { - Preset &preset = this->filaments.load_preset( - is_external ? name_or_path : this->filaments.path_from_name(name), name, config); if (is_external) - preset.is_external = true; + this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config); else - preset.save(); + this->filaments.load_preset(this->filaments.path_from_name(name), name, config).save(); this->filament_presets.clear(); this->filament_presets.emplace_back(name); } else { @@ -548,13 +552,13 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool sprintf(suffix, " (%d)", i); std::string new_name = name + suffix; // Load all filament presets, but only select the first one in the preset dialog. - Preset &preset = this->filaments.load_preset( - is_external ? name_or_path : this->filaments.path_from_name(new_name), - new_name, std::move(configs[i]), i == 0); if (is_external) - preset.is_external = true; + this->filaments.load_external_preset(name_or_path, new_name, + (i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "", + std::move(configs[i]), i == 0); else - preset.save(); + this->filaments.load_preset(this->filaments.path_from_name(new_name), + new_name, std::move(configs[i]), i == 0).save(); this->filament_presets.emplace_back(new_name); } } From 1175dc95f688a8b17e75a7cdf5ef1b472905bede Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 26 Jun 2018 10:50:50 +0200 Subject: [PATCH 07/12] Storing and recovering the "compatible_printers_condition" and "inherits" fields from / to the AMF/3MF/Config files. The "compatible_printers_condition" are collected over all active profiles (one print, possibly multiple filament, and one printer profile) into a single vector. --- xs/src/libslic3r/Config.cpp | 5 +- xs/src/libslic3r/GCode.cpp | 5 +- xs/src/libslic3r/PrintConfig.cpp | 14 ++-- xs/src/slic3r/GUI/Preset.cpp | 32 ++++----- xs/src/slic3r/GUI/PresetBundle.cpp | 105 ++++++++++++++++++++++++----- xs/src/slic3r/GUI/Tab.cpp | 8 +-- 6 files changed, 128 insertions(+), 41 deletions(-) diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 8c1349e08..4218fbcf9 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -188,7 +188,10 @@ void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys throw UnknownOptionException(opt_key); } const ConfigOption *other_opt = other.option(opt_key); - if (other_opt != nullptr) + if (other_opt == nullptr) { + // The key was not found in the source config, therefore it will not be initialized! +// printf("Not found, therefore not initialized: %s\n", opt_key.c_str()); + } else my_opt->set(other_opt); } } diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 009493113..16f8ac736 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1419,7 +1419,10 @@ void GCode::append_full_config(const Print& print, std::string& str) str += "; " + key + " = " + cfg->serialize(key) + "\n"; } const DynamicConfig &full_config = print.placeholder_parser.config(); - for (const char *key : { "print_settings_id", "filament_settings_id", "printer_settings_id" }) + for (const char *key : { + "print_settings_id", "filament_settings_id", "printer_settings_id", + "printer_model", "printer_variant", "default_print_profile", "default_filament_profile", + "compatible_printers_condition", "inherits" }) str += std::string("; ") + key + " = " + full_config.serialize(key) + "\n"; } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 486e6fe18..02961493e 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -147,12 +147,15 @@ PrintConfigDef::PrintConfigDef() def->label = L("Compatible printers"); def->default_value = new ConfigOptionStrings(); - def = this->add("compatible_printers_condition", coString); + // The following value is defined as a vector of strings, so it could + // collect the "inherits" values over the print and filaments profiles + // when storing into a project file (AMF, 3MF, Config ...) + def = this->add("compatible_printers_condition", coStrings); def->label = L("Compatible printers condition"); def->tooltip = L("A boolean expression using the configuration values of an active printer profile. " "If this expression evaluates to true, this profile is considered compatible " "with the active printer profile."); - def->default_value = new ConfigOptionString(); + def->default_value = new ConfigOptionStrings { "" }; def = this->add("complete_objects", coBool); def->label = L("Complete individual objects"); @@ -819,12 +822,15 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloat(80); - def = this->add("inherits", coString); + // The following value is defined as a vector of strings, so it could + // collect the "inherits" values over the print and filaments profiles + // when storing into a project file (AMF, 3MF, Config ...) + def = this->add("inherits", coStrings); def->label = L("Inherits profile"); def->tooltip = L("Name of the profile, from which this profile inherits."); def->full_width = true; def->height = 50; - def->default_value = new ConfigOptionString(""); + def->default_value = new ConfigOptionStrings { "" }; def = this->add("interface_shells", coBool); def->label = L("Interface shells"); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index d9774bfc2..120e1c9a7 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -180,7 +180,7 @@ void Preset::normalize(DynamicPrintConfig &config) size_t n = (nozzle_diameter == nullptr) ? 1 : nozzle_diameter->values.size(); const auto &defaults = FullPrintConfig::defaults(); for (const std::string &key : Preset::filament_options()) { - if (key == "compatible_printers") + if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits") continue; auto *opt = config.option(key, false); assert(opt != nullptr); @@ -234,12 +234,12 @@ std::string Preset::label() const bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const { - auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); + auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); bool has_compatible_printers = compatible_printers != nullptr && ! compatible_printers->values.empty(); - if (! has_compatible_printers && condition != nullptr && ! condition->value.empty()) { + if (! has_compatible_printers && condition != nullptr && ! condition->values.empty() && ! condition->values.front().empty()) { try { - return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config, extra_config); + return PlaceholderParser::evaluate_boolean_expression(condition->values.front(), active_printer.config, extra_config); } catch (const std::runtime_error &err) { //FIXME in case of an error, return "compatible with everything". printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); @@ -449,9 +449,8 @@ Preset& PresetCollection::load_external_preset( std::deque::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name); if (it != m_presets.end()) { t_config_option_keys diff = it->config.diff(cfg); - //FIXME Following keys are either not updated in the preset (the *_settings_id), - // or not stored into the AMF/3MF/Config file, therefore they will most likely not match. - // Ignore these differences for now. + // Following keys are used by the UI, not by the slicing core, therefore they are not important + // when comparing profiles for equality. Ignore them. for (const char *key : { "compatible_printers", "compatible_printers_condition", "inherits", "print_settings_id", "filament_settings_id", "printer_settings_id", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" }) @@ -503,7 +502,10 @@ void PresetCollection::save_current_preset(const std::string &new_name) } else { // Creating a new preset. Preset &preset = *m_presets.insert(it, m_edited_preset); - std::string &inherits = preset.config.opt_string("inherits", true); + ConfigOptionStrings *opt_inherits = preset.config.option("inherits", true); + if (opt_inherits->values.empty()) + opt_inherits->values.emplace_back(std::string()); + std::string &inherits = opt_inherits->values.front(); std::string old_name = preset.name; preset.name = new_name; preset.file = this->path_from_name(new_name); @@ -556,20 +558,20 @@ bool PresetCollection::load_bitmap_default(const std::string &file_name) const Preset* PresetCollection::get_selected_preset_parent() const { - auto *inherits = dynamic_cast(this->get_edited_preset().config.option("inherits")); - if (inherits == nullptr || inherits->value.empty()) - return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; // nullptr; - const Preset* preset = this->find_preset(inherits->value, false); + auto *inherits = dynamic_cast(this->get_edited_preset().config.option("inherits")); + if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty()) + return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; + const Preset* preset = this->find_preset(inherits->values.front(), false); return (preset == nullptr || preset->is_default || preset->is_external) ? nullptr : preset; } const Preset* PresetCollection::get_preset_parent(const Preset& child) const { - auto *inherits = dynamic_cast(child.config.option("inherits")); - if (inherits == nullptr || inherits->value.empty()) + auto *inherits = dynamic_cast(child.config.option("inherits")); + if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty()) // return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; return nullptr; - const Preset* preset = this->find_preset(inherits->value, false); + const Preset* preset = this->find_preset(inherits->values.front(), false); return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; } diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 8f417fcfe..147975f16 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -52,26 +52,40 @@ PresetBundle::PresetBundle() : if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) wxImage::AddHandler(new wxPNGHandler); - // Create the ID config keys, as they are not part of the Static print config classes. - this->prints.default_preset().config.opt_string("print_settings_id", true); - this->filaments.default_preset().config.option("filament_settings_id", true)->values.assign(1, std::string()); - this->printers.default_preset().config.opt_string("printer_settings_id", true); - // "compatible printers" are not mandatory yet. + // The following keys are handled by the UI, they do not have a counterpart in any StaticPrintConfig derived classes, + // therefore they need to be handled differently. As they have no counterpart in StaticPrintConfig, they are not being + // initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings). + // + // "compatible_printers", "compatible_printers_condition", "inherits", + // "print_settings_id", "filament_settings_id", "printer_settings_id", + // "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" + // //FIXME Rename "compatible_printers" and "compatible_printers_condition", as they are defined in both print and filament profiles, // therefore they are clashing when generating a a config file, G-code or AMF/3MF. -// this->filaments.default_preset().config.optptr("compatible_printers", true); -// this->filaments.default_preset().config.optptr("compatible_printers_condition", true); -// this->prints.default_preset().config.optptr("compatible_printers", true); -// this->prints.default_preset().config.optptr("compatible_printers_condition", true); - // Create the "printer_vendor", "printer_model" and "printer_variant" keys. + + // Create the ID config keys, as they are not part of the Static print config classes. + this->prints.default_preset().config.optptr("print_settings_id", true); + this->prints.default_preset().config.option("compatible_printers_condition", true)->values = { "" }; + this->prints.default_preset().config.option("inherits", true)->values = { "" }; + + this->filaments.default_preset().config.option("filament_settings_id", true)->values = { "" }; + this->filaments.default_preset().config.option("compatible_printers_condition", true)->values = { "" }; + this->filaments.default_preset().config.option("inherits", true)->values = { "" }; + + this->printers.default_preset().config.optptr("printer_settings_id", true); this->printers.default_preset().config.optptr("printer_vendor", true); this->printers.default_preset().config.optptr("printer_model", true); this->printers.default_preset().config.optptr("printer_variant", true); - // Load the default preset bitmaps. + this->printers.default_preset().config.optptr("default_print_profile", true); + this->printers.default_preset().config.optptr("default_filament_profile", true); + this->printers.default_preset().config.option("inherits", true)->values = { "" }; + + // Load the default preset bitmaps. this->prints .load_bitmap_default("cog.png"); this->filaments.load_bitmap_default("spool.png"); this->printers .load_bitmap_default("printer_empty.png"); this->load_compatible_bitmaps(); + // Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above. this->prints .select_preset(0); this->filaments.select_preset(0); @@ -370,9 +384,20 @@ DynamicPrintConfig PresetBundle::full_config() const auto *nozzle_diameter = dynamic_cast(out.option("nozzle_diameter")); size_t num_extruders = nozzle_diameter->values.size(); + // Collect the "compatible_printers_condition" and "inherits" values over all presets (print, filaments, printers) into a single vector. + std::vector compatible_printers_condition; + std::vector inherits; + auto append_config_string = [](const DynamicConfig &cfg, const std::string &key, std::vector &dst) { + const ConfigOptionStrings *opt = cfg.opt(key); + dst.emplace_back((opt == nullptr || opt->values.empty()) ? "" : opt->values.front()); + }; + append_config_string(this->prints.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition); + append_config_string(this->prints.get_edited_preset().config, "inherits", inherits); if (num_extruders <= 1) { out.apply(this->filaments.get_edited_preset().config); + append_config_string(this->filaments.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition); + append_config_string(this->filaments.get_edited_preset().config, "inherits", inherits); } else { // Retrieve filament presets and build a single config object for them. // First collect the filament configurations based on the user selection of this->filament_presets. @@ -382,11 +407,15 @@ DynamicPrintConfig PresetBundle::full_config() const filament_configs.emplace_back(&this->filaments.find_preset(filament_preset_name, true)->config); while (filament_configs.size() < num_extruders) filament_configs.emplace_back(&this->filaments.first_visible().config); + for (const DynamicPrintConfig *cfg : filament_configs) { + append_config_string(*cfg, "compatible_printers_condition", compatible_printers_condition); + append_config_string(*cfg, "inherits", inherits); + } // Option values to set a ConfigOptionVector from. std::vector filament_opts(num_extruders, nullptr); // loop through options and apply them to the resulting config. for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) { - if (key == "compatible_printers" || key == "compatible_printers_condition") + if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits") continue; // Get a destination option. ConfigOption *opt_dst = out.option(key, false); @@ -404,9 +433,13 @@ DynamicPrintConfig PresetBundle::full_config() const } } - //FIXME These two value types clash between the print and filament profiles. They should be renamed. + // Don't store the "compatible_printers_condition" for the printer profile, there is none. + append_config_string(this->printers.get_edited_preset().config, "inherits", inherits); + + // These two value types clash between the print and filament profiles. They should be renamed. out.erase("compatible_printers"); out.erase("compatible_printers_condition"); + out.erase("inherits"); static const char *keys[] = { "perimeter", "infill", "solid_infill", "support_material", "support_material_interface" }; for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++ i) { @@ -419,6 +452,22 @@ DynamicPrintConfig PresetBundle::full_config() const out.option("print_settings_id", true)->value = this->prints.get_selected_preset().name; out.option("filament_settings_id", true)->values = this->filament_presets; out.option("printer_settings_id", true)->value = this->printers.get_selected_preset().name; + + // Serialize the collected "compatible_printers_condition" and "inherits" fields. + // There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored. + // The vector will not be stored if all fields are empty strings. + auto add_if_some_non_empty = [&out](std::vector &&values, const std::string &key) { + bool nonempty = false; + for (const std::string &v : values) + if (! v.empty()) { + nonempty = true; + break; + } + if (nonempty) + out.set_key_value(key, new ConfigOptionStrings(std::move(values))); + }; + add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition"); + add_if_some_non_empty(std::move(inherits), "inherits"); return out; } @@ -497,6 +546,20 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool } } + size_t num_extruders = std::min(config.option("nozzle_diameter" )->values.size(), + config.option("filament_diameter")->values.size()); + // Make a copy of the "compatible_printers_condition" and "inherits" vectors, which + // accumulate values over all presets (print, filaments, printers). + // These values will be distributed into their particular presets when loading. + auto *compatible_printers_condition = config.option("compatible_printers_condition", true); + auto *inherits = config.option("inherits", true); + std::vector compatible_printers_condition_values = std::move(compatible_printers_condition->values); + std::vector inherits_values = std::move(inherits->values); + if (compatible_printers_condition_values.empty()) + compatible_printers_condition_values.emplace_back(std::string()); + if (inherits_values.empty()) + inherits_values.emplace_back(std::string()); + // 1) Create a name from the file name. // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles. std::string name = is_external ? boost::filesystem::path(name_or_path).filename().string() : name_or_path; @@ -505,6 +568,11 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // First load the print and printer presets. for (size_t i_group = 0; i_group < 2; ++ i_group) { PresetCollection &presets = (i_group == 0) ? this->prints : this->printers; + // Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles. + size_t idx = (i_group == 0) ? 0 : num_extruders + 1; + inherits->values = { (idx < inherits_values.size()) ? inherits_values[idx] : "" }; + if (i_group == 0) + compatible_printers_condition->values = { compatible_printers_condition_values.front() }; if (is_external) presets.load_external_preset(name_or_path, name, config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id"), @@ -513,10 +581,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool presets.load_preset(presets.path_from_name(name), name, config).save(); } + // Update the "compatible_printers_condition" and "inherits" vectors, so their number matches the number of extruders. + compatible_printers_condition_values.erase(compatible_printers_condition_values.begin()); + inherits_values.erase(inherits_values.begin()); + compatible_printers_condition_values.resize(num_extruders, std::string()); + inherits_values.resize(num_extruders, std::string()); + compatible_printers_condition->values = std::move(compatible_printers_condition_values); + inherits->values = std::move(inherits_values); + // 3) Now load the filaments. If there are multiple filament presets, split them and load them. - auto *nozzle_diameter = dynamic_cast(config.option("nozzle_diameter")); - auto *filament_diameter = dynamic_cast(config.option("filament_diameter")); - size_t num_extruders = std::min(nozzle_diameter->values.size(), filament_diameter->values.size()); const ConfigOptionStrings *old_filament_profile_names = config.option("filament_settings_id", false); assert(old_filament_profile_names != nullptr); if (num_extruders <= 1) { diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 6eabc2f47..3bfab54b3 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -803,7 +803,7 @@ void Tab::reload_compatible_printers_widget() bool has_any = !m_config->option("compatible_printers")->values.empty(); has_any ? m_compatible_printers_btn->Enable() : m_compatible_printers_btn->Disable(); m_compatible_printers_checkbox->SetValue(!has_any); - get_field("compatible_printers_condition")->toggle(!has_any); + get_field("compatible_printers_condition", 0)->toggle(!has_any); } void TabPrint::build() @@ -1014,7 +1014,7 @@ void TabPrint::build() }; optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition"); + option = optgroup->get_option("compatible_printers_condition", 0); option.opt.full_width = true; optgroup->append_single_option_line(option); @@ -1365,7 +1365,7 @@ void TabFilament::build() }; optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition"); + option = optgroup->get_option("compatible_printers_condition", 0); option.opt.full_width = true; optgroup->append_single_option_line(option); @@ -2240,7 +2240,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox // All printers have been made compatible with this preset. if ((*checkbox)->GetValue()) load_key_value("compatible_printers", std::vector {}); - get_field("compatible_printers_condition")->toggle((*checkbox)->GetValue()); + get_field("compatible_printers_condition", 0)->toggle((*checkbox)->GetValue()); update_changed_ui(); }) ); From 59510c42d1b2e03a9d08dedc5d330801f12e269a Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 26 Jun 2018 11:31:01 +0200 Subject: [PATCH 08/12] When loading an archive (AMF/3MF/Config), the original name of the profile is show in braces next to the file name. --- xs/src/slic3r/GUI/Preset.cpp | 53 +++++++++++++++++++++++------- xs/src/slic3r/GUI/PresetBundle.cpp | 27 ++++++++------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 120e1c9a7..d52ea6215 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -427,6 +427,19 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string return this->load_preset(path, name, std::move(cfg), select); } +static bool profile_print_params_same(const DynamicPrintConfig &cfg1, const DynamicPrintConfig &cfg2) +{ + t_config_option_keys diff = cfg1.diff(cfg2); + // Following keys are used by the UI, not by the slicing core, therefore they are not important + // when comparing profiles for equality. Ignore them. + for (const char *key : { "compatible_printers", "compatible_printers_condition", "inherits", + "print_settings_id", "filament_settings_id", "printer_settings_id", + "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" }) + diff.erase(std::remove(diff.begin(), diff.end(), key), diff.end()); + // Preset with the same name as stored inside the config exists. + return diff.empty(); +} + // Load a preset from an already parsed config file, insert it into the sorted sequence of presets // and select it, losing previous modifications. // In case @@ -447,24 +460,40 @@ Preset& PresetCollection::load_external_preset( cfg.apply_only(config, cfg.keys(), true); // Is there a preset already loaded with the name stored inside the config? std::deque::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name); - if (it != m_presets.end()) { - t_config_option_keys diff = it->config.diff(cfg); - // Following keys are used by the UI, not by the slicing core, therefore they are not important - // when comparing profiles for equality. Ignore them. - for (const char *key : { "compatible_printers", "compatible_printers_condition", "inherits", - "print_settings_id", "filament_settings_id", "printer_settings_id", - "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" }) - diff.erase(std::remove(diff.begin(), diff.end(), key), diff.end()); - // Preset with the same name as stored inside the config exists. - if (diff.empty()) { + if (it != m_presets.end() && profile_print_params_same(it->config, cfg)) { + // The preset exists and it matches the values stored inside config. + if (select) + this->select_preset(it - m_presets.begin()); + return *it; + } + // The external preset does not match an internal preset, load the external preset. + std::string new_name; + for (size_t idx = 0;; ++ idx) { + std::string suffix; + if (original_name.empty()) { + if (idx > 0) + suffix = " (" + std::to_string(idx) + ")"; + } else { + if (idx == 0) + suffix = " (" + original_name + ")"; + else + suffix = " (" + original_name + "-" + std::to_string(idx) + ")"; + } + new_name = name + suffix; + it = this->find_preset_internal(new_name); + if (it == m_presets.end()) + // Unique profile name. Insert a new profile. + break; + if (profile_print_params_same(it->config, cfg)) { // The preset exists and it matches the values stored inside config. if (select) this->select_preset(it - m_presets.begin()); return *it; } + // Form another profile name. } - // The external preset does not match an internal preset, load the external preset. - Preset &preset = this->load_preset(path, name, std::move(cfg), select); + // Insert a new profile. + Preset &preset = this->load_preset(path, new_name, std::move(cfg), select); preset.is_external = true; return preset; } diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 147975f16..fcf8ce859 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -618,21 +618,26 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // Load the configs into this->filaments and make them active. this->filament_presets.clear(); for (size_t i = 0; i < configs.size(); ++ i) { - char suffix[64]; - if (i == 0) - suffix[0] = 0; - else - sprintf(suffix, " (%d)", i); - std::string new_name = name + suffix; // Load all filament presets, but only select the first one in the preset dialog. + Preset *loaded = nullptr; if (is_external) - this->filaments.load_external_preset(name_or_path, new_name, + loaded = &this->filaments.load_external_preset(name_or_path, name, (i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "", std::move(configs[i]), i == 0); - else - this->filaments.load_preset(this->filaments.path_from_name(new_name), - new_name, std::move(configs[i]), i == 0).save(); - this->filament_presets.emplace_back(new_name); + else { + // Used by the config wizard when creating a custom setup. + // Therefore this block should only be called for a single extruder. + char suffix[64]; + if (i == 0) + suffix[0] = 0; + else + sprintf(suffix, "%d", i); + std::string new_name = name + suffix; + loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name), + new_name, std::move(configs[i]), i == 0); + loaded->save(); + } + this->filament_presets.emplace_back(loaded->name); } } From 22463343a738f7a36b6d59cd038b77a7ec83d8de Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 26 Jun 2018 13:22:24 +0200 Subject: [PATCH 09/12] Fixed integration tests. --- xs/src/libslic3r/GCode.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 16f8ac736..b007fbea0 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1419,11 +1419,14 @@ void GCode::append_full_config(const Print& print, std::string& str) str += "; " + key + " = " + cfg->serialize(key) + "\n"; } const DynamicConfig &full_config = print.placeholder_parser.config(); - for (const char *key : { - "print_settings_id", "filament_settings_id", "printer_settings_id", - "printer_model", "printer_variant", "default_print_profile", "default_filament_profile", - "compatible_printers_condition", "inherits" }) - str += std::string("; ") + key + " = " + full_config.serialize(key) + "\n"; + for (const char *key : { + "print_settings_id", "filament_settings_id", "printer_settings_id", + "printer_model", "printer_variant", "default_print_profile", "default_filament_profile", + "compatible_printers_condition", "inherits" }) { + const ConfigOption *opt = full_config.option(key); + if (opt != nullptr) + str += std::string("; ") + key + " = " + opt->serialize() + "\n"; + } } void GCode::set_extruders(const std::vector &extruder_ids) From 80b430ad94daa8b34b6432076e8d3ee03c2e2732 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 27 Jun 2018 16:57:42 +0200 Subject: [PATCH 10/12] Simplified handling of the "compatible_printers_condition" and "inherits" configuration values. Implemented correct setting of the "inherits" flag for the profiles loaded from AMF/3MF/Config files. --- xs/src/slic3r/GUI/Preset.cpp | 35 +++++++++++++++++------------- xs/src/slic3r/GUI/Preset.hpp | 25 ++++++++++++++++++--- xs/src/slic3r/GUI/PresetBundle.cpp | 28 ++++++++++-------------- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index d52ea6215..c0b02d460 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -234,12 +234,12 @@ std::string Preset::label() const bool Preset::is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const { - auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); + auto &condition = this->compatible_printers_condition(); auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); bool has_compatible_printers = compatible_printers != nullptr && ! compatible_printers->values.empty(); - if (! has_compatible_printers && condition != nullptr && ! condition->values.empty() && ! condition->values.front().empty()) { + if (! has_compatible_printers && ! condition.empty()) { try { - return PlaceholderParser::evaluate_boolean_expression(condition->values.front(), active_printer.config, extra_config); + return PlaceholderParser::evaluate_boolean_expression(condition, active_printer.config, extra_config); } catch (const std::runtime_error &err) { //FIXME in case of an error, return "compatible with everything". printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); @@ -466,6 +466,15 @@ Preset& PresetCollection::load_external_preset( this->select_preset(it - m_presets.begin()); return *it; } + // Update the "inherits" field. + std::string &inherits = Preset::inherits(cfg); + if (it != m_presets.end() && inherits.empty()) { + // There is a profile with the same name already loaded. Should we update the "inherits" field? + if (it->vendor == nullptr) + inherits = it->inherits(); + else + inherits = it->name; + } // The external preset does not match an internal preset, load the external preset. std::string new_name; for (size_t idx = 0;; ++ idx) { @@ -531,10 +540,7 @@ void PresetCollection::save_current_preset(const std::string &new_name) } else { // Creating a new preset. Preset &preset = *m_presets.insert(it, m_edited_preset); - ConfigOptionStrings *opt_inherits = preset.config.option("inherits", true); - if (opt_inherits->values.empty()) - opt_inherits->values.emplace_back(std::string()); - std::string &inherits = opt_inherits->values.front(); + std::string &inherits = preset.inherits(); std::string old_name = preset.name; preset.name = new_name; preset.file = this->path_from_name(new_name); @@ -549,7 +555,6 @@ void PresetCollection::save_current_preset(const std::string &new_name) // Inherited from a user preset. Just maintain the "inherited" flag, // meaning it will inherit from either the system preset, or the inherited user preset. } - preset.inherits = inherits; preset.is_default = false; preset.is_system = false; preset.is_external = false; @@ -587,20 +592,20 @@ bool PresetCollection::load_bitmap_default(const std::string &file_name) const Preset* PresetCollection::get_selected_preset_parent() const { - auto *inherits = dynamic_cast(this->get_edited_preset().config.option("inherits")); - if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty()) + const std::string &inherits = this->get_edited_preset().inherits(); + if (inherits.empty()) return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; - const Preset* preset = this->find_preset(inherits->values.front(), false); + const Preset* preset = this->find_preset(inherits, false); return (preset == nullptr || preset->is_default || preset->is_external) ? nullptr : preset; } const Preset* PresetCollection::get_preset_parent(const Preset& child) const { - auto *inherits = dynamic_cast(child.config.option("inherits")); - if (inherits == nullptr || inherits->values.empty() || inherits->values.front().empty()) + const std::string &inherits = child.inherits(); + if (inherits.empty()) // return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; return nullptr; - const Preset* preset = this->find_preset(inherits->values.front(), false); + const Preset* preset = this->find_preset(inherits, false); return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; } @@ -837,7 +842,7 @@ std::vector PresetCollection::dirty_options(const Preset *edited, c // The "compatible_printers" option key is handled differently from the others: // It is not mandatory. If the key is missing, it means it is compatible with any printer. // If the key exists and it is empty, it means it is compatible with no printer. - std::initializer_list optional_keys { "compatible_printers", "compatible_printers_condition" }; + std::initializer_list optional_keys { "compatible_printers" }; for (auto &opt_key : optional_keys) { if (reference->config.has(opt_key) != edited->config.has(opt_key)) changed.emplace_back(opt_key); diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index ee0cdc18b..42ef6ceee 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -113,9 +113,6 @@ public: // or a Configuration file bundling the Print + Filament + Printer presets (in that case is_external and possibly is_system will be true), // or it could be a G-code (again, is_external will be true). std::string file; - // A user profile may inherit its settings either from a system profile, or from a user profile. - // A system profile shall never derive from any other profile, as the system profile hierarchy is being flattened during loading. - std::string inherits; // If this is a system profile, then there should be a vendor data available to display at the UI. const VendorProfile *vendor = nullptr; @@ -142,6 +139,28 @@ public: bool is_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config) const; bool is_compatible_with_printer(const Preset &active_printer) const; + // Returns the name of the preset, from which this preset inherits. + static std::string& inherits(DynamicPrintConfig &cfg) + { + auto option = cfg.option("inherits", true); + if (option->values.empty()) + option->values.emplace_back(std::string()); + return option->values.front(); + } + std::string& inherits() { return Preset::inherits(this->config); } + const std::string& inherits() const { return Preset::inherits(const_cast(this)->config); } + + // Returns the "compatible_printers_condition". + static std::string& compatible_printers_condition(DynamicPrintConfig &cfg) + { + auto option = cfg.option("compatible_printers_condition", true); + if (option->values.empty()) + option->values.emplace_back(std::string()); + return option->values.front(); + } + std::string& compatible_printers_condition() { return Preset::compatible_printers_condition(this->config); } + const std::string& compatible_printers_condition() const { return Preset::compatible_printers_condition(const_cast(this)->config); } + // Mark this preset as compatible if it is compatible with active_printer. bool update_compatible_with_printer(const Preset &active_printer, const DynamicPrintConfig *extra_config); diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index fcf8ce859..c11816d06 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -65,12 +65,12 @@ PresetBundle::PresetBundle() : // Create the ID config keys, as they are not part of the Static print config classes. this->prints.default_preset().config.optptr("print_settings_id", true); - this->prints.default_preset().config.option("compatible_printers_condition", true)->values = { "" }; - this->prints.default_preset().config.option("inherits", true)->values = { "" }; + this->prints.default_preset().compatible_printers_condition(); + this->prints.default_preset().inherits(); this->filaments.default_preset().config.option("filament_settings_id", true)->values = { "" }; - this->filaments.default_preset().config.option("compatible_printers_condition", true)->values = { "" }; - this->filaments.default_preset().config.option("inherits", true)->values = { "" }; + this->filaments.default_preset().compatible_printers_condition(); + this->filaments.default_preset().inherits(); this->printers.default_preset().config.optptr("printer_settings_id", true); this->printers.default_preset().config.optptr("printer_vendor", true); @@ -78,7 +78,7 @@ PresetBundle::PresetBundle() : this->printers.default_preset().config.optptr("printer_variant", true); this->printers.default_preset().config.optptr("default_print_profile", true); this->printers.default_preset().config.optptr("default_filament_profile", true); - this->printers.default_preset().config.option("inherits", true)->values = { "" }; + this->printers.default_preset().inherits(); // Load the default preset bitmaps. this->prints .load_bitmap_default("cog.png"); @@ -387,17 +387,13 @@ DynamicPrintConfig PresetBundle::full_config() const // Collect the "compatible_printers_condition" and "inherits" values over all presets (print, filaments, printers) into a single vector. std::vector compatible_printers_condition; std::vector inherits; - auto append_config_string = [](const DynamicConfig &cfg, const std::string &key, std::vector &dst) { - const ConfigOptionStrings *opt = cfg.opt(key); - dst.emplace_back((opt == nullptr || opt->values.empty()) ? "" : opt->values.front()); - }; - append_config_string(this->prints.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition); - append_config_string(this->prints.get_edited_preset().config, "inherits", inherits); + compatible_printers_condition.emplace_back(this->prints.get_edited_preset().compatible_printers_condition()); + inherits .emplace_back(this->prints.get_edited_preset().inherits()); if (num_extruders <= 1) { out.apply(this->filaments.get_edited_preset().config); - append_config_string(this->filaments.get_edited_preset().config, "compatible_printers_condition", compatible_printers_condition); - append_config_string(this->filaments.get_edited_preset().config, "inherits", inherits); + compatible_printers_condition.emplace_back(this->filaments.get_edited_preset().compatible_printers_condition()); + inherits .emplace_back(this->filaments.get_edited_preset().inherits()); } else { // Retrieve filament presets and build a single config object for them. // First collect the filament configurations based on the user selection of this->filament_presets. @@ -408,8 +404,8 @@ DynamicPrintConfig PresetBundle::full_config() const while (filament_configs.size() < num_extruders) filament_configs.emplace_back(&this->filaments.first_visible().config); for (const DynamicPrintConfig *cfg : filament_configs) { - append_config_string(*cfg, "compatible_printers_condition", compatible_printers_condition); - append_config_string(*cfg, "inherits", inherits); + compatible_printers_condition.emplace_back(Preset::compatible_printers_condition(*const_cast(cfg))); + inherits .emplace_back(Preset::inherits(*const_cast(cfg))); } // Option values to set a ConfigOptionVector from. std::vector filament_opts(num_extruders, nullptr); @@ -434,7 +430,7 @@ DynamicPrintConfig PresetBundle::full_config() const } // Don't store the "compatible_printers_condition" for the printer profile, there is none. - append_config_string(this->printers.get_edited_preset().config, "inherits", inherits); + inherits.emplace_back(this->printers.get_edited_preset().inherits()); // These two value types clash between the print and filament profiles. They should be renamed. out.erase("compatible_printers"); From 26b003073b48b56356e1d00fd5e064cca9f9b557 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 28 Jun 2018 20:13:01 +0200 Subject: [PATCH 11/12] Renamed the "compatible_printers_condition" and "inherits" vectors to "compatible_printers_condition_cummulative" and "inherits_cummulative" when storing to AMF/3MF/Config files. Improved escaping of strings stored / loaded from config files. --- xs/src/libslic3r/Config.cpp | 25 +++++++++++-- xs/src/libslic3r/GCode.cpp | 2 +- xs/src/libslic3r/PrintConfig.cpp | 24 +++++++----- xs/src/slic3r/GUI/Preset.cpp | 19 ++-------- xs/src/slic3r/GUI/Preset.hpp | 21 ++--------- xs/src/slic3r/GUI/PresetBundle.cpp | 59 ++++++++++++++---------------- xs/src/slic3r/GUI/Tab.cpp | 8 ++-- xs/src/slic3r/GUI/Tab.hpp | 2 +- 8 files changed, 76 insertions(+), 84 deletions(-) diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 4218fbcf9..989a4ab82 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -20,6 +20,7 @@ namespace Slic3r { +// Escape \n, \r and \\ std::string escape_string_cstyle(const std::string &str) { // Allocate a buffer twice the input string length, @@ -28,9 +29,15 @@ std::string escape_string_cstyle(const std::string &str) char *outptr = out.data(); for (size_t i = 0; i < str.size(); ++ i) { char c = str[i]; - if (c == '\n' || c == '\r') { + if (c == '\r') { + (*outptr ++) = '\\'; + (*outptr ++) = 'r'; + } else if (c == '\n') { (*outptr ++) = '\\'; (*outptr ++) = 'n'; + } else if (c == '\\') { + (*outptr ++) = '\\'; + (*outptr ++) = '\\'; } else (*outptr ++) = c; } @@ -69,7 +76,10 @@ std::string escape_strings_cstyle(const std::vector &strs) if (c == '\\' || c == '"') { (*outptr ++) = '\\'; (*outptr ++) = c; - } else if (c == '\n' || c == '\r') { + } else if (c == '\r') { + (*outptr ++) = '\\'; + (*outptr ++) = 'r'; + } else if (c == '\n') { (*outptr ++) = '\\'; (*outptr ++) = 'n'; } else @@ -84,6 +94,7 @@ std::string escape_strings_cstyle(const std::vector &strs) return std::string(out.data(), outptr - out.data()); } +// Unescape \n, \r and \\ bool unescape_string_cstyle(const std::string &str, std::string &str_out) { std::vector out(str.size(), 0); @@ -94,8 +105,12 @@ bool unescape_string_cstyle(const std::string &str, std::string &str_out) if (++ i == str.size()) return false; c = str[i]; - if (c == 'n') + if (c == 'r') + (*outptr ++) = '\r'; + else if (c == 'n') (*outptr ++) = '\n'; + else + (*outptr ++) = c; } else (*outptr ++) = c; } @@ -134,7 +149,9 @@ bool unescape_strings_cstyle(const std::string &str, std::vector &o if (++ i == str.size()) return false; c = str[i]; - if (c == 'n') + if (c == 'r') + c = '\r'; + else if (c == 'n') c = '\n'; } buf.push_back(c); diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b007fbea0..93f4bb3e7 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1422,7 +1422,7 @@ void GCode::append_full_config(const Print& print, std::string& str) for (const char *key : { "print_settings_id", "filament_settings_id", "printer_settings_id", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile", - "compatible_printers_condition", "inherits" }) { + "compatible_printers_condition_cummulative", "inherits_cummulative" }) { const ConfigOption *opt = full_config.option(key); if (opt != nullptr) str += std::string("; ") + key + " = " + opt->serialize() + "\n"; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 02961493e..88f028b45 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -147,15 +147,17 @@ PrintConfigDef::PrintConfigDef() def->label = L("Compatible printers"); def->default_value = new ConfigOptionStrings(); - // The following value is defined as a vector of strings, so it could - // collect the "inherits" values over the print and filaments profiles - // when storing into a project file (AMF, 3MF, Config ...) - def = this->add("compatible_printers_condition", coStrings); + def = this->add("compatible_printers_condition", coString); def->label = L("Compatible printers condition"); def->tooltip = L("A boolean expression using the configuration values of an active printer profile. " "If this expression evaluates to true, this profile is considered compatible " "with the active printer profile."); - def->default_value = new ConfigOptionStrings { "" }; + def->default_value = new ConfigOptionString(); + + // The following value is to be stored into the project file (AMF, 3MF, Config ...) + // and it contains a sum of "compatible_printers_condition" values over the print and filament profiles. + def = this->add("compatible_printers_condition_cummulative", coStrings); + def->default_value = new ConfigOptionStrings(); def = this->add("complete_objects", coBool); def->label = L("Complete individual objects"); @@ -822,15 +824,17 @@ PrintConfigDef::PrintConfigDef() def->min = 0; def->default_value = new ConfigOptionFloat(80); - // The following value is defined as a vector of strings, so it could - // collect the "inherits" values over the print and filaments profiles - // when storing into a project file (AMF, 3MF, Config ...) - def = this->add("inherits", coStrings); + def = this->add("inherits", coString); def->label = L("Inherits profile"); def->tooltip = L("Name of the profile, from which this profile inherits."); def->full_width = true; def->height = 50; - def->default_value = new ConfigOptionStrings { "" }; + def->default_value = new ConfigOptionString(); + + // The following value is to be stored into the project file (AMF, 3MF, Config ...) + // and it contains a sum of "inherits" values over the print and filament profiles. + def = this->add("inherits_cummulative", coStrings); + def->default_value = new ConfigOptionStrings(); def = this->add("interface_shells", coBool); def->label = L("Interface shells"); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index c0b02d460..0d6239b2c 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -180,7 +180,7 @@ void Preset::normalize(DynamicPrintConfig &config) size_t n = (nozzle_diameter == nullptr) ? 1 : nozzle_diameter->values.size(); const auto &defaults = FullPrintConfig::defaults(); for (const std::string &key : Preset::filament_options()) { - if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits") + if (key == "compatible_printers") continue; auto *opt = config.option(key, false); assert(opt != nullptr); @@ -459,8 +459,8 @@ Preset& PresetCollection::load_external_preset( DynamicPrintConfig cfg(this->default_preset().config); cfg.apply_only(config, cfg.keys(), true); // Is there a preset already loaded with the name stored inside the config? - std::deque::iterator it = original_name.empty() ? m_presets.end() : this->find_preset_internal(original_name); - if (it != m_presets.end() && profile_print_params_same(it->config, cfg)) { + std::deque::iterator it = this->find_preset_internal(original_name); + if (it != m_presets.end() && it->name == original_name && profile_print_params_same(it->config, cfg)) { // The preset exists and it matches the values stored inside config. if (select) this->select_preset(it - m_presets.begin()); @@ -490,7 +490,7 @@ Preset& PresetCollection::load_external_preset( } new_name = name + suffix; it = this->find_preset_internal(new_name); - if (it == m_presets.end()) + if (it == m_presets.end() || it->name != new_name) // Unique profile name. Insert a new profile. break; if (profile_print_params_same(it->config, cfg)) { @@ -851,17 +851,6 @@ std::vector PresetCollection::dirty_options(const Preset *edited, c return changed; } -std::vector PresetCollection::system_equal_options() const -{ - const Preset *edited = &this->get_edited_preset(); - const Preset *reference = this->get_selected_preset_parent(); - std::vector equal; - if (edited != nullptr && reference != nullptr) { - equal = reference->config.equal(edited->config); - } - return equal; -} - // Select a new preset. This resets all the edits done to the currently selected preset. // If the preset with index idx does not exist, a first visible preset is selected. Preset& PresetCollection::select_preset(size_t idx) diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 42ef6ceee..a2ee1d2eb 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -140,24 +140,12 @@ public: bool is_compatible_with_printer(const Preset &active_printer) const; // Returns the name of the preset, from which this preset inherits. - static std::string& inherits(DynamicPrintConfig &cfg) - { - auto option = cfg.option("inherits", true); - if (option->values.empty()) - option->values.emplace_back(std::string()); - return option->values.front(); - } + static std::string& inherits(DynamicPrintConfig &cfg) { return cfg.option("inherits", true)->value; } std::string& inherits() { return Preset::inherits(this->config); } const std::string& inherits() const { return Preset::inherits(const_cast(this)->config); } // Returns the "compatible_printers_condition". - static std::string& compatible_printers_condition(DynamicPrintConfig &cfg) - { - auto option = cfg.option("compatible_printers_condition", true); - if (option->values.empty()) - option->values.emplace_back(std::string()); - return option->values.front(); - } + static std::string& compatible_printers_condition(DynamicPrintConfig &cfg) { return cfg.option("compatible_printers_condition", true)->value; } std::string& compatible_printers_condition() { return Preset::compatible_printers_condition(this->config); } const std::string& compatible_printers_condition() const { return Preset::compatible_printers_condition(const_cast(this)->config); } @@ -343,8 +331,6 @@ public: // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. std::vector current_different_from_parent_options(const bool is_printer_type = false) const { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), is_printer_type); } - // Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal. - std::vector system_equal_options() const; // Update the choice UI from the list of presets. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. @@ -380,9 +366,10 @@ private: PresetCollection(const PresetCollection &other); PresetCollection& operator=(const PresetCollection &other); - // Find a preset in the sorted list of presets. + // Find a preset position in the sorted list of presets. // The "-- default -- " preset is always the first, so it needs // to be handled differently. + // If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name. std::deque::iterator find_preset_internal(const std::string &name) { Preset key(m_type, name); diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index c11816d06..db4e31173 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -59,9 +59,6 @@ PresetBundle::PresetBundle() : // "compatible_printers", "compatible_printers_condition", "inherits", // "print_settings_id", "filament_settings_id", "printer_settings_id", // "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile" - // - //FIXME Rename "compatible_printers" and "compatible_printers_condition", as they are defined in both print and filament profiles, - // therefore they are clashing when generating a a config file, G-code or AMF/3MF. // Create the ID config keys, as they are not part of the Static print config classes. this->prints.default_preset().config.optptr("print_settings_id", true); @@ -77,7 +74,7 @@ PresetBundle::PresetBundle() : this->printers.default_preset().config.optptr("printer_model", true); this->printers.default_preset().config.optptr("printer_variant", true); this->printers.default_preset().config.optptr("default_print_profile", true); - this->printers.default_preset().config.optptr("default_filament_profile", true); + this->printers.default_preset().config.option("default_filament_profile", true)->values = { "" }; this->printers.default_preset().inherits(); // Load the default preset bitmaps. @@ -411,7 +408,7 @@ DynamicPrintConfig PresetBundle::full_config() const std::vector filament_opts(num_extruders, nullptr); // loop through options and apply them to the resulting config. for (const t_config_option_key &key : this->filaments.default_preset().config.keys()) { - if (key == "compatible_printers" || key == "compatible_printers_condition" || key == "inherits") + if (key == "compatible_printers") continue; // Get a destination option. ConfigOption *opt_dst = out.option(key, false); @@ -462,8 +459,8 @@ DynamicPrintConfig PresetBundle::full_config() const if (nonempty) out.set_key_value(key, new ConfigOptionStrings(std::move(values))); }; - add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition"); - add_if_some_non_empty(std::move(inherits), "inherits"); + add_if_some_non_empty(std::move(compatible_printers_condition), "compatible_printers_condition_cummulative"); + add_if_some_non_empty(std::move(inherits), "inherits_cummulative"); return out; } @@ -544,17 +541,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool size_t num_extruders = std::min(config.option("nozzle_diameter" )->values.size(), config.option("filament_diameter")->values.size()); - // Make a copy of the "compatible_printers_condition" and "inherits" vectors, which + // Make a copy of the "compatible_printers_condition_cummulative" and "inherits_cummulative" vectors, which // accumulate values over all presets (print, filaments, printers). // These values will be distributed into their particular presets when loading. - auto *compatible_printers_condition = config.option("compatible_printers_condition", true); - auto *inherits = config.option("inherits", true); - std::vector compatible_printers_condition_values = std::move(compatible_printers_condition->values); - std::vector inherits_values = std::move(inherits->values); - if (compatible_printers_condition_values.empty()) - compatible_printers_condition_values.emplace_back(std::string()); - if (inherits_values.empty()) - inherits_values.emplace_back(std::string()); + std::vector compatible_printers_condition_values = std::move(config.option("compatible_printers_condition_cummulative", true)->values); + std::vector inherits_values = std::move(config.option("inherits_cummulative", true)->values); + std::string &compatible_printers_condition = Preset::compatible_printers_condition(config); + std::string &inherits = Preset::inherits(config); + compatible_printers_condition_values.resize(num_extruders + 2, std::string()); + inherits_values.resize(num_extruders + 2, std::string()); // 1) Create a name from the file name. // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles. @@ -566,29 +561,25 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool PresetCollection &presets = (i_group == 0) ? this->prints : this->printers; // Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles. size_t idx = (i_group == 0) ? 0 : num_extruders + 1; - inherits->values = { (idx < inherits_values.size()) ? inherits_values[idx] : "" }; - if (i_group == 0) - compatible_printers_condition->values = { compatible_printers_condition_values.front() }; + inherits = inherits_values[idx]; + compatible_printers_condition = compatible_printers_condition_values[idx]; if (is_external) presets.load_external_preset(name_or_path, name, - config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id"), + config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id", true), config); else presets.load_preset(presets.path_from_name(name), name, config).save(); } - // Update the "compatible_printers_condition" and "inherits" vectors, so their number matches the number of extruders. - compatible_printers_condition_values.erase(compatible_printers_condition_values.begin()); - inherits_values.erase(inherits_values.begin()); - compatible_printers_condition_values.resize(num_extruders, std::string()); - inherits_values.resize(num_extruders, std::string()); - compatible_printers_condition->values = std::move(compatible_printers_condition_values); - inherits->values = std::move(inherits_values); - // 3) Now load the filaments. If there are multiple filament presets, split them and load them. - const ConfigOptionStrings *old_filament_profile_names = config.option("filament_settings_id", false); - assert(old_filament_profile_names != nullptr); + auto old_filament_profile_names = config.option("filament_settings_id", true); + old_filament_profile_names->values.resize(num_extruders, std::string()); + config.option("default_filament_profile", true)->values.resize(num_extruders, std::string()); + if (num_extruders <= 1) { + // Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets. + inherits = inherits_values[1]; + compatible_printers_condition = compatible_printers_condition_values[1]; if (is_external) this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config); else @@ -614,12 +605,16 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // Load the configs into this->filaments and make them active. this->filament_presets.clear(); for (size_t i = 0; i < configs.size(); ++ i) { + DynamicPrintConfig &cfg = configs[i]; + // Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets. + cfg.opt_string("compatible_printers_condition", true) = compatible_printers_condition_values[i + 1]; + cfg.opt_string("inherits", true) = inherits_values[i + 1]; // Load all filament presets, but only select the first one in the preset dialog. Preset *loaded = nullptr; if (is_external) loaded = &this->filaments.load_external_preset(name_or_path, name, (i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "", - std::move(configs[i]), i == 0); + std::move(cfg), i == 0); else { // Used by the config wizard when creating a custom setup. // Therefore this block should only be called for a single extruder. @@ -630,7 +625,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool sprintf(suffix, "%d", i); std::string new_name = name + suffix; loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name), - new_name, std::move(configs[i]), i == 0); + new_name, std::move(cfg), i == 0); loaded->save(); } this->filament_presets.emplace_back(loaded->name); diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index f89ddddcc..94f8cc3ea 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -803,7 +803,7 @@ void Tab::reload_compatible_printers_widget() bool has_any = !m_config->option("compatible_printers")->values.empty(); has_any ? m_compatible_printers_btn->Enable() : m_compatible_printers_btn->Disable(); m_compatible_printers_checkbox->SetValue(!has_any); - get_field("compatible_printers_condition", 0)->toggle(!has_any); + get_field("compatible_printers_condition")->toggle(!has_any); } void TabPrint::build() @@ -1014,7 +1014,7 @@ void TabPrint::build() }; optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition", 0); + option = optgroup->get_option("compatible_printers_condition"); option.opt.full_width = true; optgroup->append_single_option_line(option); @@ -1365,7 +1365,7 @@ void TabFilament::build() }; optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition", 0); + option = optgroup->get_option("compatible_printers_condition"); option.opt.full_width = true; optgroup->append_single_option_line(option); @@ -2240,7 +2240,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox // All printers have been made compatible with this preset. if ((*checkbox)->GetValue()) load_key_value("compatible_printers", std::vector {}); - get_field("compatible_printers_condition", 0)->toggle((*checkbox)->GetValue()); + get_field("compatible_printers_condition")->toggle((*checkbox)->GetValue()); update_changed_ui(); }) ); diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index d6bf2cf43..eccae4daa 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -172,7 +172,7 @@ protected: std::vector m_reload_dependent_tabs = {}; enum OptStatus { osSystemValue = 1, osInitValue = 2 }; std::map m_options_list; - int m_opt_status_value; + int m_opt_status_value = 0; t_icon_descriptions m_icon_descriptions = {}; From 082f88ad5ffb641c890a470a08bb8e8d1eaaf0ee Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 28 Jun 2018 21:46:23 +0200 Subject: [PATCH 12/12] gcc / clang did not like backslashes inside comments --- xs/src/libslic3r/Config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 989a4ab82..5db093c5c 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -20,7 +20,7 @@ namespace Slic3r { -// Escape \n, \r and \\ +// Escape \n, \r and backslash std::string escape_string_cstyle(const std::string &str) { // Allocate a buffer twice the input string length, @@ -94,7 +94,7 @@ std::string escape_strings_cstyle(const std::vector &strs) return std::string(out.data(), outptr - out.data()); } -// Unescape \n, \r and \\ +// Unescape \n, \r and backslash bool unescape_string_cstyle(const std::string &str, std::string &str_out) { std::vector out(str.size(), 0);