diff --git a/resources/icons/edit_layers_all.svg b/resources/icons/edit_layers_all.svg index 4fccc1388..fe4f26c52 100644 --- a/resources/icons/edit_layers_all.svg +++ b/resources/icons/edit_layers_all.svg @@ -3,39 +3,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/resources/icons/edit_layers_some.svg b/resources/icons/edit_layers_some.svg index 7db56b3f0..fb1e7f8b1 100644 --- a/resources/icons/edit_layers_some.svg +++ b/resources/icons/edit_layers_some.svg @@ -2,68 +2,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/resources/icons/lock_closed_f.svg b/resources/icons/lock_closed_f.svg new file mode 100644 index 000000000..2920ea0aa --- /dev/null +++ b/resources/icons/lock_closed_f.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/resources/icons/lock_open_f.svg b/resources/icons/lock_open_f.svg new file mode 100644 index 000000000..9440d9266 --- /dev/null +++ b/resources/icons/lock_open_f.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/resources/icons/mirroring_off.svg b/resources/icons/mirroring_off.svg index b68748e90..4ed9da748 100644 --- a/resources/icons/mirroring_off.svg +++ b/resources/icons/mirroring_off.svg @@ -4,19 +4,19 @@ viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> - + - + - + - - + + diff --git a/resources/icons/mirroring_on.svg b/resources/icons/mirroring_on.svg index 55ea49516..8481246a3 100644 --- a/resources/icons/mirroring_on.svg +++ b/resources/icons/mirroring_on.svg @@ -2,21 +2,21 @@ - + - + - + - + - - + + diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index de5e3d106..a7fd819d4 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,4 +1,9 @@ +min_slic3r_version = 2.1.0-alpha0 +1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX min_slic3r_version = 1.42.0-alpha6 +0.8.3 FW version and SL1 materials update +0.8.2 FFF and SL1 settings update +0.8.1 Output settings and SLA materials update 0.8.0 Updated for the PrusaSlicer 2.0.0 final release 0.8.0-rc2 Updated firmware versions for MK2.5/S and MK3/S 0.8.0-rc1 Updated SLA profiles @@ -18,6 +23,8 @@ min_slic3r_version = 1.42.0-alpha 0.4.0-alpha3 Update of SLA profiles 0.4.0-alpha2 First SLA profiles min_slic3r_version = 1.41.3-alpha +0.4.8 MK2.5/3/S FW update +0.4.7 MK2/S/MMU FW update 0.4.6 Updated firmware versions for MK2.5/S and MK3/S 0.4.5 Enabled remaining time support for MK2/S/MMU1 0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt @@ -26,6 +33,8 @@ min_slic3r_version = 1.41.3-alpha 0.4.1 New MK2.5S and MK3S FW versions 0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt min_slic3r_version = 1.41.1 +0.3.8 MK2.5/3/S FW update +0.3.7 MK2/S/MMU FW update 0.3.6 Updated firmware versions for MK2.5 and MK3 0.3.5 New MK2.5 and MK3 FW versions 0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt @@ -60,6 +69,8 @@ min_slic3r_version = 1.41.0-alpha 0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0 0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters min_slic3r_version = 1.40.0 +0.1.16 MK2.5/3/S FW update +0.1.15 MK2/S/MMU FW update 0.1.14 Updated firmware versions for MK2.5 and MK3 0.1.13 New MK2.5 and MK3 FW versions 0.1.12 New MK2.5 and MK3 FW versions diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 9db3a7a14..b78eb7f54 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -4,8 +4,8 @@ # Vendor name will be shown by the Config Wizard. name = Prusa Research # Configuration version of this file. Config file will only be installed, if the config_version differs. -# This means, the server may force the Slic3r configuration to be downgraded. -config_version = 0.8.0 +# This means, the server may force the PrusaSlicer configuration to be downgraded. +config_version = 1.0.0-alpha0 # Where to get the updates from? config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/ changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -105,8 +105,8 @@ external_fill_pattern = rectilinear external_perimeters_first = 0 external_perimeter_extrusion_width = 0.45 extra_perimeters = 0 -extruder_clearance_height = 20 -extruder_clearance_radius = 20 +extruder_clearance_height = 25 +extruder_clearance_radius = 45 extrusion_width = 0.45 fill_angle = 45 fill_density = 20% @@ -133,7 +133,7 @@ notes = overhangs = 0 only_retract_when_crossing_perimeters = 0 ooze_prevention = 0 -output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}.gcode +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode perimeters = 2 perimeter_extruder = 1 perimeter_extrusion_width = 0.45 @@ -213,6 +213,7 @@ support_material_interface_layers = 0 support_material_interface_spacing = 0.15 support_material_spacing = 1 support_material_xy_spacing = 150% +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode [print:*0.25nozzleMK3*] external_perimeter_extrusion_width = 0.25 @@ -245,6 +246,7 @@ max_print_speed = 80 perimeters = 3 fill_pattern = grid fill_density = 20% +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode # Print parameters common to a 0.6mm diameter nozzle. [print:*0.6nozzle*] @@ -256,6 +258,7 @@ perimeter_extrusion_width = 0.65 solid_infill_extrusion_width = 0.65 top_infill_extrusion_width = 0.6 support_material_extrusion_width = 0.55 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode [print:*0.6nozzleMK3*] external_perimeter_extrusion_width = 0.65 @@ -268,6 +271,7 @@ top_infill_extrusion_width = 0.6 support_material_extrusion_width = 0.55 bridge_flow_ratio = 0.95 bridge_speed = 25 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode [print:*soluble_support*] overhangs = 1 @@ -807,7 +811,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and # MK2 MMU # [print:0.35mm FAST sol full 0.6 nozzle] inherits = *0.35mm*; *0.6nozzle*; *soluble_support* -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_model=="MK2SMM" and nozzle_diameter[0]==0.6 and num_extruders>1 external_perimeter_extrusion_width = 0.6 external_perimeter_speed = 30 notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder @@ -872,8 +876,8 @@ solid_infill_speed = 70 top_solid_infill_speed = 45 external_perimeter_extrusion_width = 0.7 perimeter_extrusion_width = 0.7 -infill_extrusion_width = 0.72 -solid_infill_extrusion_width = 0.72 +infill_extrusion_width = 0.7 +solid_infill_extrusion_width = 0.7 # XXXXXXXXXXXXXXXXXXXXXX # XXX----- MK2.5 ----XXX @@ -987,7 +991,7 @@ first_layer_temperature = 215 max_fan_speed = 100 min_fan_speed = 100 temperature = 210 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}18{else}30{endif} ; Filament gcode" [filament:*PET*] inherits = *common* @@ -1003,14 +1007,24 @@ first_layer_bed_temperature = 85 first_layer_temperature = 230 max_fan_speed = 50 min_fan_speed = 30 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}22{else}45{endif} ; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}24{else}45{endif} ; Filament gcode" temperature = 240 +filament_retract_length = 1.4 +filament_retract_lift = 0.2 +compatible_printers_condition = printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) [filament:*PET06*] inherits = *PET* -compatible_printers_condition = nozzle_diameter[0]==0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +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_max_volumetric_speed = 15 +[filament:*PETMMU1*] +inherits = *PET* +filament_retract_length = nil +filament_retract_speed = nil +filament_retract_lift = 0.2 +compatible_printers_condition = printer_model=="MK2SMM" + [filament:*ABS*] inherits = *common* bed_temperature = 110 @@ -1028,14 +1042,14 @@ first_layer_temperature = 255 max_fan_speed = 30 min_fan_speed = 20 temperature = 255 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}18{else}30{endif} ; Filament gcode" [filament:*FLEX*] inherits = *common* bed_temperature = 50 bridge_fan_speed = 100 # For now, all but selected filaments are disabled for the MMU 2.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) +compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model!="MK2SMM" and num_extruders==1 && ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material) cooling = 0 disable_fan_first_layers = 1 extrusion_multiplier = 1.2 @@ -1048,8 +1062,10 @@ first_layer_bed_temperature = 50 first_layer_temperature = 240 max_fan_speed = 90 min_fan_speed = 70 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" +start_filament_gcode = "M900 K0"; Filament gcode" temperature = 240 +filament_retract_length = 0.4 +filament_retract_lift = 0 [filament:ColorFabb Brass Bronze] inherits = *PLA* @@ -1120,7 +1136,7 @@ temperature = 270 [filament:ColorFabb XT-CF20] inherits = *PET* -compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) extrusion_multiplier = 1.2 filament_cost = 80.65 filament_density = 1.35 @@ -1130,6 +1146,8 @@ first_layer_bed_temperature = 90 first_layer_temperature = 260 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" temperature = 260 +filament_retract_length = nil +filament_retract_lift = 0.2 [filament:ColorFabb nGen] inherits = *PET* @@ -1159,16 +1177,20 @@ first_layer_temperature = 260 max_fan_speed = 35 min_fan_speed = 20 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:E3D Edge] inherits = *PET* filament_cost = 56.9 filament_density = 1.26 -filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +filament_type = EDGE [filament:E3D PC-ABS] inherits = *ABS* filament_cost = 0 +filament_type = PC filament_density = 1.05 first_layer_temperature = 270 temperature = 270 @@ -1187,12 +1209,13 @@ filament_density = 1.04 fan_always_on = 1 first_layer_temperature = 265 temperature = 265 +filament_type = ASA -[filament:Fillamentum CPE HG100 HM100] +[filament:Fillamentum CPE] inherits = *PET* filament_cost = 54.1 filament_density = 1.25 -filament_notes = "CPE HG100 , CPE HM100" +filament_type = CPE first_layer_bed_temperature = 90 first_layer_temperature = 275 max_fan_speed = 50 @@ -1230,10 +1253,20 @@ 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:Generic FLEX] +inherits = *FLEX* +filament_cost = 82 +filament_density = 1.22 +filament_max_volumetric_speed = 1.2 +filament_retract_length = 0 +filament_retract_speed = nil +filament_retract_lift = nil + [filament:Polymaker PC-Max] inherits = *ABS* filament_cost = 77.3 filament_density = 1.20 +filament_type = PC bed_temperature = 115 filament_colour = #3A80CA first_layer_bed_temperature = 100 @@ -1304,7 +1337,7 @@ inherits = *PET* 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_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +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:Prusament PETG] inherits = *PET* @@ -1312,7 +1345,8 @@ first_layer_temperature = 240 temperature = 250 filament_cost = 24.99 filament_density = 1.27 -compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +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:Prusa PET 0.6 nozzle] inherits = *PET06* @@ -1326,10 +1360,11 @@ first_layer_temperature = 240 temperature = 250 filament_cost = 24.99 filament_density = 1.27 +filament_type = PETG [filament:*PET MMU2*] inherits = Prusa PET -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material +compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material temperature = 230 first_layer_temperature = 230 filament_cooling_final_speed = 1 @@ -1343,6 +1378,13 @@ filament_unload_time = 12 filament_unloading_speed = 20 filament_unloading_speed_start = 120 filament_loading_speed_start = 19 +filament_retract_length = 1.4 +filament_retract_lift = 0.2 + +[filament:*PET MMU2 06*] +inherits = *PET MMU2* +compatible_printers_condition = nozzle_diameter[0]==0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material +filament_max_volumetric_speed = 13 [filament:Generic PET MMU2] inherits = *PET MMU2* @@ -1352,12 +1394,23 @@ inherits = *PET MMU2* [filament:Prusament PETG MMU2] inherits = *PET MMU2* +filament_type = PETG + +[filament:Generic PET MMU2 0.6 nozzle] +inherits = *PET MMU2 06* + +[filament:Prusa PET MMU2 0.6 nozzle] +inherits = *PET MMU2 06* + +[filament:Prusament PETG MMU2 0.6 nozzle] +inherits = *PET MMU2 06* +filament_type = PETG [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\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +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:Prusament PLA] inherits = *PLA* @@ -1395,6 +1448,7 @@ inherits = *PLA MMU2* inherits = *FLEX* filament_cost = 82 filament_density = 1.22 +filament_max_volumetric_speed = 1.35 [filament:Taulman Bridge] inherits = *common* @@ -1409,7 +1463,7 @@ fan_below_layer_time = 20 filament_colour = #DEE0E6 filament_max_volumetric_speed = 10 filament_soluble = 0 -filament_type = PET +filament_type = NYLON first_layer_bed_temperature = 60 first_layer_temperature = 240 max_fan_speed = 5 @@ -1524,7 +1578,7 @@ fan_below_layer_time = 100 filament_colour = #DEE0E6 filament_max_volumetric_speed = 5 filament_notes = "List of materials tested with standard PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA" -filament_type = PLA +filament_type = PP first_layer_bed_temperature = 100 first_layer_temperature = 220 max_fan_speed = 100 @@ -1532,6 +1586,130 @@ min_fan_speed = 100 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 220 +## Filaments MMU1 + +[filament:ColorFabb HT MMU1] +inherits = *PETMMU1* +bed_temperature = 110 +bridge_fan_speed = 30 +cooling = 1 +disable_fan_first_layers = 3 +fan_always_on = 0 +fan_below_layer_time = 10 +filament_cost = 58.66 +filament_density = 1.18 +first_layer_bed_temperature = 105 +first_layer_temperature = 270 +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:ColorFabb XT MMU1] +inherits = *PETMMU1* +filament_type = PET +filament_cost = 62.9 +filament_density = 1.27 +first_layer_bed_temperature = 90 +first_layer_temperature = 260 +temperature = 270 + +[filament:ColorFabb XT-CF20 MMU1] +inherits = *PETMMU1* +compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model=="MK2SMM" +extrusion_multiplier = 1.2 +filament_cost = 80.65 +filament_density = 1.35 +filament_colour = #804040 +filament_max_volumetric_speed = 1 +first_layer_bed_temperature = 90 +first_layer_temperature = 260 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" +temperature = 260 + +[filament:ColorFabb nGen MMU1] +inherits = *PETMMU1* +filament_cost = 21.2 +filament_density = 1.2 +bridge_fan_speed = 40 +fan_always_on = 0 +fan_below_layer_time = 10 +filament_type = NGEN +first_layer_temperature = 240 +max_fan_speed = 35 +min_fan_speed = 20 + +[filament:E3D Edge MMU1] +inherits = *PETMMU1* +filament_cost = 56.9 +filament_density = 1.26 +filament_type = EDGE +filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" + +[filament:Fillamentum CPE MMU1] +inherits = *PETMMU1* +filament_cost = 54.1 +filament_density = 1.25 +filament_type = CPE +first_layer_bed_temperature = 90 +first_layer_temperature = 275 +max_fan_speed = 50 +min_fan_speed = 50 +temperature = 275 + +[filament:Generic PET MMU1] +inherits = *PETMMU1* +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:Prusa PET MMU1] +inherits = *PETMMU1* +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:Prusament PETG MMU1] +inherits = *PETMMU1* +first_layer_temperature = 240 +temperature = 250 +filament_cost = 24.99 +filament_density = 1.27 +filament_type = PETG + +[filament:Taulman T-Glase MMU1] +inherits = *PETMMU1* +filament_cost = 40 +filament_density = 1.27 +bridge_fan_speed = 40 +cooling = 0 +fan_always_on = 0 +first_layer_bed_temperature = 90 +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:SemiFlex or Flexfill 98A MMU1] +inherits = *FLEX* +filament_cost = 82 +filament_density = 1.22 +filament_max_volumetric_speed = 1.35 +filament_retract_length = nil +filament_retract_speed = nil +filament_retract_lift = nil +compatible_printers_condition = printer_model=="MK2SMM" + +[filament:Generic FLEX MMU1] +inherits = *FLEX* +filament_cost = 82 +filament_density = 1.22 +filament_max_volumetric_speed = 1.2 +filament_retract_length = 0 +filament_retract_speed = nil +filament_retract_lift = nil +compatible_printers_condition = printer_model=="MK2SMM" + [sla_print:*common*] compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_SL1.*/ layer_height = 0.05 @@ -1575,6 +1753,9 @@ layer_height = 0.05 [sla_print:0.1 Fast] inherits = *common* layer_height = 0.1 +support_head_front_diameter = 0.5 +support_head_penetration = 0.5 +support_pillar_diameter = 1.3 ########### Materials 0.025 @@ -1605,82 +1786,117 @@ initial_layer_height = 0.035 inherits = *common 0.05* compatible_prints_condition = layer_height == 0.1 exposure_time = 20 -initial_exposure_time = 90 +initial_exposure_time = 45 initial_layer_height = 0.1 ########### Materials 0.025 -[sla_material:Bluecast Phrozen Wax 0.025] +[sla_material:BlueCast Phrozen Wax 0.025] inherits = *common 0.025* -exposure_time = 8 +exposure_time = 15 +initial_exposure_time = 50 + +[sla_material:BlueCast EcoGray 0.025] +inherits = *common 0.025* +exposure_time = 6 +initial_exposure_time = 40 + +[sla_material:BlueCast Keramaster Dental 0.025] +inherits = *common 0.025* +exposure_time = 6 initial_exposure_time = 45 +[sla_material:BlueCast X10 0.025] +inherits = *common 0.025* +exposure_time = 4 +initial_exposure_time = 100 + [sla_material:Prusa Orange Tough 0.025] inherits = *common 0.025* exposure_time = 6 initial_exposure_time = 30 +[sla_material:Prusa Grey Tough 0.025] +inherits = *common 0.025* +exposure_time = 7 +initial_exposure_time = 30 + +[sla_material:Prusa Azure Blue Tough 0.025] +inherits = *common 0.025* +exposure_time = 7 +initial_exposure_time = 30 + +[sla_material:Prusa Maroon Tough 0.025] +inherits = *common 0.025* +exposure_time = 6 +initial_exposure_time = 30 + +[sla_material:Prusa Beige Tough 0.025] +inherits = *common 0.025* +exposure_time = 6 +initial_exposure_time = 30 + +[sla_material:Prusa Pink Tough 0.025] +inherits = *common 0.025* +exposure_time = 7 +initial_exposure_time = 30 + +[sla_material:Prusa White Tough 0.025] +inherits = *common 0.025* +exposure_time = 6.5 +initial_exposure_time = 30 + +[sla_material:Prusa Transparent Tough 0.025] +inherits = *common 0.025* +exposure_time = 6 +initial_exposure_time = 15 + +[sla_material:Prusa Green Casting 0.025] +inherits = *common 0.025* +exposure_time = 12 +initial_exposure_time = 35 + +## [sla_material:Prusa Transparent Green Tough 0.025] +## inherits = *common 0.025* +## exposure_time = 5 +## initial_exposure_time = 30 + ########### Materials 0.05 -[sla_material:3DM-HTR140 (high temperature) 0.05] -inherits = *common 0.05* -exposure_time = 12 -initial_exposure_time = 45 - -[sla_material:Bluecast Ecogray 0.05] -inherits = *common 0.05* -exposure_time = 8 -initial_exposure_time = 45 - -[sla_material:Bluecast Keramaster 0.05] -inherits = *common 0.05* -exposure_time = 8 -initial_exposure_time = 45 - -[sla_material:Bluecast Keramaster Dental 0.05] +[sla_material:BlueCast EcoGray 0.05] inherits = *common 0.05* exposure_time = 7 +initial_exposure_time = 35 + +[sla_material:BlueCast Keramaster 0.05] +inherits = *common 0.05* +exposure_time = 8 initial_exposure_time = 45 -[sla_material:Bluecast LCD-DLP Original 0.05] +[sla_material:BlueCast Keramaster Dental 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 50 + +[sla_material:BlueCast LCD-DLP Original 0.05] inherits = *common 0.05* exposure_time = 10 initial_exposure_time = 60 -[sla_material:Bluecast Phrozen Wax 0.05] +[sla_material:BlueCast Phrozen Wax 0.05] inherits = *common 0.05* -exposure_time = 10 -initial_exposure_time = 55 +exposure_time = 16 +initial_exposure_time = 50 -[sla_material:Bluecast S+ 0.05] +[sla_material:BlueCast S+ 0.05] inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 45 -[sla_material:Bluecast X2 0.05] -inherits = *common 0.05* -exposure_time = 10 -initial_exposure_time = 60 - -[sla_material:Prusa Skin Tough 0.05] +[sla_material:BlueCast X10 0.05] inherits = *common 0.05* exposure_time = 6 -initial_exposure_time = 30 - -[sla_material:Prusa Orange Tough 0.05] -inherits = *common 0.05* -exposure_time = 7.5 -initial_exposure_time = 30 - -[sla_material:Prusa Grey Tough 0.05] -inherits = *common 0.05* -exposure_time = 8.5 -initial_exposure_time = 30 - -[sla_material:Prusa Black Tough 0.05] -inherits = *common 0.05* -exposure_time = 6 -initial_exposure_time = 30 +initial_exposure_time = 100 [sla_material:Monocure 3D Black Rapid Resin 0.05] inherits = *common 0.05* @@ -1697,20 +1913,30 @@ inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 40 -[sla_material:Monocure 3D Gray Rapid Resin 0.05] +[sla_material:Monocure 3D Grey Rapid Resin 0.05] inherits = *common 0.05* -exposure_time = 7 -initial_exposure_time = 40 +exposure_time = 10 +initial_exposure_time = 30 [sla_material:Monocure 3D White Rapid Resin 0.05] inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 40 +[sla_material:3DM-HTR140 (high temperature) 0.05] +inherits = *common 0.05* +exposure_time = 12 +initial_exposure_time = 45 + [sla_material:3DM-ABS 0.05] inherits = *common 0.05* -exposure_time = 9 -initial_exposure_time = 35 +exposure_time = 13 +initial_exposure_time = 25 + +[sla_material:3DM-BLACK 0.05] +inherits = *common 0.05* +exposure_time = 20 +initial_exposure_time = 40 [sla_material:3DM-DENT 0.05] inherits = *common 0.05* @@ -1737,7 +1963,39 @@ inherits = *common 0.05* exposure_time = 9 initial_exposure_time = 40 -## [sla_material:Prusa Skin Super Low Odor 0.05] +[sla_material:Harz Labs Model Resin Cherry 0.05] +inherits = *common 0.05* +exposure_time = 8 +initial_exposure_time = 45 + +[sla_material:Photocentric Hard Grey 0.05] +inherits = *common 0.05* +exposure_time = 15 +initial_exposure_time = 30 + +## Prusa + +[sla_material:Prusa Beige Tough 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 30 + +[sla_material:Prusa Orange Tough 0.05] +inherits = *common 0.05* +exposure_time = 7.5 +initial_exposure_time = 30 + +[sla_material:Prusa Grey Tough 0.05] +inherits = *common 0.05* +exposure_time = 8.5 +initial_exposure_time = 30 + +[sla_material:Prusa Black Tough 0.05] +inherits = *common 0.05* +exposure_time = 6 +initial_exposure_time = 30 + +## [sla_material:Prusa Beige Super Low Odor 0.05] ## inherits = *common 0.05* ## exposure_time = 7.5 ## initial_exposure_time = 30 @@ -1752,11 +2010,6 @@ initial_exposure_time = 40 ## exposure_time = 6.5 ## initial_exposure_time = 30 -[sla_material:Harz Labs Model Resin Cherry 0.05] -inherits = *common 0.05* -exposure_time = 8 -initial_exposure_time = 45 - ## [sla_material:Prusa Black High Tenacity 0.05] ## inherits = *common 0.05* ## exposure_time = 7 @@ -1765,7 +2018,7 @@ initial_exposure_time = 45 [sla_material:Prusa Green Casting 0.05] inherits = *common 0.05* exposure_time = 13 -initial_exposure_time = 30 +initial_exposure_time = 40 ## [sla_material:Prusa Yellow Solid 0.05] ## inherits = *common 0.05* @@ -1774,10 +2027,10 @@ initial_exposure_time = 30 [sla_material:Prusa White Tough 0.05] inherits = *common 0.05* -exposure_time = 7 +exposure_time = 7.5 initial_exposure_time = 30 -## [sla_material:Prusa Green Transparent 0.05] +## [sla_material:Prusa Transparent Green Tough 0.05] ## inherits = *common 0.05* ## exposure_time = 6 ## initial_exposure_time = 30 @@ -1789,12 +2042,12 @@ initial_exposure_time = 30 [sla_material:Prusa Maroon Tough 0.05] inherits = *common 0.05* -exposure_time = 9 +exposure_time = 7.5 initial_exposure_time = 30 [sla_material:Prusa Pink Tough 0.05] inherits = *common 0.05* -exposure_time = 7 +exposure_time = 8 initial_exposure_time = 30 [sla_material:Prusa Azure Blue Tough 0.05] @@ -1802,6 +2055,11 @@ inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 30 +[sla_material:Prusa Transparent Tough 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 15 + ## [sla_material:Prusa Yellow Flexible 0.05] ## inherits = *common 0.05* ## exposure_time = 9 @@ -1809,8 +2067,8 @@ initial_exposure_time = 30 ## [sla_material:Prusa Clear Flexible 0.05] ## inherits = *common 0.05* -## exposure_time = 9 -## initial_exposure_time = 30 +## exposure_time = 5 +## initial_exposure_time = 15 ## [sla_material:Prusa White Flexible 0.05] ## inherits = *common 0.05* @@ -1843,9 +2101,49 @@ initial_exposure_time = 30 [sla_material:Prusa Orange Tough 0.1] inherits = *common 0.1* -exposure_time = 10 +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa Beige Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa Pink Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa Azure Blue Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa Maroon Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa White Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 45 + +[sla_material:Prusa Black Tough 0.1] +inherits = *common 0.1* +exposure_time = 13 +initial_exposure_time = 55 + +[sla_material:Prusa Transparent Tough 0.1] +inherits = *common 0.1* +exposure_time = 8 initial_exposure_time = 30 +[sla_material:Prusa Green Casting 0.1] +inherits = *common 0.1* +exposure_time = 15 +initial_exposure_time = 50 + [printer:*common*] printer_technology = FFF bed_shape = 0x0,250x0,250x210,0x210 @@ -1897,7 +2195,7 @@ retract_speed = 35 serial_port = serial_speed = 250000 single_extruder_multi_material = 0 -start_gcode = M115 U3.1.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.2.3 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 toolchange_gcode = use_firmware_retraction = 0 use_relative_e_distances = 1 @@ -1934,7 +2232,7 @@ printer_model = MK2SMM inherits = *multimaterial* end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN -start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG92 E0.0 +start_gcode = M115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG92 E0.0 default_print_profile = 0.15mm OPTIMAL [printer:*mm-multi*] @@ -1944,7 +2242,7 @@ end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes. extruder_colour = #FFAA55;#E37BA0;#4ECDD3;#FB7259 nozzle_diameter = 0.4,0.4,0.4,0.4 printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN -start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_single_extruder_multi_material_priming}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\n{endif}\nG92 E0.0 +start_gcode = M115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_single_extruder_multi_material_priming}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\n{endif}\nG92 E0.0 default_print_profile = 0.15mm OPTIMAL # XXXXXXXXXXXXXXXXX @@ -2012,19 +2310,19 @@ min_layer_height = 0.1 inherits = Original Prusa i3 MK2S printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 0.25 nozzle] inherits = Original Prusa i3 MK2S 0.25 nozzle printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 0.6 nozzle] inherits = Original Prusa i3 MK2S 0.6 nozzle printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 MMU2 Single] inherits = Original Prusa i3 MK2.5; *mm2* @@ -2053,7 +2351,7 @@ machine_min_travel_rate = 0 default_print_profile = 0.15mm OPTIMAL MK2.5 default_filament_profile = Prusament PLA printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; load to nozzle\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK2.5 MMU2 Single 0.6 nozzle] @@ -2095,23 +2393,23 @@ single_extruder_multi_material = 1 # to be defined explicitely. nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n [printer:Original Prusa i3 MK2.5S] inherits = Original Prusa i3 MK2.5 printer_model = MK2.5S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S 0.25 nozzle] inherits = Original Prusa i3 MK2.5 0.25 nozzle printer_model = MK2.5S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S 0.6 nozzle] inherits = Original Prusa i3 MK2.5 0.6 nozzle printer_model = MK2.5S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S MMU2S Single] inherits = Original Prusa i3 MK2.5; *mm2s* @@ -2140,7 +2438,7 @@ machine_min_travel_rate = 0 default_print_profile = 0.15mm OPTIMAL MK2.5 default_filament_profile = Prusament PLA printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK2.5S MMU2S Single 0.6 nozzle] @@ -2160,7 +2458,7 @@ min_layer_height = 0.05 nozzle_diameter = 0.25 printer_variant = 0.25 default_print_profile = 0.10mm DETAIL 0.25 nozzle -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n [printer:Original Prusa i3 MK2.5S MMU2S] inherits = Original Prusa i3 MK2.5; *mm2s* @@ -2193,9 +2491,24 @@ single_extruder_multi_material = 1 # to be defined explicitely. nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n +[printer:Original Prusa i3 MK2.5S MMU2S 0.6 nozzle] +inherits = Original Prusa i3 MK2.5S MMU2S +nozzle_diameter = 0.6,0.6,0.6,0.6,0.6 +max_layer_height = 0.40 +min_layer_height = 0.15 +printer_variant = 0.6 +default_print_profile = 0.20mm NORMAL 0.6 nozzle + +[printer:Original Prusa i3 MK2.5 MMU2 0.6 nozzle] +inherits = Original Prusa i3 MK2.5 MMU2 +nozzle_diameter = 0.6,0.6,0.6,0.6,0.6 +max_layer_height = 0.40 +min_layer_height = 0.15 +printer_variant = 0.6 +default_print_profile = 0.20mm NORMAL 0.6 nozzle # XXXXXXXXXXXXXXXXX # XXX--- MK3 ---XXX @@ -2225,7 +2538,7 @@ remaining_times = 1 printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_lift_below = 209 max_print_height = 210 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} printer_model = MK3 default_print_profile = 0.15mm QUALITY MK3 @@ -2235,7 +2548,7 @@ nozzle_diameter = 0.25 max_layer_height = 0.15 min_layer_height = 0.05 printer_variant = 0.25 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 [printer:Original Prusa i3 MK3 0.6 nozzle] @@ -2249,17 +2562,17 @@ default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3 [printer:Original Prusa i3 MK3S] inherits = Original Prusa i3 MK3 printer_model = MK3S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:Original Prusa i3 MK3S 0.25 nozzle] inherits = Original Prusa i3 MK3 0.25 nozzle printer_model = MK3S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:Original Prusa i3 MK3S 0.6 nozzle] inherits = Original Prusa i3 MK3 0.6 nozzle printer_model = MK3S -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:*mm2*] inherits = Original Prusa i3 MK3 @@ -2289,7 +2602,7 @@ default_filament_profile = Prusament PLA MMU2 inherits = *mm2* single_extruder_multi_material = 0 default_filament_profile = Prusament PLA -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK3 MMU2 Single 0.6 nozzle] @@ -2308,7 +2621,7 @@ nozzle_diameter = 0.25 max_layer_height = 0.15 min_layer_height = 0.05 printer_variant = 0.25 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F1000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 [printer:Original Prusa i3 MK3 MMU2] @@ -2319,14 +2632,14 @@ inherits = *mm2* machine_max_acceleration_e = 8000,8000 nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n [printer:Original Prusa i3 MK3S MMU2S Single] inherits = *mm2s* single_extruder_multi_material = 0 default_filament_profile = Prusament PLA -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK3S MMU2S Single 0.6 nozzle] @@ -2345,7 +2658,7 @@ nozzle_diameter = 0.25 max_layer_height = 0.15 min_layer_height = 0.05 printer_variant = 0.25 -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F1400.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 [printer:Original Prusa i3 MK3S MMU2S] @@ -2353,18 +2666,26 @@ inherits = *mm2s* machine_max_acceleration_e = 8000,8000 nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M115 U3.7.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n +start_gcode = M115 U3.7.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors\n -# 0.6 nozzle MMU printer profile - only for single mode for now +## 0.6mm nozzle MMU2/S printer profiles -# [printer:Original Prusa i3 MK3S MMU2S 0.6 nozzle] -# inherits = Original Prusa i3 MK3S MMU2S -# nozzle_diameter = 0.6,0.6,0.6,0.6,0.6 -# max_layer_height = 0.40 -# min_layer_height = 0.15 -# printer_variant = 0.6 -# default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3 +[printer:Original Prusa i3 MK3S MMU2S 0.6 nozzle] +inherits = Original Prusa i3 MK3S MMU2S +nozzle_diameter = 0.6,0.6,0.6,0.6,0.6 +max_layer_height = 0.40 +min_layer_height = 0.15 +printer_variant = 0.6 +default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3 + +[printer:Original Prusa i3 MK3 MMU2 0.6 nozzle] +inherits = Original Prusa i3 MK3 MMU2 +nozzle_diameter = 0.6,0.6,0.6,0.6,0.6 +max_layer_height = 0.40 +min_layer_height = 0.15 +printer_variant = 0.6 +default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3 [printer:Original Prusa SL1] printer_technology = SLA diff --git a/src/boost/nowide/utf8_codecvt.hpp b/src/boost/nowide/utf8_codecvt.hpp index cc5046fc8..877c9f0e0 100644 --- a/src/boost/nowide/utf8_codecvt.hpp +++ b/src/boost/nowide/utf8_codecvt.hpp @@ -102,7 +102,7 @@ protected: #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST return from - save_from; #else - return save_max - max; + return int(save_max - max); #endif } diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 9d0649a1f..577698071 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -211,25 +211,35 @@ std::vector ConfigOptionDef::cli_args(const std::string &key) const ConfigOption* ConfigOptionDef::create_empty_option() const { - switch (this->type) { - case coFloat: return new ConfigOptionFloat(); - case coFloats: return new ConfigOptionFloats(); - case coInt: return new ConfigOptionInt(); - case coInts: return new ConfigOptionInts(); - case coString: return new ConfigOptionString(); - case coStrings: return new ConfigOptionStrings(); - case coPercent: return new ConfigOptionPercent(); - case coPercents: return new ConfigOptionPercents(); - case coFloatOrPercent: return new ConfigOptionFloatOrPercent(); - case coPoint: return new ConfigOptionPoint(); - case coPoints: return new ConfigOptionPoints(); - case coPoint3: return new ConfigOptionPoint3(); -// case coPoint3s: return new ConfigOptionPoint3s(); - case coBool: return new ConfigOptionBool(); - case coBools: return new ConfigOptionBools(); - case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map); - default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label); - } + if (this->nullable) { + switch (this->type) { + case coFloats: return new ConfigOptionFloatsNullable(); + case coInts: return new ConfigOptionIntsNullable(); + case coPercents: return new ConfigOptionPercentsNullable(); + case coBools: return new ConfigOptionBoolsNullable(); + default: throw std::runtime_error(std::string("Unknown option type for nullable option ") + this->label); + } + } else { + switch (this->type) { + case coFloat: return new ConfigOptionFloat(); + case coFloats: return new ConfigOptionFloats(); + case coInt: return new ConfigOptionInt(); + case coInts: return new ConfigOptionInts(); + case coString: return new ConfigOptionString(); + case coStrings: return new ConfigOptionStrings(); + case coPercent: return new ConfigOptionPercent(); + case coPercents: return new ConfigOptionPercents(); + case coFloatOrPercent: return new ConfigOptionFloatOrPercent(); + case coPoint: return new ConfigOptionPoint(); + case coPoints: return new ConfigOptionPoints(); + case coPoint3: return new ConfigOptionPoint3(); + // case coPoint3s: return new ConfigOptionPoint3s(); + case coBool: return new ConfigOptionBool(); + case coBools: return new ConfigOptionBools(); + case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map); + default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label); + } + } } ConfigOption* ConfigOptionDef::create_default_option() const @@ -254,6 +264,13 @@ ConfigOptionDef* ConfigDef::add(const t_config_option_key &opt_key, ConfigOption return opt; } +ConfigOptionDef* ConfigDef::add_nullable(const t_config_option_key &opt_key, ConfigOptionType type) +{ + ConfigOptionDef *def = this->add(opt_key, type); + def->nullable = true; + return def; +} + std::string ConfigOptionDef::nocli = "~~~noCLI"; std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function filter) const @@ -642,6 +659,17 @@ void ConfigBase::save(const std::string &file) const c.close(); } +// Set all the nullable values to nils. +void ConfigBase::null_nullables() +{ + for (const std::string &opt_key : this->keys()) { + ConfigOption *opt = this->optptr(opt_key, false); + assert(opt != nullptr); + if (opt->nullable()) + opt->deserialize("nil"); + } +} + bool DynamicConfig::operator==(const DynamicConfig &rhs) const { auto it1 = this->options.begin(); @@ -655,6 +683,19 @@ bool DynamicConfig::operator==(const DynamicConfig &rhs) const return it1 == it1_end && it2 == it2_end; } +// Remove options with all nil values, those are optional and it does not help to hold them. +size_t DynamicConfig::remove_nil_options() +{ + size_t cnt_removed = 0; + for (auto it = options.begin(); it != options.end();) + if (it->second->is_nil()) { + it = options.erase(it); + ++ cnt_removed; + } else + ++ it; + return cnt_removed; +} + ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) { auto it = options.find(opt_key); @@ -838,18 +879,22 @@ CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloat) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloats) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInt) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInts) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionIntsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionString) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionStrings) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercent) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercents) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercentsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatOrPercent) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoints) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint3) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBool) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBools) +CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric) CEREAL_REGISTER_TYPE(Slic3r::ConfigBase) CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig) @@ -868,17 +913,21 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::Con CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionFloat) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionFloats) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionFloatsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionInt) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionInts) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionIntsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionString) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionStrings) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloat, Slic3r::ConfigOptionPercent) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloats, Slic3r::ConfigOptionPercents) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloats, Slic3r::ConfigOptionPercentsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionPercent, Slic3r::ConfigOptionFloatOrPercent) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionPoint) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionPoints) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionPoint3) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle, Slic3r::ConfigOptionBool) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionBools) +CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector, Slic3r::ConfigOptionBoolsNullable) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 7d96f6cf3..2850f1cb9 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -15,6 +15,7 @@ #include "clonable_ptr.hpp" #include "Point.hpp" +#include #include #include @@ -124,6 +125,23 @@ public: bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); } bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; } bool is_vector() const { return ! this->is_scalar(); } + // If this option is nullable, then it may have its value or values set to nil. + virtual bool nullable() const { return false; } + // A scalar is nil, or all values of a vector are nil. + virtual bool is_nil() const { return false; } + // Is this option overridden by another option? + // An option overrides another option if it is not nil and not equal. + virtual bool overriden_by(const ConfigOption *rhs) const { + assert(! this->nullable() && ! rhs->nullable()); + return *this != *rhs; + } + // Apply an override option, possibly a nullable one. + virtual bool apply_override(const ConfigOption *rhs) { + if (*this == *rhs) + return false; + *this = *rhs; + return true; + } }; typedef ConfigOption* ConfigOptionPtr; @@ -183,6 +201,8 @@ public: virtual size_t size() const = 0; // Is this vector empty? virtual bool empty() const = 0; + // Is the value nil? That should only be possible if this->nullable(). + virtual bool is_nil(size_t idx) const = 0; protected: // Used to verify type compatibility when assigning to / from a scalar ConfigOption. @@ -302,6 +322,62 @@ public: bool operator==(const std::vector &rhs) const { return this->values == rhs; } bool operator!=(const std::vector &rhs) const { return this->values != rhs; } + // Is this option overridden by another option? + // An option overrides another option if it is not nil and not equal. + bool overriden_by(const ConfigOption *rhs) const override { + if (this->nullable()) + throw std::runtime_error("Cannot override a nullable ConfigOption."); + if (rhs->type() != this->type()) + throw std::runtime_error("ConfigOptionVector.overriden_by() applied to different types."); + auto rhs_vec = static_cast*>(rhs); + if (! rhs->nullable()) + // Overridding a non-nullable object with another non-nullable object. + return this->values != rhs_vec->values; + size_t i = 0; + size_t cnt = std::min(this->size(), rhs_vec->size()); + for (; i < cnt; ++ i) + if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i]) + return true; + for (; i < rhs_vec->size(); ++ i) + if (! rhs_vec->is_nil(i)) + return true; + return false; + } + // Apply an override option, possibly a nullable one. + bool apply_override(const ConfigOption *rhs) override { + if (this->nullable()) + throw std::runtime_error("Cannot override a nullable ConfigOption."); + if (rhs->type() != this->type()) + throw std::runtime_error("ConfigOptionVector.apply_override() applied to different types."); + auto rhs_vec = static_cast*>(rhs); + if (! rhs->nullable()) { + // Overridding a non-nullable object with another non-nullable object. + if (this->values != rhs_vec->values) { + this->values = rhs_vec->values; + return true; + } + return false; + } + size_t i = 0; + size_t cnt = std::min(this->size(), rhs_vec->size()); + bool modified = false; + for (; i < cnt; ++ i) + if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i]) { + this->values[i] = rhs_vec->values[i]; + modified = true; + } + for (; i < rhs_vec->size(); ++ i) + if (! rhs_vec->is_nil(i)) { + if (this->values.empty()) + this->values.resize(i + 1); + else + this->values.resize(i + 1, this->values.front()); + this->values[i] = rhs_vec->values[i]; + modified = true; + } + return false; + } + private: friend class cereal::access; template void serialize(Archive & ar) { ar(this->values); } @@ -345,26 +421,41 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; -class ConfigOptionFloats : public ConfigOptionVector +template +class ConfigOptionFloatsTempl : public ConfigOptionVector { public: - ConfigOptionFloats() : ConfigOptionVector() {} - explicit ConfigOptionFloats(size_t n, double value) : ConfigOptionVector(n, value) {} - explicit ConfigOptionFloats(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} - explicit ConfigOptionFloats(const std::vector &vec) : ConfigOptionVector(vec) {} - explicit ConfigOptionFloats(std::vector &&vec) : ConfigOptionVector(std::move(vec)) {} + ConfigOptionFloatsTempl() : ConfigOptionVector() {} + explicit ConfigOptionFloatsTempl(size_t n, double value) : ConfigOptionVector(n, value) {} + explicit ConfigOptionFloatsTempl(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} + explicit ConfigOptionFloatsTempl(const std::vector &vec) : ConfigOptionVector(vec) {} + explicit ConfigOptionFloatsTempl(std::vector &&vec) : ConfigOptionVector(std::move(vec)) {} static ConfigOptionType static_type() { return coFloats; } ConfigOptionType type() const override { return static_type(); } - ConfigOption* clone() const override { return new ConfigOptionFloats(*this); } - bool operator==(const ConfigOptionFloats &rhs) const { return this->values == rhs.values; } + ConfigOption* clone() const override { return new ConfigOptionFloatsTempl(*this); } + bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); } + bool operator==(const ConfigOption &rhs) const override { + if (rhs.type() != this->type()) + throw std::runtime_error("ConfigOptionFloatsTempl: Comparing incompatible types"); + assert(dynamic_cast*>(&rhs)); + return vectors_equal(this->values, static_cast*>(&rhs)->values); + } + // Could a special "nil" value be stored inside the vector, indicating undefined value? + bool nullable() const override { return NULLABLE; } + // Special "nil" value to be stored into the vector if this->supports_nil(). + static double nil_value() { return std::numeric_limits::quiet_NaN(); } + // A scalar is nil, or all values of a vector are nil. + bool is_nil() const override { for (auto v : this->values) if (! std::isnan(v)) return false; return true; } + bool is_nil(size_t idx) const override { return std::isnan(this->values[idx]); } std::string serialize() const override { std::ostringstream ss; - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { - if (it - this->values.begin() != 0) ss << ","; - ss << *it; + for (const double &v : this->values) { + if (&v != &this->values.front()) + ss << ","; + serialize_single_value(ss, v); } return ss.str(); } @@ -373,14 +464,14 @@ public: { std::vector vv; vv.reserve(this->values.size()); - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { + for (const double v : this->values) { std::ostringstream ss; - ss << *it; + serialize_single_value(ss, v); vv.push_back(ss.str()); } return vv; } - + bool deserialize(const std::string &str, bool append = false) override { if (! append) @@ -388,25 +479,61 @@ public: std::istringstream is(str); std::string item_str; while (std::getline(is, item_str, ',')) { - std::istringstream iss(item_str); - double value; - iss >> value; - this->values.push_back(value); + boost::trim(item_str); + if (item_str == "nil") { + if (NULLABLE) + this->values.push_back(nil_value()); + else + std::runtime_error("Deserializing nil into a non-nullable object"); + } else { + std::istringstream iss(item_str); + double value; + iss >> value; + this->values.push_back(value); + } } return true; } - ConfigOptionFloats& operator=(const ConfigOption *opt) + ConfigOptionFloatsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; } +protected: + void serialize_single_value(std::ostringstream &ss, const double v) const { + if (std::isfinite(v)) + ss << v; + else if (std::isnan(v)) { + if (NULLABLE) + ss << "nil"; + else + std::runtime_error("Serializing NaN"); + } else + std::runtime_error("Serializing invalid number"); + } + static bool vectors_equal(const std::vector &v1, const std::vector &v2) { + if (NULLABLE) { + if (v1.size() != v2.size()) + return false; + for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2) + if (! ((std::isnan(*it1) && std::isnan(*it2)) || *it1 == *it2)) + return false; + return true; + } else + // Not supporting nullable values, the default vector compare is cheaper. + return v1 == v2; + } + private: friend class cereal::access; template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionFloats = ConfigOptionFloatsTempl; +using ConfigOptionFloatsNullable = ConfigOptionFloatsTempl; + class ConfigOptionInt : public ConfigOptionSingle { public: @@ -447,35 +574,45 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; -class ConfigOptionInts : public ConfigOptionVector +template +class ConfigOptionIntsTempl : public ConfigOptionVector { public: - ConfigOptionInts() : ConfigOptionVector() {} - explicit ConfigOptionInts(size_t n, int value) : ConfigOptionVector(n, value) {} - explicit ConfigOptionInts(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} + ConfigOptionIntsTempl() : ConfigOptionVector() {} + explicit ConfigOptionIntsTempl(size_t n, int value) : ConfigOptionVector(n, value) {} + explicit ConfigOptionIntsTempl(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} static ConfigOptionType static_type() { return coInts; } ConfigOptionType type() const override { return static_type(); } - ConfigOption* clone() const override { return new ConfigOptionInts(*this); } - ConfigOptionInts& operator=(const ConfigOption *opt) { this->set(opt); return *this; } - bool operator==(const ConfigOptionInts &rhs) const { return this->values == rhs.values; } + ConfigOption* clone() const override { return new ConfigOptionIntsTempl(*this); } + ConfigOptionIntsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; } + bool operator==(const ConfigOptionIntsTempl &rhs) const { return this->values == rhs.values; } + // Could a special "nil" value be stored inside the vector, indicating undefined value? + bool nullable() const override { return NULLABLE; } + // Special "nil" value to be stored into the vector if this->supports_nil(). + static int nil_value() { return std::numeric_limits::max(); } + // A scalar is nil, or all values of a vector are nil. + bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; } + bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); } - std::string serialize() const override { + std::string serialize() const override + { std::ostringstream ss; - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { - if (it - this->values.begin() != 0) ss << ","; - ss << *it; + for (const int &v : this->values) { + if (&v != &this->values.front()) + ss << ","; + serialize_single_value(ss, v); } return ss.str(); } - std::vector vserialize() const override + std::vector vserialize() const override { std::vector vv; vv.reserve(this->values.size()); - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { + for (const int v : this->values) { std::ostringstream ss; - ss << *it; + serialize_single_value(ss, v); vv.push_back(ss.str()); } return vv; @@ -488,19 +625,40 @@ public: std::istringstream is(str); std::string item_str; while (std::getline(is, item_str, ',')) { - std::istringstream iss(item_str); - int value; - iss >> value; - this->values.push_back(value); + boost::trim(item_str); + if (item_str == "nil") { + if (NULLABLE) + this->values.push_back(nil_value()); + else + std::runtime_error("Deserializing nil into a non-nullable object"); + } else { + std::istringstream iss(item_str); + int value; + iss >> value; + this->values.push_back(value); + } } return true; } private: + void serialize_single_value(std::ostringstream &ss, const int v) const { + if (v == nil_value()) { + if (NULLABLE) + ss << "nil"; + else + std::runtime_error("Serializing NaN"); + } else + ss << v; + } + friend class cereal::access; template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionInts = ConfigOptionIntsTempl; +using ConfigOptionIntsNullable = ConfigOptionIntsTempl; + class ConfigOptionString : public ConfigOptionSingle { public: @@ -544,6 +702,7 @@ public: ConfigOption* clone() const override { return new ConfigOptionStrings(*this); } ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; } + bool is_nil(size_t idx) const override { return false; } std::string serialize() const override { @@ -603,64 +762,61 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class(this)); } }; -class ConfigOptionPercents : public ConfigOptionFloats +template +class ConfigOptionPercentsTempl : public ConfigOptionFloatsTempl { public: - ConfigOptionPercents() : ConfigOptionFloats() {} - explicit ConfigOptionPercents(size_t n, double value) : ConfigOptionFloats(n, value) {} - explicit ConfigOptionPercents(std::initializer_list il) : ConfigOptionFloats(std::move(il)) {} + ConfigOptionPercentsTempl() : ConfigOptionFloatsTempl() {} + explicit ConfigOptionPercentsTempl(size_t n, double value) : ConfigOptionFloatsTempl(n, value) {} + explicit ConfigOptionPercentsTempl(std::initializer_list il) : ConfigOptionFloatsTempl(std::move(il)) {} + explicit ConfigOptionPercentsTempl(const std::vector& vec) : ConfigOptionFloatsTempl(vec) {} + explicit ConfigOptionPercentsTempl(std::vector&& vec) : ConfigOptionFloatsTempl(std::move(vec)) {} static ConfigOptionType static_type() { return coPercents; } ConfigOptionType type() const override { return static_type(); } - ConfigOption* clone() const override { return new ConfigOptionPercents(*this); } - ConfigOptionPercents& operator=(const ConfigOption *opt) { this->set(opt); return *this; } - bool operator==(const ConfigOptionPercents &rhs) const { return this->values == rhs.values; } + ConfigOption* clone() const override { return new ConfigOptionPercentsTempl(*this); } + ConfigOptionPercentsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; } + bool operator==(const ConfigOptionPercentsTempl &rhs) const { return this->values == rhs.values; } std::string serialize() const override { std::ostringstream ss; - for (const auto &v : this->values) { - if (&v != &this->values.front()) ss << ","; - ss << v << "%"; + for (const double &v : this->values) { + if (&v != &this->values.front()) + ss << ","; + this->serialize_single_value(ss, v); + if (! std::isnan(v)) + ss << "%"; } std::string str = ss.str(); return str; } - + std::vector vserialize() const override { std::vector vv; vv.reserve(this->values.size()); - for (const auto v : this->values) { + for (const double v : this->values) { std::ostringstream ss; - ss << v; - std::string sout = ss.str() + "%"; - vv.push_back(sout); + this->serialize_single_value(ss, v); + if (! std::isnan(v)) + ss << "%"; + vv.push_back(ss.str()); } return vv; } - bool deserialize(const std::string &str, bool append = false) override - { - if (! append) - this->values.clear(); - std::istringstream is(str); - std::string item_str; - while (std::getline(is, item_str, ',')) { - std::istringstream iss(item_str); - double value; - // don't try to parse the trailing % since it's optional - iss >> value; - this->values.push_back(value); - } - return true; - } + // The float's deserialize function shall ignore the trailing optional %. + // bool deserialize(const std::string &str, bool append = false) override; private: friend class cereal::access; - template void serialize(Archive &ar) { ar(cereal::base_class(this)); } + template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionPercents = ConfigOptionPercentsTempl; +using ConfigOptionPercentsNullable = ConfigOptionPercentsTempl; + class ConfigOptionFloatOrPercent : public ConfigOptionPercent { public: @@ -761,6 +917,7 @@ public: ConfigOption* clone() const override { return new ConfigOptionPoints(*this); } ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; } + bool is_nil(size_t idx) const override { return false; } std::string serialize() const override { @@ -887,18 +1044,29 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; -class ConfigOptionBools : public ConfigOptionVector +template +class ConfigOptionBoolsTempl : public ConfigOptionVector { public: - ConfigOptionBools() : ConfigOptionVector() {} - explicit ConfigOptionBools(size_t n, bool value) : ConfigOptionVector(n, (unsigned char)value) {} - explicit ConfigOptionBools(std::initializer_list il) { values.reserve(il.size()); for (bool b : il) values.emplace_back((unsigned char)b); } + ConfigOptionBoolsTempl() : ConfigOptionVector() {} + explicit ConfigOptionBoolsTempl(size_t n, bool value) : ConfigOptionVector(n, (unsigned char)value) {} + explicit ConfigOptionBoolsTempl(std::initializer_list il) { values.reserve(il.size()); for (bool b : il) values.emplace_back((unsigned char)b); } + explicit ConfigOptionBoolsTempl(std::initializer_list il) { values.reserve(il.size()); for (unsigned char b : il) values.emplace_back(b); } + explicit ConfigOptionBoolsTempl(const std::vector& vec) : ConfigOptionVector(vec) {} + explicit ConfigOptionBoolsTempl(std::vector&& vec) : ConfigOptionVector(std::move(vec)) {} static ConfigOptionType static_type() { return coBools; } ConfigOptionType type() const override { return static_type(); } - ConfigOption* clone() const override { return new ConfigOptionBools(*this); } - ConfigOptionBools& operator=(const ConfigOption *opt) { this->set(opt); return *this; } - bool operator==(const ConfigOptionBools &rhs) const { return this->values == rhs.values; } + ConfigOption* clone() const override { return new ConfigOptionBoolsTempl(*this); } + ConfigOptionBoolsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; } + bool operator==(const ConfigOptionBoolsTempl &rhs) const { return this->values == rhs.values; } + // Could a special "nil" value be stored inside the vector, indicating undefined value? + bool nullable() const override { return NULLABLE; } + // Special "nil" value to be stored into the vector if this->supports_nil(). + static unsigned char nil_value() { return std::numeric_limits::max(); } + // A scalar is nil, or all values of a vector are nil. + bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; } + bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); } bool& get_at(size_t i) { assert(! this->values.empty()); @@ -911,19 +1079,20 @@ public: std::string serialize() const override { std::ostringstream ss; - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { - if (it - this->values.begin() != 0) ss << ","; - ss << (*it ? "1" : "0"); - } + for (const unsigned char &v : this->values) { + if (&v != &this->values.front()) + ss << ","; + this->serialize_single_value(ss, v); + } return ss.str(); } std::vector vserialize() const override { std::vector vv; - for (std::vector::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { - std::ostringstream ss; - ss << (*it ? "1" : "0"); + for (const unsigned char v : this->values) { + std::ostringstream ss; + this->serialize_single_value(ss, v); vv.push_back(ss.str()); } return vv; @@ -936,16 +1105,37 @@ public: std::istringstream is(str); std::string item_str; while (std::getline(is, item_str, ',')) { - this->values.push_back(item_str.compare("1") == 0); + boost::trim(item_str); + if (item_str == "nil") { + if (NULLABLE) + this->values.push_back(nil_value()); + else + std::runtime_error("Deserializing nil into a non-nullable object"); + } else + this->values.push_back(item_str.compare("1") == 0); } return true; } +protected: + void serialize_single_value(std::ostringstream &ss, const unsigned char v) const { + if (v == nil_value()) { + if (NULLABLE) + ss << "nil"; + else + std::runtime_error("Serializing NaN"); + } else + ss << (v ? "1" : "0"); + } + private: friend class cereal::access; template void serialize(Archive &ar) { ar(cereal::base_class>(this)); } }; +using ConfigOptionBools = ConfigOptionBoolsTempl; +using ConfigOptionBoolsNullable = ConfigOptionBoolsTempl; + // Map from an enum integer value to an enum name. typedef std::vector t_config_enum_names; // Map from an enum name to an enum integer value. @@ -1096,6 +1286,8 @@ public: t_config_option_key opt_key; // What type? bool, int, string etc. ConfigOptionType type = coNone; + // If a type is nullable, then it accepts a "nil" value (scalar) or "nil" values (vector). + bool nullable = false; // Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor. Slic3r::clonable_ptr default_value; void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr(ptr); } @@ -1107,45 +1299,65 @@ public: ConfigOption* create_default_option() const; template ConfigOption* load_option_from_archive(Archive &archive) const { - switch (this->type) { - case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; } - case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); return opt; } - case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; } - case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); return opt; } - case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; } - case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); return opt; } - case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; } - case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; } - case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; } - case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; } - case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; } - case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; } - case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } - case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; } - case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; } - default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key); - } + if (this->nullable) { + switch (this->type) { + case coFloats: { auto opt = new ConfigOptionFloatsNullable(); archive(*opt); return opt; } + case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; } + case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); return opt; } + case coBools: { auto opt = new ConfigOptionBoolsNullable(); archive(*opt); return opt; } + default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown nullable option type for option ") + this->opt_key); + } + } else { + switch (this->type) { + case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; } + case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); return opt; } + case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; } + case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); return opt; } + case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; } + case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); return opt; } + case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; } + case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; } + case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; } + case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; } + case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; } + case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; } + case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } + case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; } + case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; } + default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key); + } + } } template ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const { - switch (this->type) { - case coFloat: archive(*static_cast(opt)); break; - case coFloats: archive(*static_cast(opt)); break; - case coInt: archive(*static_cast(opt)); break; - case coInts: archive(*static_cast(opt)); break; - case coString: archive(*static_cast(opt)); break; - case coStrings: archive(*static_cast(opt)); break; - case coPercent: archive(*static_cast(opt)); break; - case coPercents: archive(*static_cast(opt)); break; - case coFloatOrPercent: archive(*static_cast(opt)); break; - case coPoint: archive(*static_cast(opt)); break; - case coPoints: archive(*static_cast(opt)); break; - case coPoint3: archive(*static_cast(opt)); break; - case coBool: archive(*static_cast(opt)); break; - case coBools: archive(*static_cast(opt)); break; - case coEnum: archive(*static_cast(opt)); break; - default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key); - } + if (this->nullable) { + switch (this->type) { + case coFloats: archive(*static_cast(opt)); break; + case coInts: archive(*static_cast(opt)); break; + case coPercents: archive(*static_cast(opt));break; + case coBools: archive(*static_cast(opt)); break; + default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown nullable option type for option ") + this->opt_key); + } + } else { + switch (this->type) { + case coFloat: archive(*static_cast(opt)); break; + case coFloats: archive(*static_cast(opt)); break; + case coInt: archive(*static_cast(opt)); break; + case coInts: archive(*static_cast(opt)); break; + case coString: archive(*static_cast(opt)); break; + case coStrings: archive(*static_cast(opt)); break; + case coPercent: archive(*static_cast(opt)); break; + case coPercents: archive(*static_cast(opt)); break; + case coFloatOrPercent: archive(*static_cast(opt)); break; + case coPoint: archive(*static_cast(opt)); break; + case coPoints: archive(*static_cast(opt)); break; + case coPoint3: archive(*static_cast(opt)); break; + case coBool: archive(*static_cast(opt)); break; + case coBools: archive(*static_cast(opt)); break; + case coEnum: archive(*static_cast(opt)); break; + default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key); + } + } // Make the compiler happy, shut up the warnings. return nullptr; } @@ -1263,6 +1475,7 @@ public: protected: ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type); + ConfigOptionDef* add_nullable(const t_config_option_key &opt_key, ConfigOptionType type); }; // An abstract configuration store. @@ -1347,6 +1560,9 @@ public: void load(const boost::property_tree::ptree &tree); void save(const std::string &file) const; + // Set all the nullable values to nils. + void null_nullables(); + private: // Set a configuration value from a string. bool set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &str, bool append); @@ -1444,9 +1660,12 @@ public: return true; } + // Remove options with all nil values, those are optional and it does not help to hold them. + size_t remove_nil_options(); + // Allow DynamicConfig to be instantiated on ints own without a definition. // If the definition is not defined, the method requiring the definition will throw NoDefinitionException. - const ConfigDef* def() const override { return nullptr; }; + const ConfigDef* def() const override { return nullptr; } template T* opt(const t_config_option_key &opt_key, bool create = false) { return dynamic_cast(this->option(opt_key, create)); } template const T* opt(const t_config_option_key &opt_key) const diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 81880831f..bc3730026 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1829,25 +1829,12 @@ void GCode::apply_print_config(const PrintConfig &print_config) m_config.apply(print_config); } -void GCode::append_full_config(const Print& print, std::string& str) +void GCode::append_full_config(const Print &print, std::string &str) { - const StaticPrintConfig *configs[] = { static_cast(&print.config()), &print.default_object_config(), &print.default_region_config() }; - for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) { - const StaticPrintConfig *cfg = configs[i]; - for (const std::string &key : cfg->keys()) - if (key != "compatible_printers") - str += "; " + key + " = " + cfg->opt_serialize(key) + "\n"; - } - const DynamicConfig &full_config = print.placeholder_parser().config(); - for (const char *key : { - "print_settings_id", "filament_settings_id", "sla_print_settings_id", "sla_material_settings_id", "printer_settings_id", - "printer_model", "printer_variant", - "default_print_profile", "default_filament_profile", "default_sla_print_profile", "default_sla_material_profile", - "compatible_prints_condition_cummulative", "compatible_printers_condition_cummulative", "inherits_cummulative" }) { - const ConfigOption *opt = full_config.option(key); - if (opt != nullptr) - str += std::string("; ") + key + " = " + opt->serialize() + "\n"; - } + const DynamicPrintConfig &cfg = print.full_print_config(); + for (const std::string &key : cfg.keys()) + if (key != "compatible_prints" && key != "compatible_printers" && ! cfg.option(key)->is_nil()) + str += "; " + key + " = " + cfg.opt_serialize(key) + "\n"; } void GCode::set_extruders(const std::vector &extruder_ids) diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 6dfad1b8c..3c6b4afca 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -134,7 +134,7 @@ public: m_filpar[idx].cooling_final_speed = cooling_final_speed; } - m_filpar[idx].filament_area = (M_PI/4.f) * pow(filament_diameter, 2); // all extruders are assumed to have the same filament diameter at this point + m_filpar[idx].filament_area = float((M_PI/4.f) * pow(filament_diameter, 2)); // all extruders are assumed to have the same filament diameter at this point m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM if (max_volumetric_speed != 0.f) diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 2bfe9b745..c3ac22e96 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -62,7 +62,7 @@ namespace Slic3r { -PlaceholderParser::PlaceholderParser() +PlaceholderParser::PlaceholderParser(const DynamicConfig *external_config) : m_external_config(external_config) { this->set("version", std::string(SLIC3R_VERSION)); this->apply_env_variables(); @@ -94,14 +94,6 @@ void PlaceholderParser::update_timestamp(DynamicConfig &config) config.set_key_value("second", new ConfigOptionInt(timeinfo->tm_sec)); } -// Ignore this key by the placeholder parser. -static inline bool placeholder_parser_ignore(const ConfigDef *def, const std::string &opt_key) -{ - const ConfigOptionDef *opt_def = def->get(opt_key); - assert(opt_def != nullptr); - return (opt_def->multiline && boost::ends_with(opt_key, "_gcode")) || opt_key == "post_process"; -} - static inline bool opts_equal(const DynamicConfig &config_old, const DynamicConfig &config_new, const std::string &opt_key) { const ConfigOption *opt_old = config_old.option(opt_key); @@ -119,7 +111,7 @@ std::vector PlaceholderParser::config_diff(const DynamicPrintConfig const ConfigDef *def = rhs.def(); std::vector diff_keys; for (const t_config_option_key &opt_key : rhs.keys()) - if (! placeholder_parser_ignore(def, opt_key) && ! opts_equal(m_config, rhs, opt_key)) + if (! opts_equal(m_config, rhs, opt_key)) diff_keys.emplace_back(opt_key); return diff_keys; } @@ -135,8 +127,6 @@ bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs) const ConfigDef *def = rhs.def(); bool modified = false; for (const t_config_option_key &opt_key : rhs.keys()) { - if (placeholder_parser_ignore(def, opt_key)) - continue; if (! opts_equal(m_config, rhs, opt_key)) { // Store a copy of the config option. // Convert FloatOrPercent values to floats first. @@ -155,7 +145,6 @@ bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs) void PlaceholderParser::apply_only(const DynamicPrintConfig &rhs, const std::vector &keys) { for (const t_config_option_key &opt_key : keys) { - assert(! placeholder_parser_ignore(rhs.def(), opt_key)); // Store a copy of the config option. // Convert FloatOrPercent values to floats first. //FIXME there are some ratio_over chains, which end with empty ratio_with. @@ -167,6 +156,11 @@ void PlaceholderParser::apply_only(const DynamicPrintConfig &rhs, const std::vec } } +void PlaceholderParser::apply_config(DynamicPrintConfig &&rhs) +{ + m_config += std::move(rhs); +} + void PlaceholderParser::apply_env_variables() { for (char** env = environ; *env; ++ env) { @@ -608,6 +602,7 @@ namespace client } struct MyContext { + const DynamicConfig *external_config = nullptr; const DynamicConfig *config = nullptr; const DynamicConfig *config_override = nullptr; size_t current_extruder_id = 0; @@ -628,6 +623,8 @@ namespace client opt = config_override->option(opt_key); if (opt == nullptr) opt = config->option(opt_key); + if (opt == nullptr && external_config != nullptr) + opt = external_config->option(opt_key); return opt; } @@ -1255,6 +1252,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const { client::MyContext context; + context.external_config = this->external_config(); context.config = &this->config(); context.config_override = config_override; context.current_extruder_id = current_extruder_id; @@ -1266,8 +1264,8 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override) { client::MyContext context; - context.config = &config; - context.config_override = config_override; + context.config = &config; + context.config_override = config_override; // Let the macro processor parse just a boolean expression, not the full macro language. context.just_boolean_expression = true; return process_macro(templ, context) == "true"; diff --git a/src/libslic3r/PlaceholderParser.hpp b/src/libslic3r/PlaceholderParser.hpp index 22c790e6b..14fdc5c28 100644 --- a/src/libslic3r/PlaceholderParser.hpp +++ b/src/libslic3r/PlaceholderParser.hpp @@ -12,13 +12,14 @@ namespace Slic3r { class PlaceholderParser { public: - PlaceholderParser(); + PlaceholderParser(const DynamicConfig *external_config = nullptr); // Return a list of keys, which should be changed in m_config from rhs. // This contains keys, which are found in rhs, but not in m_config. std::vector config_diff(const DynamicPrintConfig &rhs); // Return true if modified. bool apply_config(const DynamicPrintConfig &config); + void apply_config(DynamicPrintConfig &&config); // To be called on the values returned by PlaceholderParser::config_diff(). // The keys should already be valid. void apply_only(const DynamicPrintConfig &config, const std::vector &keys); @@ -35,6 +36,8 @@ public: DynamicConfig& config_writable() { return m_config; } const DynamicConfig& config() const { return m_config; } const ConfigOption* option(const std::string &key) const { return m_config.option(key); } + // External config is not owned by PlaceholderParser. It has a lowest priority when looking up an option. + const DynamicConfig* external_config() const { return m_external_config; } // Fill in the template using a macro processing language. // Throws std::runtime_error on syntax or runtime error. @@ -50,7 +53,9 @@ public: void update_timestamp() { update_timestamp(m_config); } private: - DynamicConfig m_config; + // config has a higher priority than external_config when looking up a symbol. + DynamicConfig m_config; + const DynamicConfig *m_external_config; }; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 5702f49e3..c423afeb9 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -485,25 +485,82 @@ bool layer_height_ranges_equal(const t_layer_config_ranges &lr1, const t_layer_c return true; } -Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &config_in) +// Collect diffs of configuration values at various containers, +// resolve the filament rectract overrides of extruder retract values. +void Print::config_diffs( + const DynamicPrintConfig &new_full_config, + t_config_option_keys &print_diff, t_config_option_keys &object_diff, t_config_option_keys ®ion_diff, + t_config_option_keys &full_config_diff, + DynamicPrintConfig &placeholder_parser_overrides, + DynamicPrintConfig &filament_overrides) const +{ + // Collect changes to print config, account for overrides of extruder retract values by filament presets. + { + const std::vector &extruder_retract_keys = print_config_def.extruder_retract_keys(); + const std::string filament_prefix = "filament_"; + for (const t_config_option_key &opt_key : m_config.keys()) { + const ConfigOption *opt_old = m_config.option(opt_key); + assert(opt_old != nullptr); + const ConfigOption *opt_new = new_full_config.option(opt_key); + // assert(opt_new != nullptr); + if (opt_new == nullptr) + //FIXME This may happen when executing some test cases. + continue; + const ConfigOption *opt_new_filament = std::binary_search(extruder_retract_keys.begin(), extruder_retract_keys.end(), opt_key) ? new_full_config.option(filament_prefix + opt_key) : nullptr; + if (opt_new_filament != nullptr && ! opt_new_filament->is_nil()) { + // An extruder retract override is available at some of the filament presets. + if (*opt_old != *opt_new || opt_new->overriden_by(opt_new_filament)) { + auto opt_copy = opt_new->clone(); + opt_copy->apply_override(opt_new_filament); + if (*opt_old == *opt_copy) + delete opt_copy; + else { + filament_overrides.set_key_value(opt_key, opt_copy); + print_diff.emplace_back(opt_key); + } + } + } else if (*opt_new != *opt_old) + print_diff.emplace_back(opt_key); + } + } + // Collect changes to object and region configs. + object_diff = m_default_object_config.diff(new_full_config); + region_diff = m_default_region_config.diff(new_full_config); + // Prepare for storing of the full print config into new_full_config to be exported into the G-code and to be used by the PlaceholderParser. + // As the PlaceholderParser does not interpret the FloatOrPercent values itself, these values are stored into the PlaceholderParser converted to floats. + for (const t_config_option_key &opt_key : new_full_config.keys()) { + const ConfigOption *opt_old = m_full_print_config.option(opt_key); + const ConfigOption *opt_new = new_full_config.option(opt_key); + if (opt_old == nullptr || *opt_new != *opt_old) + full_config_diff.emplace_back(opt_key); + if (opt_new->type() == coFloatOrPercent) { + // The m_placeholder_parser is never modified by the background processing, GCode.cpp/hpp makes a copy. + const ConfigOption *opt_old_pp = this->placeholder_parser().config().option(opt_key); + double new_value = new_full_config.get_abs_value(opt_key); + if (opt_old_pp == nullptr || static_cast(opt_old_pp)->value != new_value) + placeholder_parser_overrides.set_key_value(opt_key, new ConfigOptionFloat(new_value)); + } + } +} + +Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_config) { #ifdef _DEBUG check_model_ids_validity(model); #endif /* _DEBUG */ - // Make a copy of the config, normalize it. - DynamicPrintConfig config(config_in); - config.option("print_settings_id", true); - config.option("filament_settings_id", true); - config.option("printer_settings_id", true); - config.normalize(); - // Collect changes to print config. - t_config_option_keys print_diff = m_config.diff(config); - t_config_option_keys object_diff = m_default_object_config.diff(config); - t_config_option_keys region_diff = m_default_region_config.diff(config); - t_config_option_keys placeholder_parser_diff = this->placeholder_parser().config_diff(config); + // Normalize the config. + new_full_config.option("print_settings_id", true); + new_full_config.option("filament_settings_id", true); + new_full_config.option("printer_settings_id", true); + new_full_config.normalize(); - // Do not use the ApplyStatus as we will use the max function when updating apply_status. + // Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles. + t_config_option_keys print_diff, object_diff, region_diff, full_config_diff; + DynamicPrintConfig placeholder_parser_overrides, filament_overrides; + this->config_diffs(new_full_config, print_diff, object_diff, region_diff, full_config_diff, placeholder_parser_overrides, filament_overrides); + + // Do not use the ApplyStatus as we will use the max function when updating apply_status. unsigned int apply_status = APPLY_STATUS_UNCHANGED; auto update_apply_status = [&apply_status](bool invalidated) { apply_status = std::max(apply_status, invalidated ? APPLY_STATUS_INVALIDATED : APPLY_STATUS_CHANGED); }; @@ -516,24 +573,25 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co // The following call may stop the background processing. if (! print_diff.empty()) update_apply_status(this->invalidate_state_by_config_options(print_diff)); + // Apply variables to placeholder parser. The placeholder parser is used by G-code export, // which should be stopped if print_diff is not empty. - if (! placeholder_parser_diff.empty()) { + if (! full_config_diff.empty() || ! placeholder_parser_overrides.empty()) { update_apply_status(this->invalidate_step(psGCodeExport)); - PlaceholderParser &pp = this->placeholder_parser(); - pp.apply_only(config, placeholder_parser_diff); + m_placeholder_parser.apply_config(std::move(placeholder_parser_overrides)); // Set the profile aliases for the PrintBase::output_filename() - pp.set("print_preset", config.option("print_settings_id")->clone()); - pp.set("filament_preset", config.option("filament_settings_id")->clone()); - pp.set("printer_preset", config.option("printer_settings_id")->clone()); + m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone()); + m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone()); + m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone()); + // It is also safe to change m_config now after this->invalidate_state_by_config_options() call. + m_config.apply_only(new_full_config, print_diff, true); + m_config.apply(filament_overrides); + // Handle changes to object config defaults + m_default_object_config.apply_only(new_full_config, object_diff, true); + // Handle changes to regions config defaults + m_default_region_config.apply_only(new_full_config, region_diff, true); + m_full_print_config = std::move(new_full_config); } - - // It is also safe to change m_config now after this->invalidate_state_by_config_options() call. - m_config.apply_only(config, print_diff, true); - // Handle changes to object config defaults - m_default_object_config.apply_only(config, object_diff, true); - // Handle changes to regions config defaults - m_default_region_config.apply_only(config, region_diff, true); class LayerRanges { @@ -545,9 +603,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co m_ranges.reserve(in.size()); // Input ranges are sorted lexicographically. First range trims the other ranges. coordf_t last_z = 0; - for (const std::pair &range : in) { -// for (auto &range : in) { - if (range.first.second > last_z) { + for (const std::pair &range : in) + if (range.first.second > last_z) { coordf_t min_z = std::max(range.first.first, 0.); if (min_z > last_z + EPSILON) { m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr); @@ -559,7 +616,6 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co last_z = range.first.second; } } - } if (m_ranges.empty()) m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr); else if (m_ranges.back().second == nullptr) @@ -1707,9 +1763,9 @@ void Print::_make_wipe_tower() (float)m_config.filament_cooling_initial_speed.get_at(i), (float)m_config.filament_cooling_final_speed.get_at(i), m_config.filament_ramming_parameters.get_at(i), - m_config.filament_max_volumetric_speed.get_at(i), - m_config.nozzle_diameter.get_at(i), - m_config.filament_diameter.get_at(i)); + (float)m_config.filament_max_volumetric_speed.get_at(i), + (float)m_config.nozzle_diameter.get_at(i), + (float)m_config.filament_diameter.get_at(i)); m_wipe_tower_data.priming = Slic3r::make_unique>( wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); @@ -1791,47 +1847,7 @@ std::string Print::output_filename(const std::string &filename_base) const DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders(); return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config); } -/* -// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes -// and removing spaces. -static std::string short_time(const std::string &time) -{ - // Parse the dhms time format. - int days = 0; - int hours = 0; - int minutes = 0; - int seconds = 0; - if (time.find('d') != std::string::npos) - ::sscanf(time.c_str(), "%dd %dh %dm %ds", &days, &hours, &minutes, &seconds); - else if (time.find('h') != std::string::npos) - ::sscanf(time.c_str(), "%dh %dm %ds", &hours, &minutes, &seconds); - else if (time.find('m') != std::string::npos) - ::sscanf(time.c_str(), "%dm %ds", &minutes, &seconds); - else if (time.find('s') != std::string::npos) - ::sscanf(time.c_str(), "%ds", &seconds); - // Round to full minutes. - if (days + hours + minutes > 0 && seconds >= 30) { - if (++ minutes == 60) { - minutes = 0; - if (++ hours == 24) { - hours = 0; - ++ days; - } - } - } - // Format the dhm time. - char buffer[64]; - if (days > 0) - ::sprintf(buffer, "%dd%dh%dm", days, hours, minutes); - else if (hours > 0) - ::sprintf(buffer, "%dh%dm", hours, minutes); - else if (minutes > 0) - ::sprintf(buffer, "%dm", minutes); - else - ::sprintf(buffer, "%ds", seconds); - return buffer; -} -*/ + DynamicConfig PrintStatistics::config() const { DynamicConfig config; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 368bf4ee8..b6d7b678d 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -296,7 +296,7 @@ public: void clear() override; bool empty() const override { return m_objects.empty(); } - ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override; + ApplyStatus apply(const Model &model, DynamicPrintConfig config) override; void process() override; // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file. @@ -368,6 +368,13 @@ protected: bool invalidate_step(PrintStep step); private: + void config_diffs( + const DynamicPrintConfig &new_full_config, + t_config_option_keys &print_diff, t_config_option_keys &object_diff, t_config_option_keys ®ion_diff, + t_config_option_keys &full_config_diff, + DynamicPrintConfig &placeholder_parser_overrides, + DynamicPrintConfig &filament_overrides) const; + bool invalidate_state_by_config_options(const std::vector &opt_keys); void _make_skirt(); diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index d84d492a0..aebc87904 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -217,7 +217,7 @@ protected: class PrintBase { public: - PrintBase() { this->restart(); } + PrintBase() : m_placeholder_parser(&m_full_print_config) { this->restart(); } inline virtual ~PrintBase() {} virtual PrinterTechnology technology() const noexcept = 0; @@ -240,7 +240,7 @@ public: // Some data was changed, which in turn invalidated already calculated steps. APPLY_STATUS_INVALIDATED, }; - virtual ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) = 0; + virtual ApplyStatus apply(const Model &model, DynamicPrintConfig config) = 0; const Model& model() const { return m_model; } struct TaskParams { @@ -316,7 +316,7 @@ public: virtual bool finished() const = 0; const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; } - PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } + const DynamicPrintConfig& full_print_config() const { return m_full_print_config; } virtual std::string output_filename(const std::string &filename_base = std::string()) const = 0; // If the filename_base is set, it is used as the input for the template processing. In that case the path is expected to be the directory (may be empty). @@ -341,6 +341,8 @@ protected: void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const; Model m_model; + DynamicPrintConfig m_full_print_config; + PlaceholderParser m_placeholder_parser; private: tbb::atomic m_cancel_status; @@ -354,8 +356,6 @@ private: // The mutex will be used to guard the worker thread against entering a stage // while the data influencing the stage is modified. mutable tbb::mutex m_state_mutex; - - PlaceholderParser m_placeholder_parser; }; template diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8e091fb80..304f6f749 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -29,6 +29,7 @@ PrintConfigDef::PrintConfigDef() this->init_common_params(); assign_printer_technology_to_unknown(this->options, ptAny); this->init_fff_params(); + this->init_extruder_retract_keys(); assign_printer_technology_to_unknown(this->options, ptFFF); this->init_sla_params(); assign_printer_technology_to_unknown(this->options, ptSLA); @@ -2238,6 +2239,48 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0)); + + // Declare retract values for filament profile, overriding the printer's extruder profile. + for (const char *opt_key : { + // floats + "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", + // bools + "retract_layer_change", "wipe", + // percents + "retract_before_wipe"}) { + auto it_opt = options.find(opt_key); + assert(it_opt != options.end()); + def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type); + def->label = it_opt->second.label; + def->full_label = it_opt->second.full_label; + def->tooltip = it_opt->second.tooltip; + def->sidetext = it_opt->second.sidetext; + def->mode = it_opt->second.mode; + switch (def->type) { + case coFloats : def->set_default_value(new ConfigOptionFloatsNullable (static_cast(it_opt->second.default_value.get())->values)); break; + case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast(it_opt->second.default_value.get())->values)); break; + case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast(it_opt->second.default_value.get())->values)); break; + default: assert(false); + } + } +} + +void PrintConfigDef::init_extruder_retract_keys() +{ + m_extruder_retract_keys = { + "deretract_speed", + "retract_before_travel", + "retract_before_wipe", + "retract_layer_change", + "retract_length", + "retract_lift", + "retract_lift_above", + "retract_lift_below", + "retract_restart_extra", + "retract_speed", + "wipe" + }; + assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end())); } void PrintConfigDef::init_sla_params() @@ -2997,7 +3040,7 @@ std::string FullPrintConfig::validate() } case coFloats: case coPercents: - for (double v : static_cast(opt)->values) + for (double v : static_cast*>(opt)->values) if (v < optdef->min || v > optdef->max) { out_of_range = true; break; @@ -3010,7 +3053,7 @@ std::string FullPrintConfig::validate() break; } case coInts: - for (int v : static_cast(opt)->values) + for (int v : static_cast*>(opt)->values) if (v < optdef->min || v > optdef->max) { out_of_range = true; break; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5731bef00..f2d0775fa 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -185,10 +185,18 @@ public: static void handle_legacy(t_config_option_key &opt_key, std::string &value); + // Options defining the extruder retract properties. These keys are sorted lexicographically. + // The extruder retract keys could be overidden by the same values defined at the Filament level + // (then the key is further prefixed with the "filament_" prefix). + const std::vector& extruder_retract_keys() const { return m_extruder_retract_keys; } + private: void init_common_params(); void init_fff_params(); + void init_extruder_retract_keys(); void init_sla_params(); + + std::vector m_extruder_retract_keys; }; // The one and only global definition of SLic3r configuration options. diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 5669307ac..45f8a0c83 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -145,14 +145,13 @@ static std::vector sla_instances(const ModelObject &mo return instances; } -SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConfig &config_in) +SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig config) { #ifdef _DEBUG check_model_ids_validity(model); #endif /* _DEBUG */ - // Make a copy of the config, normalize it. - DynamicPrintConfig config(config_in); + // Normalize the config. config.option("sla_print_settings_id", true); config.option("sla_material_settings_id", true); config.option("printer_settings_id", true); @@ -162,7 +161,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf t_config_option_keys printer_diff = m_printer_config.diff(config); t_config_option_keys material_diff = m_material_config.diff(config); t_config_option_keys object_diff = m_default_object_config.diff(config); - t_config_option_keys placeholder_parser_diff = this->placeholder_parser().config_diff(config); + t_config_option_keys placeholder_parser_diff = m_placeholder_parser.config_diff(config); // Do not use the ApplyStatus as we will use the max function when updating apply_status. unsigned int apply_status = APPLY_STATUS_UNCHANGED; @@ -187,12 +186,11 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf // only to generate the output file name. if (! placeholder_parser_diff.empty()) { // update_apply_status(this->invalidate_step(slapsRasterize)); - PlaceholderParser &pp = this->placeholder_parser(); - pp.apply_config(config); + m_placeholder_parser.apply_config(config); // Set the profile aliases for the PrintBase::output_filename() - pp.set("print_preset", config.option("sla_print_settings_id")->clone()); - pp.set("material_preset", config.option("sla_material_settings_id")->clone()); - pp.set("printer_preset", config.option("printer_settings_id")->clone()); + m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone()); + m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone()); + m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone()); } // It is also safe to change m_config now after this->invalidate_state_by_config_options() call. @@ -459,6 +457,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf check_model_ids_equal(m_model, model); #endif /* _DEBUG */ + m_full_print_config = std::move(config); return static_cast(apply_status); } diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index c4e58ab39..e8cdac1b8 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -349,7 +349,7 @@ public: void clear() override; bool empty() const override { return m_objects.empty(); } - ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override; + ApplyStatus apply(const Model &model, DynamicPrintConfig config) override; void set_task(const TaskParams ¶ms) override; void process() override; void finalize() override; diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index ad58d9482..d2c76366b 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -106,6 +106,9 @@ void CopyrightsDialog::fill_entries() "2001-2016 Expat maintainers" , "http://www.libexpat.org/" }, { "AVRDUDE" , "2018 Free Software Foundation, Inc." , "http://savannah.nongnu.org/projects/avrdude" }, { "Shinyprofiler" , "2007-2010 Aidin Abedi" , "http://code.google.com/p/shinyprofiler/" }, + { "Real-Time DXT1/DXT5 C compression library" + , "Based on original by fabian \"ryg\" giesen v1.04. " + "Custom version, modified by Yann Collet" , "https://github.com/Cyan4973/RygsDXTc" }, { "Icons for STL and GCODE files." , "Akira Yasuda" , "http://3dp0.com/icons-for-stl-and-gcode/" } }; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index db935cc05..39fa9c54b 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -136,6 +136,8 @@ bool Field::is_matched(const std::string& string, const std::string& pattern) return std::regex_match(string, regex_pattern); } +static wxString na_value() { return _(L("N/A")); } + void Field::get_value_by_opt_type(wxString& str) { switch (m_opt.type) { @@ -165,7 +167,9 @@ void Field::get_value_by_opt_type(wxString& str) val = 0.0; else { - if (!str.ToCDouble(&val)) + if (m_opt.nullable && str == na_value()) + val = ConfigOptionFloatsNullable::nil_value(); + else if (!str.ToCDouble(&val)) { show_error(m_parent, _(L("Invalid numeric input."))); set_value(double_to_string(val), true); @@ -256,6 +260,7 @@ void TextCtrl::BUILD() { m_opt.default_value->getFloat() : m_opt.get_default_value()->get_at(m_opt_idx); text_value = double_to_string(val); + m_last_meaningful_value = text_value; break; } case coString: @@ -325,24 +330,7 @@ void TextCtrl::BUILD() { } propagate_value(); }), temp->GetId()); - /* - temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) - { -#ifdef __WXGTK__ - if (bChangedValueEvent) -#endif //__WXGTK__ - if(is_defined_input_value()) - on_change_field(); - }), temp->GetId()); -#ifdef __WXGTK__ - // to correct value updating on GTK we should: - // call on_change_field() on wxEVT_KEY_UP instead of wxEVT_TEXT - // and prevent value updating on wxEVT_KEY_DOWN - temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this); - temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this); -#endif //__WXGTK__ -*/ // select all text using Ctrl+A temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) { @@ -355,14 +343,70 @@ void TextCtrl::BUILD() { window = dynamic_cast(temp); } +bool TextCtrl::value_was_changed() +{ + if (m_value.empty()) + return true; + + boost::any val = m_value; + wxString ret_str = static_cast(window)->GetValue(); + // update m_value! + get_value_by_opt_type(ret_str); + + switch (m_opt.type) { + case coInt: + return boost::any_cast(m_value) != boost::any_cast(val); + case coPercent: + case coPercents: + case coFloats: + case coFloat: { + if (m_opt.nullable && std::isnan(boost::any_cast(m_value)) && + std::isnan(boost::any_cast(val))) + return false; + return boost::any_cast(m_value) != boost::any_cast(val); + } + case coString: + case coStrings: + case coFloatOrPercent: + return boost::any_cast(m_value) != boost::any_cast(val); + default: + return true; + } +} + void TextCtrl::propagate_value() { - if (is_defined_input_value(window, m_opt.type)) + if (is_defined_input_value(window, m_opt.type) && value_was_changed()) on_change_field(); else on_kill_focus(); } +void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) { + m_disable_change_event = !change_event; + if (m_opt.nullable) { + const bool m_is_na_val = boost::any_cast(value) == na_value(); + if (!m_is_na_val) + m_last_meaningful_value = value; + dynamic_cast(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast(value)); + } + else + dynamic_cast(window)->SetValue(boost::any_cast(value)); + m_disable_change_event = false; +} + +void TextCtrl::set_last_meaningful_value() +{ + dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value)); + propagate_value(); +} + +void TextCtrl::set_na_value() +{ + dynamic_cast(window)->SetValue(na_value()); + propagate_value(); +} + boost::any& TextCtrl::get_value() { wxString ret_str = static_cast(window)->GetValue(); @@ -409,6 +453,8 @@ void CheckBox::BUILD() { m_opt.get_default_value()->get_at(m_opt_idx) : false; + m_last_meaningful_value = static_cast(check_value); + // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -416,7 +462,10 @@ void CheckBox::BUILD() { temp->SetValue(check_value); if (m_opt.readonly) temp->Disable(); - temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); + temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { + m_is_na_val = false; + on_change_field(); + }), temp->GetId()); temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); @@ -424,6 +473,38 @@ void CheckBox::BUILD() { window = dynamic_cast(temp); } +void CheckBox::set_value(const boost::any& value, bool change_event) +{ + m_disable_change_event = !change_event; + if (m_opt.nullable) { + m_is_na_val = boost::any_cast(value) == ConfigOptionBoolsNullable::nil_value(); + if (!m_is_na_val) + m_last_meaningful_value = value; + dynamic_cast(window)->SetValue(m_is_na_val ? false : boost::any_cast(value) != 0); + } + else + dynamic_cast(window)->SetValue(boost::any_cast(value)); + m_disable_change_event = false; +} + +void CheckBox::set_last_meaningful_value() +{ + if (m_opt.nullable) { + m_is_na_val = false; + dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value) != 0); + on_change_field(); + } +} + +void CheckBox::set_na_value() +{ + if (m_opt.nullable) { + m_is_na_val = true; + dynamic_cast(window)->SetValue(false); + on_change_field(); + } +} + boost::any& CheckBox::get_value() { // boost::any m_value; @@ -431,7 +512,7 @@ boost::any& CheckBox::get_value() if (m_opt.type == coBool) m_value = static_cast(value); else - m_value = static_cast(value); + m_value = m_is_na_val ? ConfigOptionBoolsNullable::nil_value() : static_cast(value); return m_value; } diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 990c40e6f..6c16f90f2 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -123,6 +123,8 @@ public: /// subclasses should overload with a specific version /// Postcondition: Method does not fire the on_change event. virtual void set_value(const boost::any& value, bool change_event) = 0; + virtual void set_last_meaningful_value() {} + virtual void set_na_value() {} /// Gets a boost::any representing this control. /// subclasses should overload with a specific version @@ -247,6 +249,8 @@ protected: // current value boost::any m_value; + // last maeningful value + boost::any m_last_meaningful_value; int m_em_unit; @@ -277,6 +281,7 @@ public: ~TextCtrl() {} void BUILD(); + bool value_was_changed(); // Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER void propagate_value(); wxWindow* window {nullptr}; @@ -286,11 +291,9 @@ public: dynamic_cast(window)->SetValue(wxString(value)); m_disable_change_event = false; } - virtual void set_value(const boost::any& value, bool change_event = false) { - m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(boost::any_cast(value)); - m_disable_change_event = false; - } + virtual void set_value(const boost::any& value, bool change_event = false) override; + virtual void set_last_meaningful_value() override; + virtual void set_na_value() override; boost::any& get_value() override; @@ -303,6 +306,7 @@ public: class CheckBox : public Field { using Field::Field; + bool m_is_na_val {false}; public: CheckBox(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} @@ -316,11 +320,9 @@ public: dynamic_cast(window)->SetValue(value); m_disable_change_event = false; } - void set_value(const boost::any& value, bool change_event = false) { - m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(boost::any_cast(value)); - m_disable_change_event = false; - } + void set_value(const boost::any& value, bool change_event = false) override; + void set_last_meaningful_value() override; + void set_na_value() override; boost::any& get_value() override; void msw_rescale() override; diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index f3421f150..516f8b934 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -27,10 +27,13 @@ namespace GUI { void GLTexture::Compressor::reset() { - // force compression completion, if any - m_abort_compressing = true; - // wait for compression completion, if any - while (m_is_compressing) {} + if (m_is_compressing) + { + // force compression completion, if any + m_abort_compressing = true; + // wait for compression completion, if any + while (m_is_compressing) {} + } m_levels.clear(); } @@ -42,8 +45,6 @@ void GLTexture::Compressor::add_level(unsigned int w, unsigned int h, const std: void GLTexture::Compressor::start_compressing() { - m_is_compressing = true; - m_abort_compressing = false; std::thread t(&GLTexture::Compressor::compress, this); t.detach(); } @@ -97,6 +98,9 @@ void GLTexture::Compressor::compress() { // reference: https://github.com/Cyan4973/RygsDXTc + m_is_compressing = true; + m_abort_compressing = false; + for (Level& level : m_levels) { if (m_abort_compressing) diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 7fc5b8fcf..ec362944d 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -32,6 +32,7 @@ namespace GUI { public: explicit Compressor(GLTexture& texture) : m_texture(texture), m_is_compressing(false), m_abort_compressing(false) {} + ~Compressor() { reset(); } void reset(); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 8f41ed5a3..826f2d6fc 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -148,6 +148,13 @@ void config_wizard(int reason) void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/) { try{ + + if (config.def()->get(opt_key)->type == coBools && config.def()->get(opt_key)->nullable) { + ConfigOptionBoolsNullable* vec_new = new ConfigOptionBoolsNullable{ boost::any_cast(value) }; + config.option(opt_key)->set_at(vec_new, opt_index, 0); + return; + } + switch (config.def()->get(opt_key)->type) { case coFloatOrPercent:{ std::string str = boost::any_cast(value); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index bbb7d7115..9602bf4f7 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2843,7 +2843,7 @@ void ObjectList::update_selections_on_canvas() else { mode = Selection::Instance; - single_selection = false; + single_selection &= (obj_idx != selection.get_object_idx()); std::vector idxs = selection.get_volume_idxs_from_object(obj_idx); volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end()); } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index a4aa3c6d8..2bbf11170 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -210,6 +210,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width); auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW); btn->SetToolTip(wxString::Format(_(L("Toggle %c axis mirroring")), (int)label)); + btn->SetBitmapDisabled_(m_mirror_bitmap_hidden); m_mirror_buttons[axis_idx].first = btn; m_mirror_buttons[axis_idx].second = mbShown; @@ -286,6 +287,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(btn, wxBU_EXACTFIT); btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Reset scale"))); change_scale_value(0, 100.); change_scale_value(1, 100.); change_scale_value(2, 100.); @@ -323,7 +325,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL); selection.synchronize_unselected_volumes(); // Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing. - canvas->do_rotate(L("Set Rotation")); + canvas->do_rotate(L("Reset Rotation")); UpdateAndShow(true); }); @@ -350,6 +352,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : const Geometry::Transformation& instance_trafo = volume->get_instance_transformation(); Vec3d diff = m_cache.position - instance_trafo.get_matrix(true).inverse() * Vec3d(0., 0., get_volume_min_z(volume)); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Drop to bed"))); change_position_value(0, diff.x()); change_position_value(1, diff.y()); change_position_value(2, diff.z()); @@ -646,13 +649,13 @@ void ObjectManipulation::update_mirror_buttons_visibility() wxGetApp().CallAfter([this, new_states]{ for (int i=0; i<3; ++i) { if (new_states[i] != m_mirror_buttons[i].second) { - const wxBitmap* bmp; + const ScalableBitmap* bmp; switch (new_states[i]) { - case mbHidden : bmp = &m_mirror_bitmap_hidden.bmp(); m_mirror_buttons[i].first->Enable(false); break; - case mbShown : bmp = &m_mirror_bitmap_off.bmp(); m_mirror_buttons[i].first->Enable(true); break; - case mbActive : bmp = &m_mirror_bitmap_on.bmp(); m_mirror_buttons[i].first->Enable(true); break; + case mbHidden : bmp = &m_mirror_bitmap_hidden; m_mirror_buttons[i].first->Enable(false); break; + case mbShown : bmp = &m_mirror_bitmap_off; m_mirror_buttons[i].first->Enable(true); break; + case mbActive : bmp = &m_mirror_bitmap_on; m_mirror_buttons[i].first->Enable(true); break; } - m_mirror_buttons[i].first->SetBitmap(*bmp); + m_mirror_buttons[i].first->SetBitmap_(*bmp); m_mirror_buttons[i].second = new_states[i]; } } @@ -925,6 +928,9 @@ void ObjectManipulation::msw_rescale() m_reset_rotation_button->msw_rescale(); m_drop_to_bed_button->msw_rescale(); + for (int id = 0; id < 3; ++id) + m_mirror_buttons[id].first->msw_rescale(); + get_og()->msw_rescale(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 8929bd5dc..19b0c791c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -900,6 +900,10 @@ RENDER_AGAIN: ImGui::SameLine(diameter_slider_left); ImGui::PushItemWidth(window_width - diameter_slider_left); + // Following is a nasty way to: + // - save the initial value of the slider before one starts messing with it + // - keep updating the head radius during sliding so it is continuosly refreshed in 3D scene + // - take correct undo/redo snapshot after the user is done with moving the slider float initial_value = m_new_point_head_diameter; ImGui::SliderFloat("", &m_new_point_head_diameter, 0.1f, diameter_upper_cap, "%.1f"); if (ImGui::IsItemClicked()) { @@ -960,20 +964,35 @@ RENDER_AGAIN: float density = static_cast(opts[0])->value; float minimal_point_distance = static_cast(opts[1])->value; - bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm"); - if (value_changed) - m_model_object->config.opt("support_points_minimal_distance", true)->value = minimal_point_distance; + ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm"); + bool slider_clicked = ImGui::IsItemClicked(); // someone clicked the slider + bool slider_edited = ImGui::IsItemEdited(); // someone is dragging the slider + bool slider_released = ImGui::IsItemDeactivatedAfterEdit(); // someone has just released the slider m_imgui->text(m_desc.at("points_density")); ImGui::SameLine(settings_sliders_left); - if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) { - value_changed = true; + ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%"); + slider_clicked |= ImGui::IsItemClicked(); + slider_edited |= ImGui::IsItemEdited(); + slider_released |= ImGui::IsItemDeactivatedAfterEdit(); + + if (slider_clicked) { // stash the values of the settings so we know what to revert to after undo + m_minimal_point_distance_stash = minimal_point_distance; + m_density_stash = density; + } + if (slider_edited) { + m_model_object->config.opt("support_points_minimal_distance", true)->value = minimal_point_distance; m_model_object->config.opt("support_points_density_relative", true)->value = (int)density; } - - if (value_changed) // Update side panel + if (slider_released) { + m_model_object->config.opt("support_points_minimal_distance", true)->value = m_minimal_point_distance_stash; + m_model_object->config.opt("support_points_density_relative", true)->value = (int)m_density_stash; + wxGetApp().plater()->take_snapshot(_(L("Support parameter change"))); + m_model_object->config.opt("support_points_minimal_distance", true)->value = minimal_point_distance; + m_model_object->config.opt("support_points_density_relative", true)->value = (int)density; wxGetApp().obj_list()->update_and_show_object_settings_item(); + } bool generate = m_imgui->button(m_desc.at("auto_generate")); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 99184a90d..fb312e664 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -107,7 +107,8 @@ private: float m_new_point_head_diameter; // Size of a new point. CacheEntry m_point_before_drag; // undo/redo - so we know what state was edited float m_old_point_head_diameter = 0.; // the same - float m_minimal_point_distance = 20.f; + float m_minimal_point_distance_stash = 0.f; // and again + float m_density_stash = 0.f; // and again mutable std::vector m_editing_cache; // a support point and whether it is currently selected std::vector m_normal_cache; // to restore after discarding changes or undo/redo diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index e1978e60d..b1c000ceb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -108,11 +108,15 @@ public: ar(m_current); GLGizmoBase* curr = get_current(); - if (curr != nullptr) - { - curr->set_state(GLGizmoBase::On); - curr->load(ar); - } + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { + GLGizmoBase* gizmo = it->second; + if (gizmo != nullptr) { + gizmo->set_hover_id(-1); + gizmo->set_state((it->second == curr) ? GLGizmoBase::On : GLGizmoBase::Off); + if (gizmo == curr) + gizmo->load(ar); + } + } } template diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index b08df1690..d3da148a0 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -411,6 +411,7 @@ void MainFrame::init_menubar() }, wxID_FILE1, wxID_FILE9); std::vector recent_projects = wxGetApp().app_config->get_recent_projects(); + std::reverse(recent_projects.begin(), recent_projects.end()); for (const std::string& project : recent_projects) { m_recent_projects.AddFileToHistory(from_u8(project)); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 9feca2f3d..656e07a0e 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -202,7 +202,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // so we need a horizontal sizer to arrange these things auto sizer = new wxBoxSizer(wxHORIZONTAL); grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); - sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT, 7); + sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); } } @@ -372,30 +372,10 @@ void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const b auto option = m_options.at(opt_id).opt; - // get value -//! auto field_value = get_value(opt_id); - if (option.gui_flags.compare("serialized")==0) { - if (opt_index != -1) { - // die "Can't set serialized option indexed value" ; - } - change_opt_value(*m_config, opt_key, value); - } - else { - if (opt_index == -1) { - // change_opt_value(*m_config, opt_key, field_value); - //!? why field_value?? in this case changed value will be lose! No? - change_opt_value(*m_config, opt_key, value); - } - else { - change_opt_value(*m_config, opt_key, value, opt_index); -// auto value = m_config->get($opt_key); -// $value->[$opt_index] = $field_value; -// $self->config->set($opt_key, $value); - } - } + change_opt_value(*m_config, opt_key, value, opt_index == -1 ? 0 : opt_index); } - OptionsGroup::on_change_OG(opt_id, value); //!? Why doing this + OptionsGroup::on_change_OG(opt_id, value); } void ConfigOptionsGroup::back_to_initial_value(const std::string& opt_key) @@ -578,6 +558,34 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config boost::any ret; wxString text_value = wxString(""); const ConfigOptionDef* opt = config.def()->get(opt_key); + + if (opt->nullable) + { + switch (opt->type) + { + case coPercents: + case coFloats: { + if (config.option(opt_key)->is_nil()) + ret = _(L("N/A")); + else { + double val = opt->type == coFloats ? + config.option(opt_key)->get_at(idx) : + config.option(opt_key)->get_at(idx); + ret = double_to_string(val); } + } + break; + case coBools: + ret = config.option(opt_key)->values[idx]; + break; + case coInts: + ret = config.option(opt_key)->get_at(idx); + break; + default: + break; + } + return ret; + } + switch (opt->type) { case coFloatOrPercent:{ const auto &value = *config.option(opt_key); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index d720787b6..cc3d89b1f 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -252,6 +252,9 @@ public: Option option = get_option(title, idx); return OptionsGroup::create_single_option_line(option); } + Line create_single_option_line(const Option& option) const { + return OptionsGroup::create_single_option_line(option); + } void append_single_option_line(const Option& option) { OptionsGroup::append_single_option_line(option); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f6289efbc..1a4946637 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4406,6 +4406,12 @@ void Plater::reslice() { // Stop arrange and (or) optimize rotation tasks. this->stop_jobs(); + + if (printer_technology() == ptSLA) { + for (auto& object : model().objects) + if (object->sla_points_status == sla::PointsStatus::NoPoints) + object->sla_points_status = sla::PointsStatus::Generating; + } //FIXME Don't reslice if export of G-code or sending to OctoPrint is running. // bitmask of UpdateBackgroundProcessReturnState diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index e34c9be28..fa8b5baee 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -400,6 +400,10 @@ const std::vector& Preset::filament_options() "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode", + // Retract overrides + "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" }; return s_opts; diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 00c1f8168..7c9f7af4e 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -72,6 +72,8 @@ PresetBundle::PresetBundle() : this->filaments.default_preset().config.option("filament_settings_id", true)->values = { "" }; this->filaments.default_preset().compatible_printers_condition(); this->filaments.default_preset().inherits(); + // Set all the nullable values to nils. + this->filaments.default_preset().config.null_nullables(); this->sla_materials.default_preset().config.optptr("sla_material_settings_id", true); this->sla_materials.default_preset().compatible_printers_condition(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a00f7902f..9d7fc20a3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1497,6 +1497,105 @@ void TabPrint::OnActivate() Tab::OnActivate(); } +void TabFilament::add_filament_overrides_page() +{ + PageShp page = add_options_page(_(L("Filament Overrides")), "wrench"); + ConfigOptionsGroupShp optgroup = page->new_optgroup(_(L("Retraction"))); + + auto append_single_option_line = [optgroup, this](const std::string& opt_key, int opt_index) + { + Line line {"",""}; + if (opt_key == "filament_retract_lift_above" || opt_key == "filament_retract_lift_below") { + Option opt = optgroup->get_option(opt_key); + opt.opt.label = opt.opt.full_label; + line = optgroup->create_single_option_line(opt); + } + else + line = optgroup->create_single_option_line(optgroup->get_option(opt_key)); + + line.near_label_widget = [this, optgroup, opt_key, opt_index](wxWindow* parent) { + wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, ""); + + check_box->Bind(wxEVT_CHECKBOX, [this, optgroup, opt_key, opt_index](wxCommandEvent& evt) { + const bool is_checked = evt.IsChecked(); + Field* field = optgroup->get_fieldc(opt_key, opt_index); + if (field != nullptr) { + field->toggle(is_checked); + if (is_checked) + field->set_last_meaningful_value(); + else + field->set_na_value(); + } + }, check_box->GetId()); + + m_overrides_options[opt_key] = check_box; + return check_box; + }; + + optgroup->append_line(line); + }; + + const int extruder_idx = 0; // #ys_FIXME + + for (const std::string opt_key : { "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" + }) + append_single_option_line(opt_key, extruder_idx); +} + +void TabFilament::update_filament_overrides_page() +{ + const auto page_it = std::find_if(m_pages.begin(), m_pages.end(), [](const PageShp page) {return page->title() == _(L("Filament Overrides")); }); + if (page_it == m_pages.end()) + return; + PageShp page = *page_it; + + const auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) {return og->title == _(L("Retraction")); }); + if (og_it == page->m_optgroups.end()) + return; + ConfigOptionsGroupShp optgroup = *og_it; + + std::vector opt_keys = { "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" + }; + + const int extruder_idx = 0; // #ys_FIXME + + const bool have_retract_length = m_config->option("filament_retract_length")->is_nil() || + m_config->opt_float("filament_retract_length", extruder_idx) > 0; + + for (const std::string& opt_key : opt_keys) + { + bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length; + m_overrides_options[opt_key]->Enable(is_checked); + + is_checked &= !m_config->option(opt_key)->is_nil(); + m_overrides_options[opt_key]->SetValue(is_checked); + + Field* field = optgroup->get_fieldc(opt_key, extruder_idx); + if (field != nullptr) + field->toggle(is_checked); + } +} + void TabFilament::build() { m_presets = &m_preset_bundle->filaments; @@ -1594,10 +1693,14 @@ void TabFilament::build() }; optgroup->append_line(line); + + add_filament_overrides_page(); + + const int gcode_field_height = 15; // 150 const int notes_field_height = 25; // 250 - page = add_options_page(_(L("Custom G-code")), "cog"); + page = add_options_page(_(L("Custom G-code")), "cog"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); Option option = optgroup->get_option("start_filament_gcode"); option.opt.full_width = true; @@ -1661,7 +1764,7 @@ void TabFilament::update() return; // ys_FIXME m_update_cnt++; -// Freeze(); + wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); m_cooling_description_line->SetText(text); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); @@ -1676,7 +1779,9 @@ void TabFilament::update() for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) get_field(el)->toggle(fan_always_on); -// Thaw(); + + update_filament_overrides_page(); + m_update_cnt--; if (m_update_cnt == 0) diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 73b6bb08d..6ff76f5c4 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -337,6 +337,11 @@ class TabFilament : public Tab { ogStaticText* m_volumetric_speed_description_line; ogStaticText* m_cooling_description_line; + + void add_filament_overrides_page(); + void update_filament_overrides_page(); + + std::map m_overrides_options; public: TabFilament(wxNotebook* parent) : // Tab(parent, _(L("Filament Settings")), L("filament")) {} diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 5bb85e86d..f6dc9082e 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -513,6 +513,15 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent init_container(); } +#ifndef NDEBUG +bool ObjectDataViewModelNode::valid() +{ + // Verify that the object was not deleted yet. + assert(m_idx >= -1); + return m_idx >= -1; +} +#endif /* NDEBUG */ + void ObjectDataViewModelNode::set_action_icon() { m_action_icon_name = m_type & itObject ? "advanced_plus" : @@ -1457,6 +1466,7 @@ wxDataViewItem ObjectDataViewModel::GetParent(const wxDataViewItem &item) const return wxDataViewItem(0); ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); + assert(node != nullptr && node->valid()); // objects nodes has no parent too if (node->m_type == itObject) @@ -2783,21 +2793,20 @@ LockButton::LockButton( wxWindow *parent, const wxSize& size /*= wxDefaultSize*/): wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER) { - m_bmp_lock_on = ScalableBitmap(this, "one_layer_lock_on.png"); - m_bmp_lock_off = ScalableBitmap(this, "one_layer_lock_off.png"); - m_bmp_unlock_on = ScalableBitmap(this, "one_layer_unlock_on.png"); - m_bmp_unlock_off = ScalableBitmap(this, "one_layer_unlock_off.png"); + m_bmp_lock_closed = ScalableBitmap(this, "lock_closed"); + m_bmp_lock_closed_f = ScalableBitmap(this, "lock_closed_f"); + m_bmp_lock_open = ScalableBitmap(this, "lock_open"); + m_bmp_lock_open_f = ScalableBitmap(this, "lock_open_f"); #ifdef __WXMSW__ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); #endif // __WXMSW__ - SetBitmap(m_bmp_unlock_on.bmp()); - SetBitmapDisabled(m_bmp_lock_on.bmp()); + SetBitmap(m_bmp_lock_open.bmp()); + SetBitmapDisabled(m_bmp_lock_open.bmp()); + SetBitmapHover(m_bmp_lock_closed_f.bmp()); //button events - Bind(wxEVT_BUTTON, &LockButton::OnButton, this); - Bind(wxEVT_ENTER_WINDOW, &LockButton::OnEnterBtn, this); - Bind(wxEVT_LEAVE_WINDOW, &LockButton::OnLeaveBtn, this); + Bind(wxEVT_BUTTON, &LockButton::OnButton, this); } void LockButton::OnButton(wxCommandEvent& event) @@ -2806,7 +2815,7 @@ void LockButton::OnButton(wxCommandEvent& event) return; m_is_pushed = !m_is_pushed; - enter_button(true); + update_button_bitmaps(); event.Skip(); } @@ -2814,23 +2823,21 @@ void LockButton::OnButton(wxCommandEvent& event) void LockButton::SetLock(bool lock) { m_is_pushed = lock; - enter_button(true); + update_button_bitmaps(); } void LockButton::msw_rescale() { - m_bmp_lock_on .msw_rescale(); - m_bmp_lock_off .msw_rescale(); - m_bmp_unlock_on .msw_rescale(); - m_bmp_unlock_off.msw_rescale(); + m_bmp_lock_closed.msw_rescale(); + m_bmp_lock_closed_f.msw_rescale(); + m_bmp_lock_open.msw_rescale(); + m_bmp_lock_open_f.msw_rescale(); } -void LockButton::enter_button(const bool enter) +void LockButton::update_button_bitmaps() { - const wxBitmap& icon = m_is_pushed ? - enter ? m_bmp_lock_off.bmp() : m_bmp_lock_on.bmp() : - enter ? m_bmp_unlock_off.bmp() : m_bmp_unlock_on.bmp(); - SetBitmap(icon); + SetBitmap(m_is_pushed ? m_bmp_lock_closed.bmp() : m_bmp_lock_open.bmp()); + SetBitmapHover(m_is_pushed ? m_bmp_lock_closed_f.bmp() : m_bmp_lock_open_f.bmp()); Refresh(); Update(); @@ -2999,6 +3006,13 @@ ScalableButton::ScalableButton( wxWindow * parent, #endif // __WXMSW__ SetBitmap(create_scaled_bitmap(parent, icon_name)); + + if (size != wxDefaultSize) + { + const int em = em_unit(parent); + m_width = size.x/em; + m_height= size.y/em; + } } @@ -3025,11 +3039,24 @@ void ScalableButton::SetBitmap_(const ScalableBitmap& bmp) m_current_icon_name = bmp.name(); } +void ScalableButton::SetBitmapDisabled_(const ScalableBitmap& bmp) +{ + SetBitmapDisabled(bmp.bmp()); + m_disabled_icon_name = bmp.name(); +} + void ScalableButton::msw_rescale() { - const wxBitmap bmp = create_scaled_bitmap(m_parent, m_current_icon_name); + SetBitmap(create_scaled_bitmap(m_parent, m_current_icon_name)); + if (!m_disabled_icon_name.empty()) + SetBitmapDisabled(create_scaled_bitmap(m_parent, m_disabled_icon_name)); - SetBitmap(bmp); + if (m_width > 0 || m_height>0) + { + const int em = em_unit(m_parent); + wxSize size(m_width * em, m_height * em); + SetMinSize(size); + } } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 679d9346d..c0df69c5c 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -161,7 +161,7 @@ DECLARE_VARIANT_OBJECT(DataViewBitmapText) // ---------------------------------------------------------------------------- -// ObjectDataViewModelNode: a node inside PrusaObjectDataViewModel +// ObjectDataViewModelNode: a node inside ObjectDataViewModel // ---------------------------------------------------------------------------- enum ItemType { @@ -259,6 +259,10 @@ public: ObjectDataViewModelNode *child = m_children[i]; delete child; } +#ifndef NDEBUG + // Indicate that the object was deleted. + m_idx = -2; +#endif /* NDEBUG */ } void init_container(); @@ -269,6 +273,7 @@ public: ObjectDataViewModelNode* GetParent() { + assert(m_parent == nullptr || m_parent->valid()); return m_parent; } MyObjectTreeModelNodePtrArray& GetChildren() @@ -357,6 +362,11 @@ public: bool update_settings_digest(const std::vector& categories); int volume_type() const { return int(m_volume_type); } void msw_rescale(); + +#ifndef NDEBUG + bool valid(); +#endif /* NDEBUG */ + private: friend class ObjectDataViewModel; }; @@ -859,8 +869,6 @@ public: ~LockButton() {} void OnButton(wxCommandEvent& event); - void OnEnterBtn(wxMouseEvent& event) { enter_button(true); event.Skip(); } - void OnLeaveBtn(wxMouseEvent& event) { enter_button(false); event.Skip(); } bool IsLocked() const { return m_is_pushed; } void SetLock(bool lock); @@ -872,16 +880,16 @@ public: void msw_rescale(); protected: - void enter_button(const bool enter); + void update_button_bitmaps(); private: bool m_is_pushed = false; bool m_disabled = false; - ScalableBitmap m_bmp_lock_on; - ScalableBitmap m_bmp_lock_off; - ScalableBitmap m_bmp_unlock_on; - ScalableBitmap m_bmp_unlock_off; + ScalableBitmap m_bmp_lock_closed; + ScalableBitmap m_bmp_lock_closed_f; + ScalableBitmap m_bmp_lock_open; + ScalableBitmap m_bmp_lock_open_f; }; @@ -912,12 +920,16 @@ public: ~ScalableButton() {} void SetBitmap_(const ScalableBitmap& bmp); + void SetBitmapDisabled_(const ScalableBitmap &bmp); void msw_rescale(); private: wxWindow* m_parent; std::string m_current_icon_name = ""; + std::string m_disabled_icon_name = ""; + int m_width {-1}; // should be multiplied to em_unit + int m_height{-1}; // should be multiplied to em_unit }; diff --git a/version.inc b/version.inc index 8f5ff57d1..4e1607bda 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.0.0") +set(SLIC3R_VERSION "2.1.0-alpha0") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") -set(SLIC3R_RC_VERSION "2,0,0,0") -set(SLIC3R_RC_VERSION_DOTS "2.0.0.0") +set(SLIC3R_RC_VERSION "2,1,0,0") +set(SLIC3R_RC_VERSION_DOTS "2.1.0.0") diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index df5f48587..74c0f4b0c 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -75,7 +75,7 @@ _constant() Ref config() %code%{ RETVAL = const_cast(static_cast(&THIS->config())); %}; Ref placeholder_parser() - %code%{ RETVAL = &THIS->placeholder_parser(); %}; + %code%{ RETVAL = const_cast(&THIS->placeholder_parser()); %}; Ref skirt() %code%{ RETVAL = const_cast(&THIS->skirt()); %}; Ref brim()