Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_window

This commit is contained in:
enricoturri1966 2021-03-03 09:07:28 +01:00
commit da7d7ae11b
61 changed files with 6895 additions and 646 deletions

View file

@ -1,11 +1,4 @@
if (APPLE) set(_wx_git_tag v3.1.4-patched)
# The new OSX 11 (Big Sur) is not compatible with wxWidgets 3.1.3.
# Let's use patched wxWidgets 3.1.4, even though it is not quite tested.
set(_wx_git_tag v3.1.4-patched)
else ()
# Use the tested patched wxWidgets 3.1.3 everywhere else.
set(_wx_git_tag v3.1.3-patched)
endif ()
# set(_patch_command "") # set(_patch_command "")
set(_wx_toolkit "") set(_wx_toolkit "")

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#808080" cx="8" cy="8" r="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -41,23 +41,23 @@ bed_model = ender3v2_bed.stl
bed_texture = ender3v2.svg bed_texture = ender3v2.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:ENDER3MAX] [printer_model:ENDER3MAX]
#name = Creality Ender-3 Max name = Creality Ender-3 Max
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = ENDER family = ENDER
#bed_model = cr10v2_bed.stl bed_model = cr10v2_bed.stl
#bed_texture = cr10spro.svg bed_texture = cr10spro.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:ENDER4] [printer_model:ENDER4]
#name = Creality Ender-4 name = Creality Ender-4
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = ENDER family = ENDER
#bed_model = ender3v2_bed.stl bed_model = ender3v2_bed.stl
#bed_texture = ender3v2.svg bed_texture = ender3v2.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER5] [printer_model:ENDER5]
name = Creality Ender-5 name = Creality Ender-5
@ -77,14 +77,14 @@ bed_model = ender5plus_bed.stl
bed_texture = ender5plus.svg bed_texture = ender5plus.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:ENDER6] [printer_model:ENDER6]
#name = Creality Ender-6 name = Creality Ender-6
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = ENDER family = ENDER
#bed_model = ender6_bed.stl bed_model = ender6_bed.stl
#bed_texture = ender6.svg bed_texture = ender6.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:ENDER2] [printer_model:ENDER2]
name = Creality Ender-2 name = Creality Ender-2
@ -95,23 +95,41 @@ bed_model = ender2_bed.stl
bed_texture = ender2.svg bed_texture = ender2.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CR6SE] [printer_model:CR5PRO]
#name = Creality CR-6 SE name = Creality CR-5 Pro
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = CR family = CR
#bed_model = cr6se_bed.stl bed_model = cr5pro_bed.stl
#bed_texture = cr6se.svg bed_texture = cr5pro.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CR6MAX] [printer_model:CR5PROH]
#name = Creality CR-6 Max name = Creality CR-5 Pro H
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = CR family = CR
#bed_model = cr10s4_bed.stl bed_model = cr5pro_bed.stl
#bed_texture = cr10s4.svg bed_texture = cr5pro.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR6SE]
name = Creality CR-6 SE
variants = 0.4
technology = FFF
family = CR
bed_model = cr6se_bed.stl
bed_texture = cr6se.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR6MAX]
name = Creality CR-6 Max
variants = 0.4
technology = FFF
family = CR
bed_model = cr10s4_bed.stl
bed_texture = cr10s4.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10MINI] [printer_model:CR10MINI]
name = Creality CR-10 Mini name = Creality CR-10 Mini
@ -122,14 +140,14 @@ bed_model = cr10mini_bed.stl
bed_texture = cr10mini.svg bed_texture = cr10mini.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CR10MAX] [printer_model:CR10MAX]
#name = Creality CR-10 Max name = Creality CR-10 Max
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = CR family = CR
#bed_model = cr10max_bed.stl bed_model = cr10max_bed.stl
#bed_texture = cr10max.svg bed_texture = cr10max.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR10] [printer_model:CR10]
name = Creality CR-10 name = Creality CR-10
@ -221,14 +239,23 @@ bed_model = ender3_bed.stl
bed_texture = cr20.svg bed_texture = cr20.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CR8] [printer_model:CR200B]
#name = Creality CR-8 name = Creality CR-200B
#variants = 0.4 variants = 0.4
#technology = FFF technology = FFF
#family = CR family = CR
#bed_model = cr8_bed.stl bed_model = cr200b_bed.stl
#bed_texture = cr8.svg bed_texture = cr200b.svg
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
[printer_model:CR8]
name = Creality CR-8
variants = 0.4
technology = FFF
family = CR
bed_model = cr8_bed.stl
bed_texture = cr8.svg
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
#[printer_model:CRX] #[printer_model:CRX]
#name = Creality CR-X #name = Creality CR-X
@ -269,11 +296,11 @@ external_perimeters_first = 0
external_perimeter_extrusion_width = 0.45 external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 25 external_perimeter_speed = 25
extra_perimeters = 0 extra_perimeters = 0
extruder_clearance_height = 25 extruder_clearance_height = 34
extruder_clearance_radius = 45 extruder_clearance_radius = 47
extrusion_width = 0.45 extrusion_width = 0.45
fill_angle = 45 fill_angle = 45
fill_density = 20% fill_density = 15%
fill_pattern = grid fill_pattern = grid
first_layer_extrusion_width = 0.42 first_layer_extrusion_width = 0.42
first_layer_height = 0.2 first_layer_height = 0.2
@ -307,9 +334,9 @@ print_settings_id =
raft_layers = 0 raft_layers = 0
resolution = 0 resolution = 0
seam_position = nearest seam_position = nearest
single_extruder_multi_material_priming = 1 single_extruder_multi_material_priming = 0
skirts = 1 skirts = 1
skirt_distance = 2 skirt_distance = 3
skirt_height = 2 skirt_height = 2
small_perimeter_speed = 25 small_perimeter_speed = 25
solid_infill_below_area = 0 solid_infill_below_area = 0
@ -335,7 +362,7 @@ support_material_pattern = rectilinear
support_material_spacing = 2 support_material_spacing = 2
support_material_speed = 40 support_material_speed = 40
support_material_synchronize_layers = 0 support_material_synchronize_layers = 0
support_material_threshold = 45 support_material_threshold = 40
support_material_with_sheath = 0 support_material_with_sheath = 0
support_material_xy_spacing = 60% support_material_xy_spacing = 60%
thin_walls = 0 thin_walls = 0
@ -359,7 +386,7 @@ top_solid_layers = 11
[print:*0.10mm*] [print:*0.10mm*]
inherits = *common* inherits = *common*
layer_height = 0.1 layer_height = 0.10
perimeters = 3 perimeters = 3
bottom_solid_layers = 7 bottom_solid_layers = 7
top_solid_layers = 9 top_solid_layers = 9
@ -712,7 +739,7 @@ printer_technology = FFF
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n
between_objects_gcode = between_objects_gcode =
pause_print_gcode = pause_print_gcode =
deretract_speed = 0 deretract_speed = 40
extruder_colour = #FCE94F extruder_colour = #FCE94F
extruder_offset = 0x0 extruder_offset = 0x0
gcode_flavor = marlin gcode_flavor = marlin
@ -735,23 +762,24 @@ machine_max_jerk_z = 0.4
machine_min_extruding_rate = 0 machine_min_extruding_rate = 0
machine_min_travel_rate = 0 machine_min_travel_rate = 0
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
max_layer_height = 0.3 max_layer_height = 0.28
min_layer_height = 0.07 min_layer_height = 0.08
max_print_height = 250 max_print_height = 250
nozzle_diameter = 0.4 nozzle_diameter = 0.4
printer_notes = printer_notes =
printer_settings_id = printer_settings_id =
retract_before_travel = 1 printer_variant = 0.4
retract_before_wipe = 0% retract_before_travel = 2
retract_before_wipe = 70%
retract_layer_change = 1 retract_layer_change = 1
retract_length = 1 retract_length = 5
retract_length_toolchange = 1 retract_length_toolchange = 1
retract_lift = 0 retract_lift = 0
retract_lift_above = 0 retract_lift_above = 0
retract_lift_below = 0 retract_lift_below = 0
retract_restart_extra = 0 retract_restart_extra = 0
retract_restart_extra_toolchange = 0 retract_restart_extra_toolchange = 0
retract_speed = 35 retract_speed = 60
single_extruder_multi_material = 0 single_extruder_multi_material = 0
toolchange_gcode = toolchange_gcode =
use_firmware_retraction = 0 use_firmware_retraction = 0
@ -763,39 +791,6 @@ z_offset = 0
printer_model = printer_model =
default_print_profile = 0.16mm OPTIMAL @CREALITY default_print_profile = 0.16mm OPTIMAL @CREALITY
default_filament_profile = Generic PLA @CREALITY default_filament_profile = Generic PLA @CREALITY
[printer:Creality Ender-3]
inherits = *common*
renamed_from = "Creality ENDER-3"
printer_model = ENDER3
printer_variant = 0.4
max_layer_height = 0.28
min_layer_height = 0.08
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_CREALITY\nPRINTER_MODEL_ENDER3\nPRINTER_HAS_BOWDEN
bed_shape = 3x3,228x3,228x228,3x228
max_print_height = 250
machine_max_acceleration_e = 5000
machine_max_acceleration_extruding = 500
machine_max_acceleration_retracting = 1000
machine_max_acceleration_x = 500
machine_max_acceleration_y = 500
machine_max_acceleration_z = 100
machine_max_feedrate_e = 60
machine_max_feedrate_x = 500
machine_max_feedrate_y = 500
machine_max_feedrate_z = 10
machine_max_jerk_e = 5
machine_max_jerk_x = 8
machine_max_jerk_y = 8
machine_max_jerk_z = 0.4
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
nozzle_diameter = 0.4
retract_before_travel = 2
retract_length = 5
retract_speed = 60
deretract_speed = 40
retract_before_wipe = 70%
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0 start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors
@ -813,7 +808,6 @@ pause_print_gcode = M25 ; pause print
# Intended for printers where the Z-axis lowers the print bed during printing, like the Ender-5 series # Intended for printers where the Z-axis lowers the print bed during printing, like the Ender-5 series
[printer:*descendingz*] [printer:*descendingz*]
renamed_from = "*invertedz*"
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; move print head out of the way\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed close to the bottom\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; move print head out of the way\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed close to the bottom\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors
# Intended for printers with dual extruders and a single hotend/nozzle, like the CR-X series # Intended for printers with dual extruders and a single hotend/nozzle, like the CR-X series
@ -842,34 +836,44 @@ retract_restart_extra_toolchange = 0,0
retract_speed = 60,60 retract_speed = 60,60
wipe = 1,1 wipe = 1,1
[printer:Creality Ender-3]
inherits = *common*
renamed_from = "Creality ENDER-3"
bed_shape = 3x3,228x3,228x228,3x228
max_print_height = 250
printer_model = ENDER3
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_CREALITY\nPRINTER_MODEL_ENDER3\nPRINTER_HAS_BOWDEN
[printer:Creality Ender-3 BLTouch] [printer:Creality Ender-3 BLTouch]
inherits = Creality Ender-3; *fastabl* inherits = Creality Ender-3; *fastabl*
renamed_from = "Creality ENDER-3 BLTouch" renamed_from = "Creality ENDER-3 BLTouch"
printer_model = ENDER3BLTOUCH printer_model = ENDER3BLTOUCH
[printer:Creality Ender-3 V2] [printer:Creality Ender-3 V2]
inherits = Creality Ender-3 inherits = *common*
renamed_from = "Creality Ender-3V2" renamed_from = "Creality Ender-3V2"
printer_model = ENDER3V2
bed_shape = 5x0,215x0,215x220,5x220 bed_shape = 5x0,215x0,215x220,5x220
max_print_height = 250
printer_model = ENDER3V2
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_CREALITY\nPRINTER_MODEL_ENDER3V2\nPRINTER_HAS_BOWDEN
#[printer:Creality Ender-3 Max] [printer:Creality Ender-3 Max]
#inherits = Creality Ender-3 inherits = *common*
#retract_length = 6 retract_length = 6
#bed_shape = 5x5,295x5,295x295,5x295 bed_shape = 5x5,295x5,295x295,5x295
#max_print_height = 340 max_print_height = 340
#printer_model = ENDER3MAX printer_model = ENDER3MAX
#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_CREALITY\nPRINTER_MODEL_ENDER3MAX\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_ENDER3MAX\nPRINTER_HAS_BOWDEN
#[printer:Creality Ender-4] [printer:Creality Ender-4]
#inherits = Creality Ender-3; *descendingz* inherits = *common*; *descendingz*
#bed_shape = 5x0,215x0,215x220,5x220 bed_shape = 5x0,215x0,215x220,5x220
#max_print_height = 300 max_print_height = 300
#printer_model = ENDER4 printer_model = ENDER4
#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_CREALITY\nPRINTER_MODEL_ENDER4\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_ENDER4\nPRINTER_HAS_BOWDEN
[printer:Creality Ender-5] [printer:Creality Ender-5]
inherits = Creality Ender-3; *descendingz* inherits = *common*; *descendingz*
retract_length = 6 retract_length = 6
bed_shape = 5x2.5,225x2.5,225x222.5,5x222.5 bed_shape = 5x2.5,225x2.5,225x222.5,5x222.5
max_print_height = 300 max_print_height = 300
@ -879,7 +883,7 @@ machine_max_acceleration_e = 1000
machine_max_feedrate_z = 5 machine_max_feedrate_z = 5
[printer:Creality Ender-5 Plus] [printer:Creality Ender-5 Plus]
inherits = Creality Ender-3; *slowabl*; *descendingz* inherits = *common*; *slowabl*; *descendingz*
retract_length = 6 retract_length = 6
bed_shape = 5x5,355x5,355x355,5x355 bed_shape = 5x5,355x5,355x355,5x355
max_print_height = 400 max_print_height = 400
@ -890,53 +894,69 @@ machine_max_feedrate_z = 5
machine_max_feedrate_x = 300 machine_max_feedrate_x = 300
machine_max_feedrate_y = 300 machine_max_feedrate_y = 300
#[printer:Creality Ender-6] [printer:Creality Ender-6]
#inherits = Creality Ender-3; *descendingz* inherits = *common*; *descendingz*
#bed_shape = 5x5,255x5,255x255,5x255 bed_shape = 5x5,255x5,255x255,5x255
#max_print_height = 400 max_print_height = 400
#printer_model = ENDER6 printer_model = ENDER6
#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_CREALITY\nPRINTER_MODEL_ENDER6\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_ENDER6\nPRINTER_HAS_BOWDEN
[printer:Creality Ender-2] [printer:Creality Ender-2]
inherits = Creality Ender-3 inherits = *common*
renamed_from = "Creality ENDER-2" renamed_from = "Creality ENDER-2"
bed_shape = 0x0,150x0,150x150,0x150 bed_shape = 0x0,150x0,150x150,0x150
max_print_height = 200 max_print_height = 200
printer_model = ENDER2 printer_model = ENDER2
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_CREALITY\nPRINTER_MODEL_ENDER2\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_ENDER2\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-6 SE] [printer:Creality CR-5 Pro]
#inherits = Creality Ender-3; *fastabl*; *pauseprint* inherits = *common*; *slowabl*; *descendingz*
#bed_shape = 5x0,230x0,230x235,5x235 retract_length = 6
#printer_model = CR6SE bed_shape = 5x5,295x5,295x220,5x220
#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_CREALITY\nPRINTER_MODEL_CR6SE\nPRINTER_HAS_BOWDEN max_print_height = 380
printer_model = CR5PRO
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_CREALITY\nPRINTER_MODEL_CR5PRO\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-6 Max] [printer:Creality CR-5 Pro H]
#inherits = Creality Ender-3; *slowabl* inherits = *common*; *slowabl*; *descendingz*
#retract_length = 6 retract_length = 3
#bed_shape = 5x5,395x5,395x395,5x395 bed_shape = 5x5,295x5,295x220,5x220
#max_print_height = 400 max_print_height = 380
#printer_model = CR6MAX printer_model = CR5PROH
#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_CREALITY\nPRINTER_MODEL_CR6MAX\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR5PROH\nPRINTER_HAS_BOWDEN
[printer:Creality CR-6 SE]
inherits = *common*; *fastabl*; *pauseprint*
bed_shape = 5x0,230x0,230x235,5x235
printer_model = CR6SE
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_CREALITY\nPRINTER_MODEL_CR6SE\nPRINTER_HAS_BOWDEN
[printer:Creality CR-6 Max]
inherits = *common*; *slowabl*
retract_length = 6
bed_shape = 5x5,395x5,395x395,5x395
max_print_height = 400
printer_model = CR6MAX
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_CREALITY\nPRINTER_MODEL_CR6MAX\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 Mini] [printer:Creality CR-10 Mini]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 2.5x5,2.5x225,302.5x225,302.5x5 bed_shape = 2.5x5,302.5x5,302.5x225,2.5x225
max_print_height = 300 max_print_height = 300
printer_model = CR10MINI printer_model = CR10MINI
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_CREALITY\nPRINTER_MODEL_CR10MINI\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10MINI\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-10 Max] [printer:Creality CR-10 Max]
#inherits = Creality Ender-3; *slowabl* inherits = *common*; *slowabl*
#retract_length = 6 retract_length = 6
#bed_shape = 5x5,445x5,445x445,5x445 bed_shape = 5x5,445x5,445x445,5x445
#max_print_height = 470 max_print_height = 470
#printer_model = CR10MAX printer_model = CR10MAX
#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_CREALITY\nPRINTER_MODEL_CR10MAX\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10MAX\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10] [printer:Creality CR-10]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305 bed_shape = 5x5,305x5,305x305,5x305
max_print_height = 400 max_print_height = 400
@ -944,7 +964,7 @@ printer_model = CR10
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_CREALITY\nPRINTER_MODEL_CR10\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 V2] [printer:Creality CR-10 V2]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305 bed_shape = 5x5,305x5,305x305,5x305
max_print_height = 400 max_print_height = 400
@ -952,7 +972,7 @@ printer_model = CR10V2
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_CREALITY\nPRINTER_MODEL_CR10V2\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10V2\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 V3] [printer:Creality CR-10 V3]
inherits = Creality Ender-3 inherits = *common*
retract_length = 1 retract_length = 1
bed_shape = 5x5,305x5,305x305,5x305 bed_shape = 5x5,305x5,305x305,5x305
max_print_height = 400 max_print_height = 400
@ -960,7 +980,7 @@ printer_model = CR10V3
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_CREALITY\nPRINTER_MODEL_CR10V3 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_CREALITY\nPRINTER_MODEL_CR10V3
[printer:Creality CR-10 S] [printer:Creality CR-10 S]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305 bed_shape = 5x5,305x5,305x305,5x305
max_print_height = 400 max_print_height = 400
@ -968,7 +988,7 @@ printer_model = CR10S
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_CREALITY\nPRINTER_MODEL_CR10S\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10S\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 S Pro] [printer:Creality CR-10 S Pro]
inherits = Creality Ender-3; *slowabl* inherits = *common*; *slowabl*
retract_length = 6 retract_length = 6
bed_shape = 5x5,295x5,295x295,5x295 bed_shape = 5x5,295x5,295x295,5x295
max_print_height = 400 max_print_height = 400
@ -976,7 +996,7 @@ printer_model = CR10SPRO
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_CREALITY\nPRINTER_MODEL_CR10SPRO\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10SPRO\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 S Pro V2] [printer:Creality CR-10 S Pro V2]
inherits = Creality Ender-3; *slowabl* inherits = *common*; *slowabl*
retract_length = 6 retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305 bed_shape = 5x5,305x5,305x305,5x305
max_print_height = 400 max_print_height = 400
@ -984,7 +1004,7 @@ printer_model = CR10SPROV2
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_CREALITY\nPRINTER_MODEL_CR10SPROV2\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10SPROV2\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 S4] [printer:Creality CR-10 S4]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 5x5,395x5,395x395,5x395 bed_shape = 5x5,395x5,395x395,5x395
max_print_height = 400 max_print_height = 400
@ -992,7 +1012,7 @@ printer_model = CR10S4
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_CREALITY\nPRINTER_MODEL_CR10S4\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10S4\nPRINTER_HAS_BOWDEN
[printer:Creality CR-10 S5] [printer:Creality CR-10 S5]
inherits = Creality Ender-3 inherits = *common*
retract_length = 6 retract_length = 6
bed_shape = 5x5,505x5,505x505,5x505 bed_shape = 5x5,505x5,505x505,5x505
max_print_height = 500 max_print_height = 500
@ -1000,25 +1020,32 @@ printer_model = CR10S5
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_CREALITY\nPRINTER_MODEL_CR10S5\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR10S5\nPRINTER_HAS_BOWDEN
[printer:Creality CR-20] [printer:Creality CR-20]
inherits = Creality Ender-3 inherits = *common*
printer_model = CR20 printer_model = CR20
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_CREALITY\nPRINTER_MODEL_CR20\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR20\nPRINTER_HAS_BOWDEN
[printer:Creality CR-20 Pro] [printer:Creality CR-20 Pro]
inherits = Creality Ender-3; *fastabl* inherits = *common*; *fastabl*
retract_length = 4 retract_length = 4
printer_model = CR20PRO printer_model = CR20PRO
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_CREALITY\nPRINTER_MODEL_CR20PRO\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR20PRO\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-8] [printer:Creality CR-200B]
#inherits = Creality Ender-3 inherits = *common*; *descendingz*
#bed_shape = 5x5,215x5,215x215,5x215 bed_shape = 5x5,195x5,195x195,5x195
#max_print_height = 210 max_print_height = 200
#printer_model = CR8 printer_model = CR200B
#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_CREALITY\nPRINTER_MODEL_CR8\nPRINTER_HAS_BOWDEN 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_CREALITY\nPRINTER_MODEL_CR200B\nPRINTER_HAS_BOWDEN
[printer:Creality CR-8]
inherits = *common*
bed_shape = 5x5,215x5,215x215,5x215
max_print_height = 210
printer_model = CR8
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_CREALITY\nPRINTER_MODEL_CR8\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-X] #[printer:Creality CR-X]
#inherits = Creality Ender-3; *dualextruder* #inherits = *common*; *dualextruder*
#retract_length = 6,6 #retract_length = 6,6
#bed_shape = 5x5,295x5,295x295,5x295 #bed_shape = 5x5,295x5,295x295,5x295
#max_print_height = 400 #max_print_height = 400
@ -1026,7 +1053,7 @@ printer_notes = Don't remove the following keywords! These keywords are used in
#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_CREALITY\nPRINTER_MODEL_CRX\nPRINTER_HAS_BOWDEN #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_CREALITY\nPRINTER_MODEL_CRX\nPRINTER_HAS_BOWDEN
#[printer:Creality CR-X Pro] #[printer:Creality CR-X Pro]
#inherits = Creality Ender-3; *dualextruder*; *slowabl* #inherits = *common*; *dualextruder*; *slowabl*
#retract_length = 6,6 #retract_length = 6,6
#bed_shape = 5x5,295x5,295x295,5x295 #bed_shape = 5x5,295x5,295x295,5x295
#max_print_height = 400 #max_print_height = 400

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="190mm" height="190mm" version="1.1" viewBox="0 0 190 190" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="189.5" height="189.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="290mm" height="215mm" version="1.1" viewBox="0 0 290 215" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="289.5" height="214.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
[vendor] [vendor]
# Vendor name will be shown by the Config Wizard. # Vendor name will be shown by the Config Wizard.
name = INAT s.r.o. name = INAT
config_version = 0.0.1 config_version = 0.0.1
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/ config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/

View file

@ -68,14 +68,12 @@ void AppConfig::set_defaults()
if (get("export_sources_full_pathnames").empty()) if (get("export_sources_full_pathnames").empty())
set("export_sources_full_pathnames", "0"); set("export_sources_full_pathnames", "0");
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
if (get("associate_3mf").empty()) if (get("associate_3mf").empty())
set("associate_3mf", "0"); set("associate_3mf", "0");
if (get("associate_stl").empty()) if (get("associate_stl").empty())
set("associate_stl", "0"); set("associate_stl", "0");
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
// remove old 'use_legacy_opengl' parameter from this config, if present // remove old 'use_legacy_opengl' parameter from this config, if present
if (!get("use_legacy_opengl").empty()) if (!get("use_legacy_opengl").empty())
@ -127,14 +125,12 @@ void AppConfig::set_defaults()
if (get("color_mapinulation_panel").empty()) if (get("color_mapinulation_panel").empty())
set("color_mapinulation_panel", "0"); set("color_mapinulation_panel", "0");
} }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
else { else {
#ifdef _WIN32 #ifdef _WIN32
if (get("associate_gcode").empty()) if (get("associate_gcode").empty())
set("associate_gcode", "0"); set("associate_gcode", "0");
#endif // _WIN32 #endif // _WIN32
} }
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (get("seq_top_layer_only").empty()) if (get("seq_top_layer_only").empty())
set("seq_top_layer_only", "1"); set("seq_top_layer_only", "1");
@ -156,12 +152,10 @@ void AppConfig::set_defaults()
if (get("show_splash_screen").empty()) if (get("show_splash_screen").empty())
set("show_splash_screen", "1"); set("show_splash_screen", "1");
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32 #ifdef _WIN32
if (get("use_legacy_3DConnexion").empty()) if (get("use_legacy_3DConnexion").empty())
set("use_legacy_3DConnexion", "0"); set("use_legacy_3DConnexion", "0");
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
// Remove legacy window positions/sizes // Remove legacy window positions/sizes
erase("", "main_frame_maximized"); erase("", "main_frame_maximized");

View file

@ -145,6 +145,8 @@ add_library(libslic3r STATIC
Point.hpp Point.hpp
Polygon.cpp Polygon.cpp
Polygon.hpp Polygon.hpp
MutablePolygon.cpp
MutablePolygon.hpp
PolygonTrimmer.cpp PolygonTrimmer.cpp
PolygonTrimmer.hpp PolygonTrimmer.hpp
Polyline.cpp Polyline.cpp

View file

@ -667,6 +667,14 @@ namespace DoExport {
break; break;
} }
} }
if (ret.size() < MAX_TAGS_COUNT) {
const CustomGCode::Info& custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
for (const auto& gcode : custom_gcode_per_print_z.gcodes) {
check(_(L("Custom G-code")), gcode.extra);
if (ret.size() == MAX_TAGS_COUNT)
break;
}
}
return ret; return ret;
} }
@ -1705,7 +1713,9 @@ namespace ProcessLayer
{ {
static std::string emit_custom_gcode_per_print_z( static std::string emit_custom_gcode_per_print_z(
GCode &gcodegen,
const CustomGCode::Item *custom_gcode, const CustomGCode::Item *custom_gcode,
unsigned int current_extruder_id,
// ID of the first extruder printing this layer. // ID of the first extruder printing this layer.
unsigned int first_extruder_id, unsigned int first_extruder_id,
const PrintConfig &config) const PrintConfig &config)
@ -1746,12 +1756,14 @@ namespace ProcessLayer
// && !MMU1 // && !MMU1
) { ) {
//! FIXME_in_fw show message during print pause //! FIXME_in_fw show message during print pause
gcode += config.pause_print_gcode;// pause print DynamicConfig cfg;
cfg.set_key_value("color_change_extruder", new ConfigOptionInt(m600_extruder_before_layer));
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg);
gcode += "\n"; gcode += "\n";
gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n"; gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n";
} }
else { else {
gcode += config.color_change_gcode;//ColorChangeCode; gcode += gcodegen.placeholder_parser_process("color_change_gcode", config.color_change_gcode, current_extruder_id);
gcode += "\n"; gcode += "\n";
} }
} }
@ -1767,7 +1779,7 @@ namespace ProcessLayer
//! FIXME_in_fw show message during print pause //! FIXME_in_fw show message during print pause
if (!pause_print_msg.empty()) if (!pause_print_msg.empty())
gcode += "M117 " + pause_print_msg + "\n"; gcode += "M117 " + pause_print_msg + "\n";
gcode += config.pause_print_gcode; gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id);
} }
else { else {
// add tag for processor // add tag for processor
@ -1776,8 +1788,8 @@ namespace ProcessLayer
#else #else
gcode += ";" + GCodeProcessor::Custom_Code_Tag + "\n"; gcode += ";" + GCodeProcessor::Custom_Code_Tag + "\n";
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
if (gcode_type == CustomGCode::Template) // Template Cistom Gcode if (gcode_type == CustomGCode::Template) // Template Custom Gcode
gcode += config.template_custom_gcode; gcode += gcodegen.placeholder_parser_process("template_custom_gcode", config.template_custom_gcode, current_extruder_id);
else // custom Gcode else // custom Gcode
gcode += custom_gcode->extra; gcode += custom_gcode->extra;
@ -1803,7 +1815,6 @@ namespace Skirt {
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_1st_layer( static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_1st_layer(
const Print &print, const Print &print,
const std::vector<GCode::LayerToPrint> & /*layers */,
const LayerTools &layer_tools, const LayerTools &layer_tools,
// Heights (print_z) at which the skirt has already been extruded. // Heights (print_z) at which the skirt has already been extruded.
std::vector<coordf_t> &skirt_done) std::vector<coordf_t> &skirt_done)
@ -1811,7 +1822,8 @@ namespace Skirt {
// Extrude skirt at the print_z of the raft layers and normal object layers // Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers. // not at the print_z of the interlaced support material layers.
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out; std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) { assert(skirt_done.empty());
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) {
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
skirt_done.emplace_back(layer_tools.print_z); skirt_done.emplace_back(layer_tools.print_z);
} }
@ -1820,36 +1832,34 @@ namespace Skirt {
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_other_layers( static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_other_layers(
const Print &print, const Print &print,
const std::vector<GCode::LayerToPrint> &layers,
const LayerTools &layer_tools, const LayerTools &layer_tools,
// First non-empty support layer.
const SupportLayer *support_layer,
// Heights (print_z) at which the skirt has already been extruded. // Heights (print_z) at which the skirt has already been extruded.
std::vector<coordf_t> &skirt_done) std::vector<coordf_t> &skirt_done)
{ {
// Extrude skirt at the print_z of the raft layers and normal object layers // Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers. // not at the print_z of the interlaced support material layers.
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out; std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (print.has_skirt() && ! print.skirt().entities.empty() && if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt &&
// Not enough skirt layers printed yet. // Not enough skirt layers printed yet.
//FIXME infinite or high skirt does not make sense for sequential print! //FIXME infinite or high skirt does not make sense for sequential print!
(skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt()) && (skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt())) {
bool valid = ! skirt_done.empty() && skirt_done.back() < layer_tools.print_z - EPSILON;
assert(valid);
// This print_z has not been extruded yet (sequential print) // This print_z has not been extruded yet (sequential print)
// FIXME: The skirt_done should not be empty at this point. The check is a workaround // FIXME: The skirt_done should not be empty at this point. The check is a workaround
// of https://github.com/prusa3d/PrusaSlicer/issues/5652, but it deserves a real fix. // of https://github.com/prusa3d/PrusaSlicer/issues/5652, but it deserves a real fix.
(! skirt_done.empty() && skirt_done.back() < layer_tools.print_z - EPSILON) && if (valid) {
// and this layer is an object layer, or it is a raft layer.
(layer_tools.has_object || support_layer->id() < (size_t)support_layer->object()->config().raft_layers.value)) {
#if 0 #if 0
// Prime just the first printing extruder. This is original Slic3r's implementation. // Prime just the first printing extruder. This is original Slic3r's implementation.
skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirts.value); skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirts.value);
#else #else
// Prime all extruders planned for this layer, see // Prime all extruders planned for this layer, see
// https://github.com/prusa3d/PrusaSlicer/issues/469#issuecomment-322450619 // https://github.com/prusa3d/PrusaSlicer/issues/469#issuecomment-322450619
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out); skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
#endif #endif
assert(!skirt_done.empty()); assert(!skirt_done.empty());
skirt_done.emplace_back(layer_tools.print_z); skirt_done.emplace_back(layer_tools.print_z);
}
} }
return skirt_loops_per_extruder_out; return skirt_loops_per_extruder_out;
} }
@ -1987,13 +1997,13 @@ void GCode::process_layer(
if (single_object_instance_idx == size_t(-1)) { if (single_object_instance_idx == size_t(-1)) {
// Normal (non-sequential) print. // Normal (non-sequential) print.
gcode += ProcessLayer::emit_custom_gcode_per_print_z(layer_tools.custom_gcode, first_extruder_id, print.config()); gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
} }
// Extrude skirt at the print_z of the raft layers and normal object layers // Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers. // not at the print_z of the interlaced support material layers.
skirt_loops_per_extruder = first_layer ? skirt_loops_per_extruder = first_layer ?
Skirt::make_skirt_loops_per_extruder_1st_layer(print, layers, layer_tools, m_skirt_done) : Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) :
Skirt::make_skirt_loops_per_extruder_other_layers(print, layers, layer_tools, support_layer, m_skirt_done); Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done);
// Group extrusions by an extruder, then by an object, an island and a region. // Group extrusions by an extruder, then by an object, an island and a region.
std::map<unsigned int, std::vector<ObjectByExtruder>> by_extruder; std::map<unsigned int, std::vector<ObjectByExtruder>> by_extruder;
@ -2840,9 +2850,11 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
Polyline travel { this->last_pos(), point }; Polyline travel { this->last_pos(), point };
// check whether a straight travel move would need retraction // check whether a straight travel move would need retraction
bool needs_retraction = this->needs_retraction(travel, role); bool needs_retraction = this->needs_retraction(travel, role);
// check whether wipe could be disabled without causing visible stringing // check whether wipe could be disabled without causing visible stringing
bool could_be_wipe_disabled = false; bool could_be_wipe_disabled = false;
// Save state of use_external_mp_once for the case that will be needed to call twice m_avoid_crossing_perimeters.travel_to.
const bool used_external_mp_once = m_avoid_crossing_perimeters.used_external_mp_once();
// if a retraction would be needed, try to use avoid_crossing_perimeters to plan a // if a retraction would be needed, try to use avoid_crossing_perimeters to plan a
// multi-hop travel path inside the configuration space // multi-hop travel path inside the configuration space
@ -2870,8 +2882,13 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
// Because of it, it is necessary to call avoid crossing perimeters again with new starting point after calling retraction() // Because of it, it is necessary to call avoid crossing perimeters again with new starting point after calling retraction()
// FIXME Lukas H.: Try to predict if this second calling of avoid crossing perimeters will be needed or not. It could save computations. // FIXME Lukas H.: Try to predict if this second calling of avoid crossing perimeters will be needed or not. It could save computations.
if (last_post_before_retract != this->last_pos() && m_config.avoid_crossing_perimeters) { if (last_post_before_retract != this->last_pos() && m_config.avoid_crossing_perimeters) {
Polyline retract_travel = m_avoid_crossing_perimeters.travel_to(*this, point); // If in the previous call of m_avoid_crossing_perimeters.travel_to was use_external_mp_once set to true restore this value for next call.
travel = std::move(retract_travel); if (used_external_mp_once)
m_avoid_crossing_perimeters.use_external_mp_once();
travel = m_avoid_crossing_perimeters.travel_to(*this, point);
// If state of use_external_mp_once was changed reset it to right value.
if (used_external_mp_once)
m_avoid_crossing_perimeters.reset_once_modifiers();
} }
} else } else
// Reset the wipe path when traveling, so one would not wipe along an old path. // Reset the wipe path when traveling, so one would not wipe along an old path.

View file

@ -18,6 +18,7 @@ public:
// Routing around the objects vs. inside a single object. // Routing around the objects vs. inside a single object.
void use_external_mp(bool use = true) { m_use_external_mp = use; }; void use_external_mp(bool use = true) { m_use_external_mp = use; };
void use_external_mp_once() { m_use_external_mp_once = true; } void use_external_mp_once() { m_use_external_mp_once = true; }
bool used_external_mp_once() { return m_use_external_mp_once; }
void disable_once() { m_disabled_once = true; } void disable_once() { m_disabled_once = true; }
bool disabled_once() const { return m_disabled_once; } bool disabled_once() const { return m_disabled_once; }
void reset_once_modifiers() { m_use_external_mp_once = false; m_disabled_once = false; } void reset_once_modifiers() { m_use_external_mp_once = false; m_disabled_once = false; }

View file

@ -4,6 +4,9 @@
#include "GCodeProcessor.hpp" #include "GCodeProcessor.hpp"
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#if ENABLE_VALIDATE_CUSTOM_GCODE
#include <boost/algorithm/string/predicate.hpp>
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#include <boost/nowide/cstdio.hpp> #include <boost/nowide/cstdio.hpp>
#if ENABLE_GCODE_WINDOW #if ENABLE_GCODE_WINDOW
@ -597,12 +600,6 @@ const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProces
unsigned int GCodeProcessor::s_result_id = 0; unsigned int GCodeProcessor::s_result_id = 0;
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
{
size_t tag_len = tag.size();
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
}
bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string& found_tag) bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string& found_tag)
{ {
bool ret = false; bool ret = false;
@ -613,7 +610,7 @@ bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string
if (comment.length() > 2 && comment.front() == ';') { if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1); comment = comment.substr(1);
for (const std::string& s : Reserved_Tags) { for (const std::string& s : Reserved_Tags) {
if (starts_with(comment, s)) { if (boost::starts_with(comment, s)) {
ret = true; ret = true;
found_tag = comment; found_tag = comment;
parser.quit_parsing(); parser.quit_parsing();
@ -638,7 +635,7 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i
if (comment.length() > 2 && comment.front() == ';') { if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1); comment = comment.substr(1);
for (const std::string& s : Reserved_Tags) { for (const std::string& s : Reserved_Tags) {
if (starts_with(comment, s)) { if (boost::starts_with(comment, s)) {
ret = true; ret = true;
found_tag.push_back(comment); found_tag.push_back(comment);
if (found_tag.size() == max_count) { if (found_tag.size() == max_count) {
@ -681,6 +678,8 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_extruder_colors[i] = static_cast<unsigned char>(i); m_extruder_colors[i] = static_cast<unsigned char>(i);
} }
m_extruder_temps.resize(extruders_count);
m_filament_diameters.resize(config.filament_diameter.values.size()); m_filament_diameters.resize(config.filament_diameter.values.size());
for (size_t i = 0; i < config.filament_diameter.values.size(); ++i) { for (size_t i = 0; i < config.filament_diameter.values.size(); ++i) {
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]); m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
@ -708,10 +707,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
} }
m_time_processor.export_remaining_time_enabled = config.remaining_times.value; m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
m_use_volumetric_e = config.use_volumetric_e; m_use_volumetric_e = config.use_volumetric_e;
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
} }
void GCodeProcessor::apply_config(const DynamicPrintConfig& config) void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@ -782,6 +778,8 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
m_extruder_colors[i] = static_cast<unsigned char>(i); m_extruder_colors[i] = static_cast<unsigned char>(i);
} }
m_extruder_temps.resize(m_result.extruders_count);
const ConfigOptionFloats* filament_load_time = config.option<ConfigOptionFloats>("filament_load_time"); const ConfigOptionFloats* filament_load_time = config.option<ConfigOptionFloats>("filament_load_time");
if (filament_load_time != nullptr) { if (filament_load_time != nullptr) {
m_time_processor.filament_load_times.resize(filament_load_time->values.size()); m_time_processor.filament_load_times.resize(filament_load_time->values.size());
@ -873,11 +871,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1) if (m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1)
enable_stealth_time_estimator(true); enable_stealth_time_estimator(true);
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e"); const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e");
if (use_volumetric_e != nullptr) if (use_volumetric_e != nullptr)
m_use_volumetric_e = use_volumetric_e->value; m_use_volumetric_e = use_volumetric_e->value;
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
} }
void GCodeProcessor::enable_stealth_time_estimator(bool enabled) void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
@ -918,6 +914,10 @@ void GCodeProcessor::reset()
for (size_t i = 0; i < Min_Extruder_Count; ++i) { for (size_t i = 0; i < Min_Extruder_Count; ++i) {
m_extruder_colors[i] = static_cast<unsigned char>(i); m_extruder_colors[i] = static_cast<unsigned char>(i);
} }
m_extruder_temps.resize(Min_Extruder_Count);
for (size_t i = 0; i < Min_Extruder_Count; ++i) {
m_extruder_temps[i] = 0.0f;
}
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f); m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
m_extruded_last_z = 0.0f; m_extruded_last_z = 0.0f;
@ -933,9 +933,7 @@ void GCodeProcessor::reset()
m_result.reset(); m_result.reset();
m_result.id = ++s_result_id; m_result.id = ++s_result_id;
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
m_use_volumetric_e = false; m_use_volumetric_e = false;
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_mm3_per_mm_compare.reset(); m_mm3_per_mm_compare.reset();
@ -1136,9 +1134,11 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
case 1: { process_M1(line); break; } // Sleep or Conditional stop case 1: { process_M1(line); break; } // Sleep or Conditional stop
case 82: { process_M82(line); break; } // Set extruder to absolute mode case 82: { process_M82(line); break; } // Set extruder to absolute mode
case 83: { process_M83(line); break; } // Set extruder to relative mode case 83: { process_M83(line); break; } // Set extruder to relative mode
case 104: { process_M104(line); break; } // Set extruder temperature
case 106: { process_M106(line); break; } // Set fan speed case 106: { process_M106(line); break; } // Set fan speed
case 107: { process_M107(line); break; } // Disable fan case 107: { process_M107(line); break; } // Disable fan
case 108: { process_M108(line); break; } // Set tool (Sailfish) case 108: { process_M108(line); break; } // Set tool (Sailfish)
case 109: { process_M109(line); break; } // Set extruder temperature and wait
case 132: { process_M132(line); break; } // Recall stored home offsets case 132: { process_M132(line); break; } // Recall stored home offsets
case 135: { process_M135(line); break; } // Set tool (MakerWare) case 135: { process_M135(line); break; } // Set tool (MakerWare)
case 201: { process_M201(line); break; } // Set max printing acceleration case 201: { process_M201(line); break; } // Set max printing acceleration
@ -1171,14 +1171,6 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
} }
} }
#if !ENABLE_VALIDATE_CUSTOM_GCODE
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
{
size_t tag_len = tag.size();
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
}
#endif // !ENABLE_VALIDATE_CUSTOM_GCODE
#if __has_include(<charconv>) #if __has_include(<charconv>)
template <typename T, typename = void> template <typename T, typename = void>
struct is_from_chars_convertible : std::false_type {}; struct is_from_chars_convertible : std::false_type {};
@ -1232,37 +1224,37 @@ void GCodeProcessor::process_tags(const std::string_view comment)
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
// extrusion role tag // extrusion role tag
if (starts_with(comment, reserved_tag(ETags::Role))) { if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length())); m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
return; return;
} }
// wipe start tag // wipe start tag
if (starts_with(comment, reserved_tag(ETags::Wipe_Start))) { if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
m_wiping = true; m_wiping = true;
return; return;
} }
// wipe end tag // wipe end tag
if (starts_with(comment, reserved_tag(ETags::Wipe_End))) { if (boost::starts_with(comment, reserved_tag(ETags::Wipe_End))) {
m_wiping = false; m_wiping = false;
return; return;
} }
#else #else
// extrusion role tag // extrusion role tag
if (starts_with(comment, Extrusion_Role_Tag)) { if (boost::starts_with(comment, Extrusion_Role_Tag)) {
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(Extrusion_Role_Tag.length())); m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(Extrusion_Role_Tag.length()));
return; return;
} }
// wipe start tag // wipe start tag
if (starts_with(comment, Wipe_Start_Tag)) { if (boost::starts_with(comment, Wipe_Start_Tag)) {
m_wiping = true; m_wiping = true;
return; return;
} }
// wipe end tag // wipe end tag
if (starts_with(comment, Wipe_End_Tag)) { if (boost::starts_with(comment, Wipe_End_Tag)) {
m_wiping = false; m_wiping = false;
return; return;
} }
@ -1271,26 +1263,26 @@ void GCodeProcessor::process_tags(const std::string_view comment)
if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) { if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) {
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
// height tag // height tag
if (starts_with(comment, reserved_tag(ETags::Height))) { if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height)) if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
return; return;
} }
// width tag // width tag
if (starts_with(comment, reserved_tag(ETags::Width))) { if (boost::starts_with(comment, reserved_tag(ETags::Width))) {
if (!parse_number(comment.substr(reserved_tag(ETags::Width).size()), m_forced_width)) if (!parse_number(comment.substr(reserved_tag(ETags::Width).size()), m_forced_width))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
return; return;
} }
#else #else
// height tag // height tag
if (starts_with(comment, Height_Tag)) { if (boost::starts_with(comment, Height_Tag)) {
if (!parse_number(comment.substr(Height_Tag.size()), m_forced_height)) if (!parse_number(comment.substr(Height_Tag.size()), m_forced_height))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
return; return;
} }
// width tag // width tag
if (starts_with(comment, Width_Tag)) { if (boost::starts_with(comment, Width_Tag)) {
if (!parse_number(comment.substr(Width_Tag.size()), m_forced_width)) if (!parse_number(comment.substr(Width_Tag.size()), m_forced_width))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
return; return;
@ -1300,9 +1292,9 @@ void GCodeProcessor::process_tags(const std::string_view comment)
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
// color change tag // color change tag
if (starts_with(comment, reserved_tag(ETags::Color_Change))) { if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) {
unsigned char extruder_id = 0; unsigned char extruder_id = 0;
if (starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) { if (boost::starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) {
int eid; int eid;
if (!parse_number(comment.substr(reserved_tag(ETags::Color_Change).size() + 2), eid) || eid < 0 || eid > 255) { if (!parse_number(comment.substr(reserved_tag(ETags::Color_Change).size() + 2), eid) || eid < 0 || eid > 255) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
@ -1346,9 +1338,9 @@ void GCodeProcessor::process_tags(const std::string_view comment)
} }
#else #else
// color change tag // color change tag
if (starts_with(comment, Color_Change_Tag)) { if (boost::starts_with(comment, Color_Change_Tag)) {
unsigned char extruder_id = 0; unsigned char extruder_id = 0;
if (starts_with(comment.substr(Color_Change_Tag.size()), ",T")) { if (boost::starts_with(comment.substr(Color_Change_Tag.size()), ",T")) {
int eid; int eid;
if (! parse_number(comment.substr(Color_Change_Tag.size() + 2), eid) || eid < 0 || eid > 255) { if (! parse_number(comment.substr(Color_Change_Tag.size() + 2), eid) || eid < 0 || eid > 255) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
@ -1394,7 +1386,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
// mm3_per_mm print tag // mm3_per_mm print tag
if (starts_with(comment, Mm3_Per_Mm_Tag)) { if (boost::starts_with(comment, Mm3_Per_Mm_Tag)) {
if (! parse_number(comment.substr(Mm3_Per_Mm_Tag.size()), m_mm3_per_mm_compare.last_tag_value)) if (! parse_number(comment.substr(Mm3_Per_Mm_Tag.size()), m_mm3_per_mm_compare.last_tag_value))
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ").";
return; return;
@ -1846,14 +1838,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
{ {
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back(); float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back();
float filament_radius = 0.5f * filament_diameter; float filament_radius = 0.5f * filament_diameter;
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius); float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) { auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
#else
auto absolute_position = [this](Axis axis, const GCodeReader::GCodeLine& lineG1) {
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
bool is_relative = (m_global_positioning_type == EPositioningType::Relative); bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
if (axis == E) if (axis == E)
is_relative |= (m_e_local_positioning_type == EPositioningType::Relative); is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
@ -1861,10 +1849,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (lineG1.has(Slic3r::Axis(axis))) { if (lineG1.has(Slic3r::Axis(axis))) {
float lengthsScaleFactor = (m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f; float lengthsScaleFactor = (m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor; float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
if (axis == E && m_use_volumetric_e) if (axis == E && m_use_volumetric_e)
ret /= area_filament_cross_section; ret /= area_filament_cross_section;
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret; return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
} }
else else
@ -1922,11 +1908,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (type == EMoveType::Extrude) { if (type == EMoveType::Extrude) {
float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
#if !ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back();
float filament_radius = 0.5f * filament_diameter;
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
#endif // !ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
@ -2235,6 +2216,13 @@ void GCodeProcessor::process_M83(const GCodeReader::GCodeLine& line)
m_e_local_positioning_type = EPositioningType::Relative; m_e_local_positioning_type = EPositioningType::Relative;
} }
void GCodeProcessor::process_M104(const GCodeReader::GCodeLine& line)
{
float new_temp;
if (line.has_value('S', new_temp))
m_extruder_temps[m_extruder_id] = new_temp;
}
void GCodeProcessor::process_M106(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_M106(const GCodeReader::GCodeLine& line)
{ {
if (!line.has('P')) { if (!line.has('P')) {
@ -2267,6 +2255,21 @@ void GCodeProcessor::process_M108(const GCodeReader::GCodeLine& line)
process_T(cmd.substr(pos)); process_T(cmd.substr(pos));
} }
void GCodeProcessor::process_M109(const GCodeReader::GCodeLine& line)
{
float new_temp;
if (line.has_value('R', new_temp)) {
float val;
if (line.has_value('T', val)) {
size_t eid = static_cast<size_t>(val);
if (eid < m_extruder_temps.size())
m_extruder_temps[eid] = new_temp;
}
else
m_extruder_temps[m_extruder_id] = new_temp;
}
}
void GCodeProcessor::process_M132(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_M132(const GCodeReader::GCodeLine& line)
{ {
// This command is used by Makerbot to load the current home position from EEPROM // This command is used by Makerbot to load the current home position from EEPROM
@ -2555,6 +2558,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
m_height, m_height,
m_mm3_per_mm, m_mm3_per_mm,
m_fan_speed, m_fan_speed,
m_extruder_temps[m_extruder_id],
static_cast<float>(m_result.moves.size()) static_cast<float>(m_result.moves.size())
}; };
m_result.moves.emplace_back(vertex); m_result.moves.emplace_back(vertex);

View file

@ -121,6 +121,7 @@ namespace Slic3r {
private: private:
using AxisCoords = std::array<float, 4>; using AxisCoords = std::array<float, 4>;
using ExtruderColors = std::vector<unsigned char>; using ExtruderColors = std::vector<unsigned char>;
using ExtruderTemps = std::vector<float>;
enum class EUnits : unsigned char enum class EUnits : unsigned char
{ {
@ -211,6 +212,7 @@ namespace Slic3r {
float height{ 0.0f }; // mm float height{ 0.0f }; // mm
float mm3_per_mm{ 0.0f }; float mm3_per_mm{ 0.0f };
float fan_speed{ 0.0f }; // percentage float fan_speed{ 0.0f }; // percentage
float temperature{ 0.0f }; // Celsius degrees
float time{ 0.0f }; // s float time{ 0.0f }; // s
float volumetric_rate() const { return feedrate * mm3_per_mm; } float volumetric_rate() const { return feedrate * mm3_per_mm; }
@ -320,6 +322,7 @@ namespace Slic3r {
float height{ 0.0f }; // mm float height{ 0.0f }; // mm
float mm3_per_mm{ 0.0f }; float mm3_per_mm{ 0.0f };
float fan_speed{ 0.0f }; // percentage float fan_speed{ 0.0f }; // percentage
float temperature{ 0.0f }; // Celsius degrees
float time{ 0.0f }; // s float time{ 0.0f }; // s
float volumetric_rate() const { return feedrate * mm3_per_mm; } float volumetric_rate() const { return feedrate * mm3_per_mm; }
@ -470,14 +473,13 @@ namespace Slic3r {
ExtrusionRole m_extrusion_role; ExtrusionRole m_extrusion_role;
unsigned char m_extruder_id; unsigned char m_extruder_id;
ExtruderColors m_extruder_colors; ExtruderColors m_extruder_colors;
ExtruderTemps m_extruder_temps;
std::vector<float> m_filament_diameters; std::vector<float> m_filament_diameters;
float m_extruded_last_z; float m_extruded_last_z;
unsigned int m_g1_line_id; unsigned int m_g1_line_id;
unsigned int m_layer_id; unsigned int m_layer_id;
CpColor m_cp_color; CpColor m_cp_color;
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
bool m_use_volumetric_e; bool m_use_volumetric_e;
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
enum class EProducer enum class EProducer
{ {
@ -590,6 +592,9 @@ namespace Slic3r {
// Set extruder to relative mode // Set extruder to relative mode
void process_M83(const GCodeReader::GCodeLine& line); void process_M83(const GCodeReader::GCodeLine& line);
// Set extruder temperature
void process_M104(const GCodeReader::GCodeLine& line);
// Set fan speed // Set fan speed
void process_M106(const GCodeReader::GCodeLine& line); void process_M106(const GCodeReader::GCodeLine& line);
@ -599,6 +604,9 @@ namespace Slic3r {
// Set tool (Sailfish) // Set tool (Sailfish)
void process_M108(const GCodeReader::GCodeLine& line); void process_M108(const GCodeReader::GCodeLine& line);
// Set extruder temperature and wait
void process_M109(const GCodeReader::GCodeLine& line);
// Recall stored home offsets // Recall stored home offsets
void process_M132(const GCodeReader::GCodeLine& line); void process_M132(const GCodeReader::GCodeLine& line);

View file

@ -70,6 +70,20 @@ unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, c
return (extruder == 0) ? 0 : extruder - 1; return (extruder == 0) ? 0 : extruder - 1;
} }
static double calc_max_layer_height(const PrintConfig &config, double max_object_layer_height)
{
double max_layer_height = std::numeric_limits<double>::max();
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
double mlh = config.max_layer_height.values[i];
if (mlh == 0.)
mlh = 0.75 * config.nozzle_diameter.values[i];
max_layer_height = std::min(max_layer_height, mlh);
}
// The Prusa3D Fast (0.35mm layer height) print profile sets a higher layer height than what is normally allowed
// by the nozzle. This is a hack and it works by increasing extrusion width. See GH #3919.
return std::max(max_layer_height, max_object_layer_height);
}
// For the use case when each object is printed separately // For the use case when each object is printed separately
// (print.config().complete_objects is true). // (print.config().complete_objects is true).
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material) ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
@ -87,6 +101,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
zs.emplace_back(layer->print_z); zs.emplace_back(layer->print_z);
this->initialize_layers(zs); this->initialize_layers(zs);
} }
double max_layer_height = calc_max_layer_height(object.print()->config(), object.config().layer_height);
// Collect extruders reuqired to print the layers. // Collect extruders reuqired to print the layers.
this->collect_extruders(object, std::vector<std::pair<double, unsigned int>>()); this->collect_extruders(object, std::vector<std::pair<double, unsigned int>>());
@ -94,9 +109,11 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
// Reorder the extruders to minimize tool switches. // Reorder the extruders to minimize tool switches.
this->reorder_extruders(first_extruder); this->reorder_extruders(first_extruder);
this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, object.config().layer_height); this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, max_layer_height);
this->collect_extruder_statistics(prime_multi_material); this->collect_extruder_statistics(prime_multi_material);
this->mark_skirt_layers(object.print()->config(), max_layer_height);
} }
// For the use case when all objects are printed at once. // For the use case when all objects are printed at once.
@ -128,6 +145,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
} }
this->initialize_layers(zs); this->initialize_layers(zs);
} }
max_layer_height = calc_max_layer_height(print.config(), max_layer_height);
// Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object. // Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object.
// Do it only if all the objects were configured to be printed with a single extruder. // Do it only if all the objects were configured to be printed with a single extruder.
@ -150,6 +168,8 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
this->collect_extruder_statistics(prime_multi_material); this->collect_extruder_statistics(prime_multi_material);
this->mark_skirt_layers(print.config(), max_layer_height);
} }
void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs) void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
@ -321,7 +341,7 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id)
} }
} }
void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_object_layer_height) void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height)
{ {
if (m_layer_tools.empty()) if (m_layer_tools.empty())
return; return;
@ -347,17 +367,6 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
lt.has_wipe_tower = (lt.has_object && lt.wipe_tower_partitions > 0) || lt.print_z < object_bottom_z + EPSILON; lt.has_wipe_tower = (lt.has_object && lt.wipe_tower_partitions > 0) || lt.print_z < object_bottom_z + EPSILON;
// Test for a raft, insert additional wipe tower layer to fill in the raft separation gap. // Test for a raft, insert additional wipe tower layer to fill in the raft separation gap.
double max_layer_height = std::numeric_limits<double>::max();
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
double mlh = config.max_layer_height.values[i];
if (mlh == 0.)
mlh = 0.75 * config.nozzle_diameter.values[i];
max_layer_height = std::min(max_layer_height, mlh);
}
// The Prusa3D Fast (0.35mm layer height) print profile sets a higher layer height than what is normally allowed
// by the nozzle. This is a hack and it works by increasing extrusion width. See GH #3919.
max_layer_height = std::max(max_layer_height, max_object_layer_height);
for (size_t i = 0; i + 1 < m_layer_tools.size(); ++ i) { for (size_t i = 0; i + 1 < m_layer_tools.size(); ++ i) {
const LayerTools &lt = m_layer_tools[i]; const LayerTools &lt = m_layer_tools[i];
const LayerTools &lt_next = m_layer_tools[i + 1]; const LayerTools &lt_next = m_layer_tools[i + 1];
@ -460,6 +469,48 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
} }
} }
// Layers are marked for infinite skirt aka draft shield. Not all the layers have to be printed.
void ToolOrdering::mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height)
{
if (m_layer_tools.empty())
return;
if (m_layer_tools.front().extruders.empty()) {
// Empty first layer, no skirt will be printed.
//FIXME throw an exception?
return;
}
size_t i = 0;
for (;;) {
m_layer_tools[i].has_skirt = true;
size_t j = i + 1;
for (; j < m_layer_tools.size() && ! m_layer_tools[j].has_object; ++ j);
// i and j are two successive layers printing an object.
if (j == m_layer_tools.size())
// Don't print skirt above the last object layer.
break;
// Mark some printing intermediate layers as having skirt.
double last_z = m_layer_tools[i].print_z;
for (size_t k = i + 1; k < j; ++ k) {
if (m_layer_tools[k + 1].print_z - last_z > max_layer_height + EPSILON) {
// Layer k is the last one not violating the maximum layer height.
// Don't extrude skirt on empty layers.
while (m_layer_tools[k].extruders.empty())
-- k;
if (m_layer_tools[k].has_skirt) {
// Skirt cannot be generated due to empty layers, there would be a missing layer in the skirt.
//FIXME throw an exception?
break;
}
m_layer_tools[k].has_skirt = true;
last_z = m_layer_tools[k].print_z;
}
}
i = j;
}
}
// Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools. // Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools.
// Ignore color changes, which are performed on a layer and for such an extruder, that the extruder will not be printing above that layer. // Ignore color changes, which are performed on a layer and for such an extruder, that the extruder will not be printing above that layer.
// If multiple events are planned over a span of a single layer, use the last one. // If multiple events are planned over a span of a single layer, use the last one.

View file

@ -17,8 +17,6 @@ class LayerTools;
namespace CustomGCode { struct Item; } namespace CustomGCode { struct Item; }
class PrintRegion; class PrintRegion;
// Object of this class holds information about whether an extrusion is printed immediately // Object of this class holds information about whether an extrusion is printed immediately
// after a toolchange (as part of infill/perimeter wiping) or not. One extrusion can be a part // after a toolchange (as part of infill/perimeter wiping) or not. One extrusion can be a part
// of several copies - this has to be taken into account. // of several copies - this has to be taken into account.
@ -69,8 +67,6 @@ private:
const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to
}; };
class LayerTools class LayerTools
{ {
public: public:
@ -99,6 +95,9 @@ public:
// If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with. // If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with.
// If not overriden, it is set to 0. // If not overriden, it is set to 0.
unsigned int extruder_override = 0; unsigned int extruder_override = 0;
// Should a skirt be printed at this layer?
// Layers are marked for infinite skirt aka draft shield. Not all the layers have to be printed.
bool has_skirt = false;
// Will there be anything extruded on this layer for the wipe tower? // Will there be anything extruded on this layer for the wipe tower?
// Due to the support layers possibly interleaving the object layers, // Due to the support layers possibly interleaving the object layers,
// wipe tower will be disabled for some support only layers. // wipe tower will be disabled for some support only layers.
@ -120,12 +119,10 @@ private:
WipingExtrusions m_wiping_extrusions; WipingExtrusions m_wiping_extrusions;
}; };
class ToolOrdering class ToolOrdering
{ {
public: public:
ToolOrdering() {} ToolOrdering() = default;
// For the use case when each object is printed separately // For the use case when each object is printed separately
// (print.config.complete_objects is true). // (print.config.complete_objects is true).
@ -169,6 +166,7 @@ private:
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches); void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches);
void reorder_extruders(unsigned int last_extruder_id); void reorder_extruders(unsigned int last_extruder_id);
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height); void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height);
void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height);
void collect_extruder_statistics(bool prime_multi_material); void collect_extruder_statistics(bool prime_multi_material);
std::vector<LayerTools> m_layer_tools; std::vector<LayerTools> m_layer_tools;
@ -182,8 +180,6 @@ private:
const PrintConfig* m_print_config_ptr = nullptr; const PrintConfig* m_print_config_ptr = nullptr;
}; };
} // namespace SLic3r } // namespace SLic3r
#endif /* slic3r_ToolOrdering_hpp_ */ #endif /* slic3r_ToolOrdering_hpp_ */

View file

@ -245,8 +245,7 @@ Polygon convex_hull(Points points)
return hull; return hull;
} }
Pointf3s Pointf3s convex_hull(Pointf3s points)
convex_hull(Pointf3s points)
{ {
assert(points.size() >= 3); assert(points.size() >= 3);
// sort input points // sort input points
@ -304,8 +303,7 @@ convex_hull(Pointf3s points)
return hull; return hull;
} }
Polygon Polygon convex_hull(const Polygons &polygons)
convex_hull(const Polygons &polygons)
{ {
Points pp; Points pp;
for (Polygons::const_iterator p = polygons.begin(); p != polygons.end(); ++p) { for (Polygons::const_iterator p = polygons.begin(); p != polygons.end(); ++p) {

View file

@ -0,0 +1,242 @@
#include "MutablePolygon.hpp"
#include "Line.hpp"
namespace Slic3r {
// Remove exact duplicate points. May reduce the polygon down to empty polygon.
void remove_duplicates(MutablePolygon &polygon)
{
if (! polygon.empty()) {
auto begin = polygon.begin();
auto it = begin;
for (++ it; it != begin;) {
auto prev = it.prev();
if (*prev == *it)
it = it.remove();
else
++ it;
}
}
}
// Remove nearly duplicate points. May reduce the polygon down to empty polygon.
void remove_duplicates(MutablePolygon &polygon, double eps)
{
if (! polygon.empty()) {
auto eps2 = eps * eps;
auto begin = polygon.begin();
auto it = begin;
for (++ it; it != begin;) {
auto prev = it.prev();
if ((*it - *prev).cast<double>().squaredNorm() < eps2)
it = it.remove();
else
++ it;
}
}
}
// Sample a point on line (a, b) at distance "dist" from ref_pt.
// If two points fulfill the condition, then the first one (closer to point a) is taken.
// If none of the two points falls on line (a, b), return false.
template<typename VectorType>
static inline VectorType point_on_line_at_dist(const VectorType &a, const VectorType &b, const VectorType &ref_pt, const double dist)
{
using T = typename VectorType::Scalar;
auto v = b - a;
auto l2 = v.squaredNorm();
assert(l2 > T(0));
auto vpt = ref_pt - a;
// Parameter of the foot point of ref_pt on line (a, b).
auto t = v.dot(vpt) / l2;
// Foot point of ref_pt on line (a, b).
auto foot_pt = a + t * v;
auto dfoot2 = vpt.squaredNorm() - (foot_pt - ref_pt).squaredNorm();
// Distance of the result point from the foot point, normalized to length of (a, b).
auto dfoot = dfoot2 > T(0) ? sqrt(dfoot2) / sqrt(l2) : T(0);
auto t_result = t - dfoot;
if (t_result < T(0))
t_result = t + dfoot;
t_result = Slic3r::clamp(0., 1., t_result);
return a + v * t;
}
static bool smooth_corner_complex(const Vec2d p1, MutablePolygon::iterator &it0, MutablePolygon::iterator &it2, const double shortcut_length)
{
// walk away from the corner until the shortcut > shortcut_length or it would smooth a piece inward
// - walk in both directions untill shortcut > shortcut_length
// - stop walking in one direction if it would otherwise cut off a corner in that direction
// - same in the other direction
// - stop if both are cut off
// walk by updating p0_it and p2_it
double shortcut_length2 = shortcut_length * shortcut_length;
bool forward_is_blocked = false;
bool forward_is_too_far = false;
bool backward_is_blocked = false;
bool backward_is_too_far = false;
for (;;) {
const bool forward_has_converged = forward_is_blocked || forward_is_too_far;
const bool backward_has_converged = backward_is_blocked || backward_is_too_far;
if (forward_has_converged && backward_has_converged) {
if (forward_is_too_far && backward_is_too_far && (*it0.prev() - *it2.next()).cast<double>().squaredNorm() < shortcut_length2) {
// Trim the narrowing region.
-- it0;
++ it2;
forward_is_too_far = false;
backward_is_too_far = false;
continue;
} else
break;
}
const Vec2d p0 = it0->cast<double>();
const Vec2d p2 = it2->cast<double>();
if (! forward_has_converged && (backward_has_converged || (p2 - p1).squaredNorm() < (p0 - p1).squaredNorm())) {
// walk forward
const auto it2_2 = it2.next();
const Vec2d p2_2 = it2_2->cast<double>();
if (cross2(p2 - p0, p2_2 - p0) > 0) {
forward_is_blocked = true;
} else if ((p2_2 - p0).squaredNorm() > shortcut_length2) {
forward_is_too_far = true;
} else {
it2 = it2_2; // make one step in the forward direction
backward_is_blocked = false; // invalidate data about backward walking
backward_is_too_far = false;
}
} else {
// walk backward
const auto it0_2 = it0.prev();
const Vec2d p0_2 = it0_2->cast<double>();
if (cross2(p0_2 - p0, p2 - p0_2) > 0) {
backward_is_blocked = true;
} else if ((p2 - p0_2).squaredNorm() > shortcut_length2) {
backward_is_too_far = true;
} else {
it0 = it0_2; // make one step in the backward direction
forward_is_blocked = false; // invalidate data about forward walking
forward_is_too_far = false;
}
}
if (it0.prev() == it2 || it0 == it2) {
// stop if we went all the way around the polygon
// this should only be the case for hole polygons (?)
if (forward_is_too_far && backward_is_too_far) {
// in case p0_it.prev() == p2_it :
// / .
// / /|
// | becomes | |
// \ \|
// \ .
// in case p0_it == p2_it :
// / .
// / becomes /|
// \ \|
// \ .
break;
} else {
// this whole polygon can be removed
return true;
}
}
}
const Vec2d p0 = it0->cast<double>();
const Vec2d p2 = it2->cast<double>();
const Vec2d v02 = p2 - p0;
const int64_t l2_v02 = v02.squaredNorm();
if (std::abs(l2_v02 - shortcut_length2) < shortcut_length * 10) // i.e. if (size2 < l * (l+10) && size2 > l * (l-10))
{ // v02 is approximately shortcut length
// handle this separately to avoid rounding problems below in the getPointOnLineWithDist function
// p0_it and p2_it are already correct
} else if (! backward_is_blocked && ! forward_is_blocked) {
const auto l_v02 = sqrt(l2_v02);
const Vec2d p0_2 = it0.prev()->cast<double>();
const Vec2d p2_2 = it2.next()->cast<double>();
double t = Slic3r::clamp(0., 1., (shortcut_length - l_v02) / ((p2_2 - p0_2).norm() - l_v02));
it0 = it0.prev().insert((p0 + (p0_2 - p0) * t).cast<coord_t>());
it2 = it2.insert((p2 + (p2_2 - p2) * t).cast<coord_t>());
} else if (! backward_is_blocked) {
it0 = it0.prev().insert(point_on_line_at_dist(p0, Vec2d(it0.prev()->cast<double>()), p2, shortcut_length).cast<coord_t>());
} else if (! forward_is_blocked) {
it2 = it2.insert(point_on_line_at_dist(p2, Vec2d(it2.next()->cast<double>()), p0, shortcut_length).cast<coord_t>());
} else {
// |
// __|2
// | / > shortcut cannot be of the desired length
// ___|/ .
// 0
// both are blocked and p0_it and p2_it are already correct
}
// Delete all the points between it0 and it2.
while (it0.next() != it2)
it0.next().remove();
return false;
}
void smooth_outward(MutablePolygon &polygon, double shortcut_length)
{
remove_duplicates(polygon, scaled<double>(0.01));
const int shortcut_length2 = shortcut_length * shortcut_length;
static constexpr const double cos_min_angle = -0.70710678118654752440084436210485; // cos(135 degrees)
MutablePolygon::iterator it1 = polygon.begin();
do {
const Vec2d p1 = it1->cast<double>();
auto it0 = it1.prev();
auto it2 = it1.next();
const Vec2d p0 = it0->cast<double>();
const Vec2d p2 = it2->cast<double>();
const Vec2d v1 = p0 - p1;
const Vec2d v2 = p2 - p1;
const double cos_angle = v1.dot(v2);
if (cos_angle < cos_min_angle && cross2(v1, v2) < 0) {
// Simplify the sharp angle.
const Vec2d v02 = p2 - p0;
const double l2_v02 = v02.squaredNorm();
if (l2_v02 >= shortcut_length2) {
// Trim an obtuse corner.
it1.remove();
if (l2_v02 > Slic3r::sqr(shortcut_length + SCALED_EPSILON)) {
double l2_1 = v1.squaredNorm();
double l2_2 = v2.squaredNorm();
bool trim = true;
if (cos_angle > 0.9999) {
// The triangle p0, p1, p2 is likely degenerate.
// Measure height of the triangle.
double d2 = l2_1 > l2_2 ? line_alg::distance_to_squared(Linef{ p0, p1 }, p2) : line_alg::distance_to_squared(Linef{ p2, p1 }, p0);
if (d2 < Slic3r::sqr(scaled<double>(0.02)))
trim = false;
}
if (trim) {
Vec2d bisector = v1 / l2_1 + v2 / l2_2;
double d1 = v1.dot(bisector) / l2_1;
double d2 = v2.dot(bisector) / l2_2;
double lbisector = bisector.norm();
if (d1 < shortcut_length && d2 < shortcut_length) {
it0.insert((p1 + v1 * (shortcut_length / d1)).cast<coord_t>())
.insert((p1 + v2 * (shortcut_length / d2)).cast<coord_t>());
} else if (v1.squaredNorm() < v2.squaredNorm())
it0.insert(point_on_line_at_dist(p1, p2, p0, shortcut_length).cast<coord_t>());
else
it0.insert(point_on_line_at_dist(p1, p0, p2, shortcut_length).cast<coord_t>());
}
}
} else {
bool remove_poly = smooth_corner_complex(p1, it0, it2, shortcut_length); // edits p0_it and p2_it!
if (remove_poly) {
// don't convert ListPolygon into result
return;
}
}
// update:
it1 = it2; // next point to consider for whether it's an internal corner
}
else
++ it1;
} while (it1 != polygon.begin());
}
} // namespace Slic3r

View file

@ -0,0 +1,227 @@
#ifndef slic3r_MutablePolygon_hpp_
#define slic3r_MutablePolygon_hpp_
#include "Point.hpp"
#include "Polygon.hpp"
namespace Slic3r {
class MutablePolygon
{
public:
using IndexType = int32_t;
using PointType = Point;
class const_iterator {
public:
bool operator==(const const_iterator &rhs) const { assert(m_data == rhs.m_data); assert(this->valid()); return m_idx == rhs.m_idx; }
bool operator!=(const const_iterator &rhs) const { return ! (*this == rhs); }
const_iterator& operator--() { assert(this->valid()); m_idx = m_data->at(m_idx).prev; return *this; }
const_iterator operator--(int) { const_iterator result(*this); --(*this); return result; }
const_iterator& operator++() { assert(this->valid()); m_idx = m_data->at(m_idx).next; return *this; }
const_iterator operator++(int) { const_iterator result(*this); ++(*this); return result; }
const_iterator prev() const { assert(this->valid()); return { m_data, m_data->at(m_idx).prev }; }
const_iterator next() const { assert(this->valid()); return { m_data, m_data->at(m_idx).next }; }
bool valid() const { return m_idx >= 0; }
const PointType& operator*() const { return m_data->at(m_idx).point; }
const PointType* operator->() const { return &m_data->at(m_idx).point; }
const MutablePolygon& polygon() const { assert(this->valid()); return *m_data; }
IndexType size() const { assert(this->valid()); return m_data->size(); }
private:
const_iterator(const MutablePolygon *data, IndexType idx) : m_data(data), m_idx(idx) {}
friend class MutablePolygon;
const MutablePolygon *m_data;
IndexType m_idx;
};
class iterator {
public:
bool operator==(const iterator &rhs) const { assert(m_data == rhs.m_data); assert(this->valid()); return m_idx == rhs.m_idx; }
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
iterator& operator--() { assert(this->valid()); m_idx = m_data->at(m_idx).prev; return *this; }
iterator operator--(int) { iterator result(*this); --(*this); return result; }
iterator& operator++() { assert(this->valid()); m_idx = m_data->at(m_idx).next; return *this; }
iterator operator++(int) { iterator result(*this); ++(*this); return result; }
iterator prev() const { assert(this->valid()); return { m_data, m_data->at(m_idx).prev }; }
iterator next() const { assert(this->valid()); return { m_data, m_data->at(m_idx).next }; }
bool valid() const { return m_idx >= 0; }
PointType& operator*() const { return m_data->at(m_idx).point; }
PointType* operator->() const { return &m_data->at(m_idx).point; }
MutablePolygon& polygon() const { assert(this->valid()); return *m_data; }
IndexType size() const { assert(this->valid()); return m_data->size(); }
iterator& remove() { this->m_idx = m_data->remove(*this).m_idx; return *this; }
iterator insert(const PointType pt) const { return m_data->insert(*this, pt); }
private:
iterator(MutablePolygon *data, IndexType idx) : m_data(data), m_idx(idx) {}
friend class MutablePolygon;
MutablePolygon *m_data;
IndexType m_idx;
};
MutablePolygon() = default;
MutablePolygon(const Polygon &rhs, size_t reserve = 0) : MutablePolygon(rhs.points.begin(), rhs.points.end(), reserve) {}
MutablePolygon(std::initializer_list<Point> rhs, size_t reserve = 0) : MutablePolygon(rhs.begin(), rhs.end(), reserve) {}
template<typename IT>
MutablePolygon(IT begin, IT end, size_t reserve = 0) {
m_size = IndexType(end - begin);
if (m_size > 0) {
m_head = 0;
m_data.reserve(std::max<size_t>(m_size, reserve));
auto i = IndexType(-1);
auto j = IndexType(1);
for (auto it = begin; it != end; ++ it)
m_data.push_back({ *it, i ++, j ++ });
m_data.front().prev = m_size - 1;
m_data.back ().next = 0;
}
};
Polygon polygon() const {
Polygon out;
if (this->valid()) {
out.points.reserve(this->size());
for (auto it = this->cbegin(); it != this->cend(); ++ it)
out.points.emplace_back(*it);
}
return out;
};
bool empty() const { return this->m_size == 0; }
size_t size() const { return this->m_size; }
size_t capacity() const { return this->m_data.capacity(); }
bool valid() const { return this->m_size >= 3; }
iterator begin() { return { this, m_head }; }
const_iterator cbegin() const { return { this, m_head }; }
const_iterator begin() const { return this->cbegin(); }
// End points to the last item before roll over. This is different from the usual end() concept!
iterator end() { return { this, this->empty() ? -1 : this->at(m_head).prev }; }
const_iterator cend() const { return { this, this->empty() ? -1 : this->at(m_head).prev }; }
const_iterator end() const { return this->cend(); }
// Returns iterator following the removed element. Returned iterator will become invalid if last point is removed.
// If begin() is removed, then the next element will become the new begin().
iterator remove(const iterator it) { assert(it.m_data == this); return { this, this->remove(it.m_idx) }; }
// Insert a new point before it. Returns iterator to the newly inserted point.
// begin() will not change, end() may point to the newly inserted point.
iterator insert(const iterator it, const PointType pt) { assert(it.m_data == this); return { this, this->insert(it.m_idx, pt) }; }
private:
struct LinkedPoint {
PointType point;
IndexType prev;
IndexType next;
};
std::vector<LinkedPoint> m_data;
// Number of points in the linked list.
IndexType m_size { 0 };
IndexType m_head { IndexType(-1) };
// Head of the free list.
IndexType m_head_free { IndexType(-1) };
LinkedPoint& at(IndexType i) { return m_data[i]; }
const LinkedPoint& at(IndexType i) const { return m_data[i]; }
IndexType remove(const IndexType i) {
assert(i >= 0);
assert(m_size > 0);
assert(m_head != -1);
LinkedPoint &lp = this->at(i);
IndexType prev = lp.prev;
IndexType next = lp.next;
lp.next = m_head_free;
m_head_free = i;
if (-- m_size == 0)
m_head = -1;
else if (m_head == i)
m_head = next;
assert(! this->empty() || (prev == i && next == i));
if (this->empty())
return IndexType(-1);
this->at(prev).next = next;
this->at(next).prev = prev;
return next;
}
IndexType insert(const IndexType i, const Point pt) {
assert(i >= 0);
IndexType n;
IndexType j = this->at(i).prev;
if (m_head_free == -1) {
// Allocate a new item.
n = IndexType(m_data.size());
m_data.push_back({ pt, j, i });
} else {
n = m_head_free;
LinkedPoint &nlp = this->at(n);
m_head_free = nlp.next;
nlp = { pt, j, i };
}
this->at(j).next = n;
this->at(i).prev = n;
++ m_size;
return n;
}
/*
IndexType insert(const IndexType i, const Point pt) {
assert(i >= 0);
if (this->at(i).point == pt)
return i;
IndexType j = this->at(i).next;
if (this->at(j).point == pt)
return i;
IndexType n;
if (m_head_free == -1) {
// Allocate a new item.
n = IndexType(m_data.size());
m_data.push_back({ pt, i, j });
} else {
LinkedPoint &nlp = this->at(m_head_free);
m_head_free = nlp.next;
nlp = { pt, i, j };
}
this->at(i).next = n;
this->at(j).prev = n;
++ m_size;
return n;
}
*/
};
inline bool operator==(const MutablePolygon &p1, const MutablePolygon &p2)
{
if (p1.size() != p2.size())
return false;
if (p1.empty())
return true;
auto begin = p1.cbegin();
auto it = begin;
auto it2 = p2.cbegin();
for (;;) {
if (! (*it == *it2))
return false;
if (++ it == begin)
return true;
++ it2;
}
}
inline bool operator!=(const MutablePolygon &p1, const MutablePolygon &p2) { return ! (p1 == p2); }
// Remove exact duplicate points. May reduce the polygon down to empty polygon.
void remove_duplicates(MutablePolygon &polygon);
void remove_duplicates(MutablePolygon &polygon, double eps);
void smooth_outward(MutablePolygon &polygon, double shortcut_length);
inline Polygon smooth_outward(const Polygon &polygon, double shortcut_length)
{
MutablePolygon mp(polygon, polygon.size() * 2);
smooth_outward(mp, shortcut_length);
return mp.polygon();
}
}
#endif // slic3r_MutablePolygon_hpp_

View file

@ -56,11 +56,21 @@ typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); } inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
// One likely does not want to perform the cross product with a 32bit accumulator. template<int Options>
//inline int32_t cross2(const Vec2i32 &v1, const Vec2i32 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } int32_t cross2(const Eigen::MatrixBase<Eigen::Matrix<int32_t, 2, 1, Options>> &v1, const Eigen::MatrixBase<Eigen::Matrix<int32_t, 2, 1, Options>> &v2) = delete;
inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } template<typename T, int Options>
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } inline T cross2(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v1, const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v2)
{
return v1(0) * v2(1) - v1(1) * v2(0);
}
template<typename Derived, typename Derived2>
inline typename Derived::Scalar cross2(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
{
static_assert(std::is_same<typename Derived::Scalar, typename Derived2::Scalar>::value, "cross2(): Scalar types of 1st and 2nd operand must be equal.");
return v1(0) * v2(1) - v1(1) * v2(0);
}
template<typename T, int Options> template<typename T, int Options>
inline Eigen::Matrix<T, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v) { return Eigen::Matrix<T, 2, 1, Eigen::DontAlign>(- v.y(), v.x()); } inline Eigen::Matrix<T, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v) { return Eigen::Matrix<T, 2, 1, Eigen::DontAlign>(- v.y(), v.x()); }

View file

@ -1393,9 +1393,8 @@ const std::vector<std::string>& PhysicalPrinter::printer_options()
static std::vector<std::string> s_opts; static std::vector<std::string> s_opts;
if (s_opts.empty()) { if (s_opts.empty()) {
s_opts = { s_opts = {
"preset_name", "preset_names",
"printer_technology", "printer_technology",
// "printer_model",
"host_type", "host_type",
"print_host", "print_host",
"printhost_apikey", "printhost_apikey",
@ -1453,11 +1452,10 @@ bool PhysicalPrinter::has_empty_config() const
void PhysicalPrinter::update_preset_names_in_config() void PhysicalPrinter::update_preset_names_in_config()
{ {
if (!preset_names.empty()) { if (!preset_names.empty()) {
std::string name; std::vector<std::string>& values = config.option<ConfigOptionStrings>("preset_names")->values;
for (auto el : preset_names) values.clear();
name += el + ";"; for (auto preset : preset_names)
name.pop_back(); values.push_back(preset);
config.set_key_value("preset_name", new ConfigOptionString(name));
} }
} }
@ -1482,14 +1480,13 @@ void PhysicalPrinter::update_from_config(const DynamicPrintConfig& new_config)
{ {
config.apply_only(new_config, printer_options(), false); config.apply_only(new_config, printer_options(), false);
std::string str = config.opt_string("preset_name"); const std::vector<std::string>& values = config.option<ConfigOptionStrings>("preset_names")->values;
std::set<std::string> values{};
if (!str.empty()) { if (values.empty())
boost::split(values, str, boost::is_any_of(";")); preset_names.clear();
else
for (const std::string& val : values) for (const std::string& val : values)
preset_names.emplace(val); preset_names.emplace(val);
}
preset_names = values;
} }
void PhysicalPrinter::reset_presets() void PhysicalPrinter::reset_presets()
@ -1817,7 +1814,7 @@ bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string&
return true; return true;
} }
// Get list of printers which have more than one preset and "preset_name" preset is one of them // Get list of printers which have more than one preset and "preset_names" preset is one of them
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name) std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name)
{ {
std::vector<std::string> printers; std::vector<std::string> printers;
@ -1832,7 +1829,7 @@ std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(con
return printers; return printers;
} }
// Get list of printers which has only "preset_name" preset // Get list of printers which has only "preset_names" preset
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_only_preset(const std::string& preset_name) std::vector<std::string> PhysicalPrinterCollection::get_printers_with_only_preset(const std::string& preset_name)
{ {
std::vector<std::string> printers; std::vector<std::string> printers;

View file

@ -685,9 +685,9 @@ public:
// returns true if all presets were deleted successfully. // returns true if all presets were deleted successfully.
bool delete_preset_from_printers(const std::string& preset_name); bool delete_preset_from_printers(const std::string& preset_name);
// Get list of printers which have more than one preset and "preset_name" preset is one of them // Get list of printers which have more than one preset and "preset_names" preset is one of them
std::vector<std::string> get_printers_with_preset( const std::string &preset_name); std::vector<std::string> get_printers_with_preset( const std::string &preset_name);
// Get list of printers which has only "preset_name" preset // Get list of printers which has only "preset_names" preset
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name); std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);
// Return the selected preset, without the user modifications applied. // Return the selected preset, without the user modifications applied.

View file

@ -876,6 +876,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
this->filament_presets[i] = loaded->name; this->filament_presets[i] = loaded->name;
} }
} }
// 4) Load the project config values (the per extruder wipe matrix etc). // 4) Load the project config values (the per extruder wipe matrix etc).
this->project_config.apply_only(config, s_project_options); this->project_config.apply_only(config, s_project_options);

View file

@ -94,12 +94,14 @@ std::string PrintBase::output_filepath(const std::string &path, const std::strin
return path; return path;
} }
void PrintBase::status_update_warnings(ObjectID object_id, int step, PrintStateBase::WarningLevel /* warning_level */, const std::string &message) void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel /* warning_level */, const std::string &message, const PrintObjectBase* print_object)
{ {
if (this->m_status_callback) if (this->m_status_callback) {
m_status_callback(SlicingStatus(*this, step)); auto status = print_object ? SlicingStatus(*print_object, step) : SlicingStatus(*this, step);
m_status_callback(status);
}
else if (! message.empty()) else if (! message.empty())
printf("%s warning: %s\n", (object_id == this->id()) ? "print" : "print object", message.c_str()); printf("%s warning: %s\n", print_object ? "print_object" : "print", message.c_str());
} }
tbb::mutex& PrintObjectBase::state_mutex(PrintBase *print) tbb::mutex& PrintObjectBase::state_mutex(PrintBase *print)
@ -114,7 +116,7 @@ std::function<void()> PrintObjectBase::cancel_callback(PrintBase *print)
void PrintObjectBase::status_update_warnings(PrintBase *print, int step, PrintStateBase::WarningLevel warning_level, const std::string &message) void PrintObjectBase::status_update_warnings(PrintBase *print, int step, PrintStateBase::WarningLevel warning_level, const std::string &message)
{ {
print->status_update_warnings(this->id(), step, warning_level, message); print->status_update_warnings(step, warning_level, message, this);
} }
} // namespace Slic3r } // namespace Slic3r

View file

@ -481,7 +481,7 @@ protected:
// Notify UI about a new warning of a milestone "step" on this PrintBase. // Notify UI about a new warning of a milestone "step" on this PrintBase.
// The UI will be notified by calling a status callback. // The UI will be notified by calling a status callback.
// If no status callback is registered, the message is printed to console. // If no status callback is registered, the message is printed to console.
void status_update_warnings(ObjectID object_id, int step, PrintStateBase::WarningLevel warning_level, const std::string &message); void status_update_warnings(int step, PrintStateBase::WarningLevel warning_level, const std::string &message, const PrintObjectBase* print_object = nullptr);
// If the background processing stop was requested, throw CanceledException. // If the background processing stop was requested, throw CanceledException.
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
@ -528,7 +528,7 @@ protected:
PrintStateBase::TimeStamp set_done(PrintStepEnum step) { PrintStateBase::TimeStamp set_done(PrintStepEnum step) {
std::pair<PrintStateBase::TimeStamp, bool> status = m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); std::pair<PrintStateBase::TimeStamp, bool> status = m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); });
if (status.second) if (status.second)
this->status_update_warnings(this->id(), static_cast<int>(step), PrintStateBase::WarningLevel::NON_CRITICAL, std::string()); this->status_update_warnings(static_cast<int>(step), PrintStateBase::WarningLevel::NON_CRITICAL, std::string());
return status.first; return status.first;
} }
bool invalidate_step(PrintStepEnum step) bool invalidate_step(PrintStepEnum step)
@ -550,7 +550,7 @@ protected:
std::pair<PrintStepEnum, bool> active_step = m_state.active_step_add_warning(warning_level, message, message_id, this->state_mutex()); std::pair<PrintStepEnum, bool> active_step = m_state.active_step_add_warning(warning_level, message, message_id, this->state_mutex());
if (active_step.second) if (active_step.second)
// Update UI. // Update UI.
this->status_update_warnings(this->id(), static_cast<int>(active_step.first), warning_level, message); this->status_update_warnings(static_cast<int>(active_step.first), warning_level, message);
} }
private: private:

View file

@ -151,11 +151,11 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionString(""));
def = this->add("preset_name", coString); def = this->add("preset_names", coStrings);
def->label = L("Printer preset name"); def->label = L("Printer preset names");
def->tooltip = L("Related printer preset name"); def->tooltip = L("Names of presets related to the physical printer");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionStrings());
def = this->add("printhost_authorization_type", coEnum); def = this->add("printhost_authorization_type", coEnum);
def->label = L("Authorization Type"); def->label = L("Authorization Type");
@ -3366,6 +3366,8 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
opt_key = "printhost_cafile"; opt_key = "printhost_cafile";
} else if (opt_key == "octoprint_apikey") { } else if (opt_key == "octoprint_apikey") {
opt_key = "printhost_apikey"; opt_key = "printhost_apikey";
} else if (opt_key == "preset_name") {
opt_key = "preset_names";
} }
// Ignore the following obsolete configuration keys: // Ignore the following obsolete configuration keys:

View file

@ -513,7 +513,7 @@ public:
ConfigOptionFloat support_material_interface_spacing; ConfigOptionFloat support_material_interface_spacing;
ConfigOptionFloatOrPercent support_material_interface_speed; ConfigOptionFloatOrPercent support_material_interface_speed;
ConfigOptionEnum<SupportMaterialPattern> support_material_pattern; ConfigOptionEnum<SupportMaterialPattern> support_material_pattern;
ConfigOptionEnum<SupportMaterialPattern> support_material_interface_pattern; ConfigOptionEnum<SupportMaterialInterfacePattern> support_material_interface_pattern;
// Spacing between support material lines (the hatching distance). // Spacing between support material lines (the hatching distance).
ConfigOptionFloat support_material_spacing; ConfigOptionFloat support_material_spacing;
ConfigOptionFloat support_material_speed; ConfigOptionFloat support_material_speed;

View file

@ -418,7 +418,7 @@ void PrintObject::generate_support_material()
{ {
if (this->set_started(posSupportMaterial)) { if (this->set_started(posSupportMaterial)) {
this->clear_support_layers(); this->clear_support_layers();
if (this->has_support_material() && m_layers.size() > 1) { if ((this->has_support() && m_layers.size() > 1) || (this->has_raft() && ! m_layers.empty())) {
m_print->set_status(85, L("Generating support material")); m_print->set_status(85, L("Generating support material"));
this->_generate_support_material(); this->_generate_support_material();
m_print->throw_if_canceled(); m_print->throw_if_canceled();

View file

@ -501,7 +501,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
// If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette with holes filled. // If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette with holes filled.
// There is also a 1st intermediate layer containing bases of support columns. // There is also a 1st intermediate layer containing bases of support columns.
// Inflate the bases of the support columns and create the raft base under the object. // Inflate the bases of the support columns and create the raft base under the object.
MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, intermediate_layers, layer_storage); MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, intermediate_layers, base_interface_layers, layer_storage);
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
for (const MyLayer *l : interface_layers) for (const MyLayer *l : interface_layers)
@ -1264,6 +1264,14 @@ namespace SupportMaterialInternal {
offset(layerm->unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)); offset(layerm->unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS));
// Remove bridged areas from the supported areas. // Remove bridged areas from the supported areas.
contact_polygons = diff(contact_polygons, bridges, true); contact_polygons = diff(contact_polygons, bridges, true);
#ifdef SLIC3R_DEBUG
static int iRun = 0;
SVG::export_expolygons(debug_out_path("support-top-contacts-remove-bridges-run%d.svg", iRun ++),
{ { { union_ex(offset(layerm->unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS), false) }, { "unsupported_bridge_edges", "orange", 0.5f } },
{ { union_ex(contact_polygons, false) }, { "contact_polygons", "blue", 0.5f } },
{ { union_ex(bridges, false) }, { "bridges", "red", "black", "", scaled<coord_t>(0.1f), 0.5f } } });
#endif /* SLIC3R_DEBUG */
} }
} }
@ -1678,7 +1686,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
#endif /* SLIC3R_DEBUG */ #endif /* SLIC3R_DEBUG */
} }
} }
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z),
{ { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "gray", 0.2f } }, { { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "gray", 0.2f } },
{ { union_ex(*new_layer.contact_polygons, false) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, { { union_ex(*new_layer.contact_polygons, false) }, { "new_layer.contact_polygons", "yellow", 0.5f } },
@ -2538,6 +2546,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
const PrintObject &object, const PrintObject &object,
const MyLayersPtr &top_contacts, const MyLayersPtr &top_contacts,
const MyLayersPtr &interface_layers, const MyLayersPtr &interface_layers,
const MyLayersPtr &base_interface_layers,
const MyLayersPtr &base_layers, const MyLayersPtr &base_layers,
MyLayerStorage &layer_storage) const MyLayerStorage &layer_storage) const
{ {
@ -2573,15 +2582,19 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
// How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed. // How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
const float inflate_factor_fine = float(scale_((m_slicing_params.raft_layers() > 1) ? 0.5 : EPSILON)); const float inflate_factor_fine = float(scale_((m_slicing_params.raft_layers() > 1) ? 0.5 : EPSILON));
const float inflate_factor_1st_layer = std::max(0.f, float(scale_(object.config().raft_first_layer_expansion)) - inflate_factor_fine); const float inflate_factor_1st_layer = std::max(0.f, float(scale_(object.config().raft_first_layer_expansion)) - inflate_factor_fine);
MyLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front(); MyLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front();
MyLayer *interfaces = interface_layers.empty() ? nullptr : interface_layers.front(); MyLayer *interfaces = interface_layers .empty() ? nullptr : interface_layers .front();
MyLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front(); MyLayer *base_interfaces = base_interface_layers.empty() ? nullptr : base_interface_layers.front();
MyLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front();
if (contacts != nullptr && contacts->print_z > std::max(m_slicing_params.first_print_layer_height, m_slicing_params.raft_contact_top_z) + EPSILON) if (contacts != nullptr && contacts->print_z > std::max(m_slicing_params.first_print_layer_height, m_slicing_params.raft_contact_top_z) + EPSILON)
// This is not the raft contact layer. // This is not the raft contact layer.
contacts = nullptr; contacts = nullptr;
if (interfaces != nullptr && interfaces->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON) if (interfaces != nullptr && interfaces->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON)
// This is not the raft column base layer. // This is not the raft column base layer.
interfaces = nullptr; interfaces = nullptr;
if (base_interfaces != nullptr && base_interfaces->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON)
// This is not the raft column base layer.
base_interfaces = nullptr;
if (columns_base != nullptr && columns_base->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON) if (columns_base != nullptr && columns_base->bottom_print_z() > m_slicing_params.raft_interface_top_z + EPSILON)
// This is not the raft interface layer. // This is not the raft interface layer.
columns_base = nullptr; columns_base = nullptr;
@ -2591,6 +2604,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
polygons_append(interface_polygons, offset(contacts->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS)); polygons_append(interface_polygons, offset(contacts->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (interfaces != nullptr && ! interfaces->polygons.empty()) if (interfaces != nullptr && ! interfaces->polygons.empty())
polygons_append(interface_polygons, offset(interfaces->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS)); polygons_append(interface_polygons, offset(interfaces->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (base_interfaces != nullptr && ! base_interfaces->polygons.empty())
polygons_append(interface_polygons, offset(base_interfaces->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS));
// Output vector. // Output vector.
MyLayersPtr raft_layers; MyLayersPtr raft_layers;
@ -2643,9 +2658,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
} }
} else if (columns_base != nullptr) { } else if (columns_base != nullptr) {
// Expand the bases of the support columns in the 1st layer. // Expand the bases of the support columns in the 1st layer.
columns_base->polygons = diff( {
inflate_factor_1st_layer > 0 ? offset(columns_base->polygons, inflate_factor_1st_layer) : columns_base->polygons, Polygons &raft = columns_base->polygons;
offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); Polygons trimming = offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS);
if (inflate_factor_1st_layer > SCALED_EPSILON) {
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / m_first_layer_flow.scaled_width())));
float step = inflate_factor_1st_layer / nsteps;
for (int i = 0; i < nsteps; ++ i)
raft = diff(offset(raft, step), trimming);
} else
raft = diff(raft, trimming);
}
if (contacts != nullptr) if (contacts != nullptr)
columns_base->polygons = diff(columns_base->polygons, interface_polygons); columns_base->polygons = diff(columns_base->polygons, interface_polygons);
if (! brim.empty()) { if (! brim.empty()) {
@ -2654,6 +2678,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
contacts->polygons = diff(contacts->polygons, brim); contacts->polygons = diff(contacts->polygons, brim);
if (interfaces) if (interfaces)
interfaces->polygons = diff(interfaces->polygons, brim); interfaces->polygons = diff(interfaces->polygons, brim);
if (base_interfaces)
base_interfaces->polygons = diff(base_interfaces->polygons, brim);
} }
} }
@ -2706,7 +2732,7 @@ std::pair<PrintObjectSupportMaterial::MyLayersPtr, PrintObjectSupportMaterial::M
layer_new.bridging = intermediate_layer.bridging; layer_new.bridging = intermediate_layer.bridging;
// Merge top into bottom, unite them with a safety offset. // Merge top into bottom, unite them with a safety offset.
append(bottom, std::move(top)); append(bottom, std::move(top));
layer_new.polygons = union_(std::move(bottom), true); layer_new.polygons = intersection(union_(std::move(bottom), true), intermediate_layer.polygons);
// Subtract the interface from the base regions. // Subtract the interface from the base regions.
intermediate_layer.polygons = diff(intermediate_layer.polygons, layer_new.polygons, false); intermediate_layer.polygons = diff(intermediate_layer.polygons, layer_new.polygons, false);
if (subtract) if (subtract)
@ -3564,8 +3590,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// Base flange. // Base flange.
filler->angle = raft_angle_1st_layer; filler->angle = raft_angle_1st_layer;
filler->spacing = m_first_layer_flow.spacing(); filler->spacing = m_first_layer_flow.spacing();
// 70% of density on the 1st layer. density = float(m_object_config->raft_first_layer_density.value * 0.01);
density = 0.7f;
} else if (support_layer_id >= m_slicing_params.base_raft_layers) { } else if (support_layer_id >= m_slicing_params.base_raft_layers) {
filler->angle = raft_angle_interface; filler->angle = raft_angle_interface;
// We don't use $base_flow->spacing because we need a constant spacing // We don't use $base_flow->spacing because we need a constant spacing

View file

@ -195,6 +195,7 @@ private:
const PrintObject &object, const PrintObject &object,
const MyLayersPtr &top_contacts, const MyLayersPtr &top_contacts,
const MyLayersPtr &interface_layers, const MyLayersPtr &interface_layers,
const MyLayersPtr &base_interface_layers,
const MyLayersPtr &base_layers, const MyLayersPtr &base_layers,
MyLayerStorage &layer_storage) const; MyLayerStorage &layer_storage) const;

View file

@ -4,7 +4,6 @@
//============= //=============
// debug techs // debug techs
//============= //=============
// Shows camera target in the 3D scene // Shows camera target in the 3D scene
#define ENABLE_SHOW_CAMERA_TARGET 0 #define ENABLE_SHOW_CAMERA_TARGET 0
// Log debug messages to console when changing selection // Log debug messages to console when changing selection
@ -29,63 +28,12 @@
#define ENABLE_GCODE_VIEWER_DATA_CHECKING 0 #define ENABLE_GCODE_VIEWER_DATA_CHECKING 0
//=================
// 2.2.0.rc1 techs
//=================
#define ENABLE_2_2_0_RC1 1
// Enable hack to remove crash when closing on OSX 10.9.5
#define ENABLE_HACK_CLOSING_ON_OSX_10_9_5 (1 && ENABLE_2_2_0_RC1)
//====================
// 2.3.0.alpha1 techs
//====================
#define ENABLE_2_3_0_ALPHA1 1
// Enable rendering of objects using environment map // Enable rendering of objects using environment map
#define ENABLE_ENVIRONMENT_MAP (0 && ENABLE_2_3_0_ALPHA1) #define ENABLE_ENVIRONMENT_MAP 0
// Enable smoothing of objects normals // Enable smoothing of objects normals
#define ENABLE_SMOOTH_NORMALS (0 && ENABLE_2_3_0_ALPHA1) #define ENABLE_SMOOTH_NORMALS 0
// Enable rendering markers for options in preview as fixed screen size points
// Enable error logging for OpenGL calls when SLIC3R_LOGLEVEL >= 5 #define ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS 1
#define ENABLE_OPENGL_ERROR_LOGGING (1 && ENABLE_2_3_0_ALPHA1)
// Enable built-in DPI changed event handler of wxWidgets 3.1.3
#define ENABLE_WX_3_1_3_DPI_CHANGED_EVENT (1 && ENABLE_2_3_0_ALPHA1)
//====================
// 2.3.0.alpha3 techs
//====================
#define ENABLE_2_3_0_ALPHA3 1
#define ENABLE_CTRL_M_ON_WINDOWS (1 && ENABLE_2_3_0_ALPHA3)
//====================
// 2.3.0.alpha4 techs
//====================
#define ENABLE_2_3_0_ALPHA4 1
#define ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS (1 && ENABLE_2_3_0_ALPHA4)
//===================
// 2.3.0.beta1 techs
//===================
#define ENABLE_2_3_0_BETA1 1
#define ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN (1 && ENABLE_2_3_0_BETA1)
//=================
// 2.3.0.rc1 techs
//=================
#define ENABLE_2_3_0_RC1 1
#define ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING (1 && ENABLE_2_3_0_RC1)
//==================== //====================
@ -93,11 +41,17 @@
//==================== //====================
#define ENABLE_2_3_1_ALPHA1 1 #define ENABLE_2_3_1_ALPHA1 1
// Enable splitting of vertex buffers used to render toolpaths
#define ENABLE_SPLITTED_VERTEX_BUFFER (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_SPLITTED_VERTEX_BUFFER (1 && ENABLE_2_3_1_ALPHA1)
#define ENABLE_RELOAD_FROM_DISK_FOR_3MF (1 && ENABLE_2_3_1_ALPHA1) // Enable rendering only starting and final caps for toolpaths
#define ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS (1 && ENABLE_SPLITTED_VERTEX_BUFFER) #define ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS (1 && ENABLE_SPLITTED_VERTEX_BUFFER)
// Enable reload from disk command for 3mf files
#define ENABLE_RELOAD_FROM_DISK_FOR_3MF (1 && ENABLE_2_3_1_ALPHA1)
// Removes obsolete warning texture code
#define ENABLE_WARNING_TEXTURE_REMOVAL (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_WARNING_TEXTURE_REMOVAL (1 && ENABLE_2_3_1_ALPHA1)
// Enable showing gcode line numbers in previeww horizontal slider
#define ENABLE_GCODE_LINES_ID_IN_H_SLIDER (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_GCODE_LINES_ID_IN_H_SLIDER (1 && ENABLE_2_3_1_ALPHA1)
// Enable validation of custom gcode against gcode processor reserved keywords
#define ENABLE_VALIDATE_CUSTOM_GCODE (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_VALIDATE_CUSTOM_GCODE (1 && ENABLE_2_3_1_ALPHA1)
#define ENABLE_GCODE_WINDOW (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_GCODE_WINDOW (1 && ENABLE_2_3_1_ALPHA1)

View file

@ -39,12 +39,11 @@
#ifdef HAS_GLSAFE #ifdef HAS_GLSAFE
void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name) void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name)
{ {
#if defined(NDEBUG) && ENABLE_OPENGL_ERROR_LOGGING #if defined(NDEBUG)
// In release mode, if OpenGL debugging was forced by ENABLE_OPENGL_ERROR_LOGGING, only show // In release mode, only show OpenGL errors if sufficiently high loglevel.
// OpenGL errors if sufficiently high loglevel.
if (Slic3r::get_logging_level() < 5) if (Slic3r::get_logging_level() < 5)
return; return;
#endif // ENABLE_OPENGL_ERROR_LOGGING #endif // NDEBUG
GLenum err = glGetError(); GLenum err = glGetError();
if (err == GL_NO_ERROR) if (err == GL_NO_ERROR)

View file

@ -10,10 +10,7 @@
#include <functional> #include <functional>
#if ENABLE_OPENGL_ERROR_LOGGING || ! defined(NDEBUG) #define HAS_GLSAFE
#define HAS_GLSAFE
#endif
#ifdef HAS_GLSAFE #ifdef HAS_GLSAFE
extern void glAssertRecentCallImpl(const char *file_name, unsigned int line, const char *function_name); extern void glAssertRecentCallImpl(const char *file_name, unsigned int line, const char *function_name);
inline void glAssertRecentCall() { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); } inline void glAssertRecentCall() { glAssertRecentCallImpl(__FILE__, __LINE__, __FUNCTION__); }

View file

@ -629,13 +629,13 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
append(html_window, 0, wxEXPAND); append(html_window, 0, wxEXPAND);
list_printer->Bind(wxEVT_LISTBOX, [this](wxCommandEvent& evt) { list_printer->Bind(wxEVT_LISTBOX, [this](wxCommandEvent& evt) {
update_lists(evt.GetInt(), list_type->GetSelection(), list_vendor->GetSelection()); update_lists(list_type->GetSelection(), list_vendor->GetSelection(), evt.GetInt());
}); });
list_type->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) { list_type->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) {
update_lists(list_printer->GetSelection(), list_type->GetSelection(), list_vendor->GetSelection()); update_lists(list_type->GetSelection(), list_vendor->GetSelection());
}); });
list_vendor->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) { list_vendor->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) {
update_lists(list_printer->GetSelection(), list_type->GetSelection(), list_vendor->GetSelection()); update_lists(list_type->GetSelection(), list_vendor->GetSelection());
}); });
list_profile->Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent &evt) { select_material(evt.GetInt()); }); list_profile->Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent &evt) { select_material(evt.GetInt()); });
@ -681,8 +681,7 @@ void PageMaterials::reload_presets()
sort_list_data(list_printer, true, false); sort_list_data(list_printer, true, false);
if (list_printer->GetCount() > 0) { if (list_printer->GetCount() > 0) {
list_printer->SetSelection(0); list_printer->SetSelection(0);
sel_printer_count_prev = wxNOT_FOUND; sel_printers_prev.Clear();
sel_printer_item_prev = wxNOT_FOUND;
sel_type_prev = wxNOT_FOUND; sel_type_prev = wxNOT_FOUND;
sel_vendor_prev = wxNOT_FOUND; sel_vendor_prev = wxNOT_FOUND;
update_lists(0, 0, 0); update_lists(0, 0, 0);
@ -812,7 +811,7 @@ void PageMaterials::on_material_highlighted(int sel_material)
set_compatible_printers_html_window(names, names.size() == materials->printers.size()); set_compatible_printers_html_window(names, names.size() == materials->printers.size());
} }
void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor) void PageMaterials::update_lists(int sel_type, int sel_vendor, int last_selected_printer/* = -1*/)
{ {
wxWindowUpdateLocker freeze_guard(this); wxWindowUpdateLocker freeze_guard(this);
(void)freeze_guard; (void)freeze_guard;
@ -820,7 +819,22 @@ void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor)
wxArrayInt sel_printers; wxArrayInt sel_printers;
int sel_printers_count = list_printer->GetSelections(sel_printers); int sel_printers_count = list_printer->GetSelections(sel_printers);
if (sel_printers_count != sel_printer_count_prev || (sel_printers_count == 1 && sel_printer_item_prev != sel_printer && sel_printer != -1)) { // Does our wxWidgets version support operator== for wxArrayInt ?
// https://github.com/prusa3d/PrusaSlicer/issues/5152#issuecomment-787208614
#if wxCHECK_VERSION(3, 1, 1)
if (sel_printers != sel_printers_prev) {
#else
auto are_equal = [](const wxArrayInt& arr_first, const wxArrayInt& arr_second) {
if (arr_first.GetCount() != arr_second.GetCount())
return false;
for (size_t i = 0; i < arr_first.GetCount(); i++)
if (arr_first[i] != arr_second[i])
return false;
return true;
};
if (!are_equal(sel_printers, sel_printers_prev)) {
#endif
// Refresh type list // Refresh type list
list_type->Clear(); list_type->Clear();
list_type->append(_L("(All)"), &EMPTY); list_type->append(_L("(All)"), &EMPTY);
@ -828,7 +842,7 @@ void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor)
// If all is selected with other printers // If all is selected with other printers
// unselect "all" or all printers depending on last value // unselect "all" or all printers depending on last value
if (sel_printers[0] == 0 && sel_printers_count > 1) { if (sel_printers[0] == 0 && sel_printers_count > 1) {
if (sel_printer == 0) { if (last_selected_printer == 0) {
list_printer->SetSelection(wxNOT_FOUND); list_printer->SetSelection(wxNOT_FOUND);
list_printer->SetSelection(0); list_printer->SetSelection(0);
} else { } else {
@ -869,8 +883,7 @@ void PageMaterials::update_lists(int sel_printer, int sel_type, int sel_vendor)
sort_list_data(list_type, true, true); sort_list_data(list_type, true, true);
} }
sel_printer_count_prev = sel_printers_count; sel_printers_prev = sel_printers;
sel_printer_item_prev = sel_printer;
sel_type = 0; sel_type = 0;
sel_type_prev = wxNOT_FOUND; sel_type_prev = wxNOT_FOUND;
list_type->SetSelection(sel_type); list_type->SetSelection(sel_type);
@ -1089,8 +1102,7 @@ void PageMaterials::clear()
list_type->Clear(); list_type->Clear();
list_vendor->Clear(); list_vendor->Clear();
list_profile->Clear(); list_profile->Clear();
sel_printer_count_prev = wxNOT_FOUND; sel_printers_prev.Clear();
sel_printer_item_prev = wxNOT_FOUND;
sel_type_prev = wxNOT_FOUND; sel_type_prev = wxNOT_FOUND;
sel_vendor_prev = wxNOT_FOUND; sel_vendor_prev = wxNOT_FOUND;
presets_loaded = false; presets_loaded = false;
@ -1189,7 +1201,6 @@ PageReloadFromDisk::PageReloadFromDisk(ConfigWizard* parent)
box_pathnames->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { this->full_pathnames = event.IsChecked(); }); box_pathnames->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { this->full_pathnames = event.IsChecked(); });
} }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
PageFilesAssociation::PageFilesAssociation(ConfigWizard* parent) PageFilesAssociation::PageFilesAssociation(ConfigWizard* parent)
: ConfigWizardPage(parent, _L("Files association"), _L("Files association")) : ConfigWizardPage(parent, _L("Files association"), _L("Files association"))
@ -1203,7 +1214,6 @@ PageFilesAssociation::PageFilesAssociation(ConfigWizard* parent)
// append(cb_gcode); // append(cb_gcode);
} }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
PageMode::PageMode(ConfigWizard *parent) PageMode::PageMode(ConfigWizard *parent)
: ConfigWizardPage(parent, _L("View mode"), _L("View mode")) : ConfigWizardPage(parent, _L("View mode"), _L("View mode"))
@ -1816,11 +1826,9 @@ void ConfigWizard::priv::load_pages()
index->add_page(page_update); index->add_page(page_update);
index->add_page(page_reload_from_disk); index->add_page(page_reload_from_disk);
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
index->add_page(page_files_association); index->add_page(page_files_association);
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
index->add_page(page_mode); index->add_page(page_mode);
index->go_to(former_active); // Will restore the active item/page if possible index->go_to(former_active); // Will restore the active item/page if possible
@ -2414,7 +2422,6 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
app_config->set("preset_update", page_update->preset_update ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0");
app_config->set("export_sources_full_pathnames", page_reload_from_disk->full_pathnames ? "1" : "0"); app_config->set("export_sources_full_pathnames", page_reload_from_disk->full_pathnames ? "1" : "0");
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
app_config->set("associate_3mf", page_files_association->associate_3mf() ? "1" : "0"); app_config->set("associate_3mf", page_files_association->associate_3mf() ? "1" : "0");
app_config->set("associate_stl", page_files_association->associate_stl() ? "1" : "0"); app_config->set("associate_stl", page_files_association->associate_stl() ? "1" : "0");
@ -2432,7 +2439,6 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
// } // }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
page_mode->serialize_mode(app_config); page_mode->serialize_mode(app_config);
@ -2597,11 +2603,9 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->add_page(p->page_update = new PageUpdate(this)); p->add_page(p->page_update = new PageUpdate(this));
p->add_page(p->page_reload_from_disk = new PageReloadFromDisk(this)); p->add_page(p->page_reload_from_disk = new PageReloadFromDisk(this));
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
p->add_page(p->page_files_association = new PageFilesAssociation(this)); p->add_page(p->page_files_association = new PageFilesAssociation(this));
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
p->add_page(p->page_mode = new PageMode(this)); p->add_page(p->page_mode = new PageMode(this));
p->add_page(p->page_firmware = new PageFirmware(this)); p->add_page(p->page_firmware = new PageFirmware(this));
p->add_page(p->page_bed = new PageBedShape(this)); p->add_page(p->page_bed = new PageBedShape(this));

View file

@ -327,7 +327,8 @@ struct PageMaterials: ConfigWizardPage
Materials *materials; Materials *materials;
StringList *list_printer, *list_type, *list_vendor; StringList *list_printer, *list_type, *list_vendor;
PresetList *list_profile; PresetList *list_profile;
int sel_printer_count_prev, sel_printer_item_prev, sel_type_prev, sel_vendor_prev; wxArrayInt sel_printers_prev;
int sel_type_prev, sel_vendor_prev;
bool presets_loaded; bool presets_loaded;
wxFlexGridSizer *grid; wxFlexGridSizer *grid;
@ -342,7 +343,7 @@ struct PageMaterials: ConfigWizardPage
PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name); PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name);
void reload_presets(); void reload_presets();
void update_lists(int sel1, int sel2, int sel3); void update_lists(int sel_type, int sel_vendor, int last_selected_printer = -1);
void on_material_highlighted(int sel_material); void on_material_highlighted(int sel_material);
void on_material_hovered(int sel_material); void on_material_hovered(int sel_material);
void select_material(int i); void select_material(int i);
@ -392,7 +393,6 @@ struct PageReloadFromDisk : ConfigWizardPage
PageReloadFromDisk(ConfigWizard* parent); PageReloadFromDisk(ConfigWizard* parent);
}; };
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
struct PageFilesAssociation : ConfigWizardPage struct PageFilesAssociation : ConfigWizardPage
{ {
@ -409,7 +409,6 @@ public:
// bool associate_gcode() const { return cb_gcode->IsChecked(); } // bool associate_gcode() const { return cb_gcode->IsChecked(); }
}; };
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
struct PageMode: ConfigWizardPage struct PageMode: ConfigWizardPage
{ {
@ -571,11 +570,9 @@ struct ConfigWizard::priv
PageCustom *page_custom = nullptr; PageCustom *page_custom = nullptr;
PageUpdate *page_update = nullptr; PageUpdate *page_update = nullptr;
PageReloadFromDisk *page_reload_from_disk = nullptr; PageReloadFromDisk *page_reload_from_disk = nullptr;
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
PageFilesAssociation* page_files_association = nullptr; PageFilesAssociation* page_files_association = nullptr;
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
PageMode *page_mode = nullptr; PageMode *page_mode = nullptr;
PageVendors *page_vendors = nullptr; PageVendors *page_vendors = nullptr;
Pages3rdparty pages_3rdparty; Pages3rdparty pages_3rdparty;

View file

@ -183,11 +183,13 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsi
// use rounding to reduce the number of generated paths // use rounding to reduce the number of generated paths
#if ENABLE_SPLITTED_VERTEX_BUFFER #if ENABLE_SPLITTED_VERTEX_BUFFER
paths.push_back({ move.type, move.extrusion_role, move.delta_extruder, paths.push_back({ move.type, move.extrusion_role, move.delta_extruder,
round_to_nearest(move.height, 2), round_to_nearest(move.width, 2), move.feedrate, move.fan_speed, round_to_nearest(move.height, 2), round_to_nearest(move.width, 2),
move.feedrate, move.fan_speed, move.temperature,
move.volumetric_rate(), move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } }); move.volumetric_rate(), move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } });
#else #else
paths.push_back({ move.type, move.extrusion_role, endpoint, endpoint, move.delta_extruder, paths.push_back({ move.type, move.extrusion_role, endpoint, endpoint, move.delta_extruder,
round_to_nearest(move.height, 2), round_to_nearest(move.width, 2), move.feedrate, move.fan_speed, round_to_nearest(move.height, 2), round_to_nearest(move.width, 2),
move.feedrate, move.fan_speed, move.temperature,
move.volumetric_rate(), move.extruder_id, move.cp_color_id }); move.volumetric_rate(), move.extruder_id, move.cp_color_id });
#endif // ENABLE_SPLITTED_VERTEX_BUFFER #endif // ENABLE_SPLITTED_VERTEX_BUFFER
} }
@ -654,6 +656,7 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std:
m_extrusions.ranges.height.update_from(round_to_nearest(curr.height, 2)); m_extrusions.ranges.height.update_from(round_to_nearest(curr.height, 2));
m_extrusions.ranges.width.update_from(round_to_nearest(curr.width, 2)); m_extrusions.ranges.width.update_from(round_to_nearest(curr.width, 2));
m_extrusions.ranges.fan_speed.update_from(curr.fan_speed); m_extrusions.ranges.fan_speed.update_from(curr.fan_speed);
m_extrusions.ranges.temperature.update_from(curr.temperature);
m_extrusions.ranges.volumetric_rate.update_from(round_to_nearest(curr.volumetric_rate(), 2)); m_extrusions.ranges.volumetric_rate.update_from(round_to_nearest(curr.volumetric_rate(), 2));
[[fallthrough]]; [[fallthrough]];
} }
@ -2898,6 +2901,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; } case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; }
case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; } case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; }
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; }
case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; }
case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; }
case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; }
case EViewType::ColorPrint: { case EViewType::ColorPrint: {
@ -3357,6 +3361,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; } case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; }
case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; } case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; }
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; }
case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; }
case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; }
case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; }
case EViewType::ColorPrint: { case EViewType::ColorPrint: {
@ -4191,6 +4196,7 @@ void GCodeViewer::render_legend() const
case EViewType::Width: { imgui.title(_u8L("Width (mm)")); break; } case EViewType::Width: { imgui.title(_u8L("Width (mm)")); break; }
case EViewType::Feedrate: { imgui.title(_u8L("Speed (mm/s)")); break; } case EViewType::Feedrate: { imgui.title(_u8L("Speed (mm/s)")); break; }
case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; }
case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; }
case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; }
case EViewType::Tool: { imgui.title(_u8L("Tool")); break; } case EViewType::Tool: { imgui.title(_u8L("Tool")); break; }
case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; } case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; }
@ -4225,6 +4231,7 @@ void GCodeViewer::render_legend() const
case EViewType::Width: { append_range(m_extrusions.ranges.width, 3); break; } case EViewType::Width: { append_range(m_extrusions.ranges.width, 3); break; }
case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1); break; } case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1); break; }
case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; }
case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; }
case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; } case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; }
case EViewType::Tool: case EViewType::Tool:
{ {

View file

@ -179,6 +179,7 @@ class GCodeViewer
float width{ 0.0f }; float width{ 0.0f };
float feedrate{ 0.0f }; float feedrate{ 0.0f };
float fan_speed{ 0.0f }; float fan_speed{ 0.0f };
float temperature{ 0.0f };
float volumetric_rate{ 0.0f }; float volumetric_rate{ 0.0f };
unsigned char extruder_id{ 0 }; unsigned char extruder_id{ 0 };
unsigned char cp_color_id{ 0 }; unsigned char cp_color_id{ 0 };
@ -407,6 +408,8 @@ class GCodeViewer
Range fan_speed; Range fan_speed;
// Color mapping by volumetric extrusion rate. // Color mapping by volumetric extrusion rate.
Range volumetric_rate; Range volumetric_rate;
// Color mapping by extrusion temperature.
Range temperature;
void reset() { void reset() {
height.reset(); height.reset();
@ -414,6 +417,7 @@ class GCodeViewer
feedrate.reset(); feedrate.reset();
fan_speed.reset(); fan_speed.reset();
volumetric_rate.reset(); volumetric_rate.reset();
temperature.reset();
} }
}; };
@ -654,6 +658,7 @@ public:
Width, Width,
Feedrate, Feedrate,
FanSpeed, FanSpeed,
Temperature,
VolumetricRate, VolumetricRate,
Tool, Tool,
ColorPrint, ColorPrint,

View file

@ -2512,8 +2512,6 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#endif /* __APPLE__ */ #endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY)); post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
break; break;
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef __APPLE__ #ifdef __APPLE__
case 'm': case 'm':
case 'M': case 'M':
@ -2532,18 +2530,6 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#endif //_WIN32 #endif //_WIN32
break; break;
} }
#else
#if defined(__linux__) || defined(__APPLE__)
case WXK_CONTROL_M:
{
Mouse3DController& controller = wxGetApp().plater()->get_mouse3d_controller();
controller.show_settings_dialog(!controller.is_settings_dialog_shown());
m_dirty = true;
break;
}
#endif /* __linux__ */
#endif // ENABLE_CTRL_M_ON_WINDOWS
#ifdef __APPLE__ #ifdef __APPLE__
case 'v': case 'v':
case 'V': case 'V':

View file

@ -835,14 +835,10 @@ bool GUI_App::on_init_inner()
if (is_editor()) { if (is_editor()) {
#ifdef __WXMSW__ #ifdef __WXMSW__
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_3mf") == "1") if (app_config->get("associate_3mf") == "1")
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
associate_3mf_files(); associate_3mf_files();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_stl") == "1") if (app_config->get("associate_stl") == "1")
associate_stl_files(); associate_stl_files();
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#endif // __WXMSW__ #endif // __WXMSW__
preset_updater = new PresetUpdater(); preset_updater = new PresetUpdater();
@ -858,9 +854,7 @@ bool GUI_App::on_init_inner()
} }
else { else {
#ifdef __WXMSW__ #ifdef __WXMSW__
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
if (app_config->get("associate_gcode") == "1") if (app_config->get("associate_gcode") == "1")
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
associate_gcode_files(); associate_gcode_files();
#endif // __WXMSW__ #endif // __WXMSW__
} }
@ -1722,7 +1716,6 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
if (dlg.seq_top_layer_only_changed()) if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
this->plater_->refresh_print(); this->plater_->refresh_print();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
if (is_editor()) { if (is_editor()) {
if (app_config->get("associate_3mf") == "1") if (app_config->get("associate_3mf") == "1")
@ -1735,7 +1728,6 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
associate_gcode_files(); associate_gcode_files();
} }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
} }
if (app_layout_changed) { if (app_layout_changed) {
// hide full main_sizer for mainFrame // hide full main_sizer for mainFrame
@ -2303,7 +2295,6 @@ void GUI_App::associate_3mf_files()
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr); ::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
} }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
void GUI_App::associate_stl_files() void GUI_App::associate_stl_files()
{ {
wchar_t app_path[MAX_PATH]; wchar_t app_path[MAX_PATH];
@ -2327,7 +2318,6 @@ void GUI_App::associate_stl_files()
// notify Windows only when any of the values gets changed // notify Windows only when any of the values gets changed
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr); ::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
} }
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
void GUI_App::associate_gcode_files() void GUI_App::associate_gcode_files()
{ {

View file

@ -279,13 +279,11 @@ public:
bool is_gl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_version_greater_or_equal_to(major, minor); } bool is_gl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_version_greater_or_equal_to(major, minor); }
bool is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_glsl_version_greater_or_equal_to(major, minor); } bool is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { return m_opengl_mgr.get_gl_info().is_glsl_version_greater_or_equal_to(major, minor); }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef __WXMSW__ #ifdef __WXMSW__
void associate_3mf_files(); void associate_3mf_files();
void associate_stl_files(); void associate_stl_files();
void associate_gcode_files(); void associate_gcode_files();
#endif // __WXMSW__ #endif // __WXMSW__
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
private: private:
bool on_init_inner(); bool on_init_inner();
@ -297,13 +295,6 @@ private:
bool config_wizard_startup(); bool config_wizard_startup();
void check_updates(const bool verbose); void check_updates(const bool verbose);
#if !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef __WXMSW__
void associate_3mf_files();
void associate_gcode_files();
#endif // __WXMSW__
#endif // !ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
}; };
DECLARE_APP(GUI_App) DECLARE_APP(GUI_App)

View file

@ -93,6 +93,7 @@ ObjectList::ObjectList(wxWindow* parent) :
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers"); CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill"); CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
CATEGORY_ICON[L("Ironing")] = create_scaled_bitmap("ironing"); CATEGORY_ICON[L("Ironing")] = create_scaled_bitmap("ironing");
CATEGORY_ICON[L("Fuzzy Skin")] = create_scaled_bitmap("fuzzy_skin");
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support"); CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support");
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time"); CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time");
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel"); CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel");

View file

@ -211,6 +211,7 @@ bool Preview::init(wxWindow* parent, Model* model)
m_choice_view_type->Append(_L("Width")); m_choice_view_type->Append(_L("Width"));
m_choice_view_type->Append(_L("Speed")); m_choice_view_type->Append(_L("Speed"));
m_choice_view_type->Append(_L("Fan speed")); m_choice_view_type->Append(_L("Fan speed"));
m_choice_view_type->Append(_L("Temperature"));
m_choice_view_type->Append(_L("Volumetric flow rate")); m_choice_view_type->Append(_L("Volumetric flow rate"));
m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Tool"));
m_choice_view_type->Append(_L("Color Print")); m_choice_view_type->Append(_L("Color Print"));

View file

@ -26,11 +26,7 @@ class wxCheckBox;
class wxTopLevelWindow; class wxTopLevelWindow;
class wxRect; class wxRect;
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) ((wxMAJOR_VERSION > major) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION > minor)) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION == minor) && (wxRELEASE_NUMBER >= release))) #define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) ((wxMAJOR_VERSION > major) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION > minor)) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION == minor) && (wxRELEASE_NUMBER >= release)))
#else
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) 0
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -99,12 +95,12 @@ public:
// Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3). // Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
// So, calculate the m_em_unit value from the font size, as before // So, calculate the m_em_unit value from the font size, as before
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && !defined(__WXGTK__) #if !defined(__WXGTK__)
m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor); m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor);
#else #else
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window. // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1); m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // __WXGTK__
// recalc_font(); // recalc_font();
@ -235,11 +231,7 @@ private:
m_normal_font = this->GetFont(); m_normal_font = this->GetFont();
// update em_unit value for new window font // update em_unit value for new window font
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
m_em_unit = std::max<int>(10, 10.0f * m_scale_factor); m_em_unit = std::max<int>(10, 10.0f * m_scale_factor);
#else
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
// rescale missed controls sizes and images // rescale missed controls sizes and images
on_dpi_changed(suggested_rect); on_dpi_changed(suggested_rect);

View file

@ -147,17 +147,11 @@ void KBShortcutsDialog::fill_shortcuts()
{ "O", L("Zoom out") }, { "O", L("Zoom out") },
{ "Tab", L("Switch between Editor/Preview") }, { "Tab", L("Switch between Editor/Preview") },
{ "Shift+Tab", L("Collapse/Expand the sidebar") }, { "Shift+Tab", L("Collapse/Expand the sidebar") },
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32 #ifdef _WIN32
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog, if enabled") }, { ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog, if enabled") },
#else #else
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") }, { ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
#endif // _WIN32 #endif // _WIN32
#else
#if defined(__linux__) || defined(__APPLE__)
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
#endif // __linux__
#endif // ENABLE_CTRL_M_ON_WINDOWS
#if ENABLE_RENDER_PICKING_PASS #if ENABLE_RENDER_PICKING_PASS
// Don't localize debugging texts. // Don't localize debugging texts.
{ "P", "Toggle picking pass texture rendering on/off" }, { "P", "Toggle picking pass texture rendering on/off" },

View file

@ -549,9 +549,10 @@ void MainFrame::init_tabpanel()
wxWindow* panel = m_tabpanel->GetCurrentPage(); wxWindow* panel = m_tabpanel->GetCurrentPage();
if (panel != nullptr) { if (panel != nullptr) {
Tab* tab = dynamic_cast<Tab*>(panel); Tab* tab = dynamic_cast<Tab*>(panel);
if (tab && (tab->type() == Preset::TYPE_FILAMENT || tab->type() == Preset::TYPE_PRINTER)) if (tab != nullptr)
if (!tab->validate_custom_gcodes()) tab->validate_custom_gcodes();
evt.Veto(); // if (tab != nullptr && !tab->validate_custom_gcodes())
// evt.Veto();
} }
}); });
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
@ -803,11 +804,7 @@ bool MainFrame::can_reslice() const
void MainFrame::on_dpi_changed(const wxRect& suggested_rect) void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
{ {
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
wxGetApp().update_fonts(this); wxGetApp().update_fonts(this);
#else
wxGetApp().update_fonts();
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
this->SetFont(this->normal_font()); this->SetFont(this->normal_font());
// update Plater // update Plater
@ -1848,14 +1845,14 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
if (wxGetApp().is_gcode_viewer()) if (wxGetApp().is_gcode_viewer())
return; return;
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__) #if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling // ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#else #else
this->SetFont(wxGetApp().normal_font()); this->SetFont(wxGetApp().normal_font());
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // __WXMSW__
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
// Load the icon either from the exe, or from the ico file. // Load the icon either from the exe, or from the ico file.

View file

@ -100,7 +100,6 @@ void Mouse3DController::State::append_button(unsigned int id, size_t /* input_qu
} }
#ifdef _WIN32 #ifdef _WIN32
#if ENABLE_CTRL_M_ON_WINDOWS
static std::string format_device_string(int vid, int pid) static std::string format_device_string(int vid, int pid)
{ {
std::string ret; std::string ret;
@ -257,7 +256,6 @@ static std::string detect_attached_device()
return ret; return ret;
} }
#endif // ENABLE_CTRL_M_ON_WINDOWS
// Called by Win32 HID enumeration callback. // Called by Win32 HID enumeration callback.
void Mouse3DController::device_attached(const std::string &device) void Mouse3DController::device_attached(const std::string &device)
@ -274,7 +272,6 @@ void Mouse3DController::device_attached(const std::string &device)
// Never mind, enumeration will be performed until connected. // Never mind, enumeration will be performed until connected.
m_wakeup = true; m_wakeup = true;
m_stop_condition.notify_all(); m_stop_condition.notify_all();
#if ENABLE_CTRL_M_ON_WINDOWS
m_device_str = format_device_string(vid, pid); m_device_str = format_device_string(vid, pid);
if (auto it_params = m_params_by_device.find(m_device_str); it_params != m_params_by_device.end()) { if (auto it_params = m_params_by_device.find(m_device_str); it_params != m_params_by_device.end()) {
tbb::mutex::scoped_lock lock(m_params_ui_mutex); tbb::mutex::scoped_lock lock(m_params_ui_mutex);
@ -283,12 +280,10 @@ void Mouse3DController::device_attached(const std::string &device)
else else
m_params_by_device[format_device_string(vid, pid)] = Params(); m_params_by_device[format_device_string(vid, pid)] = Params();
m_connected = true; m_connected = true;
#endif // ENABLE_CTRL_M_ON_WINDOWS
} }
} }
} }
#if ENABLE_CTRL_M_ON_WINDOWS
void Mouse3DController::device_detached(const std::string& device) void Mouse3DController::device_detached(const std::string& device)
{ {
int vid = 0; int vid = 0;
@ -302,7 +297,6 @@ void Mouse3DController::device_detached(const std::string& device)
m_device_str = ""; m_device_str = "";
m_connected = false; m_connected = false;
} }
#endif // ENABLE_CTRL_M_ON_WINDOWS
// Filter out mouse scroll events produced by the 3DConnexion driver. // Filter out mouse scroll events produced by the 3DConnexion driver.
bool Mouse3DController::State::process_mouse_wheel() bool Mouse3DController::State::process_mouse_wheel()
@ -415,7 +409,6 @@ bool Mouse3DController::apply(Camera& camera)
m_settings_dialog_closed_by_user = false; m_settings_dialog_closed_by_user = false;
} }
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32 #ifdef _WIN32
{ {
tbb::mutex::scoped_lock lock(m_params_ui_mutex); tbb::mutex::scoped_lock lock(m_params_ui_mutex);
@ -425,7 +418,6 @@ bool Mouse3DController::apply(Camera& camera)
} }
} }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
return m_state.apply(m_params, camera); return m_state.apply(m_params, camera);
} }
@ -661,7 +653,6 @@ bool Mouse3DController::handle_input(const DataPacketAxis& packet)
// Initialize the application. // Initialize the application.
void Mouse3DController::init() void Mouse3DController::init()
{ {
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32 #ifdef _WIN32
m_device_str = detect_attached_device(); m_device_str = detect_attached_device();
if (!m_device_str.empty()) { if (!m_device_str.empty()) {
@ -670,7 +661,6 @@ void Mouse3DController::init()
m_params = m_params_ui = it_params->second; m_params = m_params_ui = it_params->second;
} }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
assert(! m_thread.joinable()); assert(! m_thread.joinable());
if (! m_thread.joinable()) { if (! m_thread.joinable()) {
@ -698,12 +688,10 @@ void Mouse3DController::shutdown()
m_stop = false; m_stop = false;
} }
#if ENABLE_CTRL_M_ON_WINDOWS
#ifdef _WIN32 #ifdef _WIN32
if (!m_device_str.empty()) if (!m_device_str.empty())
m_params_by_device[m_device_str] = m_params_ui; m_params_by_device[m_device_str] = m_params_ui;
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CTRL_M_ON_WINDOWS
} }
// Main routine of the worker thread. // Main routine of the worker thread.
@ -1064,9 +1052,7 @@ bool Mouse3DController::handle_raw_input_win32(const unsigned char *data, const
DataPacketRaw packet; DataPacketRaw packet;
memcpy(packet.data(), data, packet_length); memcpy(packet.data(), data, packet_length);
handle_packet(packet, packet_length, m_params, m_state); handle_packet(packet, packet_length, m_params, m_state);
#if ENABLE_CTRL_M_ON_WINDOWS
m_connected = true; m_connected = true;
#endif // ENABLE_CTRL_M_ON_WINDOWS
} }
return true; return true;

View file

@ -195,9 +195,7 @@ public:
// Called by Win32 HID enumeration callback. // Called by Win32 HID enumeration callback.
void device_attached(const std::string &device); void device_attached(const std::string &device);
#if ENABLE_CTRL_M_ON_WINDOWS
void device_detached(const std::string& device); void device_detached(const std::string& device);
#endif // ENABLE_CTRL_M_ON_WINDOWS
// On Windows, the 3DConnexion driver sends out mouse wheel rotation events to an active application // On Windows, the 3DConnexion driver sends out mouse wheel rotation events to an active application
// if the application does not register at the driver. This is a workaround to ignore these superfluous // if the application does not register at the driver. This is a workaround to ignore these superfluous

View file

@ -14,14 +14,10 @@
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
#include <wx/platinfo.h> #include <wx/platinfo.h>
#endif // __APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp" #include "../Utils/MacDarkMode.hpp"
#endif // __APPLE__ #endif // __APPLE__
@ -202,34 +198,26 @@ bool OpenGLManager::s_compressed_textures_supported = false;
OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::EMultisampleState::Unknown; OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::EMultisampleState::Unknown;
OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown; OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown;
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
OpenGLManager::OSInfo OpenGLManager::s_os_info; OpenGLManager::OSInfo OpenGLManager::s_os_info;
#endif // __APPLE__ #endif // __APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
OpenGLManager::~OpenGLManager() OpenGLManager::~OpenGLManager()
{ {
m_shaders_manager.shutdown(); m_shaders_manager.shutdown();
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// This is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 with newer wxWidgets // This is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 with newer wxWidgets
// The crash is triggered inside wxGLContext destructor // The crash is triggered inside wxGLContext destructor
if (s_os_info.major != 10 || s_os_info.minor != 9 || s_os_info.micro != 5) if (s_os_info.major != 10 || s_os_info.minor != 9 || s_os_info.micro != 5)
{ {
#endif //__APPLE__ #endif //__APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
if (m_context != nullptr) if (m_context != nullptr)
delete m_context; delete m_context;
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
} }
#endif //__APPLE__ #endif //__APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
} }
bool OpenGLManager::init_gl() bool OpenGLManager::init_gl()
@ -286,14 +274,12 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas)
if (m_context == nullptr) { if (m_context == nullptr) {
m_context = new wxGLContext(&canvas); m_context = new wxGLContext(&canvas);
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion(); s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion();
s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion(); s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion();
s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion(); s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion();
#endif //__APPLE__ #endif //__APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
} }
return m_context; return m_context;
} }

View file

@ -51,7 +51,6 @@ public:
void detect() const; void detect() const;
}; };
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
struct OSInfo struct OSInfo
@ -61,7 +60,6 @@ public:
int micro{ 0 }; int micro{ 0 };
}; };
#endif //__APPLE__ #endif //__APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
private: private:
enum class EMultisampleState : unsigned char enum class EMultisampleState : unsigned char
@ -75,12 +73,10 @@ private:
wxGLContext* m_context{ nullptr }; wxGLContext* m_context{ nullptr };
GLShadersManager m_shaders_manager; GLShadersManager m_shaders_manager;
static GLInfo s_gl_info; static GLInfo s_gl_info;
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
#ifdef __APPLE__ #ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
static OSInfo s_os_info; static OSInfo s_os_info;
#endif //__APPLE__ #endif //__APPLE__
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
static bool s_compressed_textures_supported; static bool s_compressed_textures_supported;
static EMultisampleState s_multisample; static EMultisampleState s_multisample;
static EFramebufferType s_framebuffers_type; static EFramebufferType s_framebuffers_type;

View file

@ -1931,11 +1931,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->q->Bind(EVT_HID_DEVICE_ATTACHED, [this](HIDDeviceAttachedEvent &evt) { this->q->Bind(EVT_HID_DEVICE_ATTACHED, [this](HIDDeviceAttachedEvent &evt) {
mouse3d_controller.device_attached(evt.data); mouse3d_controller.device_attached(evt.data);
}); });
#if ENABLE_CTRL_M_ON_WINDOWS
this->q->Bind(EVT_HID_DEVICE_DETACHED, [this](HIDDeviceAttachedEvent& evt) { this->q->Bind(EVT_HID_DEVICE_DETACHED, [this](HIDDeviceAttachedEvent& evt) {
mouse3d_controller.device_detached(evt.data); mouse3d_controller.device_detached(evt.data);
}); });
#endif // ENABLE_CTRL_M_ON_WINDOWS
#endif /* _WIN32 */ #endif /* _WIN32 */
notification_manager = new NotificationManager(this->q); notification_manager = new NotificationManager(this->q);
@ -2191,9 +2189,56 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
{ {
if (!config.empty()) { if (!config.empty()) {
Preset::normalize(config); Preset::normalize(config);
wxGetApp().preset_bundle->load_config_model(filename.string(), std::move(config)); PresetBundle* preset_bundle = wxGetApp().preset_bundle;
preset_bundle->load_config_model(filename.string(), std::move(config));
{
// After loading of the presets from project, check if they are visible.
// Set them to visible if they are not.
auto update_selected_preset_visibility = [](PresetCollection& presets, std::vector<std::string>& names) {
if (!presets.get_selected_preset().is_visible) {
assert(presets.get_selected_preset().name == presets.get_edited_preset().name);
presets.get_selected_preset().is_visible = true;
presets.get_edited_preset().is_visible = true;
names.emplace_back(presets.get_selected_preset().name);
}
};
std::vector<std::string> names;
if (printer_technology == ptFFF) {
update_selected_preset_visibility(preset_bundle->prints, names);
for (const std::string& filament : preset_bundle->filament_presets) {
Preset* preset = preset_bundle->filaments.find_preset(filament);
if (preset && !preset->is_visible) {
preset->is_visible = true;
names.emplace_back(preset->name);
if (preset->name == preset_bundle->filaments.get_edited_preset().name)
preset_bundle->filaments.get_selected_preset().is_visible = true;
}
}
}
else {
update_selected_preset_visibility(preset_bundle->sla_prints, names);
update_selected_preset_visibility(preset_bundle->sla_materials, names);
}
update_selected_preset_visibility(preset_bundle->printers, names);
preset_bundle->update_compatible(PresetSelectCompatibleType::Never);
// show notification about temporary instaled presets
if (!names.empty()) {
std::string notif_text = into_u8(_L_PLURAL("The preset below was temporary instaled on active instance of PrusaSlicer",
"The presets below were temporary instaled on active instance of PrusaSlicer", names.size())) + ":";
for (std::string& name : names)
notif_text += "\n - " + name;
notification_manager->push_notification(NotificationType::CustomNotification,
NotificationManager::NotificationLevel::RegularNotification, notif_text);
}
}
if (printer_technology == ptFFF) if (printer_technology == ptFFF)
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &wxGetApp().preset_bundle->project_config); CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &preset_bundle->project_config);
// For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload" // For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload"
wxGetApp().load_current_presets(false); wxGetApp().load_current_presets(false);
// Update filament colors for the MM-printer profile in the full config // Update filament colors for the MM-printer profile in the full config
@ -3346,16 +3391,14 @@ void Plater::priv::set_current_panel(wxPanel* panel)
void Plater::priv::on_select_preset(wxCommandEvent &evt) void Plater::priv::on_select_preset(wxCommandEvent &evt)
{ {
auto preset_type = static_cast<Preset::Type>(evt.GetInt()); PlaterPresetComboBox* combo = static_cast<PlaterPresetComboBox*>(evt.GetEventObject());
auto *combo = static_cast<PlaterPresetComboBox*>(evt.GetEventObject()); Preset::Type preset_type = combo->get_type();
// see https://github.com/prusa3d/PrusaSlicer/issues/3889 // see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender"), // Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender"),
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive. // m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter // So, use GetSelection() from event parameter
// But in this function we couldn't use evt.GetSelection(), because m_commandInt is used for preset_type int selection = evt.GetSelection();
// Thus, get selection in this way:
int selection = combo->FindString(evt.GetString(), true);
auto idx = combo->get_extruder_idx(); auto idx = combo->get_extruder_idx();

View file

@ -106,7 +106,6 @@ void PreferencesDialog::build()
option = Option(def, "export_sources_full_pathnames"); option = Option(def, "export_sources_full_pathnames");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
// Please keep in sync with ConfigWizard // Please keep in sync with ConfigWizard
def.label = L("Associate .3mf files to PrusaSlicer"); def.label = L("Associate .3mf files to PrusaSlicer");
@ -123,7 +122,6 @@ void PreferencesDialog::build()
option = Option(def, "associate_stl"); option = Option(def, "associate_stl");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
// Please keep in sync with ConfigWizard // Please keep in sync with ConfigWizard
def.label = L("Update built-in Presets automatically"); def.label = L("Update built-in Presets automatically");
@ -184,7 +182,6 @@ void PreferencesDialog::build()
option = Option(def, "default_action_on_select_preset"); option = Option(def, "default_action_on_select_preset");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
} }
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32 #ifdef _WIN32
else { else {
def.label = L("Associate .gcode files to PrusaSlicer G-code Viewer"); def.label = L("Associate .gcode files to PrusaSlicer G-code Viewer");
@ -195,7 +192,6 @@ void PreferencesDialog::build()
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
} }
#endif // _WIN32 #endif // _WIN32
#endif // ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#if __APPLE__ #if __APPLE__
def.label = L("Use Retina resolution for the 3D scene"); def.label = L("Use Retina resolution for the 3D scene");
@ -215,7 +211,6 @@ void PreferencesDialog::build()
option = Option(def, "show_splash_screen"); option = Option(def, "show_splash_screen");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
#if ENABLE_CTRL_M_ON_WINDOWS
#if defined(_WIN32) || defined(__APPLE__) #if defined(_WIN32) || defined(__APPLE__)
def.label = L("Enable support for legacy 3DConnexion devices"); def.label = L("Enable support for legacy 3DConnexion devices");
def.type = coBool; def.type = coBool;
@ -224,7 +219,6 @@ void PreferencesDialog::build()
option = Option(def, "use_legacy_3DConnexion"); option = Option(def, "use_legacy_3DConnexion");
m_optgroup_general->append_single_option_line(option); m_optgroup_general->append_single_option_line(option);
#endif // _WIN32 || __APPLE__ #endif // _WIN32 || __APPLE__
#endif // ENABLE_CTRL_M_ON_WINDOWS
activate_options_tab(m_optgroup_general); activate_options_tab(m_optgroup_general);

View file

@ -121,23 +121,26 @@ PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const
Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_suppress_change = false; }); Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_suppress_change = false; });
Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_suppress_change = true; }); Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_suppress_change = true; });
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) { Bind(wxEVT_COMBOBOX, &PresetComboBox::OnSelect, this);
// see https://github.com/prusa3d/PrusaSlicer/issues/3889 }
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter
auto selected_item = evt.GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item)); void PresetComboBox::OnSelect(wxCommandEvent& evt)
if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) {
this->SetSelection(this->m_last_selected); // see https://github.com/prusa3d/PrusaSlicer/issues/3889
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) { // Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
m_last_selected = selected_item; // m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
on_selection_changed(selected_item); // So, use GetSelection() from event parameter
evt.StopPropagation(); auto selected_item = evt.GetSelection();
}
evt.Skip(); auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
}); if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX)
this->SetSelection(this->m_last_selected);
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
m_last_selected = selected_item;
on_selection_changed(selected_item);
evt.StopPropagation();
}
evt.Skip();
} }
PresetComboBox::~PresetComboBox() PresetComboBox::~PresetComboBox()
@ -602,34 +605,6 @@ void PresetComboBox::OnDrawItem(wxDC& dc,
PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type) : PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type) :
PresetComboBox(parent, preset_type, wxSize(15 * wxGetApp().em_unit(), -1)) PresetComboBox(parent, preset_type, wxSize(15 * wxGetApp().em_unit(), -1))
{ {
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) {
auto selected_item = evt.GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
if (marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX) {
this->SetSelection(this->m_last_selected);
evt.StopPropagation();
if (marker == LABEL_ITEM_WIZARD_PRINTERS)
show_add_menu();
else
{
ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME;
switch (marker) {
case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break;
case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break;
default: break;
}
wxTheApp->CallAfter([sp]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); });
}
} else if (marker == LABEL_ITEM_PHYSICAL_PRINTER || this->m_last_selected != selected_item || m_collection->current_is_dirty() ) {
this->m_last_selected = selected_item;
evt.SetInt(this->m_type);
evt.Skip();
} else {
evt.StopPropagation();
}
});
if (m_type == Preset::TYPE_FILAMENT) if (m_type == Preset::TYPE_FILAMENT)
{ {
Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) { Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
@ -717,6 +692,35 @@ PlaterPresetComboBox::~PlaterPresetComboBox()
edit_btn->Destroy(); edit_btn->Destroy();
} }
void PlaterPresetComboBox::OnSelect(wxCommandEvent &evt)
{
auto selected_item = evt.GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
if (marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX) {
this->SetSelection(this->m_last_selected);
evt.StopPropagation();
if (marker == LABEL_ITEM_MARKER)
return;
if (marker == LABEL_ITEM_WIZARD_PRINTERS)
show_add_menu();
else {
ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME;
switch (marker) {
case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break;
case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break;
default: break;
}
wxTheApp->CallAfter([sp]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); });
}
return;
}
else if (marker == LABEL_ITEM_PHYSICAL_PRINTER || this->m_last_selected != selected_item || m_collection->current_is_dirty())
this->m_last_selected = selected_item;
evt.Skip();
}
bool PlaterPresetComboBox::switch_to_tab() bool PlaterPresetComboBox::switch_to_tab()
{ {
Tab* tab = wxGetApp().get_tab(m_type); Tab* tab = wxGetApp().get_tab(m_type);
@ -895,7 +899,7 @@ void PlaterPresetComboBox::update()
for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) { for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
for (const std::string& preset_name : it->get_preset_names()) { for (const std::string& preset_name : it->get_preset_names()) {
Preset* preset = m_collection->find_preset(preset_name); Preset* preset = m_collection->find_preset(preset_name);
if (!preset) if (!preset || !preset->is_visible)
continue; continue;
std::string main_icon_name, bitmap_key = main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name; std::string main_icon_name, bitmap_key = main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;
wxBitmap* bmp = get_bmp(main_icon_name, wide_icons, main_icon_name); wxBitmap* bmp = get_bmp(main_icon_name, wide_icons, main_icon_name);
@ -957,40 +961,42 @@ void PlaterPresetComboBox::msw_rescale()
TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type) : TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type) :
PresetComboBox(parent, preset_type, wxSize(35 * wxGetApp().em_unit(), -1)) PresetComboBox(parent, preset_type, wxSize(35 * wxGetApp().em_unit(), -1))
{ {
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) { }
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter
auto selected_item = evt.GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item)); void TabPresetComboBox::OnSelect(wxCommandEvent &evt)
if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) { {
this->SetSelection(this->m_last_selected); // see https://github.com/prusa3d/PrusaSlicer/issues/3889
if (marker == LABEL_ITEM_WIZARD_PRINTERS) // Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
wxTheApp->CallAfter([this]() { // m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS); // So, use GetSelection() from event parameter
auto selected_item = evt.GetSelection();
// update combobox if its parent is a PhysicalPrinterDialog auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
PhysicalPrinterDialog* parent = dynamic_cast<PhysicalPrinterDialog*>(this->GetParent()); if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) {
if (parent != nullptr) this->SetSelection(this->m_last_selected);
update(); if (marker == LABEL_ITEM_WIZARD_PRINTERS)
}); wxTheApp->CallAfter([this]() {
} wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS);
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty()) ) {
m_last_selected = selected_item;
on_selection_changed(selected_item);
}
evt.StopPropagation(); // update combobox if its parent is a PhysicalPrinterDialog
PhysicalPrinterDialog* parent = dynamic_cast<PhysicalPrinterDialog*>(this->GetParent());
if (parent != nullptr)
update();
});
}
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
m_last_selected = selected_item;
on_selection_changed(selected_item);
}
evt.StopPropagation();
#ifdef __WXMSW__ #ifdef __WXMSW__
// From the Win 2004 preset combobox lose a focus after change the preset selection // From the Win 2004 preset combobox lose a focus after change the preset selection
// and that is why the up/down arrow doesn't work properly // and that is why the up/down arrow doesn't work properly
// (see https://github.com/prusa3d/PrusaSlicer/issues/5531 ). // (see https://github.com/prusa3d/PrusaSlicer/issues/5531 ).
// So, set the focus to the combobox explicitly // So, set the focus to the combobox explicitly
this->SetFocus(); this->SetFocus();
#endif #endif
});
} }
wxString TabPresetComboBox::get_preset_name(const Preset& preset) wxString TabPresetComboBox::get_preset_name(const Preset& preset)
@ -1080,7 +1086,7 @@ void TabPresetComboBox::update()
for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) { for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
for (const std::string& preset_name : it->get_preset_names()) { for (const std::string& preset_name : it->get_preset_names()) {
Preset* preset = m_collection->find_preset(preset_name); Preset* preset = m_collection->find_preset(preset_name);
if (!preset) if (!preset || !preset->is_visible)
continue; continue;
std::string main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name; std::string main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;

View file

@ -71,6 +71,7 @@ public:
void show_all(bool show_all); void show_all(bool show_all);
virtual void update(); virtual void update();
virtual void msw_rescale(); virtual void msw_rescale();
virtual void OnSelect(wxCommandEvent& evt);
protected: protected:
typedef std::size_t Marker; typedef std::size_t Marker;
@ -167,6 +168,7 @@ public:
wxString get_preset_name(const Preset& preset) override; wxString get_preset_name(const Preset& preset) override;
void update() override; void update() override;
void msw_rescale() override; void msw_rescale() override;
void OnSelect(wxCommandEvent& evt) override;
private: private:
int m_extruder_idx = -1; int m_extruder_idx = -1;
@ -193,6 +195,7 @@ public:
void update() override; void update() override;
void update_dirty(); void update_dirty();
void msw_rescale() override; void msw_rescale() override;
void OnSelect(wxCommandEvent& evt) override;
void set_enable_all(bool enable=true) { m_enable_all = enable; } void set_enable_all(bool enable=true) { m_enable_all = enable; }

View file

@ -209,12 +209,12 @@ SavePresetDialog::~SavePresetDialog()
void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix) void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix)
{ {
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__) #if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling // ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // __WXMSW__
if (suffix.empty()) if (suffix.empty())
suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName"); suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");

View file

@ -1732,10 +1732,10 @@ bool Tab::validate_custom_gcode(const wxString& title, const std::string& gcode)
return !invalid; return !invalid;
} }
static void validate_custom_gcode_cb(Tab* tab, ConfigOptionsGroupShp opt_group, const boost::any& value) { static void validate_custom_gcode_cb(Tab* tab, ConfigOptionsGroupShp opt_group, const t_config_option_key& opt_key, const boost::any& value) {
Tab::validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(value)); Tab::validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(value));
tab->update_dirty(); tab->update_dirty();
tab->update(); tab->on_value_change(opt_key, value);
} }
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
@ -1964,7 +1964,7 @@ void TabFilament::build()
optgroup = page->new_optgroup(L("Start G-code"), 0); optgroup = page->new_optgroup(L("Start G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, value); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("start_filament_gcode"); option = optgroup->get_option("start_filament_gcode");
@ -1976,7 +1976,7 @@ void TabFilament::build()
optgroup = page->new_optgroup(L("End G-code"), 0); optgroup = page->new_optgroup(L("End G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, value); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("end_filament_gcode"); option = optgroup->get_option("end_filament_gcode");
@ -2273,17 +2273,11 @@ void TabPrinter::build_fff()
const int gcode_field_height = 15; // 150 const int gcode_field_height = 15; // 150
const int notes_field_height = 25; // 250 const int notes_field_height = 25; // 250
#if ENABLE_VALIDATE_CUSTOM_GCODE
// WARNING !!
// if you are going to change any of the following optgroup/option titles
// or to add/remove optgroups/options
// update also TabPrinter::validate_custom_gcodes()
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
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); optgroup = page->new_optgroup(L("Start G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("start_gcode"); option = optgroup->get_option("start_gcode");
@ -2295,7 +2289,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("End G-code"), 0); optgroup = page->new_optgroup(L("End G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("end_gcode"); option = optgroup->get_option("end_gcode");
@ -2307,7 +2301,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Before layer change G-code"), 0); optgroup = page->new_optgroup(L("Before layer change G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("before_layer_gcode"); option = optgroup->get_option("before_layer_gcode");
@ -2319,7 +2313,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("After layer change G-code"), 0); optgroup = page->new_optgroup(L("After layer change G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("layer_gcode"); option = optgroup->get_option("layer_gcode");
@ -2331,7 +2325,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Tool change G-code"), 0); optgroup = page->new_optgroup(L("Tool change G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("toolchange_gcode"); option = optgroup->get_option("toolchange_gcode");
@ -2343,7 +2337,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0); optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("between_objects_gcode"); option = optgroup->get_option("between_objects_gcode");
@ -2355,7 +2349,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Color Change G-code"), 0); optgroup = page->new_optgroup(L("Color Change G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("color_change_gcode"); option = optgroup->get_option("color_change_gcode");
@ -2366,7 +2360,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Pause Print G-code"), 0); optgroup = page->new_optgroup(L("Pause Print G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("pause_print_gcode"); option = optgroup->get_option("pause_print_gcode");
@ -2377,7 +2371,7 @@ void TabPrinter::build_fff()
optgroup = page->new_optgroup(L("Template Custom G-code"), 0); optgroup = page->new_optgroup(L("Template Custom G-code"), 0);
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value)); validate_custom_gcode_cb(this, optgroup, opt_key, value);
}; };
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
option = optgroup->get_option("template_custom_gcode"); option = optgroup->get_option("template_custom_gcode");
@ -3832,15 +3826,35 @@ void TabPrinter::apply_extruder_cnt_from_cache()
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
bool Tab::validate_custom_gcodes() bool Tab::validate_custom_gcodes()
{ {
if (m_type != Preset::TYPE_FILAMENT &&
(m_type != Preset::TYPE_PRINTER || static_cast<TabPrinter*>(this)->m_printer_technology != ptFFF))
return true;
if (m_active_page->title() != L("Custom G-code"))
return true;
bool valid = true; bool valid = true;
if ((m_type == Preset::TYPE_FILAMENT || for (auto opt_group : m_active_page->m_optgroups) {
m_type == Preset::TYPE_PRINTER && static_cast<TabPrinter*>(this)->m_printer_technology == ptFFF) && assert(opt_group->opt_map().size() == 1);
m_active_page->title() == "Custom G-code") { std::string key = opt_group->opt_map().begin()->first;
for (auto opt_group : m_active_page->m_optgroups) { std::string value = boost::any_cast<std::string>(opt_group->get_value(key));
assert(opt_group->opt_map().size() == 1); std::string config_value = m_config->opt_string(key);
std::string key = opt_group->opt_map().begin()->first; valid &= validate_custom_gcode(opt_group->title, value);
valid &= validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(opt_group->get_value(key))); Field* field = opt_group->get_field(key);
} TextCtrl* text_ctrl = dynamic_cast<TextCtrl*>(field);
if (text_ctrl != nullptr && text_ctrl->m_on_change != nullptr && !text_ctrl->m_disable_change_event) {
Slic3r::GUI::t_change callback = opt_group->m_on_change;
// temporary disable the opt_group->m_on_change callback to avoid multiple validations
opt_group->m_on_change = nullptr;
text_ctrl->m_on_change(key, value);
// restore the opt_group->m_on_change callback
opt_group->m_on_change = callback;
update_dirty();
on_value_change(key, value);
}
if (!valid)
break;
} }
return valid; return valid;
} }

View file

@ -601,7 +601,7 @@ void DiffViewCtrl::AppendBmpTextColumn(const wxString& label, unsigned model_col
#ifdef SUPPORTS_MARKUP #ifdef SUPPORTS_MARKUP
rd->EnableMarkup(true); rd->EnableMarkup(true);
#endif #endif
wxDataViewColumn* column = new wxDataViewColumn(label, rd, model_column, width, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_CELL_INERT); wxDataViewColumn* column = new wxDataViewColumn(label, rd, model_column, width * m_em_unit, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_CELL_INERT);
#else #else
wxDataViewColumn* column = new wxDataViewColumn(label, new BitmapTextRenderer(true, wxDATAVIEW_CELL_INERT), model_column, width * m_em_unit, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE); wxDataViewColumn* column = new wxDataViewColumn(label, new BitmapTextRenderer(true, wxDATAVIEW_CELL_INERT), model_column, width * m_em_unit, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE);
#endif //__linux__ #endif //__linux__
@ -792,12 +792,12 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
SetBackgroundColour(bgr_clr); SetBackgroundColour(bgr_clr);
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__) #if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling // ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // __WXMSW__
int border = 10; int border = 10;
int em = em_unit(); int em = em_unit();
@ -806,7 +806,7 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
m_action_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold()); m_action_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
m_tree = new DiffViewCtrl(this, wxSize(em * 60, em * 30)); m_tree = new DiffViewCtrl(this, wxSize(em * 60, em * 30));
m_tree->AppendToggleColumn_(L"\u2714" , DiffModel::colToggle, wxLinux ? 8 : 6); m_tree->AppendToggleColumn_(L"\u2714" , DiffModel::colToggle, wxLinux ? 9 : 6);
m_tree->AppendBmpTextColumn("" , DiffModel::colIconText, 28); m_tree->AppendBmpTextColumn("" , DiffModel::colIconText, 28);
m_tree->AppendBmpTextColumn(_L("Old Value"), DiffModel::colOldValue, 12); m_tree->AppendBmpTextColumn(_L("Old Value"), DiffModel::colOldValue, 12);
m_tree->AppendBmpTextColumn(_L("New Value"), DiffModel::colNewValue, 12); m_tree->AppendBmpTextColumn(_L("New Value"), DiffModel::colNewValue, 12);
@ -1375,12 +1375,12 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
SetBackgroundColour(bgr_clr); SetBackgroundColour(bgr_clr);
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__) #if defined(__WXMSW__)
// ys_FIXME! temporary workaround for correct font scaling // ys_FIXME! temporary workaround for correct font scaling
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // __WXMSW__
int border = 10; int border = 10;
int em = em_unit(); int em = em_unit();

View file

@ -11,6 +11,7 @@ add_executable(${_TEST_NAME}_tests
test_geometry.cpp test_geometry.cpp
test_placeholder_parser.cpp test_placeholder_parser.cpp
test_polygon.cpp test_polygon.cpp
test_mutable_polygon.cpp
test_stl.cpp test_stl.cpp
test_meshsimplify.cpp test_meshsimplify.cpp
test_meshboolean.cpp test_meshboolean.cpp

View file

@ -0,0 +1,145 @@
#include <catch2/catch.hpp>
#include "libslic3r/MutablePolygon.hpp"
using namespace Slic3r;
SCENARIO("Iterators", "[MutablePolygon]") {
GIVEN("Polygon with three points") {
Slic3r::MutablePolygon p({ { 0, 0 }, { 0, 1 }, { 1, 0 } });
WHEN("Iterating upwards") {
auto begin = p.begin();
auto end = p.end();
auto it = begin;
THEN("++ it is not equal to begin") {
REQUIRE(++ it != begin);
} THEN("++ it is not equal to end") {
REQUIRE(++ it != end);
} THEN("++ (++ it) is not equal to begin") {
REQUIRE(++ (++ it) != begin);
} THEN("++ (++ it) is equal to end") {
REQUIRE(++ (++ it) == end);
} THEN("++ (++ (++ it)) is equal to begin") {
REQUIRE(++ (++ (++ it)) == begin);
} THEN("++ (++ (++ it)) is not equal to end") {
REQUIRE(++ (++ (++ it)) != end);
}
}
WHEN("Iterating downwards") {
auto begin = p.begin();
auto end = p.end();
auto it = begin;
THEN("-- it is not equal to begin") {
REQUIRE(-- it != begin);
} THEN("-- it is equal to end") {
REQUIRE(-- it == end);
} THEN("-- (-- it) is not equal to begin") {
REQUIRE(-- (-- it) != begin);
} THEN("-- (-- it) is not equal to end") {
REQUIRE(-- (-- it) != end);
} THEN("-- (-- (-- it)) is equal to begin") {
REQUIRE(-- (-- (-- it)) == begin);
} THEN("-- (-- (-- it)) is not equal to end") {
REQUIRE(-- (-- (-- it)) != end);
}
}
WHEN("Deleting 1st point") {
auto it_2nd = p.begin().next();
auto it_3rd = p.end();
auto it = p.begin().remove();
THEN("Size is 2") {
REQUIRE(p.size() == 2);
} THEN("p.begin().remove() == it_2nd") {
REQUIRE(it == it_2nd);
} THEN("it_2nd == new begin()") {
REQUIRE(it_2nd == p.begin());
}
}
WHEN("Deleting 2nd point") {
auto it_1st = p.begin();
auto it_2nd = it_1st.next();
auto it_3rd = p.end();
auto it = it_2nd.remove();
THEN("Size is 2") {
REQUIRE(p.size() == 2);
REQUIRE(! p.empty());
} THEN("it_2nd.remove() == it_3rd") {
REQUIRE(it == it_2nd);
} THEN("it_1st == new begin()") {
REQUIRE(it_1st == p.begin());
}
}
WHEN("Deleting two points") {
p.begin().remove().remove();
THEN("Size is 1") {
REQUIRE(p.size() == 1);
} THEN("p.begin().next() == p.begin()") {
REQUIRE(p.begin().next() == p.begin());
} THEN("p.begin().prev() == p.begin()") {
REQUIRE(p.begin().prev() == p.begin());
}
}
WHEN("Deleting all points") {
auto it = p.begin().remove().remove().remove();
THEN("Size is 0") {
REQUIRE(p.size() == 0);
REQUIRE(p.empty());
} THEN("! p.begin().valid()") {
REQUIRE(!p.begin().valid());
} THEN("last iterator not valid") {
REQUIRE(! it.valid());
}
}
WHEN("Inserting a point at the beginning") {
p.insert(p.begin(), { 3, 4 });
THEN("Polygon content is ok") {
REQUIRE(p == MutablePolygon{ { 0, 0 }, { 0, 1 }, { 1, 0 }, { 3, 4 } });
}
}
WHEN("Inserting a point at the 2nd position") {
p.insert(++ p.begin(), { 3, 4 });
THEN("Polygon content is ok") {
REQUIRE(p == MutablePolygon{ { 0, 0 }, { 3, 4 }, { 0, 1 }, { 1, 0 } });
}
} WHEN("Inserting a point after a point was removed") {
size_t capacity = p.capacity();
THEN("Initial capacity is 3") {
REQUIRE(capacity == 3);
}
p.begin().remove();
THEN("After removal of the 1st point the capacity is still 3") {
REQUIRE(p.capacity() == 3);
}
THEN("After removal of the 1st point the content is ok") {
REQUIRE(p == MutablePolygon{ { 0, 1 }, { 1, 0 } });
}
p.insert(p.begin(), { 5, 6 });
THEN("After insertion at head position the polygon content is ok") {
REQUIRE(p == MutablePolygon{ { 0, 1 }, { 1, 0 }, { 5, 6 } });
} THEN("and the capacity is still 3") {
REQUIRE(p.capacity() == 3);
}
}
}
}
SCENARIO("Remove degenerate points from MutablePolygon", "[MutablePolygon]") {
GIVEN("Polygon with duplicate points"){
Slic3r::MutablePolygon p({
{ 0, 0 },
{ 0, 100 }, { 0, 100 }, { 0, 100 },
{ 0, 150 },
{ 0, 200 },
{ 200, 200 },
{ 180, 200 }, { 180, 200 },
{ 180, 20 },
{ 180, 0 },
});
WHEN("Duplicate points are removed") {
remove_duplicates(p);
THEN("Polygon content is ok") {
REQUIRE(p == Slic3r::MutablePolygon{ { 0, 0 }, { 0, 100 }, { 0, 150 }, { 0, 200 }, { 200, 200 }, { 180, 200 }, { 180, 20 }, { 180, 0 } });
}
}
}
}