From 34b354810208fe39d8a8a0e244b5a77d81f35578 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 12 Apr 2019 16:18:46 +0200 Subject: [PATCH 01/11] Filaments and materials selection/installation --- resources/profiles/PrusaResearch.ini | 95 +++++++ src/libslic3r/PrintConfig.cpp | 8 + src/slic3r/GUI/AppConfig.hpp | 6 + src/slic3r/GUI/ConfigWizard.cpp | 362 ++++++++++++++++++++++-- src/slic3r/GUI/ConfigWizard_private.hpp | 139 +++++++-- src/slic3r/GUI/Preset.cpp | 43 ++- src/slic3r/GUI/Preset.hpp | 5 + src/slic3r/GUI/PresetBundle.cpp | 8 + 8 files changed, 608 insertions(+), 58 deletions(-) diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 406fd93c80..6904713346 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -82,6 +82,29 @@ variants = default technology = SLA family = SL1 +[default_filaments] +Generic PLA = 1 +Generic PLA MMU2 = 1 +Prusa PLA = 1 +Prusa PLA MMU2 = 1 +Prusament PLA = 1 +Prusament PLA MMU2 = 1 + +[default_sla_materials] +Prusa Azure Blue Tough 0.05 = 1 +Prusa Black Tough 0.05 = 1 +Prusa Green Casting 0.05 = 1 +Prusa Grey Tough 0.05 = 1 +Prusa Maroon Tough 0.05 = 1 +Prusa Orange Tough 0.025 = 1 +Prusa Orange Tough 0.035 = 1 +Prusa Orange Tough 0.05 = 1 +Prusa Orange Tough 0.1 = 1 +Prusa Pink Tough 0.05 = 1 +Prusa Skin Tough 0.05 = 1 +Prusa Transparent Red Tough 0.05 = 1 +Prusa White Tough 0.05 = 1 + # All presets starting with asterisk, for example *common*, are intermediate and they will # not make it into the user interface. @@ -1128,6 +1151,7 @@ filament_density = 3.9 filament_colour = #804040 filament_max_volumetric_speed = 9 filament_notes = "List of materials tested with standard print settings:\n\nColorFabb bronzeFill\nColorFabb brassFill\nColorFabb steelFill\nColorFabb copperFill" +filament_vendor = ColorFabb [filament:ColorFabb HT] inherits = *PET* @@ -1145,11 +1169,13 @@ max_fan_speed = 20 min_fan_speed = 10 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" temperature = 270 +filament_vendor = ColorFabb [filament:ColorFabb PLA-PHA] inherits = *PLA* filament_cost = 55.5 filament_density = 1.24 +filament_vendor = ColorFabb [filament:ColorFabb woodFill] inherits = *PLA* @@ -1163,6 +1189,7 @@ filament_max_volumetric_speed = 10 first_layer_temperature = 200 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 200 +filament_vendor = ColorFabb [filament:ColorFabb corkFill] inherits = *PLA* @@ -1175,6 +1202,7 @@ filament_max_volumetric_speed = 6 first_layer_temperature = 220 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 +filament_vendor = ColorFabb [filament:ColorFabb XT] inherits = *PET* @@ -1184,6 +1212,7 @@ filament_density = 1.27 first_layer_bed_temperature = 90 first_layer_temperature = 260 temperature = 270 +filament_vendor = ColorFabb [filament:ColorFabb XT-CF20] inherits = *PET* @@ -1199,6 +1228,7 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{el temperature = 260 filament_retract_length = nil filament_retract_lift = 0.2 +filament_vendor = ColorFabb [filament:ColorFabb nGen] inherits = *PET* @@ -1211,6 +1241,7 @@ filament_type = NGEN first_layer_temperature = 240 max_fan_speed = 35 min_fan_speed = 20 +filament_vendor = ColorFabb [filament:ColorFabb nGen flex] inherits = *FLEX* @@ -1231,12 +1262,14 @@ temperature = 260 filament_retract_length = nil filament_retract_lift = 0 compatible_printers_condition = nozzle_diameter[0]>0.35 and num_extruders==1 && ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material) +filament_vendor = ColorFabb [filament:E3D Edge] inherits = *PET* filament_cost = 56.9 filament_density = 1.26 filament_type = EDGE +filament_vendor = E3D [filament:E3D PC-ABS] inherits = *ABS* @@ -1245,6 +1278,7 @@ filament_type = PC filament_density = 1.05 first_layer_temperature = 270 temperature = 270 +filament_vendor = E3D [filament:Fillamentum ABS] inherits = *ABS* @@ -1252,6 +1286,7 @@ filament_cost = 32.4 filament_density = 1.04 first_layer_temperature = 240 temperature = 240 +filament_vendor = Fillamentum [filament:Fillamentum ASA] inherits = *ABS* @@ -1266,6 +1301,7 @@ slowdown_below_layer_time = 15 first_layer_temperature = 265 temperature = 265 filament_type = ASA +filament_vendor = Fillamentum [filament:Prusament ASA] inherits = *ABS* @@ -1296,6 +1332,7 @@ first_layer_temperature = 275 max_fan_speed = 50 min_fan_speed = 50 temperature = 275 +filament_vendor = Fillamentum [filament:Fillamentum Timberfill] inherits = *PLA* @@ -1309,24 +1346,28 @@ filament_max_volumetric_speed = 10 first_layer_temperature = 190 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 190 +filament_vendor = Fillamentum [filament:Generic ABS] inherits = *ABS* filament_cost = 27.82 filament_density = 1.04 filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" +filament_vendor = Generic [filament:Generic PET] inherits = *PET* filament_cost = 27.82 filament_density = 1.27 filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +filament_vendor = Generic [filament:Generic PLA] inherits = *PLA* filament_cost = 25.4 filament_density = 1.24 filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_vendor = Generic [filament:Generic FLEX] inherits = *FLEX* @@ -1347,6 +1388,7 @@ filament_colour = #3A80CA first_layer_bed_temperature = 100 first_layer_temperature = 270 temperature = 270 +filament_vendor = Polymaker [filament:PrimaSelect PVA+] inherits = *PLA* @@ -1363,12 +1405,14 @@ filament_type = PVA first_layer_temperature = 195 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 195 +filament_vendor = PrimaSelect [filament:Prusa ABS] inherits = *ABS* filament_cost = 27.82 filament_density = 1.08 filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" +filament_vendor = Prusa [filament:*ABS MMU2*] inherits = Prusa ABS @@ -1385,6 +1429,7 @@ filament_unloading_speed = 20 [filament:Generic ABS MMU2] inherits = *ABS MMU2* +filament_vendor = Generic [filament:Prusament ASA MMU2] inherits = *ABS MMU2* @@ -1410,6 +1455,7 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{el [filament:Prusa ABS MMU2] inherits = *ABS MMU2* +filament_vendor = Prusa [filament:Prusa HIPS] inherits = *ABS* @@ -1428,6 +1474,7 @@ max_fan_speed = 20 min_fan_speed = 20 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 +filament_vendor = Prusa [filament:Prusa PET] inherits = *PET* @@ -1435,6 +1482,7 @@ filament_cost = 27.82 filament_density = 1.27 filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nPlasty Mladec PETG" compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +filament_vendor = Prusa [filament:Prusament PETG] inherits = *PET* @@ -1444,12 +1492,14 @@ filament_cost = 24.99 filament_density = 1.27 filament_type = PETG compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +filament_vendor = Prusa [filament:Prusa PET 0.6 nozzle] inherits = *PET06* filament_cost = 27.82 filament_density = 1.27 filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nPlasty Mladec PETG" +filament_vendor = Prusa [filament:Prusament PETG 0.6 nozzle] inherits = *PET06* @@ -1458,6 +1508,7 @@ temperature = 250 filament_cost = 24.99 filament_density = 1.27 filament_type = PETG +filament_vendor = Prusa [filament:*PET MMU2*] inherits = Prusa PET @@ -1485,9 +1536,11 @@ filament_max_volumetric_speed = 13 [filament:Generic PET MMU2] inherits = *PET MMU2* +filament_vendor = Generic [filament:Prusa PET MMU2] inherits = *PET MMU2* +filament_vendor = Prusa [filament:Prusament PETG MMU2] inherits = *PET MMU2* @@ -1498,16 +1551,19 @@ inherits = *PET MMU2 06* [filament:Prusa PET MMU2 0.6 nozzle] inherits = *PET MMU2 06* +filament_vendor = Prusa [filament:Prusament PETG MMU2 0.6 nozzle] inherits = *PET MMU2 06* filament_type = PETG +filament_vendor = Prusa [filament:Prusa PLA] inherits = *PLA* filament_cost = 25.4 filament_density = 1.24 filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFiberlogy PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nAmazonBasics PLA" +filament_vendor = Prusa [filament:Prusament PLA] inherits = *PLA* @@ -1515,6 +1571,7 @@ temperature = 215 filament_cost = 24.99 filament_density = 1.24 filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa" +filament_vendor = Prusa [filament:*PLA MMU2*] inherits = Prusa PLA @@ -1534,18 +1591,22 @@ filament_unloading_speed_start = 100 [filament:Generic PLA MMU2] inherits = *PLA MMU2* +filament_vendor = Generic [filament:Prusa PLA MMU2] inherits = *PLA MMU2* +filament_vendor = Prusa [filament:Prusament PLA MMU2] inherits = *PLA MMU2* +filament_vendor = Prusa [filament:SemiFlex or Flexfill 98A] inherits = *FLEX* filament_cost = 82 filament_density = 1.22 filament_max_volumetric_speed = 1.35 +filament_vendor = Flexfill [filament:Taulman Bridge] inherits = *common* @@ -1567,6 +1628,7 @@ max_fan_speed = 5 min_fan_speed = 0 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 250 +filament_vendor = Taulman [filament:Taulman T-Glase] inherits = *PET* @@ -1580,6 +1642,7 @@ first_layer_temperature = 240 max_fan_speed = 5 min_fan_speed = 0 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" +filament_vendor = Taulman [filament:Verbatim BVOH] inherits = *common* @@ -1603,6 +1666,7 @@ max_fan_speed = 100 min_fan_speed = 100 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 210 +filament_vendor = Verbatim [filament:Verbatim BVOH MMU2] inherits = Verbatim BVOH @@ -1622,6 +1686,7 @@ filament_unload_time = 12 filament_unloading_speed = 20 filament_unloading_speed_start = 100 filament_loading_speed_start = 19 +filament_vendor = Verbatim [filament:PrimaSelect PVA+ MMU2] inherits = *common* @@ -1660,6 +1725,7 @@ min_print_speed = 15 slowdown_below_layer_time = 20 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 195 +filament_vendor = PrimaSelect [filament:Verbatim PP] inherits = *common* @@ -1682,6 +1748,7 @@ max_fan_speed = 100 min_fan_speed = 100 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 +filament_vendor = Verbatim ## Filaments MMU1 @@ -1902,6 +1969,7 @@ initial_exposure_time = 40 inherits = *common 0.025* exposure_time = 6 initial_exposure_time = 45 +material_vendor = Bluecast [sla_material:BlueCast X10 0.025] inherits = *common 0.025* @@ -1912,6 +1980,7 @@ initial_exposure_time = 100 inherits = *common 0.025* exposure_time = 6 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Grey Tough 0.025] inherits = *common 0.025* @@ -1964,31 +2033,37 @@ initial_exposure_time = 35 inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 35 +material_vendor = Bluecast [sla_material:BlueCast Keramaster 0.05] inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 45 +material_vendor = Bluecast [sla_material:BlueCast Keramaster Dental 0.05] inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 50 +material_vendor = Bluecast [sla_material:BlueCast LCD-DLP Original 0.05] inherits = *common 0.05* exposure_time = 10 initial_exposure_time = 60 +material_vendor = Bluecast [sla_material:BlueCast Phrozen Wax 0.05] inherits = *common 0.05* exposure_time = 16 initial_exposure_time = 50 +material_vendor = Bluecast [sla_material:BlueCast S+ 0.05] inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 45 +material_vendor = Bluecast [sla_material:BlueCast X10 0.05] inherits = *common 0.05* @@ -1999,26 +2074,31 @@ initial_exposure_time = 100 inherits = *common 0.05* exposure_time = 6 initial_exposure_time = 40 +material_vendor = Monocure [sla_material:Monocure 3D Blue Rapid Resin 0.05] inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 40 +material_vendor = Monocure [sla_material:Monocure 3D Clear Rapid Resin 0.05] inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 40 +material_vendor = Monocure [sla_material:Monocure 3D Grey Rapid Resin 0.05] inherits = *common 0.05* exposure_time = 10 initial_exposure_time = 30 +material_vendor = Monocure [sla_material:Monocure 3D White Rapid Resin 0.05] inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 40 +material_vendor = Monocure [sla_material:3DM-HTR140 (high temperature) 0.05] inherits = *common 0.05* @@ -2034,36 +2114,43 @@ initial_exposure_time = 25 inherits = *common 0.05* exposure_time = 20 initial_exposure_time = 40 +material_vendor = 3DM [sla_material:3DM-DENT 0.05] inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 45 +material_vendor = 3DM [sla_material:3DM-HR Green 0.05] inherits = *common 0.05* exposure_time = 15 initial_exposure_time = 40 +material_vendor = 3DM [sla_material:3DM-HR Red Wine 0.05] inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 35 +material_vendor = 3DM [sla_material:3DM-XPRO White 0.05] inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 35 +material_vendor = 3DM [sla_material:FTD Ash Grey 0.05] inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 40 +material_vendor = FTD [sla_material:Harz Labs Model Resin Cherry 0.05] inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 45 +material_vendor = Harz Labs [sla_material:Photocentric Hard Grey 0.05] inherits = *common 0.05* @@ -2116,6 +2203,7 @@ initial_exposure_time = 35 inherits = *common 0.05* exposure_time = 13 initial_exposure_time = 40 +material_vendor = Prusa ## [sla_material:Prusa Yellow Solid 0.05] ## inherits = *common 0.05* @@ -2126,6 +2214,7 @@ initial_exposure_time = 40 inherits = *common 0.05* exposure_time = 7.5 initial_exposure_time = 35 +material_vendor = Prusa ## [sla_material:Prusa Transparent Green Tough 0.05] ## inherits = *common 0.05* @@ -2136,21 +2225,25 @@ initial_exposure_time = 35 inherits = *common 0.05* exposure_time = 6 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Maroon Tough 0.05] inherits = *common 0.05* exposure_time = 7.5 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Pink Tough 0.05] inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Azure Blue Tough 0.05] inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Transparent Tough 0.05] inherits = *common 0.05* @@ -2193,6 +2286,7 @@ initial_exposure_time = 15 inherits = *common 0.035* exposure_time = 6 initial_exposure_time = 35 +material_vendor = Prusa ########### Materials 0.1 @@ -2235,6 +2329,7 @@ initial_exposure_time = 55 inherits = *common 0.1* exposure_time = 8 initial_exposure_time = 35 +material_vendor = Prusa [sla_material:Prusa Green Casting 0.1] inherits = *common 0.1* diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 1ce00f269d..ac30941cb1 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -749,6 +749,10 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionStrings { "" }); def->cli = ConfigOptionDef::nocli; + def = this->add("filament_vendor", coString); + def->set_default_value(new ConfigOptionString(L("(Unknown)"))); + def->cli = ConfigOptionDef::nocli; + def = this->add("fill_angle", coFloat); def->label = L("Fill angle"); def->category = L("Infill"); @@ -2474,6 +2478,10 @@ void PrintConfigDef::init_sla_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionString("")); + def = this->add("material_vendor", coString); + def->set_default_value(new ConfigOptionString(L("(Unknown)"))); + def->cli = ConfigOptionDef::nocli; + def = this->add("default_sla_material_profile", coString); def->label = L("Default SLA material profile"); def->tooltip = L("Default print profile associated with the current printer profile. " diff --git a/src/slic3r/GUI/AppConfig.hpp b/src/slic3r/GUI/AppConfig.hpp index 8ad17b9db8..fe30c0af69 100644 --- a/src/slic3r/GUI/AppConfig.hpp +++ b/src/slic3r/GUI/AppConfig.hpp @@ -80,6 +80,12 @@ public: } } + bool has_section(const std::string §ion) const + { return m_storage.find(section) != m_storage.end(); } + const std::map& get_section(const std::string §ion) const + { return m_storage.find(section)->second; } + void set_section(const std::string §ion, const std::map& data) + { m_storage[section] = data; } void clear_section(const std::string §ion) { m_storage[section].clear(); } diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 0115ff5f9c..0d35ce1afc 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1,3 +1,5 @@ +// FIXME: extract absolute units -> em + #include "ConfigWizard_private.hpp" #include @@ -19,6 +21,7 @@ #include #include #include +#include #include #include "libslic3r/Utils.hpp" @@ -62,7 +65,7 @@ struct PrinterPickerEvent : public wxEvent wxDEFINE_EVENT(EVT_PRINTER_PICK, PrinterPickerEvent); -PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter) +PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig, const ModelFilter &filter) : wxPanel(parent) , vendor_id(vendor.id) , width(0) @@ -132,7 +135,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name); i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox); - bool enabled = appconfig_vendors.get_variant("PrusaResearch", model_id, variant.name); + bool enabled = appconfig.get_variant("PrusaResearch", model_id, variant.name); cbox->SetValue(enabled); variants_sizer->Add(cbox, 0, wxBOTTOM, 3); @@ -210,8 +213,8 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt SetSizer(sizer); } -PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors) - : PrinterPicker(parent, vendor, std::move(title), max_cols, appconfig_vendors, [](const VendorProfile::PrinterModel&) { return true; }) +PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig) + : PrinterPicker(parent, vendor, std::move(title), max_cols, appconfig, [](const VendorProfile::PrinterModel&) { return true; }) {} void PrinterPicker::select_all(bool select, bool alternates) @@ -241,6 +244,19 @@ void PrinterPicker::select_one(size_t i, bool select) } } +bool PrinterPicker::any_selected() const +{ + for (const auto &cb : cboxes) { + if (cb->GetValue()) { return true; } + } + + for (const auto &cb : cboxes_alt) { + if (cb->GetValue()) { return true; } + } + + return false; +} + void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked) { PrinterPickerEvent evt(EVT_PRINTER_PICK, GetId(), vendor_id, cbox->model, cbox->variant, checked); @@ -289,6 +305,7 @@ void ConfigWizardPage::append_text(wxString text) void ConfigWizardPage::append_spacer(int space) { + // FIXME: scaling content->AddSpacer(space); } @@ -330,7 +347,7 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn bool check_first_variant = technology == T_FFF && wizard_p()->check_first_variant(); - AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors; + AppConfig &appconfig = this->wizard_p()->appconfig_new; const auto families = vendor.families(); for (const auto &family : families) { @@ -345,7 +362,7 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn } const auto picker_title = family.empty() ? wxString() : wxString::Format(_(L("%s Family")), family); - auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, appconfig_vendors, filter); + auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, appconfig, filter); if (check_first_variant) { // Select the default (first) model/variant on the Prusa vendor @@ -353,8 +370,9 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn check_first_variant = false; } - picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) { - appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); + picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) { + appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); + wizard_p()->on_printer_pick(this); }); append(new wxStaticLine(this)); @@ -377,6 +395,159 @@ int PagePrinters::get_width() const [](int acc, const PrinterPicker *picker) { return std::max(acc, picker->get_width()); }); } +bool PagePrinters::any_selected() const +{ + for (const auto *picker : printer_pickers) { + if (picker->any_selected()) { return true; } + } + + return false; +} + + +const std::string PageMaterials::EMPTY; + +PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name) + : ConfigWizardPage(parent, std::move(title), std::move(shortname)) + , materials(materials) + , list_l1(new StringList(this)) + , list_l2(new StringList(this)) + , list_l3(new PresetList(this)) + , sel1_prev(wxNOT_FOUND) + , sel2_prev(wxNOT_FOUND) +{ + append_spacer(VERTICAL_SPACING); + + const int em = parent->em_unit(); + const int list_h = 30*em; + + list_l1->SetMinSize(wxSize(8*em, list_h)); + list_l2->SetMinSize(wxSize(13*em, list_h)); + list_l3->SetMinSize(wxSize(25*em, list_h)); + + auto *grid = new wxFlexGridSizer(3, 0, em); + + grid->Add(new wxStaticText(this, wxID_ANY, list1name)); + grid->Add(new wxStaticText(this, wxID_ANY, _(L("Vendor:")))); + grid->Add(new wxStaticText(this, wxID_ANY, _(L("Profile:")))); + + grid->Add(list_l1); + grid->Add(list_l2); + grid->Add(list_l3); + + auto *btn_sizer = new wxBoxSizer(wxHORIZONTAL); + auto *sel_all = new wxButton(this, wxID_ANY, _(L("All"))); + auto *sel_none = new wxButton(this, wxID_ANY, _(L("None"))); + btn_sizer->Add(sel_all, 0, wxRIGHT, em / 2); + btn_sizer->Add(sel_none); + + grid->Add(new wxBoxSizer(wxHORIZONTAL)); + grid->Add(new wxBoxSizer(wxHORIZONTAL)); + grid->Add(btn_sizer, 0, wxALIGN_RIGHT); + + append(grid); + + list_l1->append(_(L("(All)")), &EMPTY); + + for (const std::string &type : materials->types) { + list_l1->append(type, &type); + } + + list_l1->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) { + update_lists(list_l1->GetSelection(), list_l2->GetSelection()); + }); + list_l2->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) { + update_lists(list_l1->GetSelection(), list_l2->GetSelection()); + }); + + list_l3->Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent &evt) { select_material(evt.GetInt()); }); + + sel_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(true); }); + sel_none->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(false); }); + + if (list_l1->GetCount() > 0) { + list_l1->SetSelection(0); + update_lists(0, 0); + } +} + +void PageMaterials::update_lists(int sel1, int sel2) +{ + wxWindowUpdateLocker freeze_guard(this); + (void)freeze_guard; + + if (sel1 != sel1_prev) { + // Refresh the second list + + // XXX: The vendor list is created with quadratic complexity here, + // but the number of vendors is realistically so small this shouldn't be a problem. + + list_l2->Clear(); + list_l2->append(_(L("(All)")), &EMPTY); + if (sel1 != wxNOT_FOUND) { + const std::string &type = list_l1->get_data(sel1); + + materials->filter_presets(type, EMPTY, [this](Preset &p) { + const std::string &vendor = this->materials->get_vendor(p); + + if (list_l2->find(vendor) == wxNOT_FOUND) { + list_l2->append(vendor, &vendor); + } + }); + } + + sel1_prev = sel1; + sel2 = 0; + sel2_prev = wxNOT_FOUND; + list_l2->SetSelection(sel2); + list_l3->Clear(); + } + + if (sel2 != sel2_prev) { + // Refresh the third list + + list_l3->Clear(); + if (sel1 != wxNOT_FOUND && sel2 != wxNOT_FOUND) { + const std::string &type = list_l1->get_data(sel1); + const std::string &vendor = list_l2->get_data(sel2); + + materials->filter_presets(type, vendor, [this](Preset &p) { + const int i = list_l3->append(p.name, &p); + const bool checked = wizard_p()->appconfig_new.has(materials->appconfig_section(), p.name); + list_l3->Check(i, checked); + }); + } + + sel2_prev = sel2; + } +} + +void PageMaterials::select_material(int i) +{ + const bool checked = list_l3->IsChecked(i); + const Preset &preset = list_l3->get_data(i); + + if (checked) { + wizard_p()->appconfig_new.set(materials->appconfig_section(), preset.name, "1"); + } else { + wizard_p()->appconfig_new.erase(materials->appconfig_section(), preset.name); + } +} + +void PageMaterials::select_all(bool select) +{ + wxWindowUpdateLocker freeze_guard(this); + (void)freeze_guard; + + for (int i = 0; i < list_l3->GetCount(); i++) { + const bool current = list_l3->IsChecked(i); + if (current != select) { + list_l3->Check(i, select); + select_material(i); + } + } +} + const char *PageCustom::default_profile_name = "My Settings"; @@ -400,7 +571,7 @@ PageCustom::PageCustom(ConfigWizard *parent) cb_custom->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { tc_profile_name->Enable(custom_wanted()); - wizard_p()->on_custom_setup(custom_wanted()); + wizard_p()->on_custom_setup(); }); append(cb_custom); @@ -453,20 +624,20 @@ PageVendors::PageVendors(ConfigWizard *parent) auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); boldfont.SetWeight(wxFONTWEIGHT_BOLD); - AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors; + AppConfig &appconfig = this->wizard_p()->appconfig_new; wxArrayString choices_vendors; for (const auto vendor_pair : wizard_p()->vendors) { const auto &vendor = vendor_pair.second; if (vendor.id == "PrusaResearch") { continue; } - auto *picker = new PrinterPicker(this, vendor, "", MAX_COLS, appconfig_vendors); + auto *picker = new PrinterPicker(this, vendor, "", MAX_COLS, appconfig); picker->Hide(); pickers.push_back(picker); choices_vendors.Add(vendor.name); - picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) { - appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); + picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) { + appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); }); } @@ -875,6 +1046,68 @@ void ConfigWizardIndex::msw_rescale() } +// Materials + +const std::string Materials::UNKNOWN = "(Unknown)"; +const std::string Materials::SECTION_FILAMENTS = "filaments"; +const std::string Materials::SECTION_MATERIALS = "sla_materials"; + +const std::string& Materials::appconfig_section() const +{ + return (technology & T_FFF) ? SECTION_FILAMENTS : SECTION_MATERIALS; +} + +const std::string& Materials::get_type(Preset &preset) const +{ + return (technology & T_FFF) ? get_filament_type(preset) : get_material_type(preset); +} + +const std::string& Materials::get_vendor(Preset &preset) const +{ + return (technology & T_FFF) ? get_filament_vendor(preset) : get_material_vendor(preset); +} + +const std::string& Materials::get_filament_type(const Preset &preset) +{ + const auto *opt = preset.config.opt("filament_type"); + if (opt != nullptr && opt->values.size() > 0) { + return opt->values[0]; + } else { + return UNKNOWN; + } +} + +const std::string& Materials::get_filament_vendor(const Preset &preset) +{ + const auto *opt = preset.config.opt("filament_vendor"); + return opt != nullptr ? opt->value : UNKNOWN; +} + +const std::string& Materials::get_material_type(Preset &preset) +{ + // XXX: The initial_layer_height is of a float type and contains no string to reference, + // and so here he serialize it into an ad-hoc option initial_layer_height_str, which is then referenced + + const auto *opt_str = preset.config.opt("initial_layer_height_str"); + if (opt_str == nullptr) { + const auto *opt = preset.config.opt("initial_layer_height"); + if (opt == nullptr) { return UNKNOWN; } + + auto *new_opt_str = new ConfigOptionString(opt->serialize()); + preset.config.set_key_value("initial_layer_height_str", new_opt_str); + return new_opt_str->value; + } else { + return opt_str->value; + } +} + +const std::string& Materials::get_material_vendor(const Preset &preset) +{ + const auto *opt = preset.config.opt("material_vendor"); + return opt != nullptr ? opt->value : UNKNOWN; +} + + // priv static const std::unordered_map> legacy_preset_map {{ @@ -888,7 +1121,7 @@ static const std::unordered_map { "Original Prusa i3 MK3.ini", std::make_pair("MK3", "0.4") }, }}; -void ConfigWizard::priv::load_pages(bool custom_setup) +void ConfigWizard::priv::load_pages() { const auto former_active = index->active_item(); @@ -897,9 +1130,15 @@ void ConfigWizard::priv::load_pages(bool custom_setup) index->add_page(page_welcome); index->add_page(page_fff); index->add_page(page_msla); + + index->add_page(page_filaments); + if (any_sla_selected) { + index->add_page(page_sla_materials); + } + index->add_page(page_custom); - if (custom_setup) { + if (page_custom->custom_wanted()) { index->add_page(page_firmware); index->add_page(page_bed); index->add_page(page_diams); @@ -946,10 +1185,15 @@ void ConfigWizard::priv::load_vendors() const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor"; const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles"; + PresetBundle bundle; + // Load vendors from the "vendors" directory in datadir - for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) + // XXX: The VendorProfile is loaded twice here, ditto below + for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) { if (Slic3r::is_ini_file(dir_entry)) { try { + bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + auto vp = VendorProfile::from_ini(dir_entry.path()); vendors[vp.id] = std::move(vp); } @@ -957,13 +1201,17 @@ void ConfigWizard::priv::load_vendors() BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); } } + } // Additionally load up vendors from the application resources directory, but only those not seen in the datadir - for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) + for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) { if (Slic3r::is_ini_file(dir_entry)) { const auto id = dir_entry.path().stem().string(); + if (vendors.find(id) == vendors.end()) { try { + bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + auto vp = VendorProfile::from_ini(dir_entry.path()); vendors_rsrc[vp.id] = dir_entry.path().filename().string(); vendors[vp.id] = std::move(vp); @@ -973,11 +1221,24 @@ void ConfigWizard::priv::load_vendors() } } } + } + + // Move materials to our Materials container: + for (auto &&f : bundle.filaments) { + f.vendor = nullptr; + filaments.presets.push_back(std::move(f)); + filaments.types.insert(Materials::get_filament_type(f)); + } + for (auto &&m : bundle.sla_materials) { + m.vendor = nullptr; + sla_materials.presets.push_back(std::move(m)); + sla_materials.types.insert(Materials::get_material_type(m)); + } // Load up the set of vendors / models / variants the user has had enabled up till now const AppConfig *app_config = GUI::get_app_config(); if (! app_config->legacy_datadir()) { - appconfig_vendors.set_vendors(*app_config); + appconfig_new.set_vendors(*app_config); } else { // In case of legacy datadir, try to guess the preference based on the printer preset files that are present const auto printer_dir = fs::path(Slic3r::data_dir()) / "printer"; @@ -988,9 +1249,31 @@ void ConfigWizard::priv::load_vendors() const auto &model = needle->second.first; const auto &variant = needle->second.second; - appconfig_vendors.set_variant("PrusaResearch", model, variant, true); + appconfig_new.set_variant("PrusaResearch", model, variant, true); } } + + // Load up the materials enabled till now + if (app_config->has_section(Materials::SECTION_FILAMENTS)) { + appconfig_new.set_section(Materials::SECTION_FILAMENTS, app_config->get_section(Materials::SECTION_FILAMENTS)); + } else { + // No AppConfig settings, load up defaults from vendor section(s) + for (const auto &vendor : bundle.vendors) { + for (const auto &profile : vendor.default_filaments) { + appconfig_new.set(Materials::SECTION_FILAMENTS, profile, "1"); + } + } + } + if (app_config->has_section(Materials::SECTION_MATERIALS)) { + appconfig_new.set_section(Materials::SECTION_MATERIALS, app_config->get_section(Materials::SECTION_MATERIALS)); + } else { + // No AppConfig settings, load up defaults from vendor section(s) + for (const auto &vendor : bundle.vendors) { + for (const auto &profile : vendor.default_sla_materials) { + appconfig_new.set(Materials::SECTION_MATERIALS, profile, "1"); + } + } + } } void ConfigWizard::priv::add_page(ConfigWizardPage *page) @@ -1004,14 +1287,25 @@ void ConfigWizard::priv::enable_next(bool enable) btn_finish->Enable(enable); } -void ConfigWizard::priv::on_custom_setup(bool custom_wanted) +void ConfigWizard::priv::on_custom_setup() { - load_pages(custom_wanted); + load_pages(); +} + +void ConfigWizard::priv::on_printer_pick(PagePrinters *page) +{ + if (page == page_msla) { + const bool any_sla_selected_new = page->any_selected(); + if (any_sla_selected != any_sla_selected_new) { + any_sla_selected = any_sla_selected_new; + load_pages(); + } + } } void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater) { - const auto enabled_vendors = appconfig_vendors.vendors(); + const auto enabled_vendors = appconfig_new.vendors(); // Install bundles from resources if needed: std::vector install_bundles; @@ -1066,7 +1360,13 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese preset_bundle->reset(true); } - app_config->set_vendors(appconfig_vendors); + app_config->set_vendors(appconfig_new); + if (appconfig_new.has_section(Materials::SECTION_FILAMENTS)) { + app_config->set_section(Materials::SECTION_FILAMENTS, appconfig_new.get_section(Materials::SECTION_FILAMENTS)); + } + if (appconfig_new.has_section(Materials::SECTION_MATERIALS)) { + app_config->set_section(Materials::SECTION_MATERIALS, appconfig_new.get_section(Materials::SECTION_MATERIALS)); + } app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); @@ -1155,12 +1455,17 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) p->add_page(p->page_welcome = new PageWelcome(this)); - p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", vendor_prusa, 0, PagePrinters::T_FFF); + p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", vendor_prusa, 0, T_FFF); p->add_page(p->page_fff); - p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", vendor_prusa, 0, PagePrinters::T_SLA); + p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", vendor_prusa, 0, T_SLA); p->add_page(p->page_msla); + p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments, + _(L("Filament Profiles Selection")), _(L("Filaments")), _(L("Type:")) )); + p->add_page(p->page_sla_materials = new PageMaterials(this, &p->sla_materials, + _(L("SLA Material Profiles Selection")), _(L("SLA Materials")), _(L("Layer height:")) )); + p->add_page(p->page_custom = new PageCustom(this)); p->add_page(p->page_update = new PageUpdate(this)); p->add_page(p->page_vendors = new PageVendors(this)); @@ -1169,7 +1474,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) p->add_page(p->page_diams = new PageDiameters(this)); p->add_page(p->page_temps = new PageTemperatures(this)); - p->load_pages(false); + p->any_sla_selected = p->page_msla->any_selected(); + p->load_pages(); vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN); vsizer->Add(hline, 0, wxEXPAND); @@ -1191,6 +1497,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) p->btn_finish->Hide(); p->btn_sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { + p->any_sla_selected = true; + p->load_pages(); p->page_fff->select_all(true, false); p->page_msla->select_all(true, false); p->index->go_to(p->page_update); @@ -1240,7 +1548,7 @@ void ConfigWizard::on_dpi_changed(const wxRect &suggested_rect) { p->index->msw_rescale(); - const int& em = em_unit(); + const int em = em_unit(); msw_buttons_rescale(this, em, { wxID_APPLY, wxID_CANCEL, diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index f4848933fc..b57161c00e 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "libslic3r/PrintConfig.hpp" #include "slic3r/Utils/PresetUpdater.hpp" @@ -41,6 +43,13 @@ enum { ROW_SPACING = 75, }; +enum Technology { + // Bitflag equivalent of PrinterTechnology + T_FFF = 0x1, + T_SLA = 0x2, + T_Any = ~0, +}; + typedef std::function ModelFilter; struct PrinterPicker: wxPanel @@ -61,19 +70,20 @@ struct PrinterPicker: wxPanel std::vector cboxes; std::vector cboxes_alt; - PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter); - PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors); + PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig, const ModelFilter &filter); + PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig); void select_all(bool select, bool alternates = false); void select_one(size_t i, bool select); - void on_checkbox(const Checkbox *cbox, bool checked); + bool any_selected() const; int get_width() const { return width; } const std::vector& get_button_indexes() { return m_button_indexes; } private: int width; - std::vector m_button_indexes; + + void on_checkbox(const Checkbox *cbox, bool checked); }; struct ConfigWizardPage: wxPanel @@ -111,19 +121,93 @@ struct PageWelcome: ConfigWizardPage struct PagePrinters: ConfigWizardPage { - enum Technology { - // Bitflag equivalent of PrinterTechnology - T_FFF = 0x1, - T_SLA = 0x2, - T_Any = ~0, - }; - std::vector printer_pickers; PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology); void select_all(bool select, bool alternates = false); int get_width() const; + bool any_selected() const; +}; + + +struct Materials +{ + Technology technology; + std::vector presets; + std::set types; + + Materials(Technology technology) : technology(technology) {} + + const std::string& appconfig_section() const; + const std::string& get_type(Preset &preset) const; + const std::string& get_vendor(Preset &preset) const; + + template void filter_presets(const std::string &type, const std::string &vendor, F cb) { + for (Preset &preset : presets) { + if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) { + cb(preset); + } + } + } + + static const std::string UNKNOWN; + static const std::string SECTION_FILAMENTS; + static const std::string SECTION_MATERIALS; + static const std::string& get_filament_type(const Preset &preset); + static const std::string& get_filament_vendor(const Preset &preset); + static const std::string& get_material_type(Preset &preset); + static const std::string& get_material_vendor(const Preset &preset); +}; + +// Here we extend wxListBox and wxCheckListBox +// to make the client data API much easier to use. +template struct DataList : public T +{ + DataList(wxWindow *parent) : T(parent, wxID_ANY) {} + + int append(const std::string &label, const D *data) { + void *ptr = reinterpret_cast(const_cast(data)); + return this->Append(from_u8(label), ptr); + } + + int append(const wxString &label, const D *data) { + void *ptr = reinterpret_cast(const_cast(data)); + return this->Append(label, ptr); + } + + const D& get_data(int n) { + return *reinterpret_cast(this->GetClientData(n)); + } + + int find(const D &data) { + for (int i = 0; i < this->GetCount(); i++) { + if (get_data(i) == data) { return i; } + } + + return wxNOT_FOUND; + } +}; + +typedef DataList StringList; +typedef DataList PresetList; + +struct PageMaterials: ConfigWizardPage +{ + // Technology technology; + Materials *materials; + StringList *list_l1, *list_l2; + PresetList *list_l3; + // wxCheckListBox *list_l3; + int sel1_prev, sel2_prev; + + PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name); + + void update_lists(int sel1, int sel2); + void select_material(int i); + void select_all(bool select); + + static const std::string EMPTY; }; struct PageCustom: ConfigWizardPage @@ -228,12 +312,6 @@ private: int em_w; int em_h; - /* #ys_FIXME_delete_after_testing by VK - const wxBitmap bg; - const wxBitmap bullet_black; - const wxBitmap bullet_blue; - const wxBitmap bullet_white; - */ ScalableBitmap bg; ScalableBitmap bullet_black; ScalableBitmap bullet_blue; @@ -245,9 +323,6 @@ private: ssize_t item_hover; size_t last_page; - /* #ys_FIXME_delete_after_testing by VK - int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em_w) + em_w; } - */ int item_height() const { return std::max(bullet_black.bmp().GetSize().GetHeight(), em_w) + em_w; } void on_paint(wxPaintEvent &evt); @@ -256,14 +331,18 @@ private: wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); + struct ConfigWizard::priv { ConfigWizard *q; ConfigWizard::RunReason run_reason; - AppConfig appconfig_vendors; + AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI std::unordered_map vendors; - std::unordered_map vendors_rsrc; - std::unique_ptr custom_config; + Materials filaments; // Holds available filament presets and their types & vendors + Materials sla_materials; // Ditto for SLA materials + std::unordered_map vendors_rsrc; // List of bundles to install from resources + std::unique_ptr custom_config; // Backing for custom printer definition + bool any_sla_selected; // Used to decide whether to display SLA Materials page wxScrolledWindow *hscroll = nullptr; wxBoxSizer *hscroll_sizer = nullptr; @@ -279,6 +358,8 @@ struct ConfigWizard::priv PageWelcome *page_welcome = nullptr; PagePrinters *page_fff = nullptr; PagePrinters *page_msla = nullptr; + PageMaterials *page_filaments = nullptr; + PageMaterials *page_sla_materials = nullptr; PageCustom *page_custom = nullptr; PageUpdate *page_update = nullptr; PageVendors *page_vendors = nullptr; // XXX: ? @@ -289,9 +370,14 @@ struct ConfigWizard::priv PageDiameters *page_diams = nullptr; PageTemperatures *page_temps = nullptr; - priv(ConfigWizard *q) : q(q) {} + priv(ConfigWizard *q) + : q(q) + , filaments(T_FFF) + , sla_materials(T_SLA) + , any_sla_selected(false) + {} - void load_pages(bool custom_setup); + void load_pages(); void init_dialog_size(); bool check_first_variant() const; @@ -299,7 +385,8 @@ struct ConfigWizard::priv void add_page(ConfigWizardPage *page); void enable_next(bool enable); - void on_custom_setup(bool custom_wanted); + void on_custom_setup(); + void on_printer_pick(PagePrinters *page); void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index d2503d349d..01cd4fa4d1 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -99,6 +99,9 @@ static const std::unordered_map pre_family_model_map { VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem::path &path, bool load_all) { static const std::string printer_model_key = "printer_model:"; + static const std::string filaments_section = "default_filaments"; + static const std::string materials_section = "default_sla_materials"; + const std::string id = path.stem().string(); if (! boost::filesystem::exists(path)) { @@ -107,6 +110,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem VendorProfile res(id); + // Helper to get compulsory fields auto get_or_throw = [&](const ptree &tree, const std::string &key) -> ptree::const_assoc_iterator { auto res = tree.find(key); @@ -116,6 +120,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem return res; }; + // Load the header const auto &vendor_section = get_or_throw(tree, "vendor")->second; res.name = get_or_throw(vendor_section, "name")->second.data(); @@ -127,6 +132,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem res.config_version = std::move(*config_version); } + // Load URLs const auto config_update_url = vendor_section.find("config_update_url"); if (config_update_url != vendor_section.not_found()) { res.config_update_url = config_update_url->second.data(); @@ -141,6 +147,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem return res; } + // Load printer models for (auto §ion : tree) { if (boost::starts_with(section.first, printer_model_key)) { VendorProfile::PrinterModel model; @@ -182,6 +189,24 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem } } + // Load filaments and sla materials to be installed by default + const auto filaments = tree.find(filaments_section); + if (filaments != tree.not_found()) { + for (auto &pair : filaments->second) { + if (pair.second.data() == "1") { + res.default_filaments.insert(pair.first); + } + } + } + const auto materials = tree.find(materials_section); + if (materials != tree.not_found()) { + for (auto &pair : materials->second) { + if (pair.second.data() == "1") { + res.default_sla_materials.insert(pair.first); + } + } + } + return res; } @@ -351,10 +376,17 @@ bool Preset::update_compatible(const Preset &active_printer, const DynamicPrintC void Preset::set_visible_from_appconfig(const AppConfig &app_config) { if (vendor == nullptr) { return; } - const std::string &model = config.opt_string("printer_model"); - const std::string &variant = config.opt_string("printer_variant"); - if (model.empty() || variant.empty()) { return; } - is_visible = app_config.get_variant(vendor->id, model, variant); + + if (type == TYPE_PRINTER) { + const std::string &model = config.opt_string("printer_model"); + const std::string &variant = config.opt_string("printer_variant"); + if (model.empty() || variant.empty()) { return; } + is_visible = app_config.get_variant(vendor->id, model, variant); + } else if (type == TYPE_FILAMENT) { + is_visible = app_config.has("filaments", name); + } else if (type == TYPE_SLA_MATERIAL) { + is_visible = app_config.has("sla_materials", name); + } } const std::vector& Preset::print_options() @@ -404,7 +436,7 @@ const std::vector& Preset::filament_options() "filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel", "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", // Profile compatibility - "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" + "filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" }; return s_opts; } @@ -504,6 +536,7 @@ const std::vector& Preset::sla_material_options() "initial_exposure_time", "material_correction", "material_notes", + "material_vendor", "default_sla_material_profile", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index e1efdc1ef0..dfb72d495e 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -71,9 +71,14 @@ public: }; std::vector models; + std::set default_filaments; + std::set default_sla_materials; + VendorProfile() {} VendorProfile(std::string id) : id(std::move(id)) {} + // Load VendorProfile from an ini file. + // If `load_all` is false, only the header with basic info (name, version, URLs) is loaded. static VendorProfile from_ini(const boost::filesystem::path &path, bool load_all=true); static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index d9e90333c6..f254ad15c1 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -323,6 +323,14 @@ void PresetBundle::load_installed_printers(const AppConfig &config) for (auto &preset : printers) { preset.set_visible_from_appconfig(config); } + + for (auto &preset : filaments) { + preset.set_visible_from_appconfig(config); + } + + for (auto &preset : sla_materials) { + preset.set_visible_from_appconfig(config); + } } // Load selections (current print, current filaments, current printer) from config.ini From 87b7b1cc1dc79ea77d2100481fd0f58a85b59037 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 3 Jun 2019 10:15:26 +0200 Subject: [PATCH 02/11] Load default filament/material selections from vendor profiles --- src/slic3r/GUI/AppConfig.cpp | 3 ++ src/slic3r/GUI/AppConfig.hpp | 2 ++ src/slic3r/GUI/ConfigWizard.cpp | 42 ++++++++----------------- src/slic3r/GUI/ConfigWizard_private.hpp | 2 -- src/slic3r/GUI/PresetBundle.cpp | 23 +++++++++++++- src/slic3r/GUI/PresetBundle.hpp | 6 +++- 6 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp index 5a165e8aed..6b3f54f3a7 100644 --- a/src/slic3r/GUI/AppConfig.cpp +++ b/src/slic3r/GUI/AppConfig.cpp @@ -28,6 +28,9 @@ static const std::string VENDOR_PREFIX = "vendor:"; static const std::string MODEL_PREFIX = "model:"; static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaSlicer.version"; +const std::string AppConfig::SECTION_FILAMENTS = "filaments"; +const std::string AppConfig::SECTION_MATERIALS = "sla_materials"; + void AppConfig::reset() { m_storage.clear(); diff --git a/src/slic3r/GUI/AppConfig.hpp b/src/slic3r/GUI/AppConfig.hpp index fe30c0af69..97c369ab64 100644 --- a/src/slic3r/GUI/AppConfig.hpp +++ b/src/slic3r/GUI/AppConfig.hpp @@ -131,6 +131,8 @@ public: std::vector get_recent_projects() const; void set_recent_projects(const std::vector& recent_projects); + static const std::string SECTION_FILAMENTS; + static const std::string SECTION_MATERIALS; private: // Map of section, name -> value std::map> m_storage; diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 0d35ce1afc..9dbf3d0377 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1049,12 +1049,10 @@ void ConfigWizardIndex::msw_rescale() // Materials const std::string Materials::UNKNOWN = "(Unknown)"; -const std::string Materials::SECTION_FILAMENTS = "filaments"; -const std::string Materials::SECTION_MATERIALS = "sla_materials"; const std::string& Materials::appconfig_section() const { - return (technology & T_FFF) ? SECTION_FILAMENTS : SECTION_MATERIALS; + return (technology & T_FFF) ? AppConfig::SECTION_FILAMENTS : AppConfig::SECTION_MATERIALS; } const std::string& Materials::get_type(Preset &preset) const @@ -1236,7 +1234,7 @@ void ConfigWizard::priv::load_vendors() } // Load up the set of vendors / models / variants the user has had enabled up till now - const AppConfig *app_config = GUI::get_app_config(); + AppConfig *app_config = GUI::get_app_config(); if (! app_config->legacy_datadir()) { appconfig_new.set_vendors(*app_config); } else { @@ -1253,27 +1251,13 @@ void ConfigWizard::priv::load_vendors() } } - // Load up the materials enabled till now - if (app_config->has_section(Materials::SECTION_FILAMENTS)) { - appconfig_new.set_section(Materials::SECTION_FILAMENTS, app_config->get_section(Materials::SECTION_FILAMENTS)); - } else { - // No AppConfig settings, load up defaults from vendor section(s) - for (const auto &vendor : bundle.vendors) { - for (const auto &profile : vendor.default_filaments) { - appconfig_new.set(Materials::SECTION_FILAMENTS, profile, "1"); - } - } - } - if (app_config->has_section(Materials::SECTION_MATERIALS)) { - appconfig_new.set_section(Materials::SECTION_MATERIALS, app_config->get_section(Materials::SECTION_MATERIALS)); - } else { - // No AppConfig settings, load up defaults from vendor section(s) - for (const auto &vendor : bundle.vendors) { - for (const auto &profile : vendor.default_sla_materials) { - appconfig_new.set(Materials::SECTION_MATERIALS, profile, "1"); - } - } - } + // Load up the materials enabled till now, + // apply defaults from vendor profiles if there are no selections yet. + bundle.init_materials_selection(*app_config); + wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS), + "Failed to initialize default material selections"); + appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); + appconfig_new.set_section(AppConfig::SECTION_MATERIALS, app_config->get_section(AppConfig::SECTION_MATERIALS)); } void ConfigWizard::priv::add_page(ConfigWizardPage *page) @@ -1361,11 +1345,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese } app_config->set_vendors(appconfig_new); - if (appconfig_new.has_section(Materials::SECTION_FILAMENTS)) { - app_config->set_section(Materials::SECTION_FILAMENTS, appconfig_new.get_section(Materials::SECTION_FILAMENTS)); + if (appconfig_new.has_section(AppConfig::SECTION_FILAMENTS)) { + app_config->set_section(AppConfig::SECTION_FILAMENTS, appconfig_new.get_section(AppConfig::SECTION_FILAMENTS)); } - if (appconfig_new.has_section(Materials::SECTION_MATERIALS)) { - app_config->set_section(Materials::SECTION_MATERIALS, appconfig_new.get_section(Materials::SECTION_MATERIALS)); + if (appconfig_new.has_section(AppConfig::SECTION_MATERIALS)) { + app_config->set_section(AppConfig::SECTION_MATERIALS, appconfig_new.get_section(AppConfig::SECTION_MATERIALS)); } app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index b57161c00e..1c7cc94de2 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -152,8 +152,6 @@ struct Materials } static const std::string UNKNOWN; - static const std::string SECTION_FILAMENTS; - static const std::string SECTION_MATERIALS; static const std::string& get_filament_type(const Preset &preset); static const std::string& get_filament_vendor(const Preset &preset); static const std::string& get_material_type(Preset &preset); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index f254ad15c1..2ea03d755a 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -194,7 +194,7 @@ void PresetBundle::setup_directories() } } -void PresetBundle::load_presets(const AppConfig &config, const std::string &preferred_model_id) +void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_model_id) { // First load the vendor specific system presets. std::string errors_cummulative = this->load_system_presets(); @@ -237,6 +237,10 @@ void PresetBundle::load_presets(const AppConfig &config, const std::string &pref if (! errors_cummulative.empty()) throw std::runtime_error(errors_cummulative); + // Make sure there are filament / material selections in the AppConfig, + // if there are none, load up defaults from vendor profiles. + this->init_materials_selection(config); + this->load_selections(config, preferred_model_id); } @@ -407,6 +411,23 @@ void PresetBundle::export_selections(AppConfig &config) config.set("presets", "printer", printers.get_selected_preset_name()); } +void PresetBundle::init_materials_selection(AppConfig &config) const { + if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { + for (const auto &vendor : this->vendors) { + for (const auto &profile : vendor.default_filaments) { + config.set(AppConfig::SECTION_FILAMENTS, profile, "1"); + } + } + } + if (! config.has_section(AppConfig::SECTION_MATERIALS)) { + for (const auto &vendor : this->vendors) { + for (const auto &profile : vendor.default_sla_materials) { + config.set(AppConfig::SECTION_MATERIALS, profile, "1"); + } + } + } +} + void PresetBundle::load_compatible_bitmaps(wxWindow *window) { // We don't actually pass the window pointer here and instead generate diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index f351f66ac3..847b370187 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -31,11 +31,15 @@ public: // Load ini files of all types (print, filament, printer) from Slic3r::data_dir() / presets. // Load selections (current print, current filaments, current printer) from config.ini // This is done just once on application start up. - void load_presets(const AppConfig &config, const std::string &preferred_model_id = ""); + void load_presets(AppConfig &config, const std::string &preferred_model_id = ""); // Export selections (current print, current filaments, current printer) into config.ini void export_selections(AppConfig &config); + // Make sure filament and sla_materials section in AppConfig are initialized + // to defaults from vendor profiles if they don't exist already + void init_materials_selection(AppConfig &config) const; + PresetCollection prints; PresetCollection sla_prints; PresetCollection filaments; From dba9925c4ed37d5b44f6672824987fa9ca0ad7b8 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 4 Jun 2019 18:01:41 +0200 Subject: [PATCH 03/11] Move ConfigWizard instance in GUI_App, lazy-initialized, add filament/material installation item in Sidebar combo boxes --- src/slic3r/GUI/ConfigWizard.cpp | 37 +++++++++++++------ src/slic3r/GUI/ConfigWizard.hpp | 12 +++++- src/slic3r/GUI/ConfigWizard_private.hpp | 5 +-- src/slic3r/GUI/GUI.cpp | 43 ---------------------- src/slic3r/GUI/GUI.hpp | 8 ---- src/slic3r/GUI/GUI_App.cpp | 49 +++++++++++++++++++++++-- src/slic3r/GUI/GUI_App.hpp | 7 ++++ src/slic3r/GUI/Plater.cpp | 13 +++++-- src/slic3r/GUI/Plater.hpp | 8 +++- src/slic3r/GUI/Preset.cpp | 4 +- src/slic3r/GUI/PresetBundle.cpp | 3 ++ src/slic3r/GUI/Tab.cpp | 6 +-- src/slic3r/Utils/PresetUpdater.cpp | 5 +-- 13 files changed, 115 insertions(+), 85 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 9dbf3d0377..d368d4fbdf 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -584,7 +584,7 @@ PageUpdate::PageUpdate(ConfigWizard *parent) , version_check(true) , preset_update(true) { - const AppConfig *app_config = GUI::get_app_config(); + const AppConfig *app_config = wxGetApp().app_config; auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); boldfont.SetWeight(wxFONTWEIGHT_BOLD); @@ -1084,7 +1084,7 @@ const std::string& Materials::get_filament_vendor(const Preset &preset) const std::string& Materials::get_material_type(Preset &preset) { // XXX: The initial_layer_height is of a float type and contains no string to reference, - // and so here he serialize it into an ad-hoc option initial_layer_height_str, which is then referenced + // and so here we serialize it into an ad-hoc option initial_layer_height_str, which is then referenced const auto *opt_str = preset.config.opt("initial_layer_height_str"); if (opt_str == nullptr) { @@ -1234,7 +1234,7 @@ void ConfigWizard::priv::load_vendors() } // Load up the set of vendors / models / variants the user has had enabled up till now - AppConfig *app_config = GUI::get_app_config(); + AppConfig *app_config = wxGetApp().app_config; if (! app_config->legacy_datadir()) { appconfig_new.set_vendors(*app_config); } else { @@ -1271,6 +1271,16 @@ void ConfigWizard::priv::enable_next(bool enable) btn_finish->Enable(enable); } +void ConfigWizard::priv::set_start_page(ConfigWizard::StartPage start_page) +{ + switch (start_page) { + case ConfigWizard::SP_PRINTERS: index->go_to(page_fff); break; + case ConfigWizard::SP_FILAMENTS: index->go_to(page_filaments); break; + case ConfigWizard::SP_MATERIALS: index->go_to(page_sla_materials); break; + default: index->go_to(page_welcome); break; + } +} + void ConfigWizard::priv::on_custom_setup() { load_pages(); @@ -1390,12 +1400,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // Public -ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) - : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +ConfigWizard::ConfigWizard() + : DPIDialog(nullptr, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , p(new priv(this)) { this->SetFont(wxGetApp().normal_font()); - p->run_reason = reason; p->load_vendors(); p->custom_config.reset(DynamicPrintConfig::new_from_defaults_keys({ @@ -1499,13 +1508,18 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) ConfigWizard::~ConfigWizard() {} -bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater) +bool ConfigWizard::run(RunReason reason, StartPage start_page) { - BOOST_LOG_TRIVIAL(info) << "Running ConfigWizard, reason: " << p->run_reason; + BOOST_LOG_TRIVIAL(info) << boost::format("Running ConfigWizard, reason: %1%, start_page: %2%") % reason % start_page; + + GUI_App &app = wxGetApp(); + + p->run_reason = reason; + p->set_start_page(start_page); + if (ShowModal() == wxID_OK) { - auto *app_config = GUI::get_app_config(); - p->apply_config(app_config, preset_bundle, updater); - app_config->set_legacy_datadir(false); + p->apply_config(app.app_config, app.preset_bundle, app.preset_updater); + app.app_config->set_legacy_datadir(false); BOOST_LOG_TRIVIAL(info) << "ConfigWizard applied"; return true; } else { @@ -1514,7 +1528,6 @@ bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater } } - const wxString& ConfigWizard::name(const bool from_menu/* = false*/) { // A different naming convention is used for the Wizard on Windows vs. OSX & GTK. diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index b707e525ba..3c85b73432 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -26,7 +26,15 @@ public: RR_USER, // User requested the Wizard from the menus }; - ConfigWizard(wxWindow *parent, RunReason run_reason); + // What page should wizard start on + enum StartPage { + SP_WELCOME, + SP_PRINTERS, + SP_FILAMENTS, + SP_MATERIALS, + }; + + ConfigWizard(); ConfigWizard(ConfigWizard &&) = delete; ConfigWizard(const ConfigWizard &) = delete; ConfigWizard &operator=(ConfigWizard &&) = delete; @@ -34,7 +42,7 @@ public: ~ConfigWizard(); // Run the Wizard. Return whether it was completed. - bool run(PresetBundle *preset_bundle, const PresetUpdater *updater); + bool run(RunReason reason, StartPage start_page = SP_WELCOME); static const wxString& name(const bool from_menu = false); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 1c7cc94de2..82708cc59b 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -192,11 +192,9 @@ typedef DataList PresetList; struct PageMaterials: ConfigWizardPage { - // Technology technology; Materials *materials; StringList *list_l1, *list_l2; PresetList *list_l3; - // wxCheckListBox *list_l3; int sel1_prev, sel2_prev; PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name); @@ -333,7 +331,7 @@ wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); struct ConfigWizard::priv { ConfigWizard *q; - ConfigWizard::RunReason run_reason; + ConfigWizard::RunReason run_reason = RR_USER; AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI std::unordered_map vendors; Materials filaments; // Holds available filament presets and their types & vendors @@ -382,6 +380,7 @@ struct ConfigWizard::priv void load_vendors(); void add_page(ConfigWizardPage *page); void enable_next(bool enable); + void set_start_page(ConfigWizard::StartPage start_page); void on_custom_setup(); void on_printer_pick(PagePrinters *page); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index f94372667c..c22fd6f792 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -101,49 +101,6 @@ const std::string& shortkey_alt_prefix() return str; } -bool config_wizard_startup(bool app_config_exists) -{ - if (!app_config_exists || wxGetApp().preset_bundle->printers.size() <= 1) { - config_wizard(ConfigWizard::RR_DATA_EMPTY); - return true; - } else if (get_app_config()->legacy_datadir()) { - // Looks like user has legacy pre-vendorbundle data directory, - // explain what this is and run the wizard - - MsgDataLegacy dlg; - dlg.ShowModal(); - - config_wizard(ConfigWizard::RR_DATA_LEGACY); - return true; - } - return false; -} - -void config_wizard(int reason) -{ - // Exit wizard if there are unsaved changes and the user cancels the action. - if (! wxGetApp().check_unsaved_changes()) - return; - - try { - ConfigWizard wizard(nullptr, static_cast(reason)); - wizard.run(wxGetApp().preset_bundle, wxGetApp().preset_updater); - } - catch (const std::exception &e) { - show_error(nullptr, e.what()); - } - - wxGetApp().load_current_presets(); - - if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && model_has_multi_part_objects(wxGetApp().model())) - { - show_info(nullptr, - _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + - _(L("Please check and fix your object list.")), - _(L("Attention!"))); - } -} - // opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element) void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/) { diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 4074c2afc8..0b904bad86 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -35,14 +35,6 @@ extern AppConfig* get_app_config(); extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change); -// Checks if configuration wizard needs to run, calls config_wizard if so. -// Returns whether the Wizard ran. -extern bool config_wizard_startup(bool app_config_exists); - -// Opens the configuration wizard, returns true if wizard is finished & accepted. -// The run_reason argument is actually ConfigWizard::RunReason, but int is used here because of Perl. -extern void config_wizard(int run_reason); - // Change option value in config void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 80c02ea78e..028886915d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -38,7 +38,6 @@ #include "../Utils/PresetUpdater.hpp" #include "../Utils/PrintHost.hpp" #include "../Utils/MacDarkMode.hpp" -#include "ConfigWizard.hpp" #include "slic3r/Config/Snapshot.hpp" #include "ConfigSnapshotDialog.hpp" #include "FirmwareDialog.hpp" @@ -46,6 +45,7 @@ #include "Tab.hpp" #include "SysInfoDialog.hpp" #include "KBShortcutsDialog.hpp" +#include "UpdateDialogs.hpp" #ifdef __WXMSW__ #include @@ -148,6 +148,7 @@ GUI_App::GUI_App() : wxApp() , m_em_unit(10) , m_imgui(new ImGuiWrapper()) + , m_wizard(nullptr) {} GUI_App::~GUI_App() @@ -204,7 +205,6 @@ bool GUI_App::on_init_inner() // supplied as argument to --datadir; in that case we should still run the wizard preset_bundle->setup_directories(); - app_conf_exists = app_config->exists(); // load settings app_conf_exists = app_config->exists(); if (app_conf_exists) { @@ -287,7 +287,7 @@ bool GUI_App::on_init_inner() } CallAfter([this] { - config_wizard_startup(app_conf_exists); + config_wizard_startup(); preset_updater->slic3r_update_notify(); preset_updater->sync(preset_bundle); }); @@ -826,7 +826,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent &event) { switch (event.GetId() - config_id_base) { case ConfigMenuWizard: - config_wizard(ConfigWizard::RR_USER); + run_wizard(ConfigWizard::RR_USER); break; case ConfigMenuTakeSnapshot: // Take a configuration snapshot. @@ -1057,6 +1057,29 @@ void GUI_App::open_web_page_localized(const std::string &http_address) wxLaunchDefaultBrowser(http_address + "&lng=" + this->current_language_code_safe()); } +bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page) +{ + if (! m_wizard) { + m_wizard.reset(new ConfigWizard()); + } + + const bool res = m_wizard->run(reason, start_page); + + if (res) { + load_current_presets(); + + if (preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA + && Slic3r::model_has_multi_part_objects(wxGetApp().model())) { + GUI::show_info(nullptr, + _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + + _(L("Please check and fix your object list.")), + _(L("Attention!"))); + } + } + + return res; +} + void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name) { if (name.empty()) { return; } @@ -1105,6 +1128,24 @@ void GUI_App::window_pos_sanitize(wxTopLevelWindow* window) } } +bool GUI_App::config_wizard_startup() +{ + if (!app_conf_exists || preset_bundle->printers.size() <= 1) { + run_wizard(ConfigWizard::RR_DATA_EMPTY); + return true; + } else if (get_app_config()->legacy_datadir()) { + // Looks like user has legacy pre-vendorbundle data directory, + // explain what this is and run the wizard + + MsgDataLegacy dlg; + dlg.ShowModal(); + + run_wizard(ConfigWizard::RR_DATA_LEGACY); + return true; + } + return false; +} + // static method accepting a wxWindow object as first parameter // void warning_catcher{ // my($self, $message_dialog) = @_; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index a8043e9915..8c5f0c30c8 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -6,6 +6,7 @@ #include "libslic3r/PrintConfig.hpp" #include "MainFrame.hpp" #include "ImGuiWrapper.hpp" +#include "ConfigWizard.hpp" #include #include @@ -69,6 +70,7 @@ enum ConfigMenuIDs { }; class Tab; +class ConfigWizard; static wxString dots("…", wxConvUTF8); @@ -96,6 +98,7 @@ class GUI_App : public wxApp std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; + std::unique_ptr m_wizard; public: bool OnInit() override; @@ -184,6 +187,7 @@ public: PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } void open_web_page_localized(const std::string &http_address); + bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME); private: bool on_init_inner(); @@ -191,6 +195,9 @@ private: void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false); void window_pos_sanitize(wxTopLevelWindow* window); bool select_language(); + + bool config_wizard_startup(); + #ifdef __WXMSW__ void associate_3mf_files(); #endif // __WXMSW__ diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c5aad48a9e..4427921fff 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -251,11 +251,18 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * auto selected_item = this->GetSelection(); auto marker = reinterpret_cast(this->GetClientData(selected_item)); - if (marker == LABEL_ITEM_MARKER || marker == LABEL_ITEM_CONFIG_WIZARD) { + if (marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX) { this->SetSelection(this->last_selected); evt.StopPropagation(); - if (marker == LABEL_ITEM_CONFIG_WIZARD) - wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); + if (marker >= LABEL_ITEM_WIZARD_PRINTERS) { + ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME; + switch (marker) { + case LABEL_ITEM_WIZARD_PRINTERS: sp = ConfigWizard::SP_PRINTERS; break; + case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break; + case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break; + } + wxTheApp->CallAfter([sp]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); }); + } } else if ( this->last_selected != selected_item || wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) { this->last_selected = selected_item; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 6b488fef14..eb714dcd58 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -56,8 +56,12 @@ public: ScalableButton* edit_btn { nullptr }; enum LabelItemType { - LABEL_ITEM_MARKER = 0x4d, - LABEL_ITEM_CONFIG_WIZARD = 0x4e + LABEL_ITEM_MARKER = 0xffffff01, + LABEL_ITEM_WIZARD_PRINTERS, + LABEL_ITEM_WIZARD_FILAMENTS, + LABEL_ITEM_WIZARD_MATERIALS, + + LABEL_ITEM_MAX, }; void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 01cd4fa4d1..bda096d66d 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -1070,7 +1070,9 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); bmp = m_bitmap_cache->insert(bitmap_key, bmps); } - ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_WIZARD_PRINTERS); + } else if (m_type == Preset::TYPE_SLA_MATERIAL) { + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add/Remove materials")), wxNullBitmap), GUI::PresetComboBox::LABEL_ITEM_WIZARD_MATERIALS); } ui->SetSelection(selected_preset_item); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 2ea03d755a..5f91111115 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1601,6 +1601,9 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr selected_preset_item = ui->GetCount() - 1; } } + + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add/Remove filaments")), wxNullBitmap), GUI::PresetComboBox::LABEL_ITEM_WIZARD_FILAMENTS); + ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->check_selection(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c87626a483..921a18147b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -227,9 +227,9 @@ void Tab::create_preset_tab() m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); m_presets_choice->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { - //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, + //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, //! but the OSX version derived from wxOwnerDrawnCombo, instead of: - //! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data()); + //! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data()); //! we doing next: int selected_item = m_presets_choice->GetSelection(); if (m_selected_preset_item == size_t(selected_item) && !m_presets->current_is_dirty()) @@ -241,7 +241,7 @@ void Tab::create_preset_tab() selected_string == "------- User presets -------"*/) { m_presets_choice->SetSelection(m_selected_preset_item); if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer"))) - wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); + wxTheApp->CallAfter([]() { wxGetApp().run_wizard(ConfigWizard::RR_USER); }); return; } m_selected_preset_item = selected_item; diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 5723afca2f..cafdbb14ef 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -643,13 +643,10 @@ PresetUpdater::UpdateResult PresetUpdater::config_update() const // (snapshot is taken beforehand) p->perform_updates(std::move(updates)); - GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT); - - if (! wizard.run(GUI::wxGetApp().preset_bundle, this)) { + if (! GUI::wxGetApp().run_wizard(GUI::ConfigWizard::RR_DATA_INCOMPAT)) { return R_INCOMPAT_EXIT; } - GUI::wxGetApp().load_current_presets(); return R_INCOMPAT_CONFIGURED; } else { BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye..."; From 235b659cf97211f0b80c47008d8458b9173a3a40 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 17 Jun 2019 16:39:22 +0200 Subject: [PATCH 04/11] WIP: ConfigWizard: 3rd party bundle installation roughly done --- src/slic3r/Config/Snapshot.cpp | 6 +- src/slic3r/GUI/ConfigWizard.cpp | 469 ++++++++++++++++-------- src/slic3r/GUI/ConfigWizard.hpp | 2 +- src/slic3r/GUI/ConfigWizard_private.hpp | 135 +++++-- src/slic3r/GUI/GUI_App.cpp | 4 +- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/Preset.cpp | 6 +- src/slic3r/GUI/Preset.hpp | 10 +- src/slic3r/GUI/PresetBundle.cpp | 52 ++- src/slic3r/GUI/PresetBundle.hpp | 8 +- src/slic3r/Utils/PresetUpdater.cpp | 14 +- 11 files changed, 493 insertions(+), 215 deletions(-) diff --git a/src/slic3r/Config/Snapshot.cpp b/src/slic3r/Config/Snapshot.cpp index 622b31a178..521a7c5315 100644 --- a/src/slic3r/Config/Snapshot.cpp +++ b/src/slic3r/Config/Snapshot.cpp @@ -393,9 +393,9 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot: // Read the active config bundle, parse the config version. PresetBundle bundle; bundle.load_configbundle((data_dir / "vendor" / (cfg.name + ".ini")).string(), PresetBundle::LOAD_CFGBUNDLE_VENDOR_ONLY); - for (const VendorProfile &vp : bundle.vendors) - if (vp.id == cfg.name) - cfg.version.config_version = vp.config_version; + for (const auto &vp : bundle.vendors) + if (vp.second.id == cfg.name) + cfg.version.config_version = vp.second.config_version; // Fill-in the min/max slic3r version from the config index, if possible. try { // Load the config index for the vendor. diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index d368d4fbdf..8a850b7a0b 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,7 @@ #include #include "libslic3r/Utils.hpp" -#include "PresetBundle.hpp" +// #include "PresetBundle.hpp" #include "GUI.hpp" #include "GUI_Utils.hpp" #include "slic3r/Config/Snapshot.hpp" @@ -40,6 +41,92 @@ using Config::Snapshot; using Config::SnapshotDB; +// Configuration data structures extensions needed for the wizard + +Bundle::Bundle(fs::path source_path, bool is_in_resources, bool is_prusa_bundle) + : source_path(std::move(source_path)) + , preset_bundle(new PresetBundle) + , vendor_profile(nullptr) + , is_in_resources(is_in_resources) + , is_prusa_bundle(is_prusa_bundle) +{ + // XXX: consider removing path <-> string juggling + preset_bundle->load_configbundle(this->source_path.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + auto first_vendor = preset_bundle->vendors.begin(); + wxCHECK_RET(first_vendor != preset_bundle->vendors.end(), "Failed to load preset bundle"); + vendor_profile = &first_vendor->second; +} + +Bundle::Bundle(Bundle &&other) + : source_path(std::move(source_path)) + , preset_bundle(std::move(other.preset_bundle)) + , vendor_profile(other.vendor_profile) + , is_in_resources(other.is_in_resources) + , is_prusa_bundle(other.is_prusa_bundle) +{ + other.vendor_profile = nullptr; +} + +BundleMap BundleMap::load() +{ + BundleMap res; + + // XXX: Keep Prusa bundle separate? (Probably no - keep same codepaths) + + const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred(); + const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred(); + + // XXX + // const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); + // const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor + // : (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); + auto prusa_bundle_path = (vendor_dir / PresetBundle::PRUSA_BUNDLE).replace_extension(".ini"); + auto prusa_bundle_rsrc = false; + if (! boost::filesystem::exists(prusa_bundle_path)) { + prusa_bundle_path = (rsrc_vendor_dir / PresetBundle::PRUSA_BUNDLE).replace_extension(".ini"); + prusa_bundle_rsrc = true; + } + Bundle prusa_bundle(std::move(prusa_bundle_path), prusa_bundle_rsrc, true); + res.emplace(PresetBundle::PRUSA_BUNDLE, std::move(prusa_bundle)); + + // Load the other bundles in the datadir/vendor directory + // and then additionally from resources/profiles. + bool is_in_resources = false; + for (auto dir : { &vendor_dir, &rsrc_vendor_dir }) { + for (const auto &dir_entry : boost::filesystem::directory_iterator(*dir)) { + if (Slic3r::is_ini_file(dir_entry)) { + std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part + + // Don't load this bundle if we've already loaded it. + if (res.find(id) != res.end()) { continue; } + + Bundle bundle(dir_entry.path(), is_in_resources); + res.emplace(std::move(id), std::move(bundle)); + } + } + + is_in_resources = true; + } + + return res; +} + +Bundle& BundleMap::prusa_bundle() +{ + auto it = find(PresetBundle::PRUSA_BUNDLE); + if (it == end()) { + throw std::runtime_error("ConfigWizard: Internal error in BundleMap: PRUSA_BUNDLE not loaded"); + } + + return it->second; +} + +const Bundle& BundleMap::prusa_bundle() const +{ + return const_cast(this)->prusa_bundle(); +} + + // Printer model picker GUI control struct PrinterPickerEvent : public wxEvent @@ -65,6 +152,8 @@ struct PrinterPickerEvent : public wxEvent wxDEFINE_EVENT(EVT_PRINTER_PICK, PrinterPickerEvent); +const std::string PrinterPicker::PRINTER_PLACEHOLDER = "printer_placeholder.png"; + PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig, const ModelFilter &filter) : wxPanel(parent) , vendor_id(vendor.id) @@ -96,6 +185,17 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt if (wxFileExists(bitmap_file)) { bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG); bitmap_width = bitmap.GetWidth(); + } else { + BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead") + % bitmap_file + % vendor.id + % model.id; + + const wxString placeholder_file = GUI::from_u8(Slic3r::var(PRINTER_PLACEHOLDER)); + if (wxFileExists(placeholder_file)) { + bitmap.LoadFile(placeholder_file, wxBITMAP_TYPE_PNG); + bitmap_width = bitmap.GetWidth(); + } } auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); @@ -135,7 +235,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name); i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox); - bool enabled = appconfig.get_variant("PrusaResearch", model_id, variant.name); + bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name); cbox->SetValue(enabled); variants_sizer->Add(cbox, 0, wxBOTTOM, 3); @@ -295,12 +395,13 @@ ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxStrin ConfigWizardPage::~ConfigWizardPage() {} -void ConfigWizardPage::append_text(wxString text) +wxStaticText* ConfigWizardPage::append_text(wxString text) { auto *widget = new wxStaticText(this, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); widget->Wrap(WRAP_WIDTH); widget->SetMinSize(wxSize(WRAP_WIDTH, -1)); append(widget); + return widget; } void ConfigWizardPage::append_spacer(int space) @@ -320,34 +421,42 @@ PageWelcome::PageWelcome(ConfigWizard *parent) _(L("Welcome to the %s Configuration Wizard")) #endif , SLIC3R_APP_NAME), _(L("Welcome"))) - , cbox_reset(nullptr) + , welcome_text(append_text(wxString::Format( + _(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")), + SLIC3R_APP_NAME, + ConfigWizard::name()) + )) + , cbox_reset(append( + new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)"))) + )) { - if (wizard_p()->run_reason == ConfigWizard::RR_DATA_EMPTY) { - wxString::Format(_(L("Run %s")), ConfigWizard::name()); - append_text(wxString::Format( - _(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")), - SLIC3R_APP_NAME, - ConfigWizard::name()) - ); - } else { - cbox_reset = new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)"))); - append(cbox_reset); - } + welcome_text->Hide(); + cbox_reset->Hide(); +} - Show(); +void PageWelcome::set_run_reason(ConfigWizard::RunReason run_reason) +{ + const bool data_empty = run_reason == ConfigWizard::RR_DATA_EMPTY; + welcome_text->Show(data_empty); + cbox_reset->Show(!data_empty); } -PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology) +PagePrinters::PagePrinters(ConfigWizard *parent, + wxString title, + wxString shortname, + const VendorProfile &vendor, + unsigned indent, + Technology technology) : ConfigWizardPage(parent, std::move(title), std::move(shortname), indent) + , technology(technology) + , install(false) // only used for 3rd party vendors { enum { COL_SIZE = 200, }; - bool check_first_variant = technology == T_FFF && wizard_p()->check_first_variant(); - - AppConfig &appconfig = this->wizard_p()->appconfig_new; + AppConfig *appconfig = &this->wizard_p()->appconfig_new; const auto families = vendor.families(); for (const auto &family : families) { @@ -362,16 +471,10 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn } const auto picker_title = family.empty() ? wxString() : wxString::Format(_(L("%s Family")), family); - auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, appconfig, filter); + auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, *appconfig, filter); - if (check_first_variant) { - // Select the default (first) model/variant on the Prusa vendor - picker->select_one(0, true); - check_first_variant = false; - } - - picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) { - appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); + picker->Bind(EVT_PRINTER_PICK, [this, appconfig](const PrinterPickerEvent &evt) { + appconfig->set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); wizard_p()->on_printer_pick(this); }); @@ -404,6 +507,15 @@ bool PagePrinters::any_selected() const return false; } +void PagePrinters::set_run_reason(ConfigWizard::RunReason run_reason) +{ + if (technology == T_FFF + && (run_reason == ConfigWizard::RR_DATA_EMPTY || run_reason == ConfigWizard::RR_DATA_LEGACY) + && printer_pickers.size() > 0) { + printer_pickers[0]->select_one(0, true); + } +} + const std::string PageMaterials::EMPTY; @@ -619,48 +731,26 @@ PageUpdate::PageUpdate(ConfigWizard *parent) PageVendors::PageVendors(ConfigWizard *parent) : ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors"))) { - append_text(wxString::Format(_(L("Pick another vendor supported by %s:")), SLIC3R_APP_NAME)); + + + // FIXME: persistence: this doesn't reload choices + + + append_text(wxString::Format(_(L("Pick another vendor supported by %s: (FIXME: this text)")), SLIC3R_APP_NAME)); auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); boldfont.SetWeight(wxFONTWEIGHT_BOLD); - AppConfig &appconfig = this->wizard_p()->appconfig_new; - wxArrayString choices_vendors; + for (const auto &pair : wizard_p()->bundles) { + const VendorProfile *vendor = pair.second.vendor_profile; + if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; } - for (const auto vendor_pair : wizard_p()->vendors) { - const auto &vendor = vendor_pair.second; - if (vendor.id == "PrusaResearch") { continue; } - - auto *picker = new PrinterPicker(this, vendor, "", MAX_COLS, appconfig); - picker->Hide(); - pickers.push_back(picker); - choices_vendors.Add(vendor.name); - - picker->Bind(EVT_PRINTER_PICK, [this, &appconfig](const PrinterPickerEvent &evt) { - appconfig.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); + auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name); + cbox->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent &event) { + wizard_p()->on_3rdparty_install(vendor, cbox->IsChecked()); }); - } - auto *vendor_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices_vendors); - if (choices_vendors.GetCount() > 0) { - vendor_picker->SetSelection(0); - on_vendor_pick(0); - } - - vendor_picker->Bind(wxEVT_CHOICE, [this](wxCommandEvent &evt) { - this->on_vendor_pick(evt.GetInt()); - }); - - append(vendor_picker); - for (PrinterPicker *picker : pickers) { this->append(picker); } -} - -void PageVendors::on_vendor_pick(size_t i) -{ - for (PrinterPicker *picker : pickers) { picker->Hide(); } - if (i < pickers.size()) { - pickers[i]->Show(); - parent->Layout(); + append(cbox); } } @@ -954,12 +1044,15 @@ void ConfigWizardIndex::go_to(size_t i) } } -void ConfigWizardIndex::go_to(ConfigWizardPage *page) +void ConfigWizardIndex::go_to(const ConfigWizardPage *page) { if (page == nullptr) { return; } for (size_t i = 0; i < items.size(); i++) { - if (items[i].page == page) { go_to(i); } + if (items[i].page == page) { + go_to(i); + return; + } } } @@ -1121,21 +1214,25 @@ static const std::unordered_map void ConfigWizard::priv::load_pages() { - const auto former_active = index->active_item(); + wxWindowUpdateLocker freeze_guard(q); + (void)freeze_guard; + + const ConfigWizardPage *former_active = index->active_page(); index->clear(); index->add_page(page_welcome); + + // Printers index->add_page(page_fff); index->add_page(page_msla); - - index->add_page(page_filaments); - if (any_sla_selected) { - index->add_page(page_sla_materials); + index->add_page(page_vendors); + for (const auto &pair : pages_3rdparty) { + PagePrinters *page = pair.second; + if (page->install) { index->add_page(page); } } index->add_page(page_custom); - if (page_custom->custom_wanted()) { index->add_page(page_firmware); index->add_page(page_bed); @@ -1143,6 +1240,10 @@ void ConfigWizard::priv::load_pages() index->add_page(page_temps); } + // Filaments & Materials + if (any_fff_selected) { index->add_page(page_filaments); } + if (any_sla_selected) { index->add_page(page_sla_materials); } + index->add_page(page_update); index->go_to(former_active); // Will restore the active item/page if possible @@ -1173,66 +1274,75 @@ void ConfigWizard::priv::init_dialog_size() q->SetSize(window_rect); } -bool ConfigWizard::priv::check_first_variant() const -{ - return run_reason == RR_DATA_EMPTY || run_reason == RR_DATA_LEGACY; -} - void ConfigWizard::priv::load_vendors() { - const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor"; - const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles"; + // const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor"; + // const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles"; - PresetBundle bundle; + // PresetBundle bundle; + // bundle.load_available_system_presets(); + bundles = BundleMap::load(); - // Load vendors from the "vendors" directory in datadir - // XXX: The VendorProfile is loaded twice here, ditto below - for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) { - if (Slic3r::is_ini_file(dir_entry)) { - try { - bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + // // Load vendors from the "vendors" directory in datadir + // // XXX: The VendorProfile is loaded twice here, ditto below + // for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) { + // if (Slic3r::is_ini_file(dir_entry)) { + // try { + // bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); - auto vp = VendorProfile::from_ini(dir_entry.path()); - vendors[vp.id] = std::move(vp); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); - } + // auto vp = VendorProfile::from_ini(dir_entry.path()); + // vendors[vp.id] = std::move(vp); + // } + // catch (const std::exception& e) { + // BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); + // } + // } + // } + + // // Additionally load up vendors from the application resources directory, but only those not seen in the datadir + // for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) { + // if (Slic3r::is_ini_file(dir_entry)) { + // const auto id = dir_entry.path().stem().string(); + + // if (vendors.find(id) == vendors.end()) { + // try { + // bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + + // auto vp = VendorProfile::from_ini(dir_entry.path()); + // vendors_rsrc[vp.id] = dir_entry.path().filename().string(); + // vendors[vp.id] = std::move(vp); + // } + // catch (const std::exception& e) { + // BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); + // } + // } + // } + // } + + // // Move materials to our Materials container: + // for (auto &&f : bundle.filaments) { + // f.vendor = nullptr; + // filaments.presets.push_back(std::move(f)); + // filaments.types.insert(Materials::get_filament_type(f)); + // } + // for (auto &&m : bundle.sla_materials) { + // m.vendor = nullptr; + // sla_materials.presets.push_back(std::move(m)); + // sla_materials.types.insert(Materials::get_material_type(m)); + // } + for (auto &pair : bundles) { + for (auto &&f : pair.second.preset_bundle->filaments) { + f.vendor = nullptr; + filaments.presets.push_back(std::move(f)); + filaments.types.insert(Materials::get_filament_type(f)); } - } - - // Additionally load up vendors from the application resources directory, but only those not seen in the datadir - for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) { - if (Slic3r::is_ini_file(dir_entry)) { - const auto id = dir_entry.path().stem().string(); - - if (vendors.find(id) == vendors.end()) { - try { - bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); - - auto vp = VendorProfile::from_ini(dir_entry.path()); - vendors_rsrc[vp.id] = dir_entry.path().filename().string(); - vendors[vp.id] = std::move(vp); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); - } - } + for (auto &&m : pair.second.preset_bundle->sla_materials) { + m.vendor = nullptr; + sla_materials.presets.push_back(std::move(m)); + sla_materials.types.insert(Materials::get_material_type(m)); } } - // Move materials to our Materials container: - for (auto &&f : bundle.filaments) { - f.vendor = nullptr; - filaments.presets.push_back(std::move(f)); - filaments.types.insert(Materials::get_filament_type(f)); - } - for (auto &&m : bundle.sla_materials) { - m.vendor = nullptr; - sla_materials.presets.push_back(std::move(m)); - sla_materials.types.insert(Materials::get_material_type(m)); - } - // Load up the set of vendors / models / variants the user has had enabled up till now AppConfig *app_config = wxGetApp().app_config; if (! app_config->legacy_datadir()) { @@ -1251,11 +1361,14 @@ void ConfigWizard::priv::load_vendors() } } +// TODO: This'll be done differently, cf. the design document // Load up the materials enabled till now, // apply defaults from vendor profiles if there are no selections yet. - bundle.init_materials_selection(*app_config); - wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS), - "Failed to initialize default material selections"); + // bundle.init_materials_selection(*app_config); + + // XXX: ? + // wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS), + // "Failed to initialize default material selections"); appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); appconfig_new.set_section(AppConfig::SECTION_MATERIALS, app_config->get_section(AppConfig::SECTION_MATERIALS)); } @@ -1263,6 +1376,7 @@ void ConfigWizard::priv::load_vendors() void ConfigWizard::priv::add_page(ConfigWizardPage *page) { hscroll_sizer->Add(page, 0, wxEXPAND); + all_pages.push_back(page); } void ConfigWizard::priv::enable_next(bool enable) @@ -1281,6 +1395,27 @@ void ConfigWizard::priv::set_start_page(ConfigWizard::StartPage start_page) } } +void ConfigWizard::priv::create_3rdparty_pages() +{ + for (const auto &pair : bundles) { + const VendorProfile *vendor = pair.second.vendor_profile; + if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; } + + auto *page = new PagePrinters(q, vendor->name, vendor->name, *vendor, 1, T_ANY); + add_page(page); + + pages_3rdparty.insert({vendor->id, page}); + } +} + +void ConfigWizard::priv::set_run_reason(RunReason run_reason) +{ + this->run_reason = run_reason; + for (auto &page : all_pages) { + page->set_run_reason(run_reason); + } +} + void ConfigWizard::priv::on_custom_setup() { load_pages(); @@ -1288,23 +1423,43 @@ void ConfigWizard::priv::on_custom_setup() void ConfigWizard::priv::on_printer_pick(PagePrinters *page) { - if (page == page_msla) { - const bool any_sla_selected_new = page->any_selected(); - if (any_sla_selected != any_sla_selected_new) { - any_sla_selected = any_sla_selected_new; - load_pages(); - } + if (page_msla->any_selected() != any_sla_selected || + page_fff->any_selected() != any_fff_selected) { + any_fff_selected = page_fff->any_selected(); + any_sla_selected = page_msla->any_selected(); + + load_pages(); } } +void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install) +{ + auto it = pages_3rdparty.find(vendor->id); + wxCHECK_RET(it != pages_3rdparty.end(), "Internal error: GUI page not found for 3rd party vendor profile"); + PagePrinters *page = it->second; + page->install = install; + page->Layout(); + + load_pages(); +} + void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater) { const auto enabled_vendors = appconfig_new.vendors(); // Install bundles from resources if needed: std::vector install_bundles; - for (const auto &vendor_rsrc : vendors_rsrc) { - const auto vendor = enabled_vendors.find(vendor_rsrc.first); + for (const auto &pair : bundles) { + if (! pair.second.is_in_resources) { continue; } + + if (pair.second.is_prusa_bundle) { + // Always install Prusa bundle, because it has a lot of filaments/materials + // likely to be referenced by other profiles. + install_bundles.emplace_back(pair.first); + continue; + } + + const auto vendor = enabled_vendors.find(pair.first); if (vendor == enabled_vendors.end()) { continue; } size_t size_sum = 0; @@ -1312,7 +1467,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese if (size_sum > 0) { // This vendor needs to be installed - install_bundles.emplace_back(vendor_rsrc.second); + install_bundles.emplace_back(pair.first); } } @@ -1370,17 +1525,18 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // The default is the first selected printer model (one with at least 1 variant selected). // The default is only applied by load_presets() if the user doesn't have a (visible) printer // selected already. - const auto vendor_prusa = vendors.find("PrusaResearch"); - const auto config_prusa = enabled_vendors.find("PrusaResearch"); - if (vendor_prusa != vendors.end() && config_prusa != enabled_vendors.end()) { - for (const auto &model : vendor_prusa->second.models) { - const auto model_it = config_prusa->second.find(model.id); - if (model_it != config_prusa->second.end() && model_it->second.size() > 0) { - preferred_model = model.id; - break; - } - } - } +// TODO + // const auto vendor_prusa = bundle.vendors.find("PrusaResearch"); + // const auto config_prusa = enabled_vendors.find("PrusaResearch"); + // if (vendor_prusa != bundle.vendors.end() && config_prusa != enabled_vendors.end()) { + // for (const auto &model : vendor_prusa->second.models) { + // const auto model_it = config_prusa->second.find(model.id); + // if (model_it != config_prusa->second.end() && model_it->second.size() > 0) { + // preferred_model = model.id; + // break; + // } + // } + // } preset_bundle->load_presets(*app_config, preferred_model); @@ -1398,10 +1554,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese preset_bundle->export_selections(*app_config); } + // Public -ConfigWizard::ConfigWizard() - : DPIDialog(nullptr, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +ConfigWizard::ConfigWizard(wxWindow *parent) + : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , p(new priv(this)) { this->SetFont(wxGetApp().normal_font()); @@ -1441,17 +1598,16 @@ ConfigWizard::ConfigWizard() p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING); p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING); - const auto &vendors = p->vendors; - const auto vendor_prusa_it = vendors.find("PrusaResearch"); - wxCHECK_RET(vendor_prusa_it != vendors.cend(), "Vendor PrusaResearch not found"); - const VendorProfile &vendor_prusa = vendor_prusa_it->second; + const auto prusa_it = p->bundles.find("PrusaResearch"); + wxCHECK_RET(prusa_it != p->bundles.cend(), "Vendor PrusaResearch not found"); + const VendorProfile *vendor_prusa = prusa_it->second.vendor_profile; p->add_page(p->page_welcome = new PageWelcome(this)); - p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", vendor_prusa, 0, T_FFF); + p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", *vendor_prusa, 0, T_FFF); p->add_page(p->page_fff); - p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", vendor_prusa, 0, T_SLA); + p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", *vendor_prusa, 0, T_SLA); p->add_page(p->page_msla); p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments, @@ -1467,7 +1623,10 @@ ConfigWizard::ConfigWizard() p->add_page(p->page_diams = new PageDiameters(this)); p->add_page(p->page_temps = new PageTemperatures(this)); + p->create_3rdparty_pages(); + p->any_sla_selected = p->page_msla->any_selected(); + p->any_fff_selected = p->page_fff->any_selected(); p->load_pages(); vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN); @@ -1514,7 +1673,7 @@ bool ConfigWizard::run(RunReason reason, StartPage start_page) GUI_App &app = wxGetApp(); - p->run_reason = reason; + p->set_run_reason(reason); p->set_start_page(start_page); if (ShowModal() == wxID_OK) { diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index 3c85b73432..942f4b4ce8 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -34,7 +34,7 @@ public: SP_MATERIALS, }; - ConfigWizard(); + ConfigWizard(wxWindow *parent); ConfigWizard(ConfigWizard &&) = delete; ConfigWizard(const ConfigWizard &) = delete; ConfigWizard &operator=(ConfigWizard &&) = delete; diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 82708cc59b..e6f389785b 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -21,7 +21,8 @@ #include "libslic3r/PrintConfig.hpp" #include "slic3r/Utils/PresetUpdater.hpp" #include "AppConfig.hpp" -#include "Preset.hpp" +// #include "Preset.hpp" +#include "PresetBundle.hpp" #include "BedShapeDialog.hpp" namespace fs = boost::filesystem; @@ -43,13 +44,70 @@ enum { ROW_SPACING = 75, }; + + +// Configuration data structures extensions needed for the wizard + enum Technology { // Bitflag equivalent of PrinterTechnology T_FFF = 0x1, T_SLA = 0x2, - T_Any = ~0, + T_ANY = ~0, }; +struct Materials +{ + Technology technology; + std::vector presets; + std::set types; + + Materials(Technology technology) : technology(technology) {} + + const std::string& appconfig_section() const; + const std::string& get_type(Preset &preset) const; + const std::string& get_vendor(Preset &preset) const; + + template void filter_presets(const std::string &type, const std::string &vendor, F cb) { + for (Preset &preset : presets) { + if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) { + cb(preset); + } + } + } + + static const std::string UNKNOWN; + static const std::string& get_filament_type(const Preset &preset); + static const std::string& get_filament_vendor(const Preset &preset); + static const std::string& get_material_type(Preset &preset); + static const std::string& get_material_vendor(const Preset &preset); +}; + +struct Bundle +{ + fs::path source_path; // XXX: not needed? + std::unique_ptr preset_bundle; + VendorProfile *vendor_profile; + const bool is_in_resources; + const bool is_prusa_bundle; + + Bundle(fs::path source_path, bool is_in_resources, bool is_prusa_bundle = false); + Bundle(Bundle &&other); + + const std::string& vendor_id() const { return vendor_profile->id; } +}; + +struct BundleMap: std::unordered_map +{ + static BundleMap load(); + + Bundle& prusa_bundle(); + const Bundle& prusa_bundle() const; +}; + + + +// GUI elements + typedef std::function ModelFilter; struct PrinterPicker: wxPanel @@ -79,6 +137,8 @@ struct PrinterPicker: wxPanel int get_width() const { return width; } const std::vector& get_button_indexes() { return m_button_indexes; } + + static const std::string PRINTER_PLACEHOLDER; private: int width; std::vector m_button_indexes; @@ -97,65 +157,50 @@ struct ConfigWizardPage: wxPanel virtual ~ConfigWizardPage(); template - void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10) + T* append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10) { content->Add(thing, proportion, flag, border); + return thing; } - void append_text(wxString text); + wxStaticText* append_text(wxString text); void append_spacer(int space); ConfigWizard::priv *wizard_p() const { return parent->p.get(); } virtual void apply_custom_config(DynamicPrintConfig &config) {} + virtual void set_run_reason(ConfigWizard::RunReason run_reason) {} }; struct PageWelcome: ConfigWizardPage { + wxStaticText *welcome_text; wxCheckBox *cbox_reset; PageWelcome(ConfigWizard *parent); bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; } + + virtual void set_run_reason(ConfigWizard::RunReason run_reason) override; }; struct PagePrinters: ConfigWizardPage { std::vector printer_pickers; + Technology technology; + bool install; - PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology); + PagePrinters(ConfigWizard *parent, + wxString title, + wxString shortname, + const VendorProfile &vendor, + unsigned indent, Technology technology); void select_all(bool select, bool alternates = false); int get_width() const; bool any_selected() const; -}; - -struct Materials -{ - Technology technology; - std::vector presets; - std::set types; - - Materials(Technology technology) : technology(technology) {} - - const std::string& appconfig_section() const; - const std::string& get_type(Preset &preset) const; - const std::string& get_vendor(Preset &preset) const; - - template void filter_presets(const std::string &type, const std::string &vendor, F cb) { - for (Preset &preset : presets) { - if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) { - cb(preset); - } - } - } - - static const std::string UNKNOWN; - static const std::string& get_filament_type(const Preset &preset); - static const std::string& get_filament_vendor(const Preset &preset); - static const std::string& get_material_type(Preset &preset); - static const std::string& get_material_vendor(const Preset &preset); + virtual void set_run_reason(ConfigWizard::RunReason run_reason) override; }; // Here we extend wxListBox and wxCheckListBox @@ -232,11 +277,11 @@ struct PageUpdate: ConfigWizardPage struct PageVendors: ConfigWizardPage { - std::vector pickers; + // std::vector pickers; PageVendors(ConfigWizard *parent); - void on_vendor_pick(size_t i); + // void on_vendor_pick(size_t i); }; struct PageFirmware: ConfigWizardPage @@ -290,7 +335,7 @@ public: void go_prev(); void go_next(); void go_to(size_t i); - void go_to(ConfigWizardPage *page); + void go_to(const ConfigWizardPage *page); void clear(); void msw_rescale(); @@ -328,16 +373,24 @@ private: wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); + +// ConfigWizard private data + struct ConfigWizard::priv { ConfigWizard *q; ConfigWizard::RunReason run_reason = RR_USER; AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI - std::unordered_map vendors; + // std::unordered_map vendors; + // PresetBundle bundle; // XXX: comment + BundleMap bundles; // XXX: comment Materials filaments; // Holds available filament presets and their types & vendors Materials sla_materials; // Ditto for SLA materials - std::unordered_map vendors_rsrc; // List of bundles to install from resources + // std::set install_3rdparty; + // XXX: rm: (?) + // std::unordered_map vendors_rsrc; // List of bundles to install from resources std::unique_ptr custom_config; // Backing for custom printer definition + bool any_fff_selected; // Used to decide whether to display Filaments page bool any_sla_selected; // Used to decide whether to display SLA Materials page wxScrolledWindow *hscroll = nullptr; @@ -359,6 +412,7 @@ struct ConfigWizard::priv PageCustom *page_custom = nullptr; PageUpdate *page_update = nullptr; PageVendors *page_vendors = nullptr; // XXX: ? + std::map pages_3rdparty; // Custom setup pages PageFirmware *page_firmware = nullptr; @@ -366,6 +420,9 @@ struct ConfigWizard::priv PageDiameters *page_diams = nullptr; PageTemperatures *page_temps = nullptr; + // Pointers to all pages (regardless or whether currently part of the ConfigWizardIndex) + std::vector all_pages; + priv(ConfigWizard *q) : q(q) , filaments(T_FFF) @@ -376,14 +433,16 @@ struct ConfigWizard::priv void load_pages(); void init_dialog_size(); - bool check_first_variant() const; void load_vendors(); void add_page(ConfigWizardPage *page); void enable_next(bool enable); void set_start_page(ConfigWizard::StartPage start_page); + void create_3rdparty_pages(); + void set_run_reason(RunReason run_reason); void on_custom_setup(); void on_printer_pick(PagePrinters *page); + void on_3rdparty_install(const VendorProfile *vendor, bool install); // XXX: ? void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 028886915d..b5d9c3d61c 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1059,8 +1059,10 @@ void GUI_App::open_web_page_localized(const std::string &http_address) bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page) { + wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null"); + if (! m_wizard) { - m_wizard.reset(new ConfigWizard()); + m_wizard = new ConfigWizard(mainframe); } const bool res = m_wizard->run(reason, start_page); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 8c5f0c30c8..c5ddc01528 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -98,7 +98,7 @@ class GUI_App : public wxApp std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; - std::unique_ptr m_wizard; + ConfigWizard* m_wizard; // Managed by wxWindow tree public: bool OnInit() override; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index bda096d66d..be53267f9c 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -1318,7 +1318,7 @@ bool PresetCollection::select_preset_by_name_strict(const std::string &name) } // Merge one vendor's presets with the other vendor's presets, report duplicates. -std::vector PresetCollection::merge_presets(PresetCollection &&other, const std::set &new_vendors) +std::vector PresetCollection::merge_presets(PresetCollection &&other, const VendorMap &new_vendors) { std::vector duplicates; for (Preset &preset : other.m_presets) { @@ -1329,9 +1329,9 @@ std::vector PresetCollection::merge_presets(PresetCollection &&othe if (it == m_presets.end() || it->name != preset.name) { if (preset.vendor != nullptr) { // Re-assign a pointer to the vendor structure in the new PresetBundle. - auto it = new_vendors.find(*preset.vendor); + auto it = new_vendors.find(preset.vendor->id); assert(it != new_vendors.end()); - preset.vendor = &(*it); + preset.vendor = &it->second; } this->m_presets.emplace(it, std::move(preset)); } else diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index dfb72d495e..8be1388f09 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -2,6 +2,8 @@ #define slic3r_Preset_hpp_ #include +#include +#include #include #include @@ -89,6 +91,12 @@ public: bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; } }; +// Note: it is imporant that map is used here rather than unordered_map, +// because we need iterators to not be invalidated, +// because Preset and the ConfigWizard hold pointers to VendorProfiles. +// XXX: maybe set is enough (cf. changes in Wizard) +typedef std::map VendorMap; + class Preset { public: @@ -435,7 +443,7 @@ protected: bool select_preset_by_name_strict(const std::string &name); // Merge one vendor's presets with the other vendor's presets, report duplicates. - std::vector merge_presets(PresetCollection &&other, const std::set &new_vendors); + std::vector merge_presets(PresetCollection &&other, const VendorMap &new_vendors); private: PresetCollection(); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 5f91111115..579c74dcac 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -41,6 +41,8 @@ static std::vector s_project_options { "wiping_volumes_matrix" }; +const char *PresetBundle::PRUSA_BUNDLE = "PrusaResearch"; + PresetBundle::PresetBundle() : prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast(FullPrintConfig::defaults())), filaments(Preset::TYPE_FILAMENT, Preset::filament_options(), static_cast(FullPrintConfig::defaults())), @@ -244,6 +246,48 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_ this->load_selections(config, preferred_model_id); } +// FIXME: Comment +// XXX: rm +void PresetBundle::load_available_system_presets() +{ + const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred(); + const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred(); + + const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); + const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor + : (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); + + // Reset this PresetBundle and load the Prusa bundle first. + this->load_configbundle(prusa_bundle.string(), LOAD_CFGBNDLE_SYSTEM); + + // Load the other bundles in the datadir/vendor directory + // and then additionally from resources/profiles. + for (auto dir : { &vendor_dir, &rsrc_vendor_dir }) { + for (const auto &dir_entry : boost::filesystem::directory_iterator(*dir)) { + if (Slic3r::is_ini_file(dir_entry)) { + std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part + + // Don't load this bundle if we've already loaded it. + // Note that this takes care of not loading the PRUSA_BUNDLE which was loaded upfront + // as well as bundles with the same name (id) in rsrc_vendor_dir as in vendor_dir. + if (vendors.find(id) != vendors.end()) { continue; } + + PresetBundle other; + other.load_configbundle(dir_entry.path().string(), LOAD_CFGBNDLE_SYSTEM); + + std::vector duplicates = this->merge_presets(std::move(other)); + if (! duplicates.empty()) { + std::string msg = "Vendor configuration file " + id + " contains the following presets with names used by other vendors: "; + for (size_t i = 0; i < duplicates.size(); ++ i) { + if (i > 0) { msg += ", "; } + msg += duplicates[i]; + } + } + } + } + } +} + // Load system presets into this PresetBundle. // For each vendor, there will be a single PresetBundle loaded. std::string PresetBundle::load_system_presets() @@ -414,14 +458,14 @@ void PresetBundle::export_selections(AppConfig &config) void PresetBundle::init_materials_selection(AppConfig &config) const { if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { for (const auto &vendor : this->vendors) { - for (const auto &profile : vendor.default_filaments) { + for (const auto &profile : vendor.second.default_filaments) { config.set(AppConfig::SECTION_FILAMENTS, profile, "1"); } } } if (! config.has_section(AppConfig::SECTION_MATERIALS)) { for (const auto &vendor : this->vendors) { - for (const auto &profile : vendor.default_sla_materials) { + for (const auto &profile : vendor.second.default_sla_materials) { config.set(AppConfig::SECTION_MATERIALS, profile, "1"); } } @@ -1061,9 +1105,9 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla auto vp = VendorProfile::from_ini(tree, path); if (vp.num_variants() == 0) return 0; - vendor_profile = &(*this->vendors.insert(vp).first); + vendor_profile = &this->vendors.insert({vp.id, vp}).first->second; } - + if (flags & LOAD_CFGBUNDLE_VENDOR_ONLY) { return 0; } diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index 847b370187..d7ec5e3f09 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -4,7 +4,9 @@ #include "AppConfig.hpp" #include "Preset.hpp" +#include #include +#include #include class wxWindow; @@ -56,7 +58,8 @@ public: // There will be an entry for each system profile loaded, // and the system profiles will point to the VendorProfile instances owned by PresetBundle::vendors. - std::set vendors; + // std::set vendors; + VendorMap vendors; struct ObsoletePresets { std::vector prints; @@ -135,6 +138,9 @@ public: void load_default_preset_bitmaps(wxWindow *window); + void load_available_system_presets(); // XXX: name XXX: retval (VendorMap stored internally) + + static const char *PRUSA_BUNDLE; private: std::string load_system_presets(); // Merge one vendor's presets with the other vendor's presets, report duplicates. diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index cafdbb14ef..3cebf2f89e 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -153,7 +153,7 @@ struct PresetUpdater::priv bool get_file(const std::string &url, const fs::path &target_path) const; void prune_tmps() const; void sync_version() const; - void sync_config(const std::set vendors); + void sync_config(const VendorMap vendors); void check_install_indices() const; Updates get_config_updates() const; @@ -266,7 +266,7 @@ void PresetUpdater::priv::sync_version() const // Download vendor indices. Also download new bundles if an index indicates there's a new one available. // Both are saved in cache. -void PresetUpdater::priv::sync_config(const std::set vendors) +void PresetUpdater::priv::sync_config(const VendorMap vendors) { BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache"; @@ -276,13 +276,13 @@ void PresetUpdater::priv::sync_config(const std::set vendors) for (auto &index : index_db) { if (cancel) { return; } - const auto vendor_it = vendors.find(VendorProfile(index.vendor())); + const auto vendor_it = vendors.find(index.vendor()); if (vendor_it == vendors.end()) { BOOST_LOG_TRIVIAL(warning) << "No such vendor: " << index.vendor(); continue; } - const VendorProfile &vendor = *vendor_it; + const VendorProfile &vendor = vendor_it->second; if (vendor.config_update_url.empty()) { BOOST_LOG_TRIVIAL(info) << "Vendor has no config_update_url: " << vendor.name; continue; @@ -574,7 +574,7 @@ void PresetUpdater::sync(PresetBundle *preset_bundle) // Copy the whole vendors data for use in the background thread // Unfortunatelly as of C++11, it needs to be copied again // into the closure (but perhaps the compiler can elide this). - std::set vendors = preset_bundle->vendors; + VendorMap vendors = preset_bundle->vendors; p->thread = std::move(std::thread([this, vendors]() { this->p->prune_tmps(); @@ -691,8 +691,8 @@ void PresetUpdater::install_bundles_rsrc(std::vector bundles, bool BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size(); for (const auto &bundle : bundles) { - auto path_in_rsrc = p->rsrc_path / bundle; - auto path_in_vendors = p->vendor_path / bundle; + auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini"); + auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini"); updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", ""); } From 270008a3fd7bade37d5cd26e1c219fa26cc42738 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 2 Aug 2019 16:15:27 +0200 Subject: [PATCH 05/11] Add material_type config option for SLA materials, use in Wizard --- resources/profiles/PrusaResearch.ini | 2 + src/libslic3r/PrintConfig.cpp | 12 ++++ src/libslic3r/PrintConfig.hpp | 8 +++ src/slic3r/GUI/ConfigWizard.cpp | 79 ++++++++++++++----------- src/slic3r/GUI/ConfigWizard_private.hpp | 10 ++-- src/slic3r/GUI/Preset.cpp | 1 + 6 files changed, 71 insertions(+), 41 deletions(-) diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 6904713346..9add73b4dc 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -1966,6 +1966,7 @@ exposure_time = 6 initial_exposure_time = 40 [sla_material:BlueCast Keramaster Dental 0.025] +material_type = Dental inherits = *common 0.025* exposure_time = 6 initial_exposure_time = 45 @@ -2042,6 +2043,7 @@ initial_exposure_time = 45 material_vendor = Bluecast [sla_material:BlueCast Keramaster Dental 0.05] +material_type = Dental inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 50 diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ac30941cb1..6a57125d01 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2401,6 +2401,18 @@ void PrintConfigDef::init_sla_params() // SLA Material settings. + def = this->add("material_type", coString); + def->label = L("SLA material type"); + def->tooltip = L("SLA material type"); + def->gui_type = "f_enum_open"; // TODO: ??? + def->gui_flags = "show_value"; + def->enum_values.push_back("Tough"); + def->enum_values.push_back("Flexible"); + def->enum_values.push_back("Casting"); + def->enum_values.push_back("Dental"); + def->enum_values.push_back("Heat-resistant"); + def->set_default_value(new ConfigOptionString("Tough")); + def = this->add("initial_layer_height", coFloat); def->label = L("Initial layer height"); def->tooltip = L("Initial layer height"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6a19edf845..fc1916f1bf 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -52,6 +52,14 @@ enum FilamentType { }; */ +enum SLAMaterial { + slamTough, + slamFlex, + slamCasting, + slamDental, + slamHeatResistant, +}; + enum SLADisplayOrientation { sladoLandscape, sladoPortrait diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 8a850b7a0b..1c70ad7261 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -235,7 +235,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name); i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox); - bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name); + const bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name); cbox->SetValue(enabled); variants_sizer->Add(cbox, 0, wxBOTTOM, 3); @@ -731,10 +731,7 @@ PageUpdate::PageUpdate(ConfigWizard *parent) PageVendors::PageVendors(ConfigWizard *parent) : ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors"))) { - - - // FIXME: persistence: this doesn't reload choices - + const AppConfig &appconfig = this->wizard_p()->appconfig_new; append_text(wxString::Format(_(L("Pick another vendor supported by %s: (FIXME: this text)")), SLIC3R_APP_NAME)); @@ -750,6 +747,16 @@ PageVendors::PageVendors(ConfigWizard *parent) wizard_p()->on_3rdparty_install(vendor, cbox->IsChecked()); }); + const auto &vendors = appconfig.vendors(); + const bool enabled = vendors.find(pair.first) != vendors.end(); + if (enabled) { + cbox->SetValue(true); + + auto pair = wizard_p()->pages_3rdparty.find(vendor->id); + wxCHECK_RET(pair != wizard_p()->pages_3rdparty.end(), "Internal error: 3rd party vendor printers page not created"); + pair->second->install = true; + } + append(cbox); } } @@ -866,18 +873,18 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config) auto set_extrusion_width = [&config, opt_nozzle](const char *key, double dmr) { char buf[64]; sprintf(buf, "%.2lf", dmr * opt_nozzle->values.front() / 0.4); - config.set_key_value(key, new ConfigOptionFloatOrPercent(atof(buf), false)); - }; + config.set_key_value(key, new ConfigOptionFloatOrPercent(atof(buf), false)); + }; set_extrusion_width("support_material_extrusion_width", 0.35); - set_extrusion_width("top_infill_extrusion_width", 0.40); - set_extrusion_width("first_layer_extrusion_width", 0.42); + set_extrusion_width("top_infill_extrusion_width", 0.40); + set_extrusion_width("first_layer_extrusion_width", 0.42); - set_extrusion_width("extrusion_width", 0.45); - set_extrusion_width("perimeter_extrusion_width", 0.45); - set_extrusion_width("external_perimeter_extrusion_width", 0.45); - set_extrusion_width("infill_extrusion_width", 0.45); - set_extrusion_width("solid_infill_extrusion_width", 0.45); + set_extrusion_width("extrusion_width", 0.45); + set_extrusion_width("perimeter_extrusion_width", 0.45); + set_extrusion_width("external_perimeter_extrusion_width", 0.45); + set_extrusion_width("infill_extrusion_width", 0.45); + set_extrusion_width("solid_infill_extrusion_width", 0.45); } PageTemperatures::PageTemperatures(ConfigWizard *parent) @@ -1114,7 +1121,7 @@ void ConfigWizardIndex::on_mouse_move(wxMouseEvent &evt) const ssize_t item_hover_new = pos.y / item_height(); - if (item_hover_new < ssize_t(items.size()) && item_hover_new != item_hover) { + if (item_hover_new < ssize_t(items.size()) && item_hover_new != item_hover) { item_hover = item_hover_new; Refresh(); } @@ -1176,19 +1183,11 @@ const std::string& Materials::get_filament_vendor(const Preset &preset) const std::string& Materials::get_material_type(Preset &preset) { - // XXX: The initial_layer_height is of a float type and contains no string to reference, - // and so here we serialize it into an ad-hoc option initial_layer_height_str, which is then referenced - - const auto *opt_str = preset.config.opt("initial_layer_height_str"); - if (opt_str == nullptr) { - const auto *opt = preset.config.opt("initial_layer_height"); - if (opt == nullptr) { return UNKNOWN; } - - auto *new_opt_str = new ConfigOptionString(opt->serialize()); - preset.config.set_key_value("initial_layer_height_str", new_opt_str); - return new_opt_str->value; + const auto *opt = preset.config.opt("material_type"); + if (opt != nullptr) { + return opt->value; } else { - return opt_str->value; + return UNKNOWN; } } @@ -1366,11 +1365,16 @@ void ConfigWizard::priv::load_vendors() // apply defaults from vendor profiles if there are no selections yet. // bundle.init_materials_selection(*app_config); - // XXX: ? - // wxCHECK_RET(app_config->has_section(AppConfig::SECTION_FILAMENTS) && app_config->has_section(AppConfig::SECTION_MATERIALS), - // "Failed to initialize default material selections"); - appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); - appconfig_new.set_section(AppConfig::SECTION_MATERIALS, app_config->get_section(AppConfig::SECTION_MATERIALS)); + // TODO: load up sane defaults if no previous data in AppConfig + // as per the design doc: + // - all f/m for installed printers if prev Slicer version + // - default f/m set from bundle + default for each printer from bundle if fresh install + if (app_config->has_section(AppConfig::SECTION_FILAMENTS)) { + appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); + } + if (app_config->has_section(AppConfig::SECTION_MATERIALS)) { + appconfig_new.set_section(AppConfig::SECTION_MATERIALS, app_config->get_section(AppConfig::SECTION_MATERIALS)); + } } void ConfigWizard::priv::add_page(ConfigWizardPage *page) @@ -1437,6 +1441,10 @@ void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool i auto it = pages_3rdparty.find(vendor->id); wxCHECK_RET(it != pages_3rdparty.end(), "Internal error: GUI page not found for 3rd party vendor profile"); PagePrinters *page = it->second; + + if (page->install && !install) { + page->select_all(false); + } page->install = install; page->Layout(); @@ -1525,7 +1533,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // The default is the first selected printer model (one with at least 1 variant selected). // The default is only applied by load_presets() if the user doesn't have a (visible) printer // selected already. -// TODO +// TODO: // const auto vendor_prusa = bundle.vendors.find("PrusaResearch"); // const auto config_prusa = enabled_vendors.find("PrusaResearch"); // if (vendor_prusa != bundle.vendors.end() && config_prusa != enabled_vendors.end()) { @@ -1617,13 +1625,14 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->add_page(p->page_custom = new PageCustom(this)); p->add_page(p->page_update = new PageUpdate(this)); - p->add_page(p->page_vendors = new PageVendors(this)); p->add_page(p->page_firmware = new PageFirmware(this)); p->add_page(p->page_bed = new PageBedShape(this)); p->add_page(p->page_diams = new PageDiameters(this)); p->add_page(p->page_temps = new PageTemperatures(this)); - p->create_3rdparty_pages(); + // Pages for 3rd party vendors + p->create_3rdparty_pages(); // Needs to ne done _before_ creating PageVendors + p->add_page(p->page_vendors = new PageVendors(this)); p->any_sla_selected = p->page_msla->any_selected(); p->any_fff_selected = p->page_fff->any_selected(); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index e6f389785b..708eb94fc6 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -96,7 +96,7 @@ struct Bundle const std::string& vendor_id() const { return vendor_profile->id; } }; -struct BundleMap: std::unordered_map +struct BundleMap: std::unordered_map { static BundleMap load(); @@ -277,11 +277,7 @@ struct PageUpdate: ConfigWizardPage struct PageVendors: ConfigWizardPage { - // std::vector pickers; - PageVendors(ConfigWizard *parent); - - // void on_vendor_pick(size_t i); }; struct PageFirmware: ConfigWizardPage @@ -319,6 +315,8 @@ struct PageTemperatures: ConfigWizardPage virtual void apply_custom_config(DynamicPrintConfig &config); }; +typedef std::map Pages3rdparty; + class ConfigWizardIndex: public wxPanel { @@ -412,7 +410,7 @@ struct ConfigWizard::priv PageCustom *page_custom = nullptr; PageUpdate *page_update = nullptr; PageVendors *page_vendors = nullptr; // XXX: ? - std::map pages_3rdparty; + Pages3rdparty pages_3rdparty; // Custom setup pages PageFirmware *page_firmware = nullptr; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index be53267f9c..9b16d94801 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -531,6 +531,7 @@ const std::vector& Preset::sla_material_options() static std::vector s_opts; if (s_opts.empty()) { s_opts = { + "material_type", "initial_layer_height", "exposure_time", "initial_exposure_time", From 9a465514ff1169d9fece05449d37285f4997b346 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 27 Aug 2019 16:59:07 +0200 Subject: [PATCH 06/11] Filament and material default installation based on enabled printers --- src/slic3r/GUI/PresetBundle.cpp | 74 +++++++++++++++++++++++---------- src/slic3r/GUI/PresetBundle.hpp | 11 ++--- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 579c74dcac..e3ee84e872 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -239,10 +240,6 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_ if (! errors_cummulative.empty()) throw std::runtime_error(errors_cummulative); - // Make sure there are filament / material selections in the AppConfig, - // if there are none, load up defaults from vendor profiles. - this->init_materials_selection(config); - this->load_selections(config, preferred_model_id); } @@ -371,10 +368,56 @@ void PresetBundle::load_installed_printers(const AppConfig &config) for (auto &preset : printers) { preset.set_visible_from_appconfig(config); } +} + +void PresetBundle::load_installed_filaments(AppConfig &config) +{ + if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { + std::unordered_set comp_filaments; + + for (const Preset &printer : printers) { + if (! printer.is_visible || printer.printer_technology() != ptFFF) { + continue; + } + + for (const Preset &filament : filaments) { + if (filament.is_compatible_with_printer(printer)) { + comp_filaments.insert(&filament); + } + } + } + + for (const auto &filament: comp_filaments) { + config.set(AppConfig::SECTION_FILAMENTS, filament->name, "1"); + } + } for (auto &preset : filaments) { preset.set_visible_from_appconfig(config); } +} + +void PresetBundle::load_installed_sla_materials(AppConfig &config) +{ + if (! config.has_section(AppConfig::SECTION_MATERIALS)) { + std::unordered_set comp_sla_materials; + + for (const Preset &printer : printers) { + if (! printer.is_visible || printer.printer_technology() != ptSLA) { + continue; + } + + for (const Preset &material : sla_materials) { + if (material.is_compatible_with_printer(printer)) { + comp_sla_materials.insert(&material); + } + } + } + + for (const auto &material: comp_sla_materials) { + config.set(AppConfig::SECTION_MATERIALS, material->name, "1"); + } + } for (auto &preset : sla_materials) { preset.set_visible_from_appconfig(config); @@ -383,11 +426,15 @@ void PresetBundle::load_installed_printers(const AppConfig &config) // Load selections (current print, current filaments, current printer) from config.ini // This is done on application start up or after updates are applied. -void PresetBundle::load_selections(const AppConfig &config, const std::string &preferred_model_id) +void PresetBundle::load_selections(AppConfig &config, const std::string &preferred_model_id) { // Update visibility of presets based on application vendor / model / variant configuration. this->load_installed_printers(config); + // Update visibility of filament and sla material presets + this->load_installed_filaments(config); + this->load_installed_sla_materials(config); + // Parse the initial print / filament / printer profile names. std::string initial_print_profile_name = remove_ini_suffix(config.get("presets", "print")); std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", "sla_print")); @@ -455,23 +502,6 @@ void PresetBundle::export_selections(AppConfig &config) config.set("presets", "printer", printers.get_selected_preset_name()); } -void PresetBundle::init_materials_selection(AppConfig &config) const { - if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { - for (const auto &vendor : this->vendors) { - for (const auto &profile : vendor.second.default_filaments) { - config.set(AppConfig::SECTION_FILAMENTS, profile, "1"); - } - } - } - if (! config.has_section(AppConfig::SECTION_MATERIALS)) { - for (const auto &vendor : this->vendors) { - for (const auto &profile : vendor.second.default_sla_materials) { - config.set(AppConfig::SECTION_MATERIALS, profile, "1"); - } - } - } -} - void PresetBundle::load_compatible_bitmaps(wxWindow *window) { // We don't actually pass the window pointer here and instead generate diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index d7ec5e3f09..0fea2a0f8a 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -38,10 +38,6 @@ public: // Export selections (current print, current filaments, current printer) into config.ini void export_selections(AppConfig &config); - // Make sure filament and sla_materials section in AppConfig are initialized - // to defaults from vendor profiles if they don't exist already - void init_materials_selection(AppConfig &config) const; - PresetCollection prints; PresetCollection sla_prints; PresetCollection filaments; @@ -151,9 +147,14 @@ private: // If the "vendor" section is missing, enable all models and variants of the particular vendor. void load_installed_printers(const AppConfig &config); + // Set the enabled flag for filaments and sla materials, + // apply defaults based on enabled printers when no filaments/materials are installed. + void load_installed_filaments(AppConfig &config); + void load_installed_sla_materials(AppConfig &config); + // Load selections (current print, current filaments, current printer) from config.ini // This is done just once on application start up. - void load_selections(const AppConfig &config, const std::string &preferred_model_id = ""); + void load_selections(AppConfig &config, const std::string &preferred_model_id = ""); // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. // and the external config is just referenced, not stored into user profile directory. From c5a67ff931f78adb78ed853756ba46c8d9da0fd4 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 30 Aug 2019 17:40:25 +0200 Subject: [PATCH 07/11] WIP: filament/material filtering per selected printers --- src/slic3r/GUI/ConfigWizard.cpp | 267 +++++++++++++++--------- src/slic3r/GUI/ConfigWizard_private.hpp | 52 +++-- src/slic3r/GUI/PresetBundle.hpp | 13 +- 3 files changed, 206 insertions(+), 126 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 1c70ad7261..691a2f2cdc 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -475,7 +475,7 @@ PagePrinters::PagePrinters(ConfigWizard *parent, picker->Bind(EVT_PRINTER_PICK, [this, appconfig](const PrinterPickerEvent &evt) { appconfig->set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable); - wizard_p()->on_printer_pick(this); + wizard_p()->on_printer_pick(this, evt); }); append(new wxStaticLine(this)); @@ -527,6 +527,7 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin , list_l3(new PresetList(this)) , sel1_prev(wxNOT_FOUND) , sel2_prev(wxNOT_FOUND) + , presets_loaded(false) { append_spacer(VERTICAL_SPACING); @@ -559,12 +560,6 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin append(grid); - list_l1->append(_(L("(All)")), &EMPTY); - - for (const std::string &type : materials->types) { - list_l1->append(type, &type); - } - list_l1->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) { update_lists(list_l1->GetSelection(), list_l2->GetSelection()); }); @@ -577,10 +572,27 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin sel_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(true); }); sel_none->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(false); }); + reload_presets(); +} + +void PageMaterials::reload_presets() +{ + list_l1->Clear(); + + list_l1->append(_(L("(All)")), &EMPTY); + + for (const std::string &type : materials->types) { + list_l1->append(type, &type); + } + if (list_l1->GetCount() > 0) { list_l1->SetSelection(0); + sel1_prev = wxNOT_FOUND; + sel2_prev = wxNOT_FOUND; update_lists(0, 0); } + + presets_loaded = true; } void PageMaterials::update_lists(int sel1, int sel2) @@ -592,14 +604,14 @@ void PageMaterials::update_lists(int sel1, int sel2) // Refresh the second list // XXX: The vendor list is created with quadratic complexity here, - // but the number of vendors is realistically so small this shouldn't be a problem. + // but the number of vendors is going to be very small this shouldn't be a problem. list_l2->Clear(); list_l2->append(_(L("(All)")), &EMPTY); if (sel1 != wxNOT_FOUND) { const std::string &type = list_l1->get_data(sel1); - materials->filter_presets(type, EMPTY, [this](Preset &p) { + materials->filter_presets(type, EMPTY, [this](const Preset *p) { const std::string &vendor = this->materials->get_vendor(p); if (list_l2->find(vendor) == wxNOT_FOUND) { @@ -623,9 +635,9 @@ void PageMaterials::update_lists(int sel1, int sel2) const std::string &type = list_l1->get_data(sel1); const std::string &vendor = list_l2->get_data(sel2); - materials->filter_presets(type, vendor, [this](Preset &p) { - const int i = list_l3->append(p.name, &p); - const bool checked = wizard_p()->appconfig_new.has(materials->appconfig_section(), p.name); + materials->filter_presets(type, vendor, [this](const Preset *p) { + const int i = list_l3->append(p->name, p); + const bool checked = wizard_p()->appconfig_new.has(materials->appconfig_section(), p->name); list_l3->Check(i, checked); }); } @@ -660,6 +672,24 @@ void PageMaterials::select_all(bool select) } } +void PageMaterials::clear() +{ + list_l1->Clear(); + list_l2->Clear(); + list_l3->Clear(); + sel1_prev = wxNOT_FOUND; + sel2_prev = wxNOT_FOUND; + presets_loaded = false; +} + +void PageMaterials::on_activate() +{ + if (! presets_loaded) { + wizard_p()->update_materials(); + reload_presets(); + } +} + const char *PageCustom::default_profile_name = "My Settings"; @@ -952,8 +982,8 @@ ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) , bullet_black(ScalableBitmap(parent, "bullet_black.png")) , bullet_blue(ScalableBitmap(parent, "bullet_blue.png")) , bullet_white(ScalableBitmap(parent, "bullet_white.png")) - , item_active(0) - , item_hover(-1) + , item_active(NO_ITEM) + , item_hover(NO_ITEM) , last_page((size_t)-1) { SetMinSize(bg.bmp().GetSize()); @@ -1015,6 +1045,8 @@ void ConfigWizardIndex::go_prev() { // Search for a preceiding item that is a page (not a label, ie. page != nullptr) + if (item_active == NO_ITEM) { return; } + for (size_t i = item_active; i > 0; i--) { if (items[i - 1].page != nullptr) { go_to(i - 1); @@ -1027,6 +1059,8 @@ void ConfigWizardIndex::go_next() { // Search for a next item that is a page (not a label, ie. page != nullptr) + if (item_active == NO_ITEM) { return; } + for (size_t i = item_active + 1; i < items.size(); i++) { if (items[i].page != nullptr) { go_to(i); @@ -1035,19 +1069,27 @@ void ConfigWizardIndex::go_next() } } +// This one actually performs the go-to op void ConfigWizardIndex::go_to(size_t i) { - if (i < items.size() && items[i].page != nullptr) { + if (i != item_active + && i < items.size() + && items[i].page != nullptr) { + auto *new_active = items[i].page; auto *former_active = active_page(); - if (former_active != nullptr) { former_active->Hide(); } + if (former_active != nullptr) { + former_active->Hide(); + } item_active = i; - items[i].page->Show(); + new_active->Show(); wxCommandEvent evt(EVT_INDEX_PAGE, GetId()); AddPendingEvent(evt); Refresh(); + + new_active->on_activate(); } } @@ -1069,7 +1111,7 @@ void ConfigWizardIndex::clear() if (former_active != nullptr) { former_active->Hide(); } items.clear(); - item_active = 0; + item_active = NO_ITEM; } void ConfigWizardIndex::on_paint(wxPaintEvent & evt) @@ -1150,24 +1192,38 @@ void ConfigWizardIndex::msw_rescale() const std::string Materials::UNKNOWN = "(Unknown)"; +void Materials::push(const Preset *preset) +{ + presets.insert(preset); + types.insert(technology & T_FFF + ? Materials::get_filament_type(preset) + : Materials::get_material_type(preset)); +} + +void Materials::clear() +{ + presets.clear(); + types.clear(); +} + const std::string& Materials::appconfig_section() const { return (technology & T_FFF) ? AppConfig::SECTION_FILAMENTS : AppConfig::SECTION_MATERIALS; } -const std::string& Materials::get_type(Preset &preset) const +const std::string& Materials::get_type(const Preset *preset) const { return (technology & T_FFF) ? get_filament_type(preset) : get_material_type(preset); } -const std::string& Materials::get_vendor(Preset &preset) const +const std::string& Materials::get_vendor(const Preset *preset) const { return (technology & T_FFF) ? get_filament_vendor(preset) : get_material_vendor(preset); } -const std::string& Materials::get_filament_type(const Preset &preset) +const std::string& Materials::get_filament_type(const Preset *preset) { - const auto *opt = preset.config.opt("filament_type"); + const auto *opt = preset->config.opt("filament_type"); if (opt != nullptr && opt->values.size() > 0) { return opt->values[0]; } else { @@ -1175,15 +1231,15 @@ const std::string& Materials::get_filament_type(const Preset &preset) } } -const std::string& Materials::get_filament_vendor(const Preset &preset) +const std::string& Materials::get_filament_vendor(const Preset *preset) { - const auto *opt = preset.config.opt("filament_vendor"); + const auto *opt = preset->config.opt("filament_vendor"); return opt != nullptr ? opt->value : UNKNOWN; } -const std::string& Materials::get_material_type(Preset &preset) +const std::string& Materials::get_material_type(const Preset *preset) { - const auto *opt = preset.config.opt("material_type"); + const auto *opt = preset->config.opt("material_type"); if (opt != nullptr) { return opt->value; } else { @@ -1191,9 +1247,9 @@ const std::string& Materials::get_material_type(Preset &preset) } } -const std::string& Materials::get_material_vendor(const Preset &preset) +const std::string& Materials::get_material_vendor(const Preset *preset) { - const auto *opt = preset.config.opt("material_vendor"); + const auto *opt = preset->config.opt("material_vendor"); return opt != nullptr ? opt->value : UNKNOWN; } @@ -1275,73 +1331,8 @@ void ConfigWizard::priv::init_dialog_size() void ConfigWizard::priv::load_vendors() { - // const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor"; - // const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles"; - - // PresetBundle bundle; - // bundle.load_available_system_presets(); bundles = BundleMap::load(); - // // Load vendors from the "vendors" directory in datadir - // // XXX: The VendorProfile is loaded twice here, ditto below - // for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) { - // if (Slic3r::is_ini_file(dir_entry)) { - // try { - // bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); - - // auto vp = VendorProfile::from_ini(dir_entry.path()); - // vendors[vp.id] = std::move(vp); - // } - // catch (const std::exception& e) { - // BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); - // } - // } - // } - - // // Additionally load up vendors from the application resources directory, but only those not seen in the datadir - // for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) { - // if (Slic3r::is_ini_file(dir_entry)) { - // const auto id = dir_entry.path().stem().string(); - - // if (vendors.find(id) == vendors.end()) { - // try { - // bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); - - // auto vp = VendorProfile::from_ini(dir_entry.path()); - // vendors_rsrc[vp.id] = dir_entry.path().filename().string(); - // vendors[vp.id] = std::move(vp); - // } - // catch (const std::exception& e) { - // BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what(); - // } - // } - // } - // } - - // // Move materials to our Materials container: - // for (auto &&f : bundle.filaments) { - // f.vendor = nullptr; - // filaments.presets.push_back(std::move(f)); - // filaments.types.insert(Materials::get_filament_type(f)); - // } - // for (auto &&m : bundle.sla_materials) { - // m.vendor = nullptr; - // sla_materials.presets.push_back(std::move(m)); - // sla_materials.types.insert(Materials::get_material_type(m)); - // } - for (auto &pair : bundles) { - for (auto &&f : pair.second.preset_bundle->filaments) { - f.vendor = nullptr; - filaments.presets.push_back(std::move(f)); - filaments.types.insert(Materials::get_filament_type(f)); - } - for (auto &&m : pair.second.preset_bundle->sla_materials) { - m.vendor = nullptr; - sla_materials.presets.push_back(std::move(m)); - sla_materials.types.insert(Materials::get_material_type(m)); - } - } - // Load up the set of vendors / models / variants the user has had enabled up till now AppConfig *app_config = wxGetApp().app_config; if (! app_config->legacy_datadir()) { @@ -1360,15 +1351,13 @@ void ConfigWizard::priv::load_vendors() } } -// TODO: This'll be done differently, cf. the design document - // Load up the materials enabled till now, - // apply defaults from vendor profiles if there are no selections yet. - // bundle.init_materials_selection(*app_config); + // Initialize the is_visible flag in printer Presets + for (auto &pair : bundles) { + pair.second.preset_bundle->load_installed_printers(appconfig_new); + } + + update_materials(); - // TODO: load up sane defaults if no previous data in AppConfig - // as per the design doc: - // - all f/m for installed printers if prev Slicer version - // - default f/m set from bundle + default for each printer from bundle if fresh install if (app_config->has_section(AppConfig::SECTION_FILAMENTS)) { appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); } @@ -1420,12 +1409,66 @@ void ConfigWizard::priv::set_run_reason(RunReason run_reason) } } +void ConfigWizard::priv::update_materials() +{ + filaments.clear(); + sla_materials.clear(); + + if (any_fff_selected) { + // Iterate filaments in all bundles + for (const auto &pair : bundles) { + for (const auto &filament : pair.second.preset_bundle->filaments) { + // Check if filament is already added + if (filaments.containts(&filament)) { continue; } + + // Iterate printers in all bundles + for (const auto &pair : bundles) { + for (const auto &printer : pair.second.preset_bundle->printers) { + // Filter out inapplicable printers + if (!printer.is_visible || printer.printer_technology() != ptFFF) { + continue; + } + + if (filament.is_compatible_with_printer(printer)) { + filaments.push(&filament); + } + } + } + } + } + } + + if (any_sla_selected) { + // Iterate SLA materials in all bundles + for (const auto &pair : bundles) { + for (const auto &material : pair.second.preset_bundle->sla_materials) { + // Check if material is already added + if (sla_materials.containts(&material)) { continue; } + + // Iterate printers in all bundles + for (const auto &pair : bundles) { + for (const auto &printer : pair.second.preset_bundle->printers) { + // Filter out inapplicable printers + if (!printer.is_visible || printer.printer_technology() != ptSLA) { + continue; + } + + if (material.is_compatible_with_printer(printer)) { + sla_materials.push(&material); + } + } + } + } + } + } +} + void ConfigWizard::priv::on_custom_setup() { load_pages(); } -void ConfigWizard::priv::on_printer_pick(PagePrinters *page) +void ConfigWizard::priv::on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt) { if (page_msla->any_selected() != any_sla_selected || page_fff->any_selected() != any_fff_selected) { @@ -1434,6 +1477,24 @@ void ConfigWizard::priv::on_printer_pick(PagePrinters *page) load_pages(); } + + // Update the is_visible flag on relevant printer profiles + for (auto &pair : bundles) { + if (pair.first != evt.vendor_id) { continue; } + + for (auto &preset : pair.second.preset_bundle->printers) { + if (preset.config.opt_string("printer_model") == evt.model_id + && preset.config.opt_string("printer_variant") == evt.variant_name) { + preset.is_visible = evt.enable; + } + } + } + + if (page == page_fff) { + page_filaments->clear(); + } else if (page == page_msla) { + page_sla_materials->clear(); + } } void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install) @@ -1636,7 +1697,9 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->any_sla_selected = p->page_msla->any_selected(); p->any_fff_selected = p->page_fff->any_selected(); + p->load_pages(); + p->index->go_to(size_t{0}); vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN); vsizer->Add(hline, 0, wxEXPAND); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 708eb94fc6..0d2123695b 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -21,7 +21,6 @@ #include "libslic3r/PrintConfig.hpp" #include "slic3r/Utils/PresetUpdater.hpp" #include "AppConfig.hpp" -// #include "Preset.hpp" #include "PresetBundle.hpp" #include "BedShapeDialog.hpp" @@ -58,17 +57,23 @@ enum Technology { struct Materials { Technology technology; - std::vector presets; + std::set presets; std::set types; Materials(Technology technology) : technology(technology) {} + void push(const Preset *preset); + void clear(); + bool containts(const Preset *preset) { + return presets.find(preset) != presets.end(); + } + const std::string& appconfig_section() const; - const std::string& get_type(Preset &preset) const; - const std::string& get_vendor(Preset &preset) const; + const std::string& get_type(const Preset *preset) const; + const std::string& get_vendor(const Preset *preset) const; template void filter_presets(const std::string &type, const std::string &vendor, F cb) { - for (Preset &preset : presets) { + for (const Preset *preset : presets) { if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) { cb(preset); } @@ -76,10 +81,10 @@ struct Materials } static const std::string UNKNOWN; - static const std::string& get_filament_type(const Preset &preset); - static const std::string& get_filament_vendor(const Preset &preset); - static const std::string& get_material_type(Preset &preset); - static const std::string& get_material_vendor(const Preset &preset); + static const std::string& get_filament_type(const Preset *preset); + static const std::string& get_filament_vendor(const Preset *preset); + static const std::string& get_material_type(const Preset *preset); + static const std::string& get_material_vendor(const Preset *preset); }; struct Bundle @@ -104,6 +109,7 @@ struct BundleMap: std::unordered_map const Bundle& prusa_bundle() const; }; +struct PrinterPickerEvent; // GUI elements @@ -170,6 +176,7 @@ struct ConfigWizardPage: wxPanel virtual void apply_custom_config(DynamicPrintConfig &config) {} virtual void set_run_reason(ConfigWizard::RunReason run_reason) {} + virtual void on_activate() {} }; struct PageWelcome: ConfigWizardPage @@ -209,6 +216,9 @@ template struct DataList : public T { DataList(wxWindow *parent) : T(parent, wxID_ANY) {} + // Note: We're _not_ using wxLB_SORT here because it doesn't do the right thing, + // eg. "ABS" is sorted before "(All)" + int append(const std::string &label, const D *data) { void *ptr = reinterpret_cast(const_cast(data)); return this->Append(from_u8(label), ptr); @@ -241,14 +251,19 @@ struct PageMaterials: ConfigWizardPage StringList *list_l1, *list_l2; PresetList *list_l3; int sel1_prev, sel2_prev; + bool presets_loaded; + + static const std::string EMPTY; PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name); + void reload_presets(); void update_lists(int sel1, int sel2); void select_material(int i); void select_all(bool select); + void clear(); - static const std::string EMPTY; + virtual void on_activate() override; }; struct PageCustom: ConfigWizardPage @@ -339,6 +354,8 @@ public: void msw_rescale(); int em() const { return em_w; } + + static const size_t NO_ITEM = size_t(-1); private: struct Item { @@ -379,14 +396,12 @@ struct ConfigWizard::priv ConfigWizard *q; ConfigWizard::RunReason run_reason = RR_USER; AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI - // std::unordered_map vendors; - // PresetBundle bundle; // XXX: comment - BundleMap bundles; // XXX: comment + BundleMap bundles; // Holds all loaded config bundles, the key is the vendor names. + // Materials refers to Presets in those bundles by pointers. + // Also we update the is_visible flag in printer Presets according to the + // PrinterPickers state. Materials filaments; // Holds available filament presets and their types & vendors Materials sla_materials; // Ditto for SLA materials - // std::set install_3rdparty; - // XXX: rm: (?) - // std::unordered_map vendors_rsrc; // List of bundles to install from resources std::unique_ptr custom_config; // Backing for custom printer definition bool any_fff_selected; // Used to decide whether to display Filaments page bool any_sla_selected; // Used to decide whether to display SLA Materials page @@ -437,10 +452,11 @@ struct ConfigWizard::priv void set_start_page(ConfigWizard::StartPage start_page); void create_3rdparty_pages(); void set_run_reason(RunReason run_reason); + void update_materials(); void on_custom_setup(); - void on_printer_pick(PagePrinters *page); - void on_3rdparty_install(const VendorProfile *vendor, bool install); // XXX: ? + void on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt); + void on_3rdparty_install(const VendorProfile *vendor, bool install); void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index 0fea2a0f8a..79519071b5 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -134,20 +134,21 @@ public: void load_default_preset_bitmaps(wxWindow *window); + // FIXME: rm void load_available_system_presets(); // XXX: name XXX: retval (VendorMap stored internally) + // Set the is_visible flag for printer vendors, printer models and printer variants + // based on the user configuration. + // If the "vendor" section is missing, enable all models and variants of the particular vendor. + void load_installed_printers(const AppConfig &config); + static const char *PRUSA_BUNDLE; private: std::string load_system_presets(); // Merge one vendor's presets with the other vendor's presets, report duplicates. std::vector merge_presets(PresetBundle &&other); - // Set the "enabled" flag for printer vendors, printer models and printer variants - // based on the user configuration. - // If the "vendor" section is missing, enable all models and variants of the particular vendor. - void load_installed_printers(const AppConfig &config); - - // Set the enabled flag for filaments and sla materials, + // Set the is_visible flag for filaments and sla materials, // apply defaults based on enabled printers when no filaments/materials are installed. void load_installed_filaments(AppConfig &config); void load_installed_sla_materials(AppConfig &config); From cb1ee5ce5542bc96a8babdb45ed3264bbb2a0855 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 17 Sep 2019 15:52:26 +0200 Subject: [PATCH 08/11] ConfigWizard: Add view mode setting page --- src/slic3r/GUI/ConfigWizard.cpp | 41 +++++++++++++++++++++++++ src/slic3r/GUI/ConfigWizard_private.hpp | 17 +++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 691a2f2cdc..d77812e3a6 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -758,6 +758,43 @@ PageUpdate::PageUpdate(ConfigWizard *parent) box_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->preset_update = event.IsChecked(); }); } +PageMode::PageMode(ConfigWizard *parent) + : ConfigWizardPage(parent, _(L("View mode")), _(L("View mode"))) +{ + append_text(_(L("PrusaSlicer's user interfaces comes in three variants:\nSimple, Advanced, and Expert.\n" + "The Simple mode shows only the most frequently used settings relevant for regular 3D printing. " + "The other two offer progressivly more specialized fine-tuning, " + "they are suitable for advanced and expert usiser, respectively. (FIXME: review this text)"))); + + radio_simple = new wxRadioButton(this, wxID_ANY, _(L("Simple mode"))); + radio_advanced = new wxRadioButton(this, wxID_ANY, _(L("Advanced mode"))); + radio_expert = new wxRadioButton(this, wxID_ANY, _(L("Expert mode"))); + + append(radio_simple); + append(radio_advanced); + append(radio_expert); +} + +void PageMode::on_activate() +{ + std::string mode { "simple" }; + wxGetApp().app_config->get("", "view_mode", mode); + + if (mode == "advanced") { radio_advanced->SetValue(true); } + else if (mode == "expert") { radio_expert->SetValue(true); } + else { radio_simple->SetValue(true); } +} + +void PageMode::serialize_mode(AppConfig *app_config) const +{ + const char *mode = "simple"; + + if (radio_advanced->GetValue()) { mode = "advanced"; } + if (radio_expert->GetValue()) { mode = "expert"; } + + app_config->set("view_mode", mode); +} + PageVendors::PageVendors(ConfigWizard *parent) : ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors"))) { @@ -1300,6 +1337,7 @@ void ConfigWizard::priv::load_pages() if (any_sla_selected) { index->add_page(page_sla_materials); } index->add_page(page_update); + index->add_page(page_mode); index->go_to(former_active); // Will restore the active item/page if possible @@ -1587,6 +1625,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese } app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); + page_mode->serialize_mode(app_config); std::string preferred_model; @@ -1686,6 +1725,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->add_page(p->page_custom = new PageCustom(this)); p->add_page(p->page_update = new PageUpdate(this)); + p->add_page(p->page_mode = new PageMode(this)); p->add_page(p->page_firmware = new PageFirmware(this)); p->add_page(p->page_bed = new PageBedShape(this)); p->add_page(p->page_diams = new PageDiameters(this)); @@ -1751,6 +1791,7 @@ bool ConfigWizard::run(RunReason reason, StartPage start_page) if (ShowModal() == wxID_OK) { p->apply_config(app.app_config, app.preset_bundle, app.preset_updater); app.app_config->set_legacy_datadir(false); + app.update_mode(); BOOST_LOG_TRIVIAL(info) << "ConfigWizard applied"; return true; } else { diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 0d2123695b..6c94d37003 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "libslic3r/PrintConfig.hpp" #include "slic3r/Utils/PresetUpdater.hpp" @@ -290,6 +291,19 @@ struct PageUpdate: ConfigWizardPage PageUpdate(ConfigWizard *parent); }; +struct PageMode: ConfigWizardPage +{ + wxRadioButton *radio_simple; + wxRadioButton *radio_advanced; + wxRadioButton *radio_expert; + + PageMode(ConfigWizard *parent); + + void serialize_mode(AppConfig *app_config) const; + + virtual void on_activate(); +}; + struct PageVendors: ConfigWizardPage { PageVendors(ConfigWizard *parent); @@ -424,7 +438,8 @@ struct ConfigWizard::priv PageMaterials *page_sla_materials = nullptr; PageCustom *page_custom = nullptr; PageUpdate *page_update = nullptr; - PageVendors *page_vendors = nullptr; // XXX: ? + PageMode *page_mode = nullptr; + PageVendors *page_vendors = nullptr; Pages3rdparty pages_3rdparty; // Custom setup pages From 107ff6fd3618e8a468aacb90903f4cc09ca65f49 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 17 Sep 2019 16:59:52 +0200 Subject: [PATCH 09/11] Materials: Cleanup --- src/slic3r/GUI/ConfigWizard.cpp | 20 +++--------- src/slic3r/GUI/ConfigWizard_private.hpp | 3 +- src/slic3r/GUI/PresetBundle.cpp | 42 ------------------------- src/slic3r/GUI/PresetBundle.hpp | 3 -- 4 files changed, 6 insertions(+), 62 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index d77812e3a6..cbbaa32b64 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -26,7 +26,6 @@ #include #include "libslic3r/Utils.hpp" -// #include "PresetBundle.hpp" #include "GUI.hpp" #include "GUI_Utils.hpp" #include "slic3r/Config/Snapshot.hpp" @@ -44,22 +43,19 @@ using Config::SnapshotDB; // Configuration data structures extensions needed for the wizard Bundle::Bundle(fs::path source_path, bool is_in_resources, bool is_prusa_bundle) - : source_path(std::move(source_path)) - , preset_bundle(new PresetBundle) + : preset_bundle(new PresetBundle) , vendor_profile(nullptr) , is_in_resources(is_in_resources) , is_prusa_bundle(is_prusa_bundle) { - // XXX: consider removing path <-> string juggling - preset_bundle->load_configbundle(this->source_path.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + preset_bundle->load_configbundle(source_path.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); auto first_vendor = preset_bundle->vendors.begin(); wxCHECK_RET(first_vendor != preset_bundle->vendors.end(), "Failed to load preset bundle"); vendor_profile = &first_vendor->second; } Bundle::Bundle(Bundle &&other) - : source_path(std::move(source_path)) - , preset_bundle(std::move(other.preset_bundle)) + : preset_bundle(std::move(other.preset_bundle)) , vendor_profile(other.vendor_profile) , is_in_resources(other.is_in_resources) , is_prusa_bundle(other.is_prusa_bundle) @@ -71,15 +67,9 @@ BundleMap BundleMap::load() { BundleMap res; - // XXX: Keep Prusa bundle separate? (Probably no - keep same codepaths) - const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred(); const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred(); - // XXX - // const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); - // const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor - // : (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); auto prusa_bundle_path = (vendor_dir / PresetBundle::PRUSA_BUNDLE).replace_extension(".ini"); auto prusa_bundle_rsrc = false; if (! boost::filesystem::exists(prusa_bundle_path)) { @@ -663,7 +653,7 @@ void PageMaterials::select_all(bool select) wxWindowUpdateLocker freeze_guard(this); (void)freeze_guard; - for (int i = 0; i < list_l3->GetCount(); i++) { + for (unsigned i = 0; i < list_l3->GetCount(); i++) { const bool current = list_l3->IsChecked(i); if (current != select) { list_l3->Check(i, select); @@ -1646,7 +1636,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // } // } - preset_bundle->load_presets(*app_config, preferred_model); + // preset_bundle->load_presets(*app_config, preferred_model); if (page_custom->custom_wanted()) { page_firmware->apply_custom_config(*custom_config); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 6c94d37003..3f688adff1 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -90,7 +90,6 @@ struct Materials struct Bundle { - fs::path source_path; // XXX: not needed? std::unique_ptr preset_bundle; VendorProfile *vendor_profile; const bool is_in_resources; @@ -235,7 +234,7 @@ template struct DataList : public T } int find(const D &data) { - for (int i = 0; i < this->GetCount(); i++) { + for (unsigned i = 0; i < this->GetCount(); i++) { if (get_data(i) == data) { return i; } } diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index e3ee84e872..54dd92a71b 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -243,48 +243,6 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_ this->load_selections(config, preferred_model_id); } -// FIXME: Comment -// XXX: rm -void PresetBundle::load_available_system_presets() -{ - const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / "vendor").make_preferred(); - const auto rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred(); - - const auto prusa_bundle_vendor = (vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); - const auto prusa_bundle = boost::filesystem::exists(prusa_bundle_vendor) ? prusa_bundle_vendor - : (rsrc_vendor_dir / PRUSA_BUNDLE).replace_extension(".ini"); - - // Reset this PresetBundle and load the Prusa bundle first. - this->load_configbundle(prusa_bundle.string(), LOAD_CFGBNDLE_SYSTEM); - - // Load the other bundles in the datadir/vendor directory - // and then additionally from resources/profiles. - for (auto dir : { &vendor_dir, &rsrc_vendor_dir }) { - for (const auto &dir_entry : boost::filesystem::directory_iterator(*dir)) { - if (Slic3r::is_ini_file(dir_entry)) { - std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part - - // Don't load this bundle if we've already loaded it. - // Note that this takes care of not loading the PRUSA_BUNDLE which was loaded upfront - // as well as bundles with the same name (id) in rsrc_vendor_dir as in vendor_dir. - if (vendors.find(id) != vendors.end()) { continue; } - - PresetBundle other; - other.load_configbundle(dir_entry.path().string(), LOAD_CFGBNDLE_SYSTEM); - - std::vector duplicates = this->merge_presets(std::move(other)); - if (! duplicates.empty()) { - std::string msg = "Vendor configuration file " + id + " contains the following presets with names used by other vendors: "; - for (size_t i = 0; i < duplicates.size(); ++ i) { - if (i > 0) { msg += ", "; } - msg += duplicates[i]; - } - } - } - } - } -} - // Load system presets into this PresetBundle. // For each vendor, there will be a single PresetBundle loaded. std::string PresetBundle::load_system_presets() diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index 79519071b5..b1010e07b0 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -134,9 +134,6 @@ public: void load_default_preset_bitmaps(wxWindow *window); - // FIXME: rm - void load_available_system_presets(); // XXX: name XXX: retval (VendorMap stored internally) - // Set the is_visible flag for printer vendors, printer models and printer variants // based on the user configuration. // If the "vendor" section is missing, enable all models and variants of the particular vendor. From eda01341d0579576ab10450017b6e160c00a3d6e Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 7 Oct 2019 11:10:18 +0200 Subject: [PATCH 10/11] ConfigWizard: Fix a memory access issue between PageMaterial instances --- src/slic3r/GUI/ConfigWizard.cpp | 26 ++++++++++++------------- src/slic3r/GUI/ConfigWizard_private.hpp | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 4038426bab..5af298cc1f 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -515,9 +515,6 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin , list_l1(new StringList(this)) , list_l2(new StringList(this)) , list_l3(new PresetList(this)) - , sel1_prev(wxNOT_FOUND) - , sel2_prev(wxNOT_FOUND) - , presets_loaded(false) { append_spacer(VERTICAL_SPACING); @@ -567,7 +564,7 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin void PageMaterials::reload_presets() { - list_l1->Clear(); + clear(); list_l1->append(_(L("(All)")), &EMPTY); @@ -675,7 +672,7 @@ void PageMaterials::clear() void PageMaterials::on_activate() { if (! presets_loaded) { - wizard_p()->update_materials(); + wizard_p()->update_materials(materials->technology); reload_presets(); } } @@ -753,8 +750,8 @@ PageMode::PageMode(ConfigWizard *parent) { append_text(_(L("PrusaSlicer's user interfaces comes in three variants:\nSimple, Advanced, and Expert.\n" "The Simple mode shows only the most frequently used settings relevant for regular 3D printing. " - "The other two offer progressivly more specialized fine-tuning, " - "they are suitable for advanced and expert usiser, respectively. (FIXME: review this text)"))); + "The other two offer progressivly more sophisticated fine-tuning, " + "they are suitable for advanced and expert usiser, respectively."))); radio_simple = new wxRadioButton(this, wxID_ANY, _(L("Simple mode"))); radio_advanced = new wxRadioButton(this, wxID_ANY, _(L("Advanced mode"))); @@ -1384,7 +1381,7 @@ void ConfigWizard::priv::load_vendors() pair.second.preset_bundle->load_installed_printers(appconfig_new); } - update_materials(); + update_materials(T_ANY); if (app_config->has_section(AppConfig::SECTION_FILAMENTS)) { appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS)); @@ -1437,12 +1434,11 @@ void ConfigWizard::priv::set_run_reason(RunReason run_reason) } } -void ConfigWizard::priv::update_materials() +void ConfigWizard::priv::update_materials(Technology technology) { - filaments.clear(); - sla_materials.clear(); - - if (any_fff_selected) { + if (any_fff_selected && (technology & T_FFF)) { + filaments.clear(); + // Iterate filaments in all bundles for (const auto &pair : bundles) { for (const auto &filament : pair.second.preset_bundle->filaments) { @@ -1466,7 +1462,9 @@ void ConfigWizard::priv::update_materials() } } - if (any_sla_selected) { + if (any_sla_selected && (technology & T_SLA)) { + sla_materials.clear(); + // Iterate SLA materials in all bundles for (const auto &pair : bundles) { for (const auto &material : pair.second.preset_bundle->sla_materials) { diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 3f688adff1..995957816f 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -466,7 +466,7 @@ struct ConfigWizard::priv void set_start_page(ConfigWizard::StartPage start_page); void create_3rdparty_pages(); void set_run_reason(RunReason run_reason); - void update_materials(); + void update_materials(Technology technology); void on_custom_setup(); void on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt); From 570c038eb78698aeb199aac0d5d85d9508039ff5 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 7 Oct 2019 11:25:05 +0200 Subject: [PATCH 11/11] ConfigWizard: Fix printer pre-selection on fresh config --- src/slic3r/GUI/ConfigWizard.cpp | 43 +++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 5af298cc1f..bc73e32625 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1617,24 +1617,37 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese std::string preferred_model; - // Figure out the default pre-selected printer based on the seletions in the picker. + // Figure out the default pre-selected printer based on the selections in the pickers. // The default is the first selected printer model (one with at least 1 variant selected). // The default is only applied by load_presets() if the user doesn't have a (visible) printer // selected already. -// TODO: - // const auto vendor_prusa = bundle.vendors.find("PrusaResearch"); - // const auto config_prusa = enabled_vendors.find("PrusaResearch"); - // if (vendor_prusa != bundle.vendors.end() && config_prusa != enabled_vendors.end()) { - // for (const auto &model : vendor_prusa->second.models) { - // const auto model_it = config_prusa->second.find(model.id); - // if (model_it != config_prusa->second.end() && model_it->second.size() > 0) { - // preferred_model = model.id; - // break; - // } - // } - // } + // Prusa printers are considered first, then 3rd party. + const auto config_prusa = enabled_vendors.find("PrusaResearch"); + if (config_prusa != enabled_vendors.end()) { + for (const auto &model : bundles.prusa_bundle().vendor_profile->models) { + const auto model_it = config_prusa->second.find(model.id); + if (model_it != config_prusa->second.end() && model_it->second.size() > 0) { + preferred_model = model.id; + break; + } + } + } + if (preferred_model.empty()) { + for (const auto &bundle : bundles) { + if (bundle.second.is_prusa_bundle) { continue; } - // preset_bundle->load_presets(*app_config, preferred_model); + const auto config = enabled_vendors.find(bundle.first); + for (const auto &model : bundle.second.vendor_profile->models) { + const auto model_it = config->second.find(model.id); + if (model_it != config->second.end() && model_it->second.size() > 0) { + preferred_model = model.id; + break; + } + } + } + } + + preset_bundle->load_presets(*app_config, preferred_model); if (page_custom->custom_wanted()) { page_firmware->apply_custom_config(*custom_config); @@ -1753,7 +1766,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->load_pages(); p->page_fff->select_all(true, false); p->page_msla->select_all(true, false); - p->index->go_to(p->page_update); + p->index->go_to(p->page_mode); }); p->index->Bind(EVT_INDEX_PAGE, [this](const wxCommandEvent &) {