Merge remote-tracking branch 'remotes/origin/master' into vb_faster_tabs

This commit is contained in:
bubnikv 2019-03-18 12:51:57 +01:00
commit b5894d334c
41 changed files with 4159 additions and 3867 deletions

View File

@ -1,14 +1,22 @@
min_slic3r_version = 1.42.0-alpha6
0.8.0-alpha7
0.8.0-alpha6
0.8.0-beta Updated SLA profiles
0.8.0-alpha9 Updated SLA and FFF profiles
0.8.0-alpha8 Updated SLA profiles
0.8.0-alpha7 Updated SLA profiles
0.8.0-alpha6 Updated SLA profiles
min_slic3r_version = 1.42.0-alpha
0.8.0-alpha
0.8.0-alpha Updated SLA profiles
0.4.0-alpha4 Updated SLA profiles
0.4.0-alpha3 Update of SLA profiles
0.4.0-alpha2 First SLA profiles
min_slic3r_version = 1.41.3-alpha
0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
0.4.3 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
0.4.2 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
0.4.1 New MK2.5S and MK3S FW versions
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
min_slic3r_version = 1.41.1
0.3.5 New MK2.5 and MK3 FW versions
0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
0.3.3 Prusament PETG released
0.3.2 New MK2.5 and MK3 FW versions
@ -41,6 +49,7 @@ min_slic3r_version = 1.41.0-alpha
0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
min_slic3r_version = 1.40.0
0.1.13 New MK2.5 and MK3 FW versions
0.1.12 New MK2.5 and MK3 FW versions
0.1.11 fw version changed to 3.3.1
0.1.10 MK3 jerk and acceleration update

View File

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the Slic3r configuration to be downgraded.
config_version = 0.8.0-alpha7
config_version = 0.8.0-beta
# Where to get the updates from?
config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/
@ -190,6 +190,14 @@ travel_speed = 180
wipe_tower_x = 170
wipe_tower_y = 125
[print:*MK306*]
fill_pattern = gyroid
fill_density = 15%
single_extruder_multi_material_priming = 0
travel_speed = 180
wipe_tower_x = 170
wipe_tower_y = 125
# Print parameters common to a 0.25mm diameter nozzle.
[print:*0.25nozzle*]
external_perimeter_extrusion_width = 0.25
@ -205,6 +213,38 @@ support_material_interface_spacing = 0.15
support_material_spacing = 1
support_material_xy_spacing = 150%
[print:*0.25nozzleMK3*]
external_perimeter_extrusion_width = 0.25
extrusion_width = 0.25
first_layer_extrusion_width = 0.35
infill_extrusion_width = 0.25
perimeter_extrusion_width = 0.25
solid_infill_extrusion_width = 0.25
top_infill_extrusion_width = 0.25
support_material_extrusion_width = 0.2
support_material_interface_layers = 0
support_material_interface_spacing = 0.15
support_material_spacing = 1
support_material_xy_spacing = 150%
perimeter_speed = 30
external_perimeter_speed = 20
small_perimeter_speed = 20
infill_speed = 45
solid_infill_speed = 45
top_solid_infill_speed = 30
support_material_speed = 40
bridge_speed = 20
gap_fill_speed = 30
perimeter_acceleration = 500
infill_acceleration = 1000
bridge_acceleration = 500
first_layer_acceleration = 500
default_acceleration = 1000
max_print_speed = 80
perimeters = 3
fill_pattern = grid
fill_density = 20%
# Print parameters common to a 0.6mm diameter nozzle.
[print:*0.6nozzle*]
external_perimeter_extrusion_width = 0.61
@ -216,6 +256,18 @@ solid_infill_extrusion_width = 0.65
top_infill_extrusion_width = 0.6
support_material_extrusion_width = 0.55
[print:*0.6nozzleMK3*]
external_perimeter_extrusion_width = 0.65
extrusion_width = 0.65
first_layer_extrusion_width = 0.65
infill_extrusion_width = 0.7
perimeter_extrusion_width = 0.65
solid_infill_extrusion_width = 0.7
top_infill_extrusion_width = 0.6
support_material_extrusion_width = 0.55
bridge_flow_ratio = 0.95
bridge_speed = 25
[print:*soluble_support*]
overhangs = 1
skirts = 0
@ -288,6 +340,9 @@ support_material_speed = 20
[print:0.05mm ULTRADETAIL 0.25 nozzle MK3]
inherits = *0.05mm*; *0.25nozzle*; *MK3*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
fill_pattern = grid
fill_density = 20%
first_layer_extrusion_width = 0.35
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.07mm ---XXX
@ -326,6 +381,17 @@ fill_pattern = gyroid
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
top_infill_extrusion_width = 0.4
[print:0.07mm ULTRADETAIL 0.25 nozzle MK3]
inherits = *0.07mm*; *0.25nozzle*; *MK3*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
infill_speed = 30
solid_infill_speed = 30
support_material_speed = 30
top_solid_infill_speed = 20
fill_pattern = grid
fill_density = 20%
first_layer_extrusion_width = 0.35
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.10mm ---XXX
# XXXXXXXXXXXXXXXXXXXX
@ -382,29 +448,10 @@ top_solid_infill_speed = 30
# MK3 #
[print:0.10mm DETAIL 0.25 nozzle MK3]
inherits = *0.10mm*; *0.25nozzle*; *MK3*
bridge_speed = 30
inherits = *0.10mm*; *0.25nozzleMK3*; *MK3*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 200
max_print_speed = 200
perimeter_speed = 45
solid_infill_speed = 200
top_solid_infill_speed = 50
# MK3 #
[print:0.10mm DETAIL 0.6 nozzle MK3]
inherits = *0.10mm*; *0.6nozzle*; *MK3*
bridge_speed = 30
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 200
max_print_speed = 200
perimeter_speed = 45
solid_infill_speed = 200
top_solid_infill_speed = 50
fill_pattern = grid
fill_density = 20%
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.15mm ---XXX
@ -531,17 +578,27 @@ support_material_with_sheath = 0
support_material_xy_spacing = 80%
# MK3 #
[print:0.15mm OPTIMAL 0.25 nozzle MK3]
inherits = *0.15mm*; *0.25nozzle*; *MK3*
bridge_speed = 30
[print:0.15mm QUALITY 0.25 nozzle MK3]
inherits = *0.15mm*; *0.25nozzleMK3*; *MK3*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
fill_pattern = grid
fill_density = 20%
# MK3 #
[print:0.15mm DETAIL 0.6 nozzle MK3]
inherits = *0.15mm*; *0.6nozzleMK3*; *MK306*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 200
max_print_speed = 200
infill_speed = 70
max_print_speed = 100
perimeter_speed = 45
solid_infill_speed = 200
top_solid_infill_speed = 50
solid_infill_speed = 70
top_solid_infill_speed = 45
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.20mm ---XXX
# XXXXXXXXXXXXXXXXXXXX
[print:*0.20mm*]
inherits = *common*
@ -557,23 +614,6 @@ solid_infill_speed = 50
top_infill_extrusion_width = 0.4
top_solid_layers = 5
# MK3 #
[print:0.15mm OPTIMAL 0.6 nozzle MK3]
inherits = *0.15mm*; *0.6nozzle*; *MK3*
bridge_speed = 30
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 200
max_print_speed = 200
perimeter_speed = 45
solid_infill_speed = 200
top_solid_infill_speed = 50
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.20mm ---XXX
# XXXXXXXXXXXXXXXXXXXX
# MK2 #
[print:0.20mm 100mms Linear Advance]
inherits = *0.20mm*
@ -664,17 +704,68 @@ support_material_with_sheath = 0
support_material_xy_spacing = 80%
# MK3 #
[print:0.20mm FAST 0.6 nozzle MK3]
inherits = *0.20mm*; *0.6nozzle*; *MK3*
bridge_speed = 30
[print:0.20mm DETAIL 0.6 nozzle MK3]
inherits = *0.20mm*; *0.6nozzleMK3*; *MK306*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 200
max_print_speed = 200
infill_speed = 70
max_print_speed = 100
perimeter_speed = 45
solid_infill_speed = 200
top_solid_infill_speed = 50
solid_infill_speed = 70
top_solid_infill_speed = 45
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.30mm ---XXX
# XXXXXXXXXXXXXXXXXXXX
[print:*0.30mm*]
inherits = *common*
bottom_solid_layers = 4
bridge_flow_ratio = 0.95
external_perimeter_speed = 40
infill_acceleration = 2000
infill_speed = 60
layer_height = 0.3
perimeter_acceleration = 800
perimeter_speed = 50
solid_infill_speed = 50
top_infill_extrusion_width = 0.4
top_solid_layers = 4
[print:0.30mm QUALITY 0.6 nozzle MK3]
inherits = *0.30mm*; *0.6nozzleMK3*; *MK306*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 70
max_print_speed = 100
perimeter_speed = 45
solid_infill_speed = 70
top_solid_infill_speed = 45
[print:0.30mm DRAFT MK3]
inherits = *0.30mm*; *MK3*
bottom_solid_layers = 3
bridge_speed = 30
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 85
max_print_speed = 200
perimeter_speed = 50
small_perimeter_speed = 30
solid_infill_speed = 80
top_solid_infill_speed = 40
support_material_speed = 45
external_perimeter_extrusion_width = 0.6
extrusion_width = 0.5
first_layer_extrusion_width = 0.42
infill_extrusion_width = 0.5
perimeter_extrusion_width = 0.5
solid_infill_extrusion_width = 0.5
top_infill_extrusion_width = 0.45
support_material_extrusion_width = 0.35
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.35mm ---XXX
@ -732,6 +823,57 @@ support_material_interface_layers = 2
support_material_with_sheath = 0
support_material_xy_spacing = 150%
# MK3 #
[print:0.35mm SPEED 0.6 nozzle MK3]
inherits = *0.35mm*; *0.6nozzleMK3*; *MK306*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 70
max_print_speed = 100
perimeter_speed = 45
solid_infill_speed = 70
top_solid_infill_speed = 45
external_perimeter_extrusion_width = 0.68
perimeter_extrusion_width = 0.68
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.40mm ---XXX
# XXXXXXXXXXXXXXXXXXXX
[print:*0.40mm*]
inherits = *common*
bottom_solid_layers = 3
external_perimeter_extrusion_width = 0.6
external_perimeter_speed = 40
first_layer_extrusion_width = 0.65
infill_acceleration = 2000
infill_speed = 60
layer_height = 0.4
perimeter_acceleration = 800
perimeter_extrusion_width = 0.65
perimeter_speed = 50
solid_infill_extrusion_width = 0.65
solid_infill_speed = 60
top_solid_infill_speed = 40
top_solid_layers = 4
# MK3 #
[print:0.40mm DRAFT 0.6 nozzle MK3]
inherits = *0.40mm*; *0.6nozzleMK3*; *MK306*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
external_perimeter_speed = 35
infill_acceleration = 1250
infill_speed = 70
max_print_speed = 100
perimeter_speed = 45
solid_infill_speed = 70
top_solid_infill_speed = 45
external_perimeter_extrusion_width = 0.7
perimeter_extrusion_width = 0.7
infill_extrusion_width = 0.72
solid_infill_extrusion_width = 0.72
# XXXXXXXXXXXXXXXXXXXXXX
# XXX----- MK2.5 ----XXX
# XXXXXXXXXXXXXXXXXXXXXX
@ -827,7 +969,7 @@ filament_settings_id = ""
filament_soluble = 0
min_print_speed = 15
slowdown_below_layer_time = 20
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode"
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif} ; Filament gcode"
[filament:*PLA*]
inherits = *common*
@ -844,6 +986,7 @@ first_layer_temperature = 215
max_fan_speed = 100
min_fan_speed = 100
temperature = 210
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode"
[filament:*PET*]
inherits = *common*
@ -859,9 +1002,14 @@ first_layer_bed_temperature = 85
first_layer_temperature = 230
max_fan_speed = 50
min_fan_speed = 30
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode"
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}22{else}45{endif} ; Filament gcode"
temperature = 240
[filament:*PET06*]
inherits = *PET*
compatible_printers_condition = nozzle_diameter[0]==0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
filament_max_volumetric_speed = 15
[filament:*ABS*]
inherits = *common*
bed_temperature = 110
@ -879,6 +1027,7 @@ first_layer_temperature = 255
max_fan_speed = 30
min_fan_speed = 20
temperature = 255
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode"
[filament:*FLEX*]
inherits = *common*
@ -906,10 +1055,11 @@ inherits = *PLA*
# For now, all but selected filaments are disabled for the MMU 2.0
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
extrusion_multiplier = 1.2
filament_cost = 80.65
filament_density = 4
filament_cost = 56.64
filament_density = 3.9
filament_colour = #804040
filament_max_volumetric_speed = 10
filament_max_volumetric_speed = 9
filament_notes = "List of materials tested with standard print settings:\n\nColorFabb bronzeFill\nColorFabb brassFill\nColorFabb steelFill\nColorFabb copperFill"
[filament:ColorFabb HT]
inherits = *PET*
@ -933,19 +1083,31 @@ inherits = *PLA*
filament_cost = 55.5
filament_density = 1.24
[filament:ColorFabb Woodfil]
[filament:ColorFabb woodFill]
inherits = *PLA*
# For now, all but selected filaments are disabled for the MMU 2.0
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
extrusion_multiplier = 1.2
filament_cost = 62.9
filament_density = 1.15
filament_colour = #804040
filament_colour = #dfc287
filament_max_volumetric_speed = 10
first_layer_temperature = 200
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
temperature = 200
[filament:ColorFabb corkFill]
inherits = *PLA*
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
extrusion_multiplier = 1.2
filament_cost = 45.45
filament_density = 1.18
filament_colour = #634d33
filament_max_volumetric_speed = 6
first_layer_temperature = 220
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
temperature = 220
[filament:ColorFabb XT]
inherits = *PET*
filament_type = PET
@ -1001,7 +1163,7 @@ temperature = 260
inherits = *PET*
filament_cost = 56.9
filament_density = 1.26
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
[filament:E3D PC-ABS]
inherits = *ABS*
@ -1036,7 +1198,7 @@ max_fan_speed = 50
min_fan_speed = 50
temperature = 275
[filament:Fillamentum Timberfil]
[filament:Fillamentum Timberfill]
inherits = *PLA*
# For now, all but selected filaments are disabled for the MMU 2.0
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
@ -1053,19 +1215,19 @@ temperature = 190
inherits = *ABS*
filament_cost = 27.82
filament_density = 1.04
filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
[filament:Generic PET]
inherits = *PET*
filament_cost = 27.82
filament_density = 1.27
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
[filament:Generic PLA]
inherits = *PLA*
filament_cost = 25.4
filament_density = 1.24
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
[filament:Polymaker PC-Max]
inherits = *ABS*
@ -1084,11 +1246,11 @@ filament_density = 1.23
cooling = 0
fan_always_on = 0
filament_colour = #FFFFD7
filament_max_volumetric_speed = 10
filament_notes = "List of materials tested with standart PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'\nVerbatim BVOH"
filament_max_volumetric_speed = 4
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'"
filament_ramming_parameters = "120 100 8.3871 8.6129 8.93548 9.22581 9.48387 9.70968 9.87097 10.0323 10.2258 10.4194 10.6452 10.8065| 0.05 8.34193 0.45 8.73548 0.95 9.34836 1.45 9.78385 1.95 10.0871 2.45 10.5161 2.95 10.8903 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
filament_soluble = 1
filament_type = PVA
filament_type = PLA
first_layer_temperature = 195
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
temperature = 195
@ -1097,7 +1259,7 @@ temperature = 195
inherits = *ABS*
filament_cost = 27.82
filament_density = 1.08
filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
[filament:*ABS MMU2*]
inherits = Prusa ABS
@ -1140,7 +1302,8 @@ temperature = 220
inherits = *PET*
filament_cost = 27.82
filament_density = 1.27
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
[filament:Prusament PETG]
inherits = *PET*
@ -1148,6 +1311,20 @@ first_layer_temperature = 240
temperature = 250
filament_cost = 24.99
filament_density = 1.27
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
[filament:Prusa PET 0.6 nozzle]
inherits = *PET06*
filament_cost = 27.82
filament_density = 1.27
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
[filament:Prusament PETG 0.6 nozzle]
inherits = *PET06*
first_layer_temperature = 240
temperature = 250
filament_cost = 24.99
filament_density = 1.27
[filament:*PET MMU2*]
inherits = Prusa PET
@ -1179,7 +1356,7 @@ inherits = *PET MMU2*
inherits = *PLA*
filament_cost = 25.4
filament_density = 1.24
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
[filament:Prusament PLA]
inherits = *PLA*
@ -1265,7 +1442,7 @@ fan_always_on = 0
fan_below_layer_time = 100
filament_colour = #FFFFD7
filament_max_volumetric_speed = 4
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH"
filament_soluble = 1
filament_type = PLA
first_layer_bed_temperature = 60
@ -1279,7 +1456,6 @@ temperature = 210
inherits = Verbatim BVOH
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
temperature = 195
filament_notes = BVOH
fan_always_on = 1
first_layer_temperature = 200
filament_cooling_final_speed = 1
@ -1316,7 +1492,7 @@ filament_loading_speed = 14
filament_loading_speed_start = 19
filament_max_volumetric_speed = 4
filament_minimal_purge_on_wipe_tower = 5
filament_notes = PVA
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+"
filament_ramming_parameters = "120 110 3.83871 3.90323 3.96774 4.03226 4.09677 4.19355 4.3871 4.83871 5.67742 6.93548 8.54839 10.3226 11.9677 13.2581 14.129 14.5806| 0.05 3.8258 0.45 3.89676 0.95 4.05807 1.45 4.23548 1.95 5.18386 2.45 7.80651 2.95 11.5356 3.45 13.9872 3.95 14.7613 4.45 7.6 4.95 7.6"
filament_soluble = 1
filament_toolchange_delay = 0
@ -1346,7 +1522,7 @@ fan_always_on = 1
fan_below_layer_time = 100
filament_colour = #DEE0E6
filament_max_volumetric_speed = 5
filament_notes = "List of materials tested with standart PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA"
filament_notes = "List of materials tested with standard PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA"
filament_type = PLA
first_layer_bed_temperature = 100
first_layer_temperature = 220
@ -1358,14 +1534,15 @@ temperature = 220
[sla_print:*common*]
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_SL1.*/
layer_height = 0.05
output_filename_format = [input_filename_base].dwz
output_filename_format = [input_filename_base].sl1
pad_edge_radius = 0.5
pad_enable = 1
pad_max_merge_distance = 50
pad_wall_height = 3
pad_wall_height = 0
pad_wall_thickness = 1
pad_wall_slope = 90
support_base_diameter = 3
support_base_height = 0.5
support_base_height = 1
support_critical_angle = 45
support_density_at_45 = 250
support_density_at_horizontal = 500
@ -1376,6 +1553,7 @@ support_max_bridge_length = 10
support_minimal_z = 0
support_object_elevation = 5
support_pillar_diameter = 1
support_pillar_connection_mode = zigzag
support_pillar_widening_factor = 0
supports_enable = 1
@ -1441,6 +1619,11 @@ inherits = *common 0.025*
exposure_time = 5
initial_exposure_time = 35
[sla_material:SL1 Orange solid 0.025]
inherits = *common 0.025*
exposure_time = 5
initial_exposure_time = 35
########### Materials 0.05
[sla_material:3DM-HTR140 (high temperature) 0.05]
@ -1458,11 +1641,31 @@ inherits = *common 0.05*
exposure_time = 8
initial_exposure_time = 45
[sla_material:Bluecast Keramaster Dental 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 45
[sla_material:Bluecast LCD-DLP Original 0.05]
inherits = *common 0.05*
exposure_time = 10
initial_exposure_time = 60
[sla_material:Bluecast Phrozen Wax 0.05]
inherits = *common 0.05*
exposure_time = 10
initial_exposure_time = 55
[sla_material:Bluecast S+ 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 45
[sla_material:Bluecast X2 0.05]
inherits = *common 0.05*
exposure_time = 10
initial_exposure_time = 60
[sla_material:Jamg He PJHC-00 Yellow 0.05]
inherits = *common 0.05*
exposure_time = 7
@ -1475,7 +1678,7 @@ initial_exposure_time = 45
[sla_material:Jamg He PJHC-30 Orange 0.05]
inherits = *common 0.05*
exposure_time = 7
exposure_time = 7.5
initial_exposure_time = 45
[sla_material:Jamg He PJHC-60 Gray 0.05]
@ -1513,8 +1716,6 @@ inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 40
# v2
[sla_material:3DM-ABS 0.05]
inherits = *common 0.05*
exposure_time = 9
@ -1560,11 +1761,101 @@ inherits = *common 0.05*
exposure_time = 6.5
initial_exposure_time = 40
[sla_material:Harz Labs Model Resin Cherry 0.05]
inherits = *common 0.05*
exposure_time = 8
initial_exposure_time = 45
[sla_material:Jamg He CRX-70C High Tenacity Black 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 40
[sla_material:Jamg He MC-2000 Casting Green 0.05]
inherits = *common 0.05*
exposure_time = 13
initial_exposure_time = 40
[sla_material:Jamg He PJHC-00 Solid Yellow 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 40
[sla_material:Jamg He PJHC-20 White 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 45
[sla_material:Jamg He PJHC-80 Transparent Green 0.05]
inherits = *common 0.05*
exposure_time = 8
initial_exposure_time = 45
[sla_material:Jamg He PJHC-80 Transparent Red 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 45
[sla_material:Jamg He PJHC-81 Solid Maroon 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 45
[sla_material:Jamg He PJHC-90 Solid Pink 0.05]
inherits = *common 0.05*
exposure_time = 7
initial_exposure_time = 40
[sla_material:Jamg He RJHC-00 Yellow Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:Jamg He RJHC-10 Clear Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:Jamg He RJHC-20 White Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:Jamg He RJHC-50 Blue Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:Jamg He RJHC-70 Black Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:Jamg He RJHC-81 Red Flexible 0.05]
inherits = *common 0.05*
exposure_time = 9
initial_exposure_time = 40
[sla_material:SL1 Orange solid 0.05]
inherits = *common 0.05*
exposure_time = 7.5
initial_exposure_time = 45
[sla_material:SL1 Red transparent 0.05]
inherits = *common 0.05*
exposure_time = 7.5
initial_exposure_time = 45
########### Materials 0.035
[sla_material:Jamg He PJHC-30 Orange 0.035]
inherits = *common 0.035*
exposure_time = 9
exposure_time = 6
initial_exposure_time = 35
[sla_material:SL1 Orange solid 0.035]
inherits = *common 0.035*
exposure_time = 6
initial_exposure_time = 35
########### Materials 0.1
@ -1574,6 +1865,11 @@ inherits = *common 0.1*
exposure_time = 10
initial_exposure_time = 45
[sla_material:SL1 Orange solid 0.1]
inherits = *common 0.1*
exposure_time = 10
initial_exposure_time = 45
[printer:*common*]
printer_technology = FFF
bed_shape = 0x0,250x0,250x210,0x210
@ -1740,19 +2036,19 @@ min_layer_height = 0.1
inherits = Original Prusa i3 MK2S
printer_model = MK2.5
remaining_times = 1
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
inherits = Original Prusa i3 MK2S 0.25 nozzle
printer_model = MK2.5
remaining_times = 1
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
inherits = Original Prusa i3 MK2S 0.6 nozzle
printer_model = MK2.5
remaining_times = 1
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5 MMU2 Single]
inherits = Original Prusa i3 MK2.5; *mm2*
@ -1781,7 +2077,7 @@ machine_min_travel_rate = 0
default_print_profile = 0.15mm OPTIMAL MK2.5
default_filament_profile = Prusament PLA
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
[printer:Original Prusa i3 MK2.5 MMU2]
@ -1815,20 +2111,23 @@ single_extruder_multi_material = 1
# to be defined explicitely.
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
[printer:Original Prusa i3 MK2.5S]
inherits = Original Prusa i3 MK2.5
printer_model = MK2.5S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5S 0.25 nozzle]
inherits = Original Prusa i3 MK2.5 0.25 nozzle
printer_model = MK2.5S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5S 0.6 nozzle]
inherits = Original Prusa i3 MK2.5 0.6 nozzle
printer_model = MK2.5S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5S MMU2S Single]
inherits = Original Prusa i3 MK2.5; *mm2s*
@ -1857,7 +2156,7 @@ machine_min_travel_rate = 0
default_print_profile = 0.15mm OPTIMAL MK2.5
default_filament_profile = Prusament PLA
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
[printer:Original Prusa i3 MK2.5S MMU2S]
@ -1891,7 +2190,7 @@ single_extruder_multi_material = 1
# to be defined explicitely.
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
@ -1923,7 +2222,7 @@ remaining_times = 1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
retract_lift_below = 209
max_print_height = 210
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
printer_model = MK3
default_print_profile = 0.15mm QUALITY MK3
@ -1933,27 +2232,31 @@ nozzle_diameter = 0.25
max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
[printer:Original Prusa i3 MK3 0.6 nozzle]
inherits = Original Prusa i3 MK3
nozzle_diameter = 0.6
max_layer_height = 0.35
min_layer_height = 0.1
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3
default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
[printer:Original Prusa i3 MK3S]
inherits = Original Prusa i3 MK3
printer_model = MK3S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
[printer:Original Prusa i3 MK3S 0.25 nozzle]
inherits = Original Prusa i3 MK3 0.25 nozzle
printer_model = MK3S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
[printer:Original Prusa i3 MK3S 0.6 nozzle]
inherits = Original Prusa i3 MK3 0.6 nozzle
printer_model = MK3S
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
[printer:*mm2*]
inherits = Original Prusa i3 MK3
@ -1983,7 +2286,7 @@ default_filament_profile = Prusament PLA MMU2
inherits = *mm2*
single_extruder_multi_material = 0
default_filament_profile = Prusament PLA
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
[printer:Original Prusa i3 MK3 MMU2]
@ -1994,14 +2297,14 @@ inherits = *mm2*
machine_max_acceleration_e = 8000,8000
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
[printer:Original Prusa i3 MK3S MMU2S Single]
inherits = *mm2s*
single_extruder_multi_material = 0
default_filament_profile = Prusament PLA
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
[printer:Original Prusa i3 MK3S MMU2S]
@ -2009,14 +2312,14 @@ inherits = *mm2s*
machine_max_acceleration_e = 8000,8000
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
[printer:Original Prusa SL1]
printer_technology = SLA
printer_model = SL1
printer_variant = default
default_sla_material_profile = Jamg He Transparent Green 0.05
default_sla_material_profile = Jamg He PJHC-30 Orange 0.05
default_sla_print_profile = 0.05 Normal
bed_shape = 0.98x1.02,119.98x1.02,119.98x68.02,0.98x68.02
display_height = 68.04

View File

@ -15,6 +15,7 @@
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/nowide/cenv.hpp>
#include <boost/nowide/iostream.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/format.hpp>
@ -713,11 +714,8 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra,
// Look for the cli -> option mapping.
const auto it = opts.find(token);
if (it == opts.end()) {
printf("Warning: unknown option --%s\n", token.c_str());
// instead of continuing, return false to caller
// to stop execution and print usage
boost::nowide::cerr << "Unknown option --" << token.c_str() << std::endl;
return false;
//continue;
}
const t_config_option_key opt_key = it->second;
const ConfigOptionDef &optdef = this->def()->options.at(opt_key);
@ -725,8 +723,8 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra,
// look for it in the next token.
if (optdef.type != coBool && optdef.type != coBools && value.empty()) {
if (i == (argc-1)) {
printf("No value supplied for --%s\n", token.c_str());
continue;
boost::nowide::cerr << "No value supplied for --" << token.c_str() << std::endl;
return false;
}
value = argv[++ i];
}
@ -759,7 +757,10 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra,
static_cast<ConfigOptionString*>(opt_base)->value = value;
} else {
// Any scalar value of a type different from Bool and String.
this->set_deserialize(opt_key, value, false);
if (! this->set_deserialize(opt_key, value, false)) {
boost::nowide::cerr << "Invalid value supplied for --" << token.c_str() << std::endl;
return false;
}
}
}
return true;

View File

@ -726,7 +726,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
GCodePreviewData::Range volumetric_rate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
@ -807,7 +807,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s
GCodePreviewData::Range feedrate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
@ -864,7 +864,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)retraction_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : retraction_moves->second)
@ -886,7 +886,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25;
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)unretraction_moves->second.size() / 25, 1);
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : unretraction_moves->second)

View File

@ -716,7 +716,7 @@ public:
assert(it != m_heads.end());
const Head& h = it->second;
assert(h.pillar_id >= 0 && h.pillar_id < long(m_pillars.size()));
return m_pillars[size_t(h.pillar_id)];
return pillar(h.pillar_id);
}
template<class...Args> const Junction& add_junction(Args&&... args) {
@ -755,6 +755,13 @@ public:
return m_compact_bridges;
}
template<class T> inline const Pillar& pillar(T id) const {
static_assert(std::is_integral<T>::value, "Invalid index type");
assert(id >= 0 && id < m_pillars.size() &&
id < std::numeric_limits<size_t>::max());
return m_pillars[size_t(id)];
}
const Pad& create_pad(const TriangleMesh& object_supports,
const ExPolygons& baseplate,
const PoolConfig& cfg) {
@ -1242,12 +1249,14 @@ class SLASupportTree::Algorithm {
}
// For connecting a head to a nearby pillar.
bool connect_to_nearpillar(const Head& head, const Pillar& nearpillar) {
if(nearpillar.bridges > m_cfg.max_bridges_on_pillar) return false;
bool connect_to_nearpillar(const Head& head, long nearpillar_id) {
auto nearpillar = [this, nearpillar_id]() { return m_result.pillar(nearpillar_id); };
if(nearpillar().bridges > m_cfg.max_bridges_on_pillar) return false;
Vec3d headjp = head.junction_point();
Vec3d nearjp_u = nearpillar.startpoint();
Vec3d nearjp_l = nearpillar.endpoint();
Vec3d nearjp_u = nearpillar().startpoint();
Vec3d nearjp_l = nearpillar().endpoint();
double r = head.r_back_mm;
double d2d = distance(to_2d(headjp), to_2d(nearjp_u));
@ -1308,7 +1317,7 @@ class SLASupportTree::Algorithm {
}
m_result.add_bridge(bridgestart, bridgeend, r);
m_result.increment_bridges(nearpillar);
m_result.increment_bridges(nearpillar());
return true;
}
@ -1336,8 +1345,7 @@ class SLASupportTree::Algorithm {
if(nearest_id >= 0) {
auto nearpillarID = unsigned(nearest_id);
if(nearpillarID < m_result.pillars().size()) {
const Pillar& nearpillar = m_result.pillars()[nearpillarID];
if(!connect_to_nearpillar(head, nearpillar)) {
if(!connect_to_nearpillar(head, nearpillarID)) {
nearest_id = -1; // continue searching
spindex.remove(ne); // without the current pillar
}
@ -1649,7 +1657,7 @@ public:
// central position where the pillar can be placed. this way
// the weight is distributed more effectively on the pillar.
const Pillar& centerpillar = m_result.head_pillar(cidx);
auto centerpillarID = m_result.head_pillar(cidx).id;
for(auto c : cl) { m_thr();
if(c == cidx) continue;
@ -1657,7 +1665,7 @@ public:
auto& sidehead = m_result.head(c);
sidehead.transform();
if(!connect_to_nearpillar(sidehead, centerpillar) &&
if(!connect_to_nearpillar(sidehead, centerpillarID) &&
!search_pillar_and_connect(sidehead))
{
Vec3d pstart = sidehead.junction_point();
@ -1859,7 +1867,7 @@ public:
}
for(auto pillid : modelpillars) {
auto& pillar = m_result.pillars()[pillid];
auto& pillar = m_result.pillar(pillid);
m_pillar_index.insert(pillar.endpoint(), pillid);
}
}
@ -1886,7 +1894,7 @@ public:
{
Vec3d qp = el.first;
const Pillar& pillar = m_result.pillars()[el.second];
const Pillar& pillar = m_result.pillar(el.second);
unsigned neighbors = m_cfg.pillar_cascade_neighbors;
@ -1946,15 +1954,15 @@ public:
size_t pillarcount = m_result.pillars().size();
for(size_t pid = 0; pid < pillarcount; pid++) {
const Pillar& pillar = m_result.pillars()[pid];
auto pillar = [this, pid]() { return m_result.pillar(pid); };
unsigned needpillars = 0;
if(pillar.bridges > m_cfg.max_bridges_on_pillar) needpillars = 3;
else if(pillar.links < 2 && pillar.height > H2) {
if(pillar().bridges > m_cfg.max_bridges_on_pillar) needpillars = 3;
else if(pillar().links < 2 && pillar().height > H2) {
// Not enough neighbors to support this pillar
needpillars = 2 - pillar.links;
needpillars = 2 - pillar().links;
}
else if(pillar.links < 1 && pillar.height > H1) {
else if(pillar().links < 1 && pillar().height > H1) {
// No neighbors could be found and the pillar is too long.
needpillars = 1;
}
@ -1963,7 +1971,7 @@ public:
bool found = false;
double alpha = 0; // goes to 2Pi
double r = 2 * m_cfg.base_radius_mm;
Vec3d pillarsp = pillar.startpoint();
Vec3d pillarsp = pillar().startpoint();
Vec3d sp(pillarsp(X), pillarsp(Y), pillarsp(Z) - r);
std::vector<bool> tv(needpillars, false);
std::vector<Vec3d> spts(needpillars);
@ -1976,7 +1984,7 @@ public:
s(X) += std::cos(a) * r;
s(Y) += std::sin(a) * r;
spts[n] = s;
auto hr = bridge_mesh_intersect(s, {0, 0, -1}, pillar.r);
auto hr = bridge_mesh_intersect(s, {0, 0, -1}, pillar().r);
tv[n] = std::isinf(hr.distance());
}
@ -1991,33 +1999,33 @@ public:
if(found) for(unsigned n = 0; n < needpillars; n++) {
Vec3d s = spts[n]; double gnd = m_result.ground_level;
Pillar p(s, Vec3d(s(X), s(Y), gnd), pillar.r);
Pillar p(s, Vec3d(s(X), s(Y), gnd), pillar().r);
p.add_base(m_cfg.base_height_mm, m_cfg.base_radius_mm);
if(interconnect(pillar, p)) {
if(interconnect(pillar(), p)) {
Pillar& pp = m_result.add_pillar(p);
m_pillar_index.insert(pp.endpoint(), unsigned(pp.id));
m_result.add_junction(s, pillar.r);
m_result.add_junction(s, pillar().r);
double t = bridge_mesh_intersect(pillarsp,
dirv(pillarsp, s),
pillar.r);
pillar().r);
if(distance(pillarsp, s) < t)
m_result.add_bridge(pillarsp, s, pillar.r);
m_result.add_bridge(pillarsp, s, pillar().r);
if(pillar.endpoint()(Z) > m_result.ground_level)
m_result.add_junction(pillar.endpoint(), pillar.r);
if(pillar().endpoint()(Z) > m_result.ground_level)
m_result.add_junction(pillar().endpoint(), pillar().r);
newpills.emplace_back(pp.id);
m_result.increment_links(pillar);
m_result.increment_links(pillar());
}
}
if(!newpills.empty()) {
for(auto it = newpills.begin(), nx = std::next(it);
nx != newpills.end(); ++it, ++nx) {
const Pillar& itpll = m_result.pillars()[size_t(*it)];
const Pillar& nxpll = m_result.pillars()[size_t(*nx)];
const Pillar& itpll = m_result.pillar(*it);
const Pillar& nxpll = m_result.pillar(*nx);
if(interconnect(itpll, nxpll)) {
m_result.increment_links(itpll);
m_result.increment_links(nxpll);

View File

@ -20,9 +20,8 @@
// Disable synchronization of unselected instances
#define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1)
// Scene's GUI made using imgui library
#define ENABLE_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI)
// Disable imgui dialog for move, rotate and scale gizmos
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
// Use wxDataViewRender instead of wxDataViewCustomRenderer
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)

View File

@ -523,6 +523,8 @@ bool CLI::setup(int argc, char **argv)
// If any option is unsupported, print usage and abort immediately.
t_config_option_keys opt_order;
if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) {
// Separate error message reported by the CLI parser from the help.
boost::nowide::cerr << std::endl;
this->print_help();
return false;
}
@ -615,7 +617,7 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co
};
auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext));
// use --output when available
std::string cmdline_param = m_config.opt_string("output", false);
std::string cmdline_param = m_config.opt_string("output");
if (! cmdline_param.empty()) {
// if we were supplied a directory, use it and append our automatically generated filename
boost::filesystem::path cmdline_path(cmdline_param);

View File

@ -28,8 +28,20 @@ set(SLIC3R_GUI_SOURCES
GUI/GLCanvas3D.cpp
GUI/GLCanvas3DManager.hpp
GUI/GLCanvas3DManager.cpp
GUI/GLGizmo.hpp
GUI/GLGizmo.cpp
GUI/Gizmos/GLGizmoBase.cpp
GUI/Gizmos/GLGizmoBase.hpp
GUI/Gizmos/GLGizmoMove.cpp
GUI/Gizmos/GLGizmoMove.hpp
GUI/Gizmos/GLGizmoRotate.cpp
GUI/Gizmos/GLGizmoRotate.hpp
GUI/Gizmos/GLGizmoScale.cpp
GUI/Gizmos/GLGizmoScale.hpp
GUI/Gizmos/GLGizmoSlaSupports.cpp
GUI/Gizmos/GLGizmoSlaSupports.hpp
GUI/Gizmos/GLGizmoFlatten.cpp
GUI/Gizmos/GLGizmoFlatten.hpp
GUI/Gizmos/GLGizmoCut.cpp
GUI/Gizmos/GLGizmoCut.hpp
GUI/GLTexture.hpp
GUI/GLTexture.cpp
GUI/GLToolbar.hpp

View File

@ -364,7 +364,7 @@ public:
void set_volume_rotation(const Vec3d& rotation) { m_volume_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
void set_volume_rotation(Axis axis, double rotation) { m_volume_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); }
Vec3d get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); }
const Vec3d& get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); }
double get_volume_scaling_factor(Axis axis) const { return m_volume_transformation.get_scaling_factor(axis); }
void set_volume_scaling_factor(const Vec3d& scaling_factor) { m_volume_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }

View File

@ -38,7 +38,7 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve
text += wxString("<font size=\"5\"><b>") + (snapshot_active ? _(L("Active: ")) : "") +
Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason);
if (! snapshot.comment.empty())
text += " (" + snapshot.comment + ")";
text += " (" + wxString::FromUTF8(snapshot.comment.data()) + ")";
text += "</b></font><br>";
// End of row header.
text += _(L("slic3r version")) + ": " + snapshot.slic3r_version_captured.to_string() + "<br>";

View File

@ -1,4 +1,4 @@
#include "slic3r/GUI/GLGizmo.hpp"
#include "slic3r/GUI/Gizmos/GLGizmos.hpp"
#include "GLCanvas3D.hpp"
#include "admesh/stl.h"
@ -16,7 +16,6 @@
#include "slic3r/GUI/GLShader.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/PresetBundle.hpp"
//#include "slic3r/GUI/GLGizmo.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
#include "GUI_ObjectManipulation.hpp"
@ -78,7 +77,7 @@ static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
static const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f };
static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f };
static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f };
static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
//static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
namespace Slic3r {
namespace GUI {
@ -3006,14 +3005,6 @@ void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const GLCanvas
::glPopMatrix();
}
#if !ENABLE_IMGUI
void GLCanvas3D::Gizmos::create_external_gizmo_widgets(wxWindow *parent)
{
for (auto &entry : m_gizmos) {
entry.second->create_external_gizmo_widgets(parent);
}
}
#endif // not ENABLE_IMGUI
void GLCanvas3D::Gizmos::reset()
{
@ -3032,13 +3023,12 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan
return;
float cnv_w = (float)canvas.get_canvas_size().get_width();
#if ENABLE_IMGUI
float cnv_h = (float)canvas.get_canvas_size().get_height();
#endif // ENABLE_IMGUI
float zoom = canvas.get_camera_zoom();
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
float height = get_total_overlay_height();
float width = get_total_overlay_width();
#if ENABLE_SVG_ICONS
float scaled_border = m_overlay_border * m_overlay_scale * inv_zoom;
#else
@ -3050,7 +3040,7 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan
float left = top_x;
float top = top_y;
float right = left + get_total_overlay_width() * inv_zoom;
float right = left + width * inv_zoom;
float bottom = top - height * inv_zoom;
// renders background
@ -3158,29 +3148,27 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan
#if ENABLE_SVG_ICONS
float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width;
float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height;
float top = sprite_id * v_icon_size;
float left = state * u_icon_size;
float bottom = top + v_icon_size;
float right = left + u_icon_size;
float v_top = sprite_id * v_icon_size;
float u_left = state * u_icon_size;
float v_bottom = v_top + v_icon_size;
float u_right = u_left + u_icon_size;
#else
float uv_icon_size = (float)m_icons_texture.metadata.icon_size * inv_texture_size;
float top = sprite_id * uv_icon_size;
float left = state * uv_icon_size;
float bottom = top + uv_icon_size;
float right = left + uv_icon_size;
float v_top = sprite_id * uv_icon_size;
float u_left = state * uv_icon_size;
float v_bottom = v_top + uv_icon_size;
float u_right = u_left + uv_icon_size;
#endif // ENABLE_SVG_ICONS
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { left, bottom }, { right, bottom }, { right, top }, { left, top } });
#if ENABLE_IMGUI
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (it->second->get_state() == GLGizmoBase::On) {
float toolbar_top = (float)cnv_h - canvas.m_view_toolbar.get_height();
#if ENABLE_SVG_ICONS
it->second->render_input_window(2.0f * m_overlay_border + m_overlay_icons_size, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
#else
it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
#endif // ENABLE_SVG_ICONS
}
#endif // ENABLE_IMGUI
#if ENABLE_SVG_ICONS
top_y -= scaled_stride_y;
#else
@ -3739,9 +3727,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
, m_color_by("volume")
, m_reload_delayed(false)
, m_render_sla_auxiliaries(true)
#if !ENABLE_IMGUI
, m_external_gizmo_widgets_parent(nullptr)
#endif // not ENABLE_IMGUI
{
if (m_canvas != nullptr) {
m_timer.SetOwner(m_canvas);
@ -3834,13 +3819,6 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
return false;
}
#if !ENABLE_IMGUI
if (m_external_gizmo_widgets_parent != nullptr) {
m_gizmos.create_external_gizmo_widgets(m_external_gizmo_widgets_parent);
m_canvas->GetParent()->Layout();
}
#endif // not ENABLE_IMGUI
}
if (!_init_toolbar())
@ -4115,27 +4093,6 @@ void GLCanvas3D::update_toolbar_items_visibility()
m_dirty = true;
}
// Returns a Rect object denoting size and position of the Reset button used by a gizmo.
// Returns in either screen or viewport coords.
#if !ENABLE_IMGUI
Rect GLCanvas3D::get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const
{
const Size& cnv_size = canvas.get_canvas_size();
float w = (viewport ? -0.5f : 0.f) * (float)cnv_size.get_width();
float h = (viewport ? 0.5f : 1.f) * (float)cnv_size.get_height();
float zoom = canvas.get_camera_zoom();
float inv_zoom = viewport ? ((zoom != 0.0f) ? 1.0f / zoom : 0.0f) : 1.f;
const float gap = 30.f;
return Rect((w + gap + 80.f) * inv_zoom, (viewport ? -1.f : 1.f) * (h - GIZMO_RESET_BUTTON_HEIGHT) * inv_zoom,
(w + gap + 80.f + GIZMO_RESET_BUTTON_WIDTH) * inv_zoom, (viewport ? -1.f : 1.f) * (h * inv_zoom));
}
bool GLCanvas3D::gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const
{
const Rect& rect = get_gizmo_reset_rect(canvas, false);
return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom());
}
#endif // not ENABLE_IMGUI
void GLCanvas3D::render()
{
@ -4158,8 +4115,11 @@ void GLCanvas3D::render()
return;
if (m_bed.get_shape().empty())
{
// this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE
post_event(SimpleEvent(EVT_GLCANVAS_UPDATE_BED_SHAPE));
return;
}
if (m_camera.requires_zoom_to_bed)
{
@ -4181,9 +4141,7 @@ void GLCanvas3D::render()
// absolute value of the rotation
theta = 360.f - theta;
#if ENABLE_IMGUI
wxGetApp().imgui()->new_frame();
#endif // ENABLE_IMGUI
// picking pass
_picking_pass();
@ -4234,9 +4192,7 @@ void GLCanvas3D::render()
if (m_layers_editing.last_object_id >= 0)
m_layers_editing.render_overlay(*this);
#if ENABLE_IMGUI
wxGetApp().imgui()->render();
#endif // ENABLE_IMGUI
m_canvas->SwapBuffers();
}
@ -4802,13 +4758,11 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
int keyCode = evt.GetKeyCode();
int ctrlMask = wxMOD_CONTROL;
#if ENABLE_IMGUI
auto imgui = wxGetApp().imgui();
if (imgui->update_key_data(evt)) {
render();
return;
}
#endif // ENABLE_IMGUI
//#ifdef __APPLE__
// ctrlMask |= wxMOD_RAW_CONTROL;
@ -4916,12 +4870,10 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
{
const int keyCode = evt.GetKeyCode();
#if ENABLE_IMGUI
auto imgui = wxGetApp().imgui();
if (imgui->update_key_data(evt)) {
render();
} else
#endif // ENABLE_IMGUI
if (evt.GetEventType() == wxEVT_KEY_UP) {
if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
// Enable switching between 3D and Preview with Tab
@ -5044,7 +4996,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
Point pos(evt.GetX(), evt.GetY());
#if ENABLE_IMGUI
ImGuiWrapper *imgui = wxGetApp().imgui();
if (imgui->update_mouse_data(evt)) {
m_mouse.position = evt.Leaving() ? Vec2d(-1.0, -1.0) : pos.cast<double>();
@ -5054,7 +5005,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
return;
}
#endif // ENABLE_IMGUI
#ifdef __WXMSW__
bool on_enter_workaround = false;
@ -5260,42 +5210,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_moving = true;
}
}
else if (evt.RightDown())
{
m_mouse.position = pos.cast<double>();
// forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while
// the context menu is already shown
render();
if (m_hover_volume_id != -1)
{
// if right clicking on volume, propagate event through callback (shows context menu)
if (m_volumes.volumes[m_hover_volume_id]->hover
&& !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower // no context menu for the wipe tower
&& m_gizmos.get_current_type() != Gizmos::SlaSupports) // disable context menu when the gizmo is open
{
// forces the selection of the volume
/** #ys_FIXME_to_delete after testing:
* Next condition allows a multiple instance selection for the context menu,
* which has no reason. So it's commented till next testing
*/
// if (!m_selection.is_multiple_full_instance()) // #ys_FIXME_to_delete
m_selection.add(m_hover_volume_id);
m_gizmos.update_on_off_state(m_selection);
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
_update_gizmos_data();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
// forces a frame render to update the view before the context menu is shown
render();
Vec2d logical_pos = pos.cast<double>();
#if ENABLE_RETINA_GL
const float factor = m_retina_helper->get_scale_factor();
logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor));
#endif // ENABLE_RETINA_GL
post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos));
}
}
}
}
}
}
@ -5517,6 +5431,37 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
m_camera.set_scene_box(scene_bounding_box());
}
else if (evt.RightUp())
{
m_mouse.position = pos.cast<double>();
// forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while
// the context menu is already shown
render();
if (m_hover_volume_id != -1)
{
// if right clicking on volume, propagate event through callback (shows context menu)
if (m_volumes.volumes[m_hover_volume_id]->hover
&& !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower // no context menu for the wipe tower
&& m_gizmos.get_current_type() != Gizmos::SlaSupports) // disable context menu when the gizmo is open
{
// forces the selection of the volume
m_selection.add(m_hover_volume_id);
m_gizmos.update_on_off_state(m_selection);
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
_update_gizmos_data();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
// forces a frame render to update the view before the context menu is shown
render();
Vec2d logical_pos = pos.cast<double>();
#if ENABLE_RETINA_GL
const float factor = m_retina_helper->get_scale_factor();
logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor));
#endif // ENABLE_RETINA_GL
post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos));
}
}
}
m_moving = false;
m_mouse.drag.move_volume_idx = -1;
@ -5630,12 +5575,6 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
}
}
#if !ENABLE_IMGUI
void GLCanvas3D::set_external_gizmo_widgets_parent(wxWindow *parent)
{
m_external_gizmo_widgets_parent = parent;
}
#endif // not ENABLE_IMGUI
void GLCanvas3D::do_move()
{
@ -6068,14 +6007,12 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
if ((m_canvas == nullptr) && (m_context == nullptr))
return;
#if ENABLE_IMGUI
wxGetApp().imgui()->set_display_size((float)w, (float)h);
#if ENABLE_RETINA_GL
wxGetApp().imgui()->set_style_scaling(m_retina_helper->get_scale_factor());
#else
wxGetApp().imgui()->set_style_scaling(m_canvas->GetContentScaleFactor());
#endif
#endif // ENABLE_IMGUI
// ensures that this canvas is current
_set_current();
@ -6285,7 +6222,6 @@ void GLCanvas3D::_picking_pass() const
::glReadPixels(pos(0), cnv_size.get_height() - pos(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color);
volume_id = color[0] + color[1] * 256 + color[2] * 256 * 256;
}
if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size()))
{
m_hover_volume_id = volume_id;
@ -6294,7 +6230,7 @@ void GLCanvas3D::_picking_pass() const
else
{
m_hover_volume_id = -1;
m_gizmos.set_hover_id(inside ? (254 - (int)color[2]) : -1);
m_gizmos.set_hover_id(inside && volume_id <= GLGizmoBase::BASE_ID ? (GLGizmoBase::BASE_ID - volume_id) : -1);
}
_update_volumes_hover_state();

View File

@ -750,10 +750,6 @@ private:
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
#if !ENABLE_IMGUI
void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
private:
void reset();
@ -894,10 +890,6 @@ private:
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
#if !ENABLE_IMGUI
wxWindow *m_external_gizmo_widgets_parent;
#endif // not ENABLE_IMGUI
public:
GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
~GLCanvas3D();
@ -971,11 +963,6 @@ public:
void update_toolbar_items_visibility();
#if !ENABLE_IMGUI
Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const;
bool gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const;
#endif // not ENABLE_IMGUI
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
void render();
@ -1016,10 +1003,6 @@ public:
void set_tooltip(const std::string& tooltip) const;
#if !ENABLE_IMGUI
void set_external_gizmo_widgets_parent(wxWindow *parent);
#endif // not ENABLE_IMGUI
void do_move();
void do_rotate();
void do_scale();

File diff suppressed because it is too large Load Diff

View File

@ -1,640 +0,0 @@
#ifndef slic3r_GLGizmo_hpp_
#define slic3r_GLGizmo_hpp_
#include <igl/AABB.h>
#include "../../slic3r/GUI/GLTexture.hpp"
#include "../../slic3r/GUI/GLCanvas3D.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/SLA/SLAAutoSupports.hpp"
#include <array>
#include <vector>
#include <memory>
class wxWindow;
class GLUquadric;
typedef class GLUquadric GLUquadricObj;
namespace Slic3r {
class BoundingBoxf3;
class Linef3;
class ModelObject;
namespace GUI {
class GLCanvas3D;
#if ENABLE_IMGUI
class ImGuiWrapper;
#endif // ENABLE_IMGUI
class GLGizmoBase
{
protected:
struct Grabber
{
static const float SizeFactor;
static const float MinHalfSize;
static const float DraggingScaleFactor;
Vec3d center;
Vec3d angles;
float color[3];
bool enabled;
bool dragging;
Grabber();
void render(bool hover, float size) const;
void render_for_picking(float size) const { render(size, color, false); }
float get_half_size(float size) const;
float get_dragging_half_size(float size) const;
private:
void render(float size, const float* render_color, bool use_lighting) const;
void render_face(float half_size) const;
};
public:
enum EState
{
Off,
Hover,
On,
Num_States
};
struct UpdateData
{
const Linef3 mouse_ray;
const Point* mouse_pos;
bool shift_down;
UpdateData(const Linef3& mouse_ray, const Point* mouse_pos = nullptr, bool shift_down = false)
: mouse_ray(mouse_ray), mouse_pos(mouse_pos), shift_down(shift_down)
{}
};
protected:
GLCanvas3D& m_parent;
int m_group_id;
EState m_state;
int m_shortcut_key;
#if ENABLE_SVG_ICONS
std::string m_icon_filename;
#endif // ENABLE_SVG_ICONS
unsigned int m_sprite_id;
int m_hover_id;
bool m_dragging;
float m_base_color[3];
float m_drag_color[3];
float m_highlight_color[3];
mutable std::vector<Grabber> m_grabbers;
#if ENABLE_IMGUI
ImGuiWrapper* m_imgui;
#endif // ENABLE_IMGUI
public:
#if ENABLE_SVG_ICONS
GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoBase() {}
bool init() { return on_init(); }
std::string get_name() const { return on_get_name(); }
int get_group_id() const { return m_group_id; }
void set_group_id(int id) { m_group_id = id; }
EState get_state() const { return m_state; }
void set_state(EState state) { m_state = state; on_set_state(); }
int get_shortcut_key() const { return m_shortcut_key; }
void set_shortcut_key(int key) { m_shortcut_key = key; }
#if ENABLE_SVG_ICONS
const std::string& get_icon_filename() const { return m_icon_filename; }
#endif // ENABLE_SVG_ICONS
bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); }
bool is_selectable() const { return on_is_selectable(); }
unsigned int get_sprite_id() const { return m_sprite_id; }
int get_hover_id() const { return m_hover_id; }
void set_hover_id(int id);
void set_highlight_color(const float* color);
void enable_grabber(unsigned int id);
void disable_grabber(unsigned int id);
void start_dragging(const GLCanvas3D::Selection& selection);
void stop_dragging();
bool is_dragging() const { return m_dragging; }
void update(const UpdateData& data, const GLCanvas3D::Selection& selection);
void render(const GLCanvas3D::Selection& selection) const { on_render(selection); }
void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); }
#if !ENABLE_IMGUI
virtual void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
#if ENABLE_IMGUI
void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
#endif // ENABLE_IMGUI
protected:
virtual bool on_init() = 0;
virtual std::string on_get_name() const = 0;
virtual void on_set_state() {}
virtual void on_set_hover_id() {}
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; }
virtual bool on_is_selectable() const { return true; }
virtual void on_enable_grabber(unsigned int id) {}
virtual void on_disable_grabber(unsigned int id) {}
virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {}
virtual void on_stop_dragging() {}
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0;
virtual void on_render(const GLCanvas3D::Selection& selection) const = 0;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {}
#endif // ENABLE_IMGUI
float picking_color_component(unsigned int id) const;
void render_grabbers(const BoundingBoxf3& box) const;
void render_grabbers(float size) const;
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
void set_tooltip(const std::string& tooltip) const;
std::string format(float value, unsigned int decimals) const;
};
class GLGizmoRotate : public GLGizmoBase
{
static const float Offset;
static const unsigned int CircleResolution;
static const unsigned int AngleResolution;
static const unsigned int ScaleStepsCount;
static const float ScaleStepRad;
static const unsigned int ScaleLongEvery;
static const float ScaleLongTooth;
static const unsigned int SnapRegionsCount;
static const float GrabberOffset;
public:
enum Axis : unsigned char
{
X,
Y,
Z
};
private:
Axis m_axis;
double m_angle;
GLUquadricObj* m_quadric;
mutable Vec3d m_center;
mutable float m_radius;
mutable float m_snap_coarse_in_radius;
mutable float m_snap_coarse_out_radius;
mutable float m_snap_fine_in_radius;
mutable float m_snap_fine_out_radius;
public:
GLGizmoRotate(GLCanvas3D& parent, Axis axis);
GLGizmoRotate(const GLGizmoRotate& other);
virtual ~GLGizmoRotate();
double get_angle() const { return m_angle; }
void set_angle(double angle);
protected:
virtual bool on_init();
virtual std::string on_get_name() const { return ""; }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
private:
void render_circle() const;
void render_scale() const;
void render_snap_radii() const;
void render_reference_radius() const;
void render_angle() const;
void render_grabber(const BoundingBoxf3& box) const;
void render_grabber_extension(const BoundingBoxf3& box, bool picking) const;
void transform_to_local(const GLCanvas3D::Selection& selection) const;
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const;
};
class GLGizmoRotate3D : public GLGizmoBase
{
std::vector<GLGizmoRotate> m_gizmos;
public:
#if ENABLE_SVG_ICONS
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_set_state()
{
for (GLGizmoRotate& g : m_gizmos)
{
g.set_state(m_state);
}
}
virtual void on_set_hover_id()
{
for (unsigned int i = 0; i < 3; ++i)
{
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
}
}
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_enable_grabber(unsigned int id)
{
if ((0 <= id) && (id < 3))
m_gizmos[id].enable_grabber(0);
}
virtual void on_disable_grabber(unsigned int id)
{
if ((0 <= id) && (id < 3))
m_gizmos[id].disable_grabber(0);
}
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
for (GLGizmoRotate& g : m_gizmos)
{
g.update(data, selection);
}
}
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
for (const GLGizmoRotate& g : m_gizmos)
{
g.render_for_picking(selection);
}
}
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
};
class GLGizmoScale3D : public GLGizmoBase
{
static const float Offset;
mutable BoundingBoxf3 m_box;
Vec3d m_scale;
double m_snap_step;
Vec3d m_starting_scale;
Vec3d m_starting_drag_position;
BoundingBoxf3 m_starting_box;
public:
#if ENABLE_SVG_ICONS
GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
double get_snap_step(double step) const { return m_snap_step; }
void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_scale() const { return m_scale; }
void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const;
void do_scale_x(const UpdateData& data);
void do_scale_y(const UpdateData& data);
void do_scale_z(const UpdateData& data);
void do_scale_uniform(const UpdateData& data);
double calc_ratio(const UpdateData& data) const;
};
class GLGizmoMove3D : public GLGizmoBase
{
static const double Offset;
Vec3d m_displacement;
double m_snap_step;
Vec3d m_starting_drag_position;
Vec3d m_starting_box_center;
Vec3d m_starting_box_bottom_center;
GLUquadricObj* m_quadric;
public:
#if ENABLE_SVG_ICONS
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoMove3D();
double get_snap_step(double step) const { return m_snap_step; }
void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_displacement() const { return m_displacement; }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
double calc_projection(const UpdateData& data) const;
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const;
};
class GLGizmoFlatten : public GLGizmoBase
{
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
private:
mutable Vec3d m_normal;
struct PlaneData {
std::vector<Vec3d> vertices;
Vec3d normal;
float area;
};
// This holds information to decide whether recalculation is necessary:
std::vector<Transform3d> m_volumes_matrices;
std::vector<ModelVolumeType> m_volumes_types;
Vec3d m_first_instance_scale;
Vec3d m_first_instance_mirror;
std::vector<PlaneData> m_planes;
bool m_planes_valid = false;
mutable Vec3d m_starting_center;
const ModelObject* m_model_object = nullptr;
std::vector<const Transform3d*> instances_matrices;
void update_planes();
bool is_plane_update_necessary() const;
public:
#if ENABLE_SVG_ICONS
GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
void set_flattening_data(const ModelObject* model_object);
Vec3d get_flattening_normal() const;
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {}
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
virtual void on_set_state()
{
if (m_state == On && is_plane_update_necessary())
update_planes();
}
};
#define SLAGIZMO_IMGUI_MODAL 0
class GLGizmoSlaSupports : public GLGizmoBase
{
private:
ModelObject* m_model_object = nullptr;
ModelObject* m_old_model_object = nullptr;
int m_active_instance = -1;
int m_old_instance_id = -1;
std::pair<Vec3f, Vec3f> unproject_on_mesh(const Vec2d& mouse_pos);
const float RenderPointScale = 1.f;
GLUquadricObj* m_quadric;
Eigen::MatrixXf m_V; // vertices
Eigen::MatrixXi m_F; // facets indices
igl::AABB<Eigen::MatrixXf,3> m_AABB;
struct SourceDataSummary {
Geometry::Transformation transformation;
};
class CacheEntry {
public:
CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) :
support_point(point), selected(sel), normal(norm) {}
sla::SupportPoint support_point;
bool selected; // whether the point is selected
Vec3f normal;
};
// This holds information to decide whether recalculation is necessary:
SourceDataSummary m_source_data;
mutable Vec3d m_starting_center;
public:
#if ENABLE_SVG_ICONS
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_selected_points(bool force = false);
private:
bool on_init();
void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
void render_selection_rectangle() const;
void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const;
bool is_mesh_update_necessary() const;
void update_mesh();
void update_cache_entry_normal(unsigned int i) const;
#if !ENABLE_IMGUI
void render_tooltip_texture() const;
mutable GLTexture m_tooltip_texture;
mutable GLTexture m_reset_texture;
#endif // not ENABLE_IMGUI
bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active?
bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
float m_new_point_head_diameter; // Size of a new point.
float m_minimal_point_distance = 20.f;
float m_density = 100.f;
mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
bool m_selection_rectangle_active = false;
Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner;
bool m_ignore_up_event = false;
bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox.
bool m_unsaved_changes = false; // Are there unsaved changes in manual mode?
bool m_selection_empty = true;
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
int m_canvas_width;
int m_canvas_height;
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
// Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc:
enum {
AllPoints = -2,
NoPoints,
};
void select_point(int i);
void editing_mode_apply_changes();
void editing_mode_discard_changes();
void editing_mode_reload_cache();
void get_data_from_backend();
void auto_generate();
void switch_to_editing_mode();
protected:
void on_set_state() override;
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override;
#endif // ENABLE_IMGUI
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual bool on_is_selectable() const;
};
#if !ENABLE_IMGUI
class GLGizmoCutPanel;
#endif // not ENABLE_IMGUI
class GLGizmoCut : public GLGizmoBase
{
static const double Offset;
static const double Margin;
static const std::array<float, 3> GrabberColor;
mutable double m_cut_z;
double m_start_z;
mutable double m_max_z;
Vec3d m_drag_pos;
Vec3d m_drag_center;
bool m_keep_upper;
bool m_keep_lower;
bool m_rotate_lower;
#if !ENABLE_IMGUI
GLGizmoCutPanel *m_panel;
#endif // not ENABLE_IMGUI
public:
#if ENABLE_SVG_ICONS
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
#if !ENABLE_IMGUI
virtual void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
#if !ENABLE_IMGUI
#endif // not ENABLE_IMGUI
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_set_state();
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
void update_max_z(const GLCanvas3D::Selection& selection) const;
void set_cut_z(double cut_z) const;
void perform_cut(const GLCanvas3D::Selection& selection);
double calc_projection(const Linef3& mouse_ray) const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmo_hpp_

View File

@ -2,6 +2,7 @@
#define slic3r_GLTexture_hpp_
#include <string>
#include <vector>
class wxImage;

View File

@ -148,9 +148,6 @@ void config_wizard(int reason)
_(L("Please check and fix your object list.")),
_(L("Attention!")));
}
// Load the currently selected preset into the GUI, update the preset selection box.
// wxGetApp().load_current_presets(); // #ys_FIXME_to_delete presets are loaded now in select_preset function
}
// opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)

View File

@ -80,9 +80,7 @@ IMPLEMENT_APP(GUI_App)
GUI_App::GUI_App()
: wxApp()
, m_em_unit(10)
#if ENABLE_IMGUI
, m_imgui(new ImGuiWrapper())
#endif // ENABLE_IMGUI
{}
bool GUI_App::OnInit()
@ -91,12 +89,9 @@ bool GUI_App::OnInit()
const wxString resources_dir = from_u8(Slic3r::resources_dir());
wxCHECK_MSG(wxDirExists(resources_dir), false,
wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir));
#if ENABLE_IMGUI
wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui");
#endif // ENABLE_IMGUI
SetAppName("Slic3rPE-alpha");
SetAppName("Slic3rPE-beta");
SetAppDisplayName("Slic3r Prusa Edition");
// wxSystemOptions::SetOption("msw.staticbox.optimized-paint", 0);

View File

@ -5,9 +5,7 @@
#include <string>
#include "libslic3r/PrintConfig.hpp"
#include "MainFrame.hpp"
#if ENABLE_IMGUI
#include "ImGuiWrapper.hpp"
#endif // ENABLE_IMGUI
#include <wx/app.h>
#include <wx/colour.h>
@ -86,10 +84,7 @@ class GUI_App : public wxApp
wxLocale* m_wxLocale{ nullptr };
#if ENABLE_IMGUI
std::unique_ptr<ImGuiWrapper> m_imgui;
#endif // ENABLE_IMGUI
std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;
public:
@ -166,9 +161,7 @@ public:
std::vector<Tab *> tabs_list;
#if ENABLE_IMGUI
ImGuiWrapper* imgui() { return m_imgui.get(); }
#endif // ENABLE_IMGUI
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }

View File

@ -30,9 +30,6 @@ namespace GUI {
View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
: m_canvas_widget(nullptr)
, m_canvas(nullptr)
#if !ENABLE_IMGUI
, m_gizmo_widget(nullptr)
#endif // !ENABLE_IMGUI
{
init(parent, bed, camera, view_toolbar, model, config, process);
}
@ -67,17 +64,8 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_
m_canvas->enable_gizmos(true);
m_canvas->enable_toolbar(true);
#if !ENABLE_IMGUI
m_gizmo_widget = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_gizmo_widget->SetSizer(new wxBoxSizer(wxVERTICAL));
m_canvas->set_external_gizmo_widgets_parent(m_gizmo_widget);
#endif // !ENABLE_IMGUI
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
#if !ENABLE_IMGUI
main_sizer->Add(m_gizmo_widget, 0, wxALL | wxEXPAND, 0);
#endif // !ENABLE_IMGUI
SetSizer(main_sizer);
SetMinSize(GetSize());

View File

@ -35,10 +35,6 @@ class View3D : public wxPanel
wxGLCanvas* m_canvas_widget;
GLCanvas3D* m_canvas;
#if !ENABLE_IMGUI
wxPanel* m_gizmo_widget;
#endif // !ENABLE_IMGUI
public:
View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process);
virtual ~View3D();

View File

@ -0,0 +1,281 @@
#include "GLGizmoBase.hpp"
#include <GL/glew.h>
#include "slic3r/GUI/GUI_App.hpp"
// TODO: Display tooltips quicker on Linux
namespace Slic3r {
namespace GUI {
const float GLGizmoBase::Grabber::SizeFactor = 0.025f;
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
GLGizmoBase::Grabber::Grabber()
: center(Vec3d::Zero())
, angles(Vec3d::Zero())
, dragging(false)
, enabled(true)
{
color[0] = 1.0f;
color[1] = 1.0f;
color[2] = 1.0f;
}
void GLGizmoBase::Grabber::render(bool hover, float size) const
{
float render_color[3];
if (hover)
{
render_color[0] = 1.0f - color[0];
render_color[1] = 1.0f - color[1];
render_color[2] = 1.0f - color[2];
}
else
::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float));
render(size, render_color, true);
}
float GLGizmoBase::Grabber::get_half_size(float size) const
{
return std::max(size * SizeFactor, MinHalfSize);
}
float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
{
return std::max(size * SizeFactor * DraggingScaleFactor, MinHalfSize);
}
void GLGizmoBase::Grabber::render(float size, const float* render_color, bool use_lighting) const
{
float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
if (use_lighting)
::glEnable(GL_LIGHTING);
::glColor3fv(render_color);
::glPushMatrix();
::glTranslated(center(0), center(1), center(2));
::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0);
::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0);
::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0);
// face min x
::glPushMatrix();
::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f);
::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
render_face(half_size);
::glPopMatrix();
// face max x
::glPushMatrix();
::glTranslatef((GLfloat)half_size, 0.0f, 0.0f);
::glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
render_face(half_size);
::glPopMatrix();
// face min y
::glPushMatrix();
::glTranslatef(0.0f, -(GLfloat)half_size, 0.0f);
::glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
render_face(half_size);
::glPopMatrix();
// face max y
::glPushMatrix();
::glTranslatef(0.0f, (GLfloat)half_size, 0.0f);
::glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
render_face(half_size);
::glPopMatrix();
// face min z
::glPushMatrix();
::glTranslatef(0.0f, 0.0f, -(GLfloat)half_size);
::glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
render_face(half_size);
::glPopMatrix();
// face max z
::glPushMatrix();
::glTranslatef(0.0f, 0.0f, (GLfloat)half_size);
render_face(half_size);
::glPopMatrix();
::glPopMatrix();
if (use_lighting)
::glDisable(GL_LIGHTING);
}
void GLGizmoBase::Grabber::render_face(float half_size) const
{
::glBegin(GL_TRIANGLES);
::glNormal3f(0.0f, 0.0f, 1.0f);
::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f);
::glVertex3f((GLfloat)half_size, -(GLfloat)half_size, 0.0f);
::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f);
::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f);
::glVertex3f(-(GLfloat)half_size, (GLfloat)half_size, 0.0f);
::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f);
::glEnd();
}
#if ENABLE_SVG_ICONS
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
#else
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id)
#endif // ENABLE_SVG_ICONS
: m_parent(parent)
, m_group_id(-1)
, m_state(Off)
, m_shortcut_key(0)
#if ENABLE_SVG_ICONS
, m_icon_filename(icon_filename)
#endif // ENABLE_SVG_ICONS
, m_sprite_id(sprite_id)
, m_hover_id(-1)
, m_dragging(false)
, m_imgui(wxGetApp().imgui())
{
::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float));
::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float));
::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 3 * sizeof(float));
}
void GLGizmoBase::set_hover_id(int id)
{
if (m_grabbers.empty() || (id < (int)m_grabbers.size()))
{
m_hover_id = id;
on_set_hover_id();
}
}
void GLGizmoBase::set_highlight_color(const float* color)
{
if (color != nullptr)
::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float));
}
void GLGizmoBase::enable_grabber(unsigned int id)
{
if ((0 <= id) && (id < (unsigned int)m_grabbers.size()))
m_grabbers[id].enabled = true;
on_enable_grabber(id);
}
void GLGizmoBase::disable_grabber(unsigned int id)
{
if ((0 <= id) && (id < (unsigned int)m_grabbers.size()))
m_grabbers[id].enabled = false;
on_disable_grabber(id);
}
void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection)
{
m_dragging = true;
for (int i = 0; i < (int)m_grabbers.size(); ++i)
{
m_grabbers[i].dragging = (m_hover_id == i);
}
on_start_dragging(selection);
}
void GLGizmoBase::stop_dragging()
{
m_dragging = false;
for (int i = 0; i < (int)m_grabbers.size(); ++i)
{
m_grabbers[i].dragging = false;
}
on_stop_dragging();
}
void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1)
on_update(data, selection);
}
std::array<float, 3> GLGizmoBase::picking_color_component(unsigned int id) const
{
static const float INV_255 = 1.0f / 255.0f;
id = BASE_ID - id;
if (m_group_id > -1)
id -= m_group_id;
// color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass()
return std::array<float, 3> { (float)((id >> 0) & 0xff) * INV_255, // red
(float)((id >> 8) & 0xff) * INV_255, // green
(float)((id >> 16) & 0xff) * INV_255 }; // blue
}
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
{
float size = (float)box.max_size();
for (int i = 0; i < (int)m_grabbers.size(); ++i)
{
if (m_grabbers[i].enabled)
m_grabbers[i].render((m_hover_id == i), size);
}
}
void GLGizmoBase::render_grabbers(float size) const
{
for (int i = 0; i < (int)m_grabbers.size(); ++i)
{
if (m_grabbers[i].enabled)
m_grabbers[i].render((m_hover_id == i), size);
}
}
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{
float size = (float)box.max_size();
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i)
{
if (m_grabbers[i].enabled)
{
std::array<float, 3> color = picking_color_component(i);
m_grabbers[i].color[0] = color[0];
m_grabbers[i].color[1] = color[1];
m_grabbers[i].color[2] = color[2];
m_grabbers[i].render_for_picking(size);
}
}
}
void GLGizmoBase::set_tooltip(const std::string& tooltip) const
{
m_parent.set_tooltip(tooltip);
}
std::string GLGizmoBase::format(float value, unsigned int decimals) const
{
return Slic3r::string_printf("%.*f", decimals, value);
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,182 @@
#ifndef slic3r_GLGizmoBase_hpp_
#define slic3r_GLGizmoBase_hpp_
#include "libslic3r/Point.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/I18N.hpp"
class wxWindow;
class GLUquadric;
typedef class GLUquadric GLUquadricObj;
namespace Slic3r {
class BoundingBoxf3;
class Linef3;
class ModelObject;
namespace GUI {
static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f };
static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f };
static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f };
static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
class ImGuiWrapper;
class GLGizmoBase
{
public:
// Starting value for ids to avoid clashing with ids used by GLVolumes
// (254 is choosen to leave some space for forward compatibility)
static const unsigned int BASE_ID = 255 * 255 * 254;
protected:
struct Grabber
{
static const float SizeFactor;
static const float MinHalfSize;
static const float DraggingScaleFactor;
Vec3d center;
Vec3d angles;
float color[3];
bool enabled;
bool dragging;
Grabber();
void render(bool hover, float size) const;
void render_for_picking(float size) const { render(size, color, false); }
float get_half_size(float size) const;
float get_dragging_half_size(float size) const;
private:
void render(float size, const float* render_color, bool use_lighting) const;
void render_face(float half_size) const;
};
public:
enum EState
{
Off,
Hover,
On,
Num_States
};
struct UpdateData
{
const Linef3 mouse_ray;
const Point* mouse_pos;
bool shift_down;
UpdateData(const Linef3& mouse_ray, const Point* mouse_pos = nullptr, bool shift_down = false)
: mouse_ray(mouse_ray), mouse_pos(mouse_pos), shift_down(shift_down)
{}
};
protected:
GLCanvas3D& m_parent;
int m_group_id;
EState m_state;
int m_shortcut_key;
#if ENABLE_SVG_ICONS
std::string m_icon_filename;
#endif // ENABLE_SVG_ICONS
unsigned int m_sprite_id;
int m_hover_id;
bool m_dragging;
float m_base_color[3];
float m_drag_color[3];
float m_highlight_color[3];
mutable std::vector<Grabber> m_grabbers;
ImGuiWrapper* m_imgui;
public:
#if ENABLE_SVG_ICONS
GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoBase() {}
bool init() { return on_init(); }
std::string get_name() const { return on_get_name(); }
int get_group_id() const { return m_group_id; }
void set_group_id(int id) { m_group_id = id; }
EState get_state() const { return m_state; }
void set_state(EState state) { m_state = state; on_set_state(); }
int get_shortcut_key() const { return m_shortcut_key; }
void set_shortcut_key(int key) { m_shortcut_key = key; }
#if ENABLE_SVG_ICONS
const std::string& get_icon_filename() const { return m_icon_filename; }
#endif // ENABLE_SVG_ICONS
bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); }
bool is_selectable() const { return on_is_selectable(); }
unsigned int get_sprite_id() const { return m_sprite_id; }
int get_hover_id() const { return m_hover_id; }
void set_hover_id(int id);
void set_highlight_color(const float* color);
void enable_grabber(unsigned int id);
void disable_grabber(unsigned int id);
void start_dragging(const GLCanvas3D::Selection& selection);
void stop_dragging();
bool is_dragging() const { return m_dragging; }
void update(const UpdateData& data, const GLCanvas3D::Selection& selection);
void render(const GLCanvas3D::Selection& selection) const { on_render(selection); }
void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); }
void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
protected:
virtual bool on_init() = 0;
virtual std::string on_get_name() const = 0;
virtual void on_set_state() {}
virtual void on_set_hover_id() {}
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; }
virtual bool on_is_selectable() const { return true; }
virtual void on_enable_grabber(unsigned int id) {}
virtual void on_disable_grabber(unsigned int id) {}
virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {}
virtual void on_stop_dragging() {}
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0;
virtual void on_render(const GLCanvas3D::Selection& selection) const = 0;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {}
// Returns the picking color for the given id, based on the BASE_ID constant
// No check is made for clashing with other picking color (i.e. GLVolumes)
std::array<float, 3> picking_color_component(unsigned int id) const;
void render_grabbers(const BoundingBoxf3& box) const;
void render_grabbers(float size) const;
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
void set_tooltip(const std::string& tooltip) const;
std::string format(float value, unsigned int decimals) const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoBase_hpp_

View File

@ -0,0 +1,257 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoCut.hpp"
#include <GL/glew.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include "slic3r/GUI/GUI_App.hpp"
namespace Slic3r {
namespace GUI {
// GLGizmoCut
class GLGizmoCutPanel : public wxPanel
{
public:
GLGizmoCutPanel(wxWindow *parent);
void display(bool display);
private:
bool m_active;
wxCheckBox *m_cb_rotate;
wxButton *m_btn_cut;
wxButton *m_btn_cancel;
};
GLGizmoCutPanel::GLGizmoCutPanel(wxWindow *parent)
: wxPanel(parent)
, m_active(false)
, m_cb_rotate(new wxCheckBox(this, wxID_ANY, _(L("Rotate lower part upwards"))))
, m_btn_cut(new wxButton(this, wxID_OK, _(L("Perform cut"))))
, m_btn_cancel(new wxButton(this, wxID_CANCEL, _(L("Cancel"))))
{
enum { MARGIN = 5 };
auto *sizer = new wxBoxSizer(wxHORIZONTAL);
auto *label = new wxStaticText(this, wxID_ANY, _(L("Cut object:")));
sizer->Add(label, 0, wxALL | wxALIGN_CENTER, MARGIN);
sizer->Add(m_cb_rotate, 0, wxALL | wxALIGN_CENTER, MARGIN);
sizer->AddStretchSpacer();
sizer->Add(m_btn_cut, 0, wxALL | wxALIGN_CENTER, MARGIN);
sizer->Add(m_btn_cancel, 0, wxALL | wxALIGN_CENTER, MARGIN);
SetSizer(sizer);
}
void GLGizmoCutPanel::display(bool display)
{
Show(display);
GetParent()->Layout();
}
const double GLGizmoCut::Offset = 10.0;
const double GLGizmoCut::Margin = 20.0;
const std::array<float, 3> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 };
#if ENABLE_SVG_ICONS
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
, m_cut_z(0.0)
, m_max_z(0.0)
, m_keep_upper(true)
, m_keep_lower(true)
, m_rotate_lower(false)
{}
bool GLGizmoCut::on_init()
{
m_grabbers.emplace_back();
m_shortcut_key = WXK_CONTROL_C;
return true;
}
std::string GLGizmoCut::on_get_name() const
{
return L("Cut [C]");
}
void GLGizmoCut::on_set_state()
{
// Reset m_cut_z on gizmo activation
if (get_state() == On) {
m_cut_z = m_parent.get_selection().get_bounding_box().size()(2) / 2.0;
}
}
bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const
{
return selection.is_single_full_instance() && !selection.is_wipe_tower();
}
void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id == -1) { return; }
const BoundingBoxf3& box = selection.get_bounding_box();
m_start_z = m_cut_z;
update_max_z(selection);
m_drag_pos = m_grabbers[m_hover_id].center;
m_drag_center = box.center();
m_drag_center(2) = m_cut_z;
}
void GLGizmoCut::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1) {
set_cut_z(m_start_z + calc_projection(data.mouse_ray));
}
}
void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const
{
if (m_grabbers[0].dragging) {
set_tooltip("Z: " + format(m_cut_z, 2));
}
update_max_z(selection);
const BoundingBoxf3& box = selection.get_bounding_box();
Vec3d plane_center = box.center();
plane_center(2) = m_cut_z;
const float min_x = box.min(0) - Margin;
const float max_x = box.max(0) + Margin;
const float min_y = box.min(1) - Margin;
const float max_y = box.max(1) + Margin;
::glEnable(GL_DEPTH_TEST);
::glDisable(GL_CULL_FACE);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Draw the cutting plane
::glBegin(GL_QUADS);
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
::glVertex3f(min_x, min_y, plane_center(2));
::glVertex3f(max_x, min_y, plane_center(2));
::glVertex3f(max_x, max_y, plane_center(2));
::glVertex3f(min_x, max_y, plane_center(2));
::glEnd();
::glEnable(GL_CULL_FACE);
::glDisable(GL_BLEND);
// TODO: draw cut part contour?
// Draw the grabber and the connecting line
m_grabbers[0].center = plane_center;
m_grabbers[0].center(2) = plane_center(2) + Offset;
::glDisable(GL_DEPTH_TEST);
::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f);
::glColor3f(1.0, 1.0, 0.0);
::glBegin(GL_LINES);
::glVertex3dv(plane_center.data());
::glVertex3dv(m_grabbers[0].center.data());
::glEnd();
std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_grabbers[0].color);
m_grabbers[0].render(m_hover_id == 0, box.max_size());
}
void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
render_grabbers_for_picking(selection.get_bounding_box());
}
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
{
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
ImGui::PushItemWidth(100.0f);
bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f");
m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper);
m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower);
m_imgui->checkbox(_(L("Rotate lower part upwards")), m_rotate_lower);
m_imgui->disabled_begin(!m_keep_upper && !m_keep_lower);
const bool cut_clicked = m_imgui->button(_(L("Perform cut")));
m_imgui->disabled_end();
m_imgui->end();
if (cut_clicked && (m_keep_upper || m_keep_lower)) {
perform_cut(selection);
}
}
void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const
{
m_max_z = selection.get_bounding_box().size()(2);
set_cut_z(m_cut_z);
}
void GLGizmoCut::set_cut_z(double cut_z) const
{
// Clamp the plane to the object's bounding box
m_cut_z = std::max(0.0, std::min(m_max_z, cut_z));
}
void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection)
{
const auto instance_idx = selection.get_instance_idx();
const auto object_idx = selection.get_object_idx();
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower);
}
double GLGizmoCut::calc_projection(const Linef3& mouse_ray) const
{
double projection = 0.0;
const Vec3d starting_vec = m_drag_pos - m_drag_center;
const double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = mouse_ray.a + (m_drag_pos - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_drag_pos;
// finds projection of the vector along the staring direction
projection = inters_vec.dot(starting_vec.normalized());
}
return projection;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,53 @@
#ifndef slic3r_GLGizmoCut_hpp_
#define slic3r_GLGizmoCut_hpp_
#include "GLGizmoBase.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoCut : public GLGizmoBase
{
static const double Offset;
static const double Margin;
static const std::array<float, 3> GrabberColor;
mutable double m_cut_z;
double m_start_z;
mutable double m_max_z;
Vec3d m_drag_pos;
Vec3d m_drag_center;
bool m_keep_upper;
bool m_keep_lower;
bool m_rotate_lower;
public:
#if ENABLE_SVG_ICONS
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_set_state();
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
private:
void update_max_z(const GLCanvas3D::Selection& selection) const;
void set_cut_z(double cut_z) const;
void perform_cut(const GLCanvas3D::Selection& selection);
double calc_projection(const Linef3& mouse_ray) const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoCut_hpp_

View File

@ -0,0 +1,357 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoFlatten.hpp"
#include <numeric>
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
#if ENABLE_SVG_ICONS
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
, m_normal(Vec3d::Zero())
, m_starting_center(Vec3d::Zero())
{
}
bool GLGizmoFlatten::on_init()
{
m_shortcut_key = WXK_CONTROL_F;
return true;
}
std::string GLGizmoFlatten::on_get_name() const
{
return L("Place on face [F]");
}
bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const
{
return selection.is_single_full_instance();
}
void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1)
{
assert(m_planes_valid);
m_normal = m_planes[m_hover_id].normal;
m_starting_center = selection.get_bounding_box().center();
}
}
void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const
{
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
::glEnable(GL_BLEND);
if (selection.is_single_full_instance())
{
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z());
::glMultMatrixd(m.data());
if (this->is_plane_update_necessary())
const_cast<GLGizmoFlatten*>(this)->update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i)
{
if (i == m_hover_id)
::glColor4f(0.9f, 0.9f, 0.9f, 0.75f);
else
::glColor4f(0.9f, 0.9f, 0.9f, 0.5f);
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
{
::glVertex3dv(vertex.data());
}
::glEnd();
}
::glPopMatrix();
}
::glEnable(GL_CULL_FACE);
::glDisable(GL_BLEND);
}
void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
::glDisable(GL_BLEND);
if (selection.is_single_full_instance())
{
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z());
::glMultMatrixd(m.data());
if (this->is_plane_update_necessary())
const_cast<GLGizmoFlatten*>(this)->update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i)
{
::glColor3fv(picking_color_component(i).data());
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
{
::glVertex3dv(vertex.data());
}
::glEnd();
}
::glPopMatrix();
}
::glEnable(GL_CULL_FACE);
}
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
{
m_starting_center = Vec3d::Zero();
if (m_model_object != model_object) {
m_planes.clear();
m_planes_valid = false;
}
m_model_object = model_object;
}
void GLGizmoFlatten::update_planes()
{
TriangleMesh ch;
for (const ModelVolume* vol : m_model_object->volumes)
{
if (vol->type() != ModelVolumeType::MODEL_PART)
continue;
TriangleMesh vol_ch = vol->get_convex_hull();
vol_ch.transform(vol->get_matrix());
ch.merge(vol_ch);
}
ch = ch.convex_hull_3d();
m_planes.clear();
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix(true);
// Following constants are used for discarding too small polygons.
const float minimal_area = 5.f; // in square mm (world coordinates)
const float minimal_side = 1.f; // mm
// Now we'll go through all the facets and append Points of facets sharing the same normal.
// This part is still performed in mesh coordinate system.
const int num_of_facets = ch.stl.stats.number_of_facets;
std::vector<int> facet_queue(num_of_facets, 0);
std::vector<bool> facet_visited(num_of_facets, false);
int facet_queue_cnt = 0;
const stl_normal* normal_ptr = nullptr;
while (1) {
// Find next unvisited triangle:
int facet_idx = 0;
for (; facet_idx < num_of_facets; ++ facet_idx)
if (!facet_visited[facet_idx]) {
facet_queue[facet_queue_cnt ++] = facet_idx;
facet_visited[facet_idx] = true;
normal_ptr = &ch.stl.facet_start[facet_idx].normal;
m_planes.emplace_back();
break;
}
if (facet_idx == num_of_facets)
break; // Everything was visited already
while (facet_queue_cnt > 0) {
int facet_idx = facet_queue[-- facet_queue_cnt];
const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal;
if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) {
stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex;
for (int j=0; j<3; ++j)
m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2));
facet_visited[facet_idx] = true;
for (int j = 0; j < 3; ++ j) {
int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j];
if (! facet_visited[neighbor_idx])
facet_queue[facet_queue_cnt ++] = neighbor_idx;
}
}
}
m_planes.back().normal = normal_ptr->cast<double>();
// Now we'll transform all the points into world coordinates, so that the areas, angles and distances
// make real sense.
m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix);
// if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway):
if (m_planes.back().vertices.size() == 3 &&
((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side
|| (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side
|| (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side))
m_planes.pop_back();
}
// Let's prepare transformation of the normal vector from mesh to instance coordinates.
Geometry::Transformation t(inst_matrix);
Vec3d scaling = t.get_scaling_factor();
t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2)));
// Now we'll go through all the polygons, transform the points into xy plane to process them:
for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) {
Pointf3s& polygon = m_planes[polygon_id].vertices;
const Vec3d& normal = m_planes[polygon_id].normal;
// transform the normal according to the instance matrix:
Vec3d normal_transformed = t.get_matrix() * normal;
// We are going to rotate about z and y to flatten the plane
Eigen::Quaterniond q;
Transform3d m = Transform3d::Identity();
m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(normal_transformed, Vec3d::UnitZ()).toRotationMatrix();
polygon = transform(polygon, m);
// Now to remove the inner points. We'll misuse Geometry::convex_hull for that, but since
// it works in fixed point representation, we will rescale the polygon to avoid overflows.
// And yes, it is a nasty thing to do. Whoever has time is free to refactor.
Vec3d bb_size = BoundingBoxf3(polygon).size();
float sf = std::min(1./bb_size(0), 1./bb_size(1));
Transform3d tr = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(sf, sf, 1.f));
polygon = transform(polygon, tr);
polygon = Slic3r::Geometry::convex_hull(polygon);
polygon = transform(polygon, tr.inverse());
// Calculate area of the polygons and discard ones that are too small
float& area = m_planes[polygon_id].area;
area = 0.f;
for (unsigned int i = 0; i < polygon.size(); i++) // Shoelace formula
area += polygon[i](0)*polygon[i + 1 < polygon.size() ? i + 1 : 0](1) - polygon[i + 1 < polygon.size() ? i + 1 : 0](0)*polygon[i](1);
area = 0.5f * std::abs(area);
bool discard = false;
if (area < minimal_area)
discard = true;
else {
// We also check the inner angles and discard polygons with angles smaller than the following threshold
const double angle_threshold = ::cos(10.0 * (double)PI / 180.0);
for (unsigned int i = 0; i < polygon.size(); ++i) {
const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1];
const Vec3d& curr = polygon[i];
const Vec3d& next = polygon[(i == polygon.size() - 1) ? 0 : i + 1];
if ((prec - curr).normalized().dot((next - curr).normalized()) > angle_threshold) {
discard = true;
break;
}
}
}
if (discard) {
m_planes.erase(m_planes.begin() + (polygon_id--));
continue;
}
// We will shrink the polygon a little bit so it does not touch the object edges:
Vec3d centroid = std::accumulate(polygon.begin(), polygon.end(), Vec3d(0.0, 0.0, 0.0));
centroid /= (double)polygon.size();
for (auto& vertex : polygon)
vertex = 0.9f*vertex + 0.1f*centroid;
// Polygon is now simple and convex, we'll round the corners to make them look nicer.
// The algorithm takes a vertex, calculates middles of respective sides and moves the vertex
// towards their average (controlled by 'aggressivity'). This is repeated k times.
// In next iterations, the neighbours are not always taken at the middle (to increase the
// rounding effect at the corners, where we need it most).
const unsigned int k = 10; // number of iterations
const float aggressivity = 0.2f; // agressivity
const unsigned int N = polygon.size();
std::vector<std::pair<unsigned int, unsigned int>> neighbours;
if (k != 0) {
Pointf3s points_out(2*k*N); // vector long enough to store the future vertices
for (unsigned int j=0; j<N; ++j) {
points_out[j*2*k] = polygon[j];
neighbours.push_back(std::make_pair((int)(j*2*k-k) < 0 ? (N-1)*2*k+k : j*2*k-k, j*2*k+k));
}
for (unsigned int i=0; i<k; ++i) {
// Calculate middle of each edge so that neighbours points to something useful:
for (unsigned int j=0; j<N; ++j)
if (i==0)
points_out[j*2*k+k] = 0.5f * (points_out[j*2*k] + points_out[j==N-1 ? 0 : (j+1)*2*k]);
else {
float r = 0.2+0.3/(k-1)*i; // the neighbours are not always taken in the middle
points_out[neighbours[j].first] = r*points_out[j*2*k] + (1-r) * points_out[neighbours[j].first-1];
points_out[neighbours[j].second] = r*points_out[j*2*k] + (1-r) * points_out[neighbours[j].second+1];
}
// Now we have a triangle and valid neighbours, we can do an iteration:
for (unsigned int j=0; j<N; ++j)
points_out[2*k*j] = (1-aggressivity) * points_out[2*k*j] +
aggressivity*0.5f*(points_out[neighbours[j].first] + points_out[neighbours[j].second]);
for (auto& n : neighbours) {
++n.first;
--n.second;
}
}
polygon = points_out; // replace the coarse polygon with the smooth one that we just created
}
// Raise a bit above the object surface to avoid flickering:
for (auto& b : polygon)
b(2) += 0.1f;
// Transform back to 3D (and also back to mesh coordinates)
polygon = transform(polygon, inst_matrix.inverse() * m.inverse());
}
// We'll sort the planes by area and only keep the 254 largest ones (because of the picking pass limitations):
std::sort(m_planes.rbegin(), m_planes.rend(), [](const PlaneData& a, const PlaneData& b) { return a.area < b.area; });
m_planes.resize(std::min((int)m_planes.size(), 254));
// Planes are finished - let's save what we calculated it from:
m_volumes_matrices.clear();
m_volumes_types.clear();
for (const ModelVolume* vol : m_model_object->volumes) {
m_volumes_matrices.push_back(vol->get_matrix());
m_volumes_types.push_back(vol->type());
}
m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor();
m_first_instance_mirror = m_model_object->instances.front()->get_mirror();
m_planes_valid = true;
}
bool GLGizmoFlatten::is_plane_update_necessary() const
{
if (m_state != On || !m_model_object || m_model_object->instances.empty())
return false;
if (! m_planes_valid || m_model_object->volumes.size() != m_volumes_matrices.size())
return true;
// We want to recalculate when the scale changes - some planes could (dis)appear.
if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale)
|| ! m_model_object->instances.front()->get_mirror().isApprox(m_first_instance_mirror))
return true;
for (unsigned int i=0; i < m_model_object->volumes.size(); ++i)
if (! m_model_object->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i])
|| m_model_object->volumes[i]->type() != m_volumes_types[i])
return true;
return false;
}
Vec3d GLGizmoFlatten::get_flattening_normal() const
{
Vec3d out = m_normal;
m_normal = Vec3d::Zero();
m_starting_center = Vec3d::Zero();
return out;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,67 @@
#ifndef slic3r_GLGizmoFlatten_hpp_
#define slic3r_GLGizmoFlatten_hpp_
#include "GLGizmoBase.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoFlatten : public GLGizmoBase
{
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
private:
mutable Vec3d m_normal;
struct PlaneData {
std::vector<Vec3d> vertices;
Vec3d normal;
float area;
};
// This holds information to decide whether recalculation is necessary:
std::vector<Transform3d> m_volumes_matrices;
std::vector<ModelVolumeType> m_volumes_types;
Vec3d m_first_instance_scale;
Vec3d m_first_instance_mirror;
std::vector<PlaneData> m_planes;
bool m_planes_valid = false;
mutable Vec3d m_starting_center;
const ModelObject* m_model_object = nullptr;
std::vector<const Transform3d*> instances_matrices;
void update_planes();
bool is_plane_update_necessary() const;
public:
#if ENABLE_SVG_ICONS
GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
void set_flattening_data(const ModelObject* model_object);
Vec3d get_flattening_normal() const;
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {}
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
virtual void on_set_state()
{
if (m_state == On && is_plane_update_necessary())
update_planes();
}
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoFlatten_hpp_

View File

@ -0,0 +1,255 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoMove.hpp"
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
const double GLGizmoMove3D::Offset = 10.0;
#if ENABLE_SVG_ICONS
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
, m_displacement(Vec3d::Zero())
, m_snap_step(1.0)
, m_starting_drag_position(Vec3d::Zero())
, m_starting_box_center(Vec3d::Zero())
, m_starting_box_bottom_center(Vec3d::Zero())
, m_quadric(nullptr)
{
m_quadric = ::gluNewQuadric();
if (m_quadric != nullptr)
::gluQuadricDrawStyle(m_quadric, GLU_FILL);
}
GLGizmoMove3D::~GLGizmoMove3D()
{
if (m_quadric != nullptr)
::gluDeleteQuadric(m_quadric);
}
bool GLGizmoMove3D::on_init()
{
for (int i = 0; i < 3; ++i)
{
m_grabbers.push_back(Grabber());
}
m_shortcut_key = WXK_CONTROL_M;
return true;
}
std::string GLGizmoMove3D::on_get_name() const
{
return L("Move [M]");
}
void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1)
{
m_displacement = Vec3d::Zero();
const BoundingBoxf3& box = selection.get_bounding_box();
m_starting_drag_position = m_grabbers[m_hover_id].center;
m_starting_box_center = box.center();
m_starting_box_bottom_center = box.center();
m_starting_box_bottom_center(2) = box.min(2);
}
}
void GLGizmoMove3D::on_stop_dragging()
{
m_displacement = Vec3d::Zero();
}
void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
if (m_hover_id == 0)
m_displacement(0) = calc_projection(data);
else if (m_hover_id == 1)
m_displacement(1) = calc_projection(data);
else if (m_hover_id == 2)
m_displacement(2) = calc_projection(data);
}
void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const
{
bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center();
if ((show_position && (m_hover_id == 0)) || m_grabbers[0].dragging)
set_tooltip("X: " + format(show_position ? position(0) : m_displacement(0), 2));
else if (!m_grabbers[0].dragging && (m_hover_id == 0))
set_tooltip("X");
else if ((show_position && (m_hover_id == 1)) || m_grabbers[1].dragging)
set_tooltip("Y: " + format(show_position ? position(1) : m_displacement(1), 2));
else if (!m_grabbers[1].dragging && (m_hover_id == 1))
set_tooltip("Y");
else if ((show_position && (m_hover_id == 2)) || m_grabbers[2].dragging)
set_tooltip("Z: " + format(show_position ? position(2) : m_displacement(2), 2));
else if (!m_grabbers[2].dragging && (m_hover_id == 2))
set_tooltip("Z");
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
const BoundingBoxf3& box = selection.get_bounding_box();
const Vec3d& center = box.center();
// x axis
m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2));
::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float));
// y axis
m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2));
::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float));
// z axis
m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset);
::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float));
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
if (m_hover_id == -1)
{
// draw axes
for (unsigned int i = 0; i < 3; ++i)
{
if (m_grabbers[i].enabled)
{
::glColor3fv(AXES_COLOR[i]);
::glBegin(GL_LINES);
::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[i].center.data());
::glEnd();
}
}
// draw grabbers
render_grabbers(box);
for (unsigned int i = 0; i < 3; ++i)
{
if (m_grabbers[i].enabled)
render_grabber_extension((Axis)i, box, false);
}
}
else
{
// draw axis
::glColor3fv(AXES_COLOR[m_hover_id]);
::glBegin(GL_LINES);
::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[m_hover_id].center.data());
::glEnd();
// draw grabber
m_grabbers[m_hover_id].render(true, box.max_size());
render_grabber_extension((Axis)m_hover_id, box, false);
}
}
void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
const BoundingBoxf3& box = selection.get_bounding_box();
render_grabbers_for_picking(box);
render_grabber_extension(X, box, true);
render_grabber_extension(Y, box, true);
render_grabber_extension(Z, box, true);
}
void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center();
Vec3d displacement = show_position ? position : m_displacement;
wxString label = show_position ? _(L("Position (mm)")) : _(L("Displacement (mm)"));
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", displacement, 100.0f, "%.2f");
m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
}
double GLGizmoMove3D::calc_projection(const UpdateData& data) const
{
double projection = 0.0;
Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = data.mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
// finds projection of the vector along the staring direction
projection = inters_vec.dot(starting_vec.normalized());
}
if (data.shift_down)
projection = m_snap_step * (double)std::round(projection / m_snap_step);
return projection;
}
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const
{
if (m_quadric == nullptr)
return;
double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[axis].get_half_size((float)box.max_size());
float color[3];
::memcpy((void*)color, (const void*)m_grabbers[axis].color, 3 * sizeof(float));
if (!picking && (m_hover_id != -1))
{
color[0] = 1.0f - color[0];
color[1] = 1.0f - color[1];
color[2] = 1.0f - color[2];
}
if (!picking)
::glEnable(GL_LIGHTING);
::glColor3fv(color);
::glPushMatrix();
::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2));
if (axis == X)
::glRotated(90.0, 0.0, 1.0, 0.0);
else if (axis == Y)
::glRotated(-90.0, 1.0, 0.0, 0.0);
::glTranslated(0.0, 0.0, 2.0 * size);
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
if (!picking)
::glDisable(GL_LIGHTING);
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,57 @@
#ifndef slic3r_GLGizmoMove_hpp_
#define slic3r_GLGizmoMove_hpp_
#include "GLGizmoBase.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoMove3D : public GLGizmoBase
{
static const double Offset;
Vec3d m_displacement;
double m_snap_step;
Vec3d m_starting_drag_position;
Vec3d m_starting_box_center;
Vec3d m_starting_box_bottom_center;
GLUquadricObj* m_quadric;
public:
#if ENABLE_SVG_ICONS
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoMove3D();
double get_snap_step(double step) const { return m_snap_step; }
void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_displacement() const { return m_displacement; }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
private:
double calc_projection(const UpdateData& data) const;
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoMove_hpp_

View File

@ -0,0 +1,503 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoRotate.hpp"
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
const float GLGizmoRotate::Offset = 5.0f;
const unsigned int GLGizmoRotate::CircleResolution = 64;
const unsigned int GLGizmoRotate::AngleResolution = 64;
const unsigned int GLGizmoRotate::ScaleStepsCount = 72;
const float GLGizmoRotate::ScaleStepRad = 2.0f * (float)PI / GLGizmoRotate::ScaleStepsCount;
const unsigned int GLGizmoRotate::ScaleLongEvery = 2;
const float GLGizmoRotate::ScaleLongTooth = 0.1f; // in percent of radius
const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius
GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
#if ENABLE_SVG_ICONS
: GLGizmoBase(parent, "", -1)
#else
: GLGizmoBase(parent, -1)
#endif // ENABLE_SVG_ICONS
, m_axis(axis)
, m_angle(0.0)
, m_quadric(nullptr)
, m_center(0.0, 0.0, 0.0)
, m_radius(0.0f)
, m_snap_coarse_in_radius(0.0f)
, m_snap_coarse_out_radius(0.0f)
, m_snap_fine_in_radius(0.0f)
, m_snap_fine_out_radius(0.0f)
{
m_quadric = ::gluNewQuadric();
if (m_quadric != nullptr)
::gluQuadricDrawStyle(m_quadric, GLU_FILL);
}
GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other)
#if ENABLE_SVG_ICONS
: GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id)
#else
: GLGizmoBase(other.m_parent, other.m_sprite_id)
#endif // ENABLE_SVG_ICONS
, m_axis(other.m_axis)
, m_angle(other.m_angle)
, m_quadric(nullptr)
, m_center(other.m_center)
, m_radius(other.m_radius)
, m_snap_coarse_in_radius(other.m_snap_coarse_in_radius)
, m_snap_coarse_out_radius(other.m_snap_coarse_out_radius)
, m_snap_fine_in_radius(other.m_snap_fine_in_radius)
, m_snap_fine_out_radius(other.m_snap_fine_out_radius)
{
m_quadric = ::gluNewQuadric();
if (m_quadric != nullptr)
::gluQuadricDrawStyle(m_quadric, GLU_FILL);
}
GLGizmoRotate::~GLGizmoRotate()
{
if (m_quadric != nullptr)
::gluDeleteQuadric(m_quadric);
}
void GLGizmoRotate::set_angle(double angle)
{
if (std::abs(angle - 2.0 * (double)PI) < EPSILON)
angle = 0.0;
m_angle = angle;
}
bool GLGizmoRotate::on_init()
{
m_grabbers.push_back(Grabber());
return true;
}
void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection)
{
const BoundingBoxf3& box = selection.get_bounding_box();
m_center = box.center();
m_radius = Offset + box.radius();
m_snap_coarse_in_radius = m_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_radius;
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
}
void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection));
Vec2d orig_dir = Vec2d::UnitX();
Vec2d new_dir = mouse_pos.normalized();
double theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir)));
if (cross2(orig_dir, new_dir) < 0.0)
theta = 2.0 * (double)PI - theta;
double len = mouse_pos.norm();
// snap to coarse snap region
if ((m_snap_coarse_in_radius <= len) && (len <= m_snap_coarse_out_radius))
{
double step = 2.0 * (double)PI / (double)SnapRegionsCount;
theta = step * (double)std::round(theta / step);
}
else
{
// snap to fine snap region (scale)
if ((m_snap_fine_in_radius <= len) && (len <= m_snap_fine_out_radius))
{
double step = 2.0 * (double)PI / (double)ScaleStepsCount;
theta = step * (double)std::round(theta / step);
}
}
if (theta == 2.0 * (double)PI)
theta = 0.0;
m_angle = theta;
}
void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const
{
if (!m_grabbers[0].enabled)
return;
const BoundingBoxf3& box = selection.get_bounding_box();
std::string axis;
switch (m_axis)
{
case X: { axis = "X"; break; }
case Y: { axis = "Y"; break; }
case Z: { axis = "Z"; break; }
}
if (!m_dragging && (m_hover_id == 0))
set_tooltip(axis);
else if (m_dragging)
set_tooltip(axis + ": " + format((float)Geometry::rad2deg(m_angle), 4) + "\u00B0");
else
{
m_center = box.center();
m_radius = Offset + box.radius();
m_snap_coarse_in_radius = m_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_radius;
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
}
::glEnable(GL_DEPTH_TEST);
::glPushMatrix();
transform_to_local(selection);
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color);
render_circle();
if (m_hover_id != -1)
{
render_scale();
render_snap_radii();
render_reference_radius();
}
::glColor3fv(m_highlight_color);
if (m_hover_id != -1)
render_angle();
render_grabber(box);
render_grabber_extension(box, false);
::glPopMatrix();
}
void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
::glPushMatrix();
transform_to_local(selection);
const BoundingBoxf3& box = selection.get_bounding_box();
render_grabbers_for_picking(box);
render_grabber_extension(box, true);
::glPopMatrix();
}
void GLGizmoRotate::render_circle() const
{
::glBegin(GL_LINE_LOOP);
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
{
float angle = (float)i * ScaleStepRad;
float x = ::cos(angle) * m_radius;
float y = ::sin(angle) * m_radius;
float z = 0.0f;
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
}
::glEnd();
}
void GLGizmoRotate::render_scale() const
{
float out_radius_long = m_snap_fine_out_radius;
float out_radius_short = m_radius * (1.0f + 0.5f * ScaleLongTooth);
::glBegin(GL_LINES);
for (unsigned int i = 0; i < ScaleStepsCount; ++i)
{
float angle = (float)i * ScaleStepRad;
float cosa = ::cos(angle);
float sina = ::sin(angle);
float in_x = cosa * m_radius;
float in_y = sina * m_radius;
float in_z = 0.0f;
float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short;
float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short;
float out_z = 0.0f;
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
}
::glEnd();
}
void GLGizmoRotate::render_snap_radii() const
{
float step = 2.0f * (float)PI / (float)SnapRegionsCount;
float in_radius = m_radius / 3.0f;
float out_radius = 2.0f * in_radius;
::glBegin(GL_LINES);
for (unsigned int i = 0; i < SnapRegionsCount; ++i)
{
float angle = (float)i * step;
float cosa = ::cos(angle);
float sina = ::sin(angle);
float in_x = cosa * in_radius;
float in_y = sina * in_radius;
float in_z = 0.0f;
float out_x = cosa * out_radius;
float out_y = sina * out_radius;
float out_z = 0.0f;
::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
}
::glEnd();
}
void GLGizmoRotate::render_reference_radius() const
{
::glBegin(GL_LINES);
::glVertex3f(0.0f, 0.0f, 0.0f);
::glVertex3f((GLfloat)(m_radius * (1.0f + GrabberOffset)), 0.0f, 0.0f);
::glEnd();
}
void GLGizmoRotate::render_angle() const
{
float step_angle = (float)m_angle / AngleResolution;
float ex_radius = m_radius * (1.0f + GrabberOffset);
::glBegin(GL_LINE_STRIP);
for (unsigned int i = 0; i <= AngleResolution; ++i)
{
float angle = (float)i * step_angle;
float x = ::cos(angle) * ex_radius;
float y = ::sin(angle) * ex_radius;
float z = 0.0f;
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
}
::glEnd();
}
void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
{
double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
m_grabbers[0].angles(2) = m_angle;
::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color);
::glBegin(GL_LINES);
::glVertex3f(0.0f, 0.0f, 0.0f);
::glVertex3dv(m_grabbers[0].center.data());
::glEnd();
::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float));
render_grabbers(box);
}
void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const
{
if (m_quadric == nullptr)
return;
double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[0].get_half_size((float)box.max_size());
float color[3];
::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float));
if (!picking && (m_hover_id != -1))
{
color[0] = 1.0f - color[0];
color[1] = 1.0f - color[1];
color[2] = 1.0f - color[2];
}
if (!picking)
::glEnable(GL_LIGHTING);
::glColor3fv(color);
::glPushMatrix();
::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2));
::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0);
::glRotated(90.0, 1.0, 0.0, 0.0);
::glTranslated(0.0, 0.0, 2.0 * size);
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
::glPushMatrix();
::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2));
::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0);
::glRotated(-90.0, 1.0, 0.0, 0.0);
::glTranslated(0.0, 0.0, 2.0 * size);
::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
::gluQuadricOrientation(m_quadric, GLU_INSIDE);
::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
::glPopMatrix();
if (!picking)
::glDisable(GL_LIGHTING);
}
void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) const
{
::glTranslated(m_center(0), m_center(1), m_center(2));
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
{
Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
::glMultMatrixd(orient_matrix.data());
}
switch (m_axis)
{
case X:
{
::glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
break;
}
case Y:
{
::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
break;
}
default:
case Z:
{
// no rotation
break;
}
}
}
Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const
{
double half_pi = 0.5 * (double)PI;
Transform3d m = Transform3d::Identity();
switch (m_axis)
{
case X:
{
m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ()));
m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitY()));
break;
}
case Y:
{
m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitY()));
m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ()));
break;
}
default:
case Z:
{
// no rotation applied
break;
}
}
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse();
m.translate(-m_center);
return transform(mouse_ray, m).intersect_plane(0.0);
}
#if ENABLE_SVG_ICONS
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
{
m_gizmos.emplace_back(parent, GLGizmoRotate::X);
m_gizmos.emplace_back(parent, GLGizmoRotate::Y);
m_gizmos.emplace_back(parent, GLGizmoRotate::Z);
for (unsigned int i = 0; i < 3; ++i)
{
m_gizmos[i].set_group_id(i);
}
}
bool GLGizmoRotate3D::on_init()
{
for (GLGizmoRotate& g : m_gizmos)
{
if (!g.init())
return false;
}
for (unsigned int i = 0; i < 3; ++i)
{
m_gizmos[i].set_highlight_color(AXES_COLOR[i]);
}
m_shortcut_key = WXK_CONTROL_R;
return true;
}
std::string GLGizmoRotate3D::on_get_name() const
{
return L("Rotate [R]");
}
void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].start_dragging(selection);
}
void GLGizmoRotate3D::on_stop_dragging()
{
if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].stop_dragging();
}
void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
{
::glClear(GL_DEPTH_BUFFER_BIT);
if ((m_hover_id == -1) || (m_hover_id == 0))
m_gizmos[X].render(selection);
if ((m_hover_id == -1) || (m_hover_id == 1))
m_gizmos[Y].render(selection);
if ((m_hover_id == -1) || (m_hover_id == 2))
m_gizmos[Z].render(selection);
}
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));
wxString label = _(L("Rotation (deg)"));
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", rotation, 100.0f, "%.2f");
m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,142 @@
#ifndef slic3r_GLGizmoRotate_hpp_
#define slic3r_GLGizmoRotate_hpp_
#include "GLGizmoBase.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoRotate : public GLGizmoBase
{
static const float Offset;
static const unsigned int CircleResolution;
static const unsigned int AngleResolution;
static const unsigned int ScaleStepsCount;
static const float ScaleStepRad;
static const unsigned int ScaleLongEvery;
static const float ScaleLongTooth;
static const unsigned int SnapRegionsCount;
static const float GrabberOffset;
public:
enum Axis : unsigned char
{
X,
Y,
Z
};
private:
Axis m_axis;
double m_angle;
GLUquadricObj* m_quadric;
mutable Vec3d m_center;
mutable float m_radius;
mutable float m_snap_coarse_in_radius;
mutable float m_snap_coarse_out_radius;
mutable float m_snap_fine_in_radius;
mutable float m_snap_fine_out_radius;
public:
GLGizmoRotate(GLCanvas3D& parent, Axis axis);
GLGizmoRotate(const GLGizmoRotate& other);
virtual ~GLGizmoRotate();
double get_angle() const { return m_angle; }
void set_angle(double angle);
protected:
virtual bool on_init();
virtual std::string on_get_name() const { return ""; }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
private:
void render_circle() const;
void render_scale() const;
void render_snap_radii() const;
void render_reference_radius() const;
void render_angle() const;
void render_grabber(const BoundingBoxf3& box) const;
void render_grabber_extension(const BoundingBoxf3& box, bool picking) const;
void transform_to_local(const GLCanvas3D::Selection& selection) const;
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const;
};
class GLGizmoRotate3D : public GLGizmoBase
{
std::vector<GLGizmoRotate> m_gizmos;
public:
#if ENABLE_SVG_ICONS
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual void on_set_state()
{
for (GLGizmoRotate& g : m_gizmos)
{
g.set_state(m_state);
}
}
virtual void on_set_hover_id()
{
for (unsigned int i = 0; i < 3; ++i)
{
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
}
}
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_enable_grabber(unsigned int id)
{
if ((0 <= id) && (id < 3))
m_gizmos[id].enable_grabber(0);
}
virtual void on_disable_grabber(unsigned int id)
{
if ((0 <= id) && (id < 3))
m_gizmos[id].disable_grabber(0);
}
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
for (GLGizmoRotate& g : m_gizmos)
{
g.update(data, selection);
}
}
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
for (const GLGizmoRotate& g : m_gizmos)
{
g.render_for_picking(selection);
}
}
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoRotate_hpp_

View File

@ -0,0 +1,362 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoScale.hpp"
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
const float GLGizmoScale3D::Offset = 5.0f;
#if ENABLE_SVG_ICONS
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
, m_scale(Vec3d::Ones())
, m_snap_step(0.05)
, m_starting_scale(Vec3d::Ones())
{
}
bool GLGizmoScale3D::on_init()
{
for (int i = 0; i < 10; ++i)
{
m_grabbers.push_back(Grabber());
}
double half_pi = 0.5 * (double)PI;
// x axis
m_grabbers[0].angles(1) = half_pi;
m_grabbers[1].angles(1) = half_pi;
// y axis
m_grabbers[2].angles(0) = half_pi;
m_grabbers[3].angles(0) = half_pi;
m_shortcut_key = WXK_CONTROL_S;
return true;
}
std::string GLGizmoScale3D::on_get_name() const
{
return L("Scale [S]");
}
void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1)
{
m_starting_drag_position = m_grabbers[m_hover_id].center;
m_starting_box = selection.get_bounding_box();
}
}
void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
if ((m_hover_id == 0) || (m_hover_id == 1))
do_scale_x(data);
else if ((m_hover_id == 2) || (m_hover_id == 3))
do_scale_y(data);
else if ((m_hover_id == 4) || (m_hover_id == 5))
do_scale_z(data);
else if (m_hover_id >= 6)
do_scale_uniform(data);
}
void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
{
bool single_instance = selection.is_single_full_instance();
bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
bool single_selection = single_instance || single_volume;
Vec3f scale = 100.0f * Vec3f::Ones();
if (single_instance)
scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor().cast<float>();
else if (single_volume)
scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor().cast<float>();
if ((single_selection && ((m_hover_id == 0) || (m_hover_id == 1))) || m_grabbers[0].dragging || m_grabbers[1].dragging)
set_tooltip("X: " + format(scale(0), 4) + "%");
else if (!m_grabbers[0].dragging && !m_grabbers[1].dragging && ((m_hover_id == 0) || (m_hover_id == 1)))
set_tooltip("X");
else if ((single_selection && ((m_hover_id == 2) || (m_hover_id == 3))) || m_grabbers[2].dragging || m_grabbers[3].dragging)
set_tooltip("Y: " + format(scale(1), 4) + "%");
else if (!m_grabbers[2].dragging && !m_grabbers[3].dragging && ((m_hover_id == 2) || (m_hover_id == 3)))
set_tooltip("Y");
else if ((single_selection && ((m_hover_id == 4) || (m_hover_id == 5))) || m_grabbers[4].dragging || m_grabbers[5].dragging)
set_tooltip("Z: " + format(scale(2), 4) + "%");
else if (!m_grabbers[4].dragging && !m_grabbers[5].dragging && ((m_hover_id == 4) || (m_hover_id == 5)))
set_tooltip("Z");
else if ((single_selection && ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9)))
|| m_grabbers[6].dragging || m_grabbers[7].dragging || m_grabbers[8].dragging || m_grabbers[9].dragging)
{
std::string tooltip = "X: " + format(scale(0), 4) + "%\n";
tooltip += "Y: " + format(scale(1), 4) + "%\n";
tooltip += "Z: " + format(scale(2), 4) + "%";
set_tooltip(tooltip);
}
else if (!m_grabbers[6].dragging && !m_grabbers[7].dragging && !m_grabbers[8].dragging && !m_grabbers[9].dragging &&
((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9)))
set_tooltip("X/Y/Z");
::glClear(GL_DEPTH_BUFFER_BIT);
::glEnable(GL_DEPTH_TEST);
BoundingBoxf3 box;
Transform3d transform = Transform3d::Identity();
Vec3d angles = Vec3d::Zero();
Transform3d offsets_transform = Transform3d::Identity();
Vec3d grabber_size = Vec3d::Zero();
if (single_instance)
{
// calculate bounding box in instance local reference system
const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int idx : idxs)
{
const GLVolume* vol = selection.get_volume(idx);
box.merge(vol->bounding_box.transformed(vol->get_volume_transformation().get_matrix()));
}
// gets transform from first selected volume
const GLVolume* v = selection.get_volume(*idxs.begin());
transform = v->get_instance_transformation().get_matrix();
// gets angles from first selected volume
angles = v->get_instance_rotation();
// consider rotation+mirror only components of the transform for offsets
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
grabber_size = v->get_instance_transformation().get_matrix(true, true, false, true) * box.size();
}
else if (single_volume)
{
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
box = v->bounding_box;
transform = v->world_matrix();
angles = Geometry::extract_euler_angles(transform);
// consider rotation+mirror only components of the transform for offsets
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
grabber_size = v->get_volume_transformation().get_matrix(true, true, false, true) * box.size();
}
else
{
box = selection.get_bounding_box();
grabber_size = box.size();
}
m_box = box;
const Vec3d& center = m_box.center();
Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
// x axis
m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x;
m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x;
::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float));
::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float));
// y axis
m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y;
m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y;
::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float));
::memcpy((void*)m_grabbers[3].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float));
// z axis
m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z;
m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z;
::memcpy((void*)m_grabbers[4].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float));
::memcpy((void*)m_grabbers[5].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float));
// uniform
m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y;
m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)) + offset_x - offset_y;
m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)) + offset_x + offset_y;
m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y;
for (int i = 6; i < 10; ++i)
{
::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float));
}
// sets grabbers orientation
for (int i = 0; i < 10; ++i)
{
m_grabbers[i].angles = angles;
}
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
float grabber_mean_size = (float)(grabber_size(0) + grabber_size(1) + grabber_size(2)) / 3.0f;
if (m_hover_id == -1)
{
// draw connections
if (m_grabbers[0].enabled && m_grabbers[1].enabled)
{
::glColor3fv(m_grabbers[0].color);
render_grabbers_connection(0, 1);
}
if (m_grabbers[2].enabled && m_grabbers[3].enabled)
{
::glColor3fv(m_grabbers[2].color);
render_grabbers_connection(2, 3);
}
if (m_grabbers[4].enabled && m_grabbers[5].enabled)
{
::glColor3fv(m_grabbers[4].color);
render_grabbers_connection(4, 5);
}
::glColor3fv(m_base_color);
render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9);
render_grabbers_connection(9, 6);
// draw grabbers
render_grabbers(grabber_mean_size);
}
else if ((m_hover_id == 0) || (m_hover_id == 1))
{
// draw connection
::glColor3fv(m_grabbers[0].color);
render_grabbers_connection(0, 1);
// draw grabbers
m_grabbers[0].render(true, grabber_mean_size);
m_grabbers[1].render(true, grabber_mean_size);
}
else if ((m_hover_id == 2) || (m_hover_id == 3))
{
// draw connection
::glColor3fv(m_grabbers[2].color);
render_grabbers_connection(2, 3);
// draw grabbers
m_grabbers[2].render(true, grabber_mean_size);
m_grabbers[3].render(true, grabber_mean_size);
}
else if ((m_hover_id == 4) || (m_hover_id == 5))
{
// draw connection
::glColor3fv(m_grabbers[4].color);
render_grabbers_connection(4, 5);
// draw grabbers
m_grabbers[4].render(true, grabber_mean_size);
m_grabbers[5].render(true, grabber_mean_size);
}
else if (m_hover_id >= 6)
{
// draw connection
::glColor3fv(m_drag_color);
render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9);
render_grabbers_connection(9, 6);
// draw grabbers
for (int i = 6; i < 10; ++i)
{
m_grabbers[i].render(true, grabber_mean_size);
}
}
}
void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glDisable(GL_DEPTH_TEST);
render_grabbers_for_picking(selection.get_bounding_box());
}
void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
{
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
bool single_instance = selection.is_single_full_instance();
wxString label = _(L("Scale (%)"));
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f");
m_imgui->end();
#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
}
void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const
{
unsigned int grabbers_count = (unsigned int)m_grabbers.size();
if ((id_1 < grabbers_count) && (id_2 < grabbers_count))
{
::glBegin(GL_LINES);
::glVertex3dv(m_grabbers[id_1].center.data());
::glVertex3dv(m_grabbers[id_2].center.data());
::glEnd();
}
}
void GLGizmoScale3D::do_scale_x(const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0)
m_scale(0) = m_starting_scale(0) * ratio;
}
void GLGizmoScale3D::do_scale_y(const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0)
m_scale(1) = m_starting_scale(1) * ratio;
}
void GLGizmoScale3D::do_scale_z(const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0)
m_scale(2) = m_starting_scale(2) * ratio;
}
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0)
m_scale = m_starting_scale * ratio;
}
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
{
double ratio = 0.0;
// vector from the center to the starting position
Vec3d starting_vec = m_starting_drag_position - m_starting_box.center();
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = data.mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
// finds projection of the vector along the staring direction
double proj = inters_vec.dot(starting_vec.normalized());
ratio = (len_starting_vec + proj) / len_starting_vec;
}
if (data.shift_down)
ratio = m_snap_step * (double)std::round(ratio / m_snap_step);
return ratio;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,62 @@
#ifndef slic3r_GLGizmoScale_hpp_
#define slic3r_GLGizmoScale_hpp_
#include "GLGizmoBase.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoScale3D : public GLGizmoBase
{
static const float Offset;
mutable BoundingBoxf3 m_box;
Vec3d m_scale;
double m_snap_step;
Vec3d m_starting_scale;
Vec3d m_starting_drag_position;
BoundingBoxf3 m_starting_box;
public:
#if ENABLE_SVG_ICONS
GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
double get_snap_step(double step) const { return m_snap_step; }
void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_scale() const { return m_scale; }
void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; }
protected:
virtual bool on_init();
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
private:
void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const;
void do_scale_x(const UpdateData& data);
void do_scale_y(const UpdateData& data);
void do_scale_z(const UpdateData& data);
void do_scale_uniform(const UpdateData& data);
double calc_ratio(const UpdateData& data) const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoScale_hpp_

View File

@ -0,0 +1,874 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoSlaSupports.hpp"
#include <GL/glew.h>
#include <wx/msgdlg.h>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/PresetBundle.hpp"
namespace Slic3r {
namespace GUI {
#if ENABLE_SVG_ICONS
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
#else
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id)
: GLGizmoBase(parent, sprite_id)
#endif // ENABLE_SVG_ICONS
, m_starting_center(Vec3d::Zero()), m_quadric(nullptr)
{
m_quadric = ::gluNewQuadric();
if (m_quadric != nullptr)
// using GLU_FILL does not work when the instance's transformation
// contains mirroring (normals are reverted)
::gluQuadricDrawStyle(m_quadric, GLU_FILL);
}
GLGizmoSlaSupports::~GLGizmoSlaSupports()
{
if (m_quadric != nullptr)
::gluDeleteQuadric(m_quadric);
}
bool GLGizmoSlaSupports::on_init()
{
m_shortcut_key = WXK_CONTROL_L;
return true;
}
void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection)
{
m_starting_center = Vec3d::Zero();
m_old_model_object = m_model_object;
m_model_object = model_object;
if (selection.is_empty())
m_old_instance_id = -1;
m_active_instance = selection.get_instance_idx();
if (model_object && selection.is_from_single_instance())
{
if (is_mesh_update_necessary()) {
update_mesh();
editing_mode_reload_cache();
}
if (m_model_object != m_old_model_object)
m_editing_mode = false;
if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified)
get_data_from_backend();
if (m_state == On) {
m_parent.toggle_model_objects_visibility(false);
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
}
}
}
void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const
{
::glEnable(GL_BLEND);
::glEnable(GL_DEPTH_TEST);
render_points(selection, false);
render_selection_rectangle();
::glDisable(GL_BLEND);
}
void GLGizmoSlaSupports::render_selection_rectangle() const
{
if (!m_selection_rectangle_active)
return;
::glLineWidth(1.5f);
float render_color[3] = {1.f, 0.f, 0.f};
::glColor3fv(render_color);
::glPushAttrib(GL_TRANSFORM_BIT); // remember current MatrixMode
::glMatrixMode(GL_MODELVIEW); // cache modelview matrix and set to identity
::glPushMatrix();
::glLoadIdentity();
::glMatrixMode(GL_PROJECTION); // cache projection matrix and set to identity
::glPushMatrix();
::glLoadIdentity();
::glOrtho(0.f, m_canvas_width, m_canvas_height, 0.f, -1.f, 1.f); // set projection matrix so that world coords = window coords
// render the selection rectangle (window coordinates):
::glPushAttrib(GL_ENABLE_BIT);
::glLineStipple(4, 0xAAAA);
::glEnable(GL_LINE_STIPPLE);
::glBegin(GL_LINE_LOOP);
::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f);
::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f);
::glEnd();
::glPopAttrib();
::glPopMatrix(); // restore former projection matrix
::glMatrixMode(GL_MODELVIEW);
::glPopMatrix(); // restore former modelview matrix
::glPopAttrib(); // restore former MatrixMode
}
void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& selection) const
{
::glEnable(GL_DEPTH_TEST);
render_points(selection, true);
}
void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, bool picking) const
{
if (m_quadric == nullptr || !selection.is_from_single_instance())
return;
if (!picking)
::glEnable(GL_LIGHTING);
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
double z_shift = vol->get_sla_shift_z();
const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
::glPushMatrix();
::glTranslated(0.0, 0.0, z_shift);
::glMultMatrixd(instance_matrix.data());
float render_color[3];
for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i)
{
const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point;
const bool& point_selected = m_editing_mode_cache[i].selected;
// First decide about the color of the point.
if (picking) {
std::array<float, 3> color = picking_color_component(i);
render_color[0] = color[0];
render_color[1] = color[1];
render_color[2] = color[2];
}
else {
if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active
render_color[0] = 0.f;
render_color[1] = 1.0f;
render_color[2] = 1.0f;
}
else { // neigher hover nor picking
bool supports_new_island = m_lock_unique_islands && m_editing_mode_cache[i].support_point.is_new_island;
if (m_editing_mode) {
render_color[0] = point_selected ? 1.0f : (supports_new_island ? 0.3f : 0.7f);
render_color[1] = point_selected ? 0.3f : (supports_new_island ? 0.3f : 0.7f);
render_color[2] = point_selected ? 0.3f : (supports_new_island ? 1.0f : 0.7f);
}
else
for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f;
}
}
::glColor3fv(render_color);
float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f};
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
::glPushMatrix();
::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2));
::glMultMatrixd(instance_scaling_matrix_inverse.data());
// Matrices set, we can render the point mark now.
// If in editing mode, we'll also render a cone pointing to the sphere.
if (m_editing_mode) {
if (m_editing_mode_cache[i].normal == Vec3f::Zero())
update_cache_entry_normal(i); // in case the normal is not yet cached, find and cache it
Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_mode_cache[i].normal.cast<double>());
Eigen::AngleAxisd aa(q);
::glRotated(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2));
const float cone_radius = 0.25f; // mm
const float cone_height = 0.75f;
::glPushMatrix();
::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale);
::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 36, 1);
::glTranslatef(0.f, 0.f, cone_height);
::gluDisk(m_quadric, 0.0, cone_radius, 36, 1);
::glPopMatrix();
}
::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 64, 36);
::glPopMatrix();
}
{
// Reset emissive component to zero (the default value)
float render_color_emissive[4] = { 0.f, 0.f, 0.f, 1.f };
::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive);
}
if (!picking)
::glDisable(GL_LIGHTING);
::glPopMatrix();
}
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
{
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
&& ((m_model_object != m_old_model_object) || m_V.size()==0);
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
// return false;
}
void GLGizmoSlaSupports::update_mesh()
{
wxBusyCursor wait;
Eigen::MatrixXf& V = m_V;
Eigen::MatrixXi& F = m_F;
// Composite mesh of all instances in the world coordinate system.
// This mesh does not account for the possible Z up SLA offset.
TriangleMesh mesh = m_model_object->raw_mesh();
const stl_file& stl = mesh.stl;
V.resize(3 * stl.stats.number_of_facets, 3);
F.resize(stl.stats.number_of_facets, 3);
for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
const stl_facet* facet = stl.facet_start+i;
V(3*i+0, 0) = facet->vertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2);
V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2);
V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2);
F(i, 0) = 3*i+0;
F(i, 1) = 3*i+1;
F(i, 2) = 3*i+2;
}
m_AABB = igl::AABB<Eigen::MatrixXf,3>();
m_AABB.init(m_V, m_F);
}
std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
{
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
if (m_V.size() == 0)
update_mesh();
Eigen::Matrix<GLint, 4, 1, Eigen::DontAlign> viewport;
::glGetIntegerv(GL_VIEWPORT, viewport.data());
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> projection_matrix;
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data());
Vec3d point1;
Vec3d point2;
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
igl::Hit hit;
const GLCanvas3D::Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z();
point1(2) -= z_offset;
point2(2) -= z_offset;
Transform3d inv = volume->get_instance_transformation().get_matrix().inverse();
point1 = inv * point1;
point2 = inv * point2;
if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hit))
throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
int fid = hit.id; // facet id
Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit
Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0)));
Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0)));
// Calculate and return both the point and the facet normal.
return std::make_pair(
bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)),
a.cross(b)
);
}
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
// concludes that the event was not intended for it, it should return false.
bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
{
if (m_editing_mode) {
// left down - show the selection rectangle:
if (action == SLAGizmoEventType::LeftDown && shift_down) {
if (m_hover_id == -1) {
m_selection_rectangle_active = true;
m_selection_rectangle_start_corner = mouse_position;
m_selection_rectangle_end_corner = mouse_position;
m_canvas_width = m_parent.get_canvas_size().get_width();
m_canvas_height = m_parent.get_canvas_size().get_height();
}
else
select_point(m_hover_id);
return true;
}
// dragging the selection rectangle:
if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) {
m_selection_rectangle_end_corner = mouse_position;
return true;
}
// mouse up without selection rectangle - place point on the mesh:
if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) {
if (m_ignore_up_event) {
m_ignore_up_event = false;
return false;
}
int instance_id = m_parent.get_selection().get_instance_idx();
if (m_old_instance_id != instance_id)
{
bool something_selected = (m_old_instance_id != -1);
m_old_instance_id = instance_id;
if (something_selected)
return false;
}
if (instance_id == -1)
return false;
// If there is some selection, don't add new point and deselect everything instead.
if (m_selection_empty) {
try {
std::pair<Vec3f, Vec3f> pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws
m_editing_mode_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
m_unsaved_changes = true;
}
catch (...) { // not clicked on object
return true; // prevents deselection of the gizmo by GLCanvas3D
}
}
else
select_point(NoPoints);
return true;
}
// left up with selection rectangle - select points inside the rectangle:
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp)
&& m_selection_rectangle_active) {
if (action == SLAGizmoEventType::ShiftUp)
m_ignore_up_event = true;
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
GLint viewport[4];
::glGetIntegerv(GL_VIEWPORT, viewport);
GLdouble modelview_matrix[16];
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
GLdouble projection_matrix[16];
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
const GLCanvas3D::Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z();
// bounding box created from the rectangle corners - will take care of order of the corners
BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast<int>()), Point(m_selection_rectangle_end_corner.cast<int>())});
const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true);
// we'll recover current look direction from the modelview matrix (in world coords)...
Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]);
// ...and transform it to model coords.
direction_to_camera = (instance_matrix_no_translation.inverse().cast<float>() * direction_to_camera).normalized().eval();
// Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh:
for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i) {
const sla::SupportPoint &support_point = m_editing_mode_cache[i].support_point;
Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
pos(2) += z_offset;
GLdouble out_x, out_y, out_z;
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
out_y = m_canvas_height - out_y;
if (rectangle.contains(Point(out_x, out_y))) {
bool is_obscured = false;
// Cast a ray in the direction of the camera and look for intersection with the mesh:
std::vector<igl::Hit> hits;
// Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies.
if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera * (support_point.head_front_radius + EPSILON), direction_to_camera, hits))
// FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction.
// Also, the threshold is in mesh coordinates, not in actual dimensions.
if (hits.size() > 1 || hits.front().t > 0.001f)
is_obscured = true;
if (!is_obscured)
select_point(i);
}
}
m_selection_rectangle_active = false;
return true;
}
if (action == SLAGizmoEventType::Delete) {
// delete key pressed
delete_selected_points();
return true;
}
if (action == SLAGizmoEventType::ApplyChanges) {
editing_mode_apply_changes();
return true;
}
if (action == SLAGizmoEventType::DiscardChanges) {
editing_mode_discard_changes();
return true;
}
if (action == SLAGizmoEventType::RightDown) {
if (m_hover_id != -1) {
select_point(NoPoints);
select_point(m_hover_id);
delete_selected_points();
return true;
}
return false;
}
if (action == SLAGizmoEventType::SelectAll) {
select_point(AllPoints);
return true;
}
}
if (!m_editing_mode) {
if (action == SLAGizmoEventType::AutomaticGeneration) {
auto_generate();
return true;
}
if (action == SLAGizmoEventType::ManualEditing) {
switch_to_editing_mode();
return true;
}
}
return false;
}
void GLGizmoSlaSupports::delete_selected_points(bool force)
{
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
if (m_editing_mode_cache[idx].selected && (!m_editing_mode_cache[idx].support_point.is_new_island || !m_lock_unique_islands || force)) {
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
m_unsaved_changes = true;
}
// This should trigger the support generation
// wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
}
select_point(NoPoints);
//m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
{
if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) {
std::pair<Vec3f, Vec3f> pos_and_normal;
try {
pos_and_normal = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1)));
}
catch (...) { return; }
m_editing_mode_cache[m_hover_id].support_point.pos = pos_and_normal.first;
m_editing_mode_cache[m_hover_id].support_point.is_new_island = false;
m_editing_mode_cache[m_hover_id].normal = pos_and_normal.second;
m_unsaved_changes = true;
// Do not update immediately, wait until the mouse is released.
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
}
std::vector<const ConfigOption*> GLGizmoSlaSupports::get_config_options(const std::vector<std::string>& keys) const
{
std::vector<const ConfigOption*> out;
if (!m_model_object)
return out;
const DynamicPrintConfig& object_cfg = m_model_object->config;
const DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
std::unique_ptr<DynamicPrintConfig> default_cfg = nullptr;
for (const std::string& key : keys) {
if (object_cfg.has(key))
out.push_back(object_cfg.option(key));
else
if (print_cfg.has(key))
out.push_back(print_cfg.option(key));
else { // we must get it from defaults
if (default_cfg == nullptr)
default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys));
out.push_back(default_cfg->option(key));
}
}
return out;
}
void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const
{
int idx = 0;
Eigen::Matrix<float, 1, 3> pp = m_editing_mode_cache[i].support_point.pos;
Eigen::Matrix<float, 1, 3> cc;
m_AABB.squared_distance(m_V, m_F, pp, idx, cc);
Vec3f a = (m_V.row(m_F(idx, 1)) - m_V.row(m_F(idx, 0)));
Vec3f b = (m_V.row(m_F(idx, 2)) - m_V.row(m_F(idx, 0)));
m_editing_mode_cache[i].normal = a.cross(b);
}
void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
{
if (!m_model_object)
return;
bool first_run = true; // This is a hack to redraw the button when all points are removed,
// so it is not delayed until the background process finishes.
RENDER_AGAIN:
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
const float scaling = m_imgui->get_style_scaling();
const ImVec2 window_size(285.f * scaling, 300.f * scaling);
ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) ));
ImGui::SetNextWindowSize(ImVec2(window_size));
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
ImGui::PushItemWidth(100.0f);
bool force_refresh = false;
bool remove_selected = false;
bool remove_all = false;
if (m_editing_mode) {
m_imgui->text(_(L("Left mouse click - add point")));
m_imgui->text(_(L("Right mouse click - remove point")));
m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)")));
m_imgui->text(" "); // vertical gap
float diameter_upper_cap = static_cast<ConfigOptionFloat*>(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value;
if (m_new_point_head_diameter > diameter_upper_cap)
m_new_point_head_diameter = diameter_upper_cap;
m_imgui->text(_(L("Head diameter: ")));
ImGui::SameLine();
if (ImGui::SliderFloat("", &m_new_point_head_diameter, 0.1f, diameter_upper_cap, "%.1f")) {
// value was changed
for (auto& cache_entry : m_editing_mode_cache)
if (cache_entry.selected) {
cache_entry.support_point.head_front_radius = m_new_point_head_diameter / 2.f;
m_unsaved_changes = true;
}
}
bool changed = m_lock_unique_islands;
m_imgui->checkbox(_(L("Lock supports under new islands")), m_lock_unique_islands);
force_refresh |= changed != m_lock_unique_islands;
m_imgui->disabled_begin(m_selection_empty);
remove_selected = m_imgui->button(_(L("Remove selected points")));
m_imgui->disabled_end();
m_imgui->disabled_begin(m_editing_mode_cache.empty());
remove_all = m_imgui->button(_(L("Remove all points")));
m_imgui->disabled_end();
m_imgui->text(" "); // vertical gap
if (m_imgui->button(_(L("Apply changes")))) {
editing_mode_apply_changes();
force_refresh = true;
}
ImGui::SameLine();
bool discard_changes = m_imgui->button(_(L("Discard changes")));
if (discard_changes) {
editing_mode_discard_changes();
force_refresh = true;
}
}
else { // not in editing mode:
ImGui::PushItemWidth(100.0f);
m_imgui->text(_(L("Minimal points distance: ")));
ImGui::SameLine();
std::vector<const ConfigOption*> opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"});
float density = static_cast<const ConfigOptionInt*>(opts[0])->value;
float minimal_point_distance = static_cast<const ConfigOptionFloat*>(opts[1])->value;
bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
if (value_changed)
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
m_imgui->text(_(L("Support points density: ")));
ImGui::SameLine();
if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) {
value_changed = true;
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
}
if (value_changed) { // Update side panel
wxTheApp->CallAfter([]() {
wxGetApp().obj_settings()->UpdateAndShow(true);
wxGetApp().obj_list()->update_settings_items();
});
}
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
if (generate)
auto_generate();
m_imgui->text("");
if (m_imgui->button(_(L("Manual editing [M]"))))
switch_to_editing_mode();
m_imgui->disabled_begin(m_editing_mode_cache.empty());
remove_all = m_imgui->button(_(L("Remove all points")));
m_imgui->disabled_end();
m_imgui->text("");
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
(m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS"))));
}
m_imgui->end();
if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode
m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode);
force_refresh = true;
}
m_old_editing_state = m_editing_mode;
if (remove_selected || remove_all) {
force_refresh = false;
m_parent.set_as_dirty();
if (remove_all)
select_point(AllPoints);
delete_selected_points(remove_all);
if (remove_all && !m_editing_mode)
editing_mode_apply_changes();
if (first_run) {
first_run = false;
goto RENDER_AGAIN;
}
}
if (force_refresh)
m_parent.set_as_dirty();
}
bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const
{
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|| !selection.is_from_single_instance())
return false;
// Check that none of the selected volumes is outside.
const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs();
for (const auto& idx : list)
if (selection.get_volume(idx)->is_outside)
return false;
return true;
}
bool GLGizmoSlaSupports::on_is_selectable() const
{
return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA);
}
std::string GLGizmoSlaSupports::on_get_name() const
{
return L("SLA Support Points [L]");
}
void GLGizmoSlaSupports::on_set_state()
{
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
if (is_mesh_update_necessary())
update_mesh();
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
}
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
}
m_old_state = m_state;
}
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
{
if (m_hover_id != -1) {
select_point(NoPoints);
select_point(m_hover_id);
}
}
void GLGizmoSlaSupports::select_point(int i)
{
if (i == AllPoints || i == NoPoints) {
for (auto& point_and_selection : m_editing_mode_cache)
point_and_selection.selected = ( i == AllPoints );
m_selection_empty = (i == NoPoints);
if (i == AllPoints)
m_new_point_head_diameter = m_editing_mode_cache[0].support_point.head_front_radius * 2.f;
}
else {
m_editing_mode_cache[i].selected = true;
m_selection_empty = false;
m_new_point_head_diameter = m_editing_mode_cache[i].support_point.head_front_radius * 2.f;
}
}
void GLGizmoSlaSupports::editing_mode_discard_changes()
{
m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.emplace_back(point, false);
m_editing_mode = false;
m_unsaved_changes = false;
}
void GLGizmoSlaSupports::editing_mode_apply_changes()
{
// If there are no changes, don't touch the front-end. The data in the cache could have been
// taken from the backend and copying them to ModelObject would needlessly invalidate them.
if (m_unsaved_changes) {
m_model_object->sla_points_status = sla::PointsStatus::UserModified;
m_model_object->sla_support_points.clear();
for (const CacheEntry& cache_entry : m_editing_mode_cache)
m_model_object->sla_support_points.push_back(cache_entry.support_point);
// Recalculate support structures once the editing mode is left.
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
}
m_editing_mode = false;
m_unsaved_changes = false;
}
void GLGizmoSlaSupports::editing_mode_reload_cache()
{
m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.emplace_back(point, false);
m_unsaved_changes = false;
}
void GLGizmoSlaSupports::get_data_from_backend()
{
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) {
m_editing_mode_cache.clear();
const std::vector<sla::SupportPoint>& points = po->get_support_points();
auto mat = po->trafo().inverse().cast<float>();
for (unsigned int i=0; i<points.size();++i)
m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false);
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified)
m_model_object->sla_points_status = sla::PointsStatus::AutoGenerated;
break;
}
}
m_unsaved_changes = false;
// We don't copy the data into ModelObject, as this would stop the background processing.
}
void GLGizmoSlaSupports::auto_generate()
{
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L(
"Autogeneration will erase all manually edited points.\n\n"
"Are you sure you want to do it?\n"
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) {
m_model_object->sla_support_points.clear();
m_model_object->sla_points_status = sla::PointsStatus::Generating;
m_editing_mode_cache.clear();
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
}
}
void GLGizmoSlaSupports::switch_to_editing_mode()
{
if (m_model_object->sla_points_status != sla::PointsStatus::AutoGenerated)
editing_mode_reload_cache();
m_unsaved_changes = false;
m_editing_mode = true;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,128 @@
#ifndef slic3r_GLGizmoSlaSupports_hpp_
#define slic3r_GLGizmoSlaSupports_hpp_
#include "GLGizmoBase.hpp"
// There is an L function in igl that would be overridden by our localization macro - let's undefine it...
#undef L
#include <igl/AABB.h>
#include "slic3r/GUI/I18N.hpp" // ...and redefine again when we are done with the igl code
#include "libslic3r/SLA/SLACommon.hpp"
#include "libslic3r/SLAPrint.hpp"
namespace Slic3r {
namespace GUI {
class GLGizmoSlaSupports : public GLGizmoBase
{
private:
ModelObject* m_model_object = nullptr;
ModelObject* m_old_model_object = nullptr;
int m_active_instance = -1;
int m_old_instance_id = -1;
std::pair<Vec3f, Vec3f> unproject_on_mesh(const Vec2d& mouse_pos);
const float RenderPointScale = 1.f;
GLUquadricObj* m_quadric;
Eigen::MatrixXf m_V; // vertices
Eigen::MatrixXi m_F; // facets indices
igl::AABB<Eigen::MatrixXf,3> m_AABB;
struct SourceDataSummary {
Geometry::Transformation transformation;
};
class CacheEntry {
public:
CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) :
support_point(point), selected(sel), normal(norm) {}
sla::SupportPoint support_point;
bool selected; // whether the point is selected
Vec3f normal;
};
// This holds information to decide whether recalculation is necessary:
SourceDataSummary m_source_data;
mutable Vec3d m_starting_center;
public:
#if ENABLE_SVG_ICONS
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
#else
GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_selected_points(bool force = false);
std::pair<float, float> get_sla_clipping_plane() const;
private:
bool on_init();
void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
void render_selection_rectangle() const;
void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const;
bool is_mesh_update_necessary() const;
void update_mesh();
void update_cache_entry_normal(unsigned int i) const;
bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active?
bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
float m_new_point_head_diameter; // Size of a new point.
float m_minimal_point_distance = 20.f;
float m_density = 100.f;
mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
float m_clipping_plane_distance = 0.f;
bool m_selection_rectangle_active = false;
Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner;
bool m_ignore_up_event = false;
bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox.
bool m_unsaved_changes = false; // Are there unsaved changes in manual mode?
bool m_selection_empty = true;
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
int m_canvas_width;
int m_canvas_height;
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
// Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc:
enum {
AllPoints = -2,
NoPoints,
};
void select_point(int i);
void editing_mode_apply_changes();
void editing_mode_discard_changes();
void editing_mode_reload_cache();
void get_data_from_backend();
void auto_generate();
void switch_to_editing_mode();
protected:
void on_set_state() override;
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override;
virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
virtual bool on_is_selectable() const;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoSlaSupports_hpp_

View File

@ -0,0 +1,11 @@
#ifndef slic3r_GLGizmos_hpp_
#define slic3r_GLGizmos_hpp_
#include "slic3r/GUI/Gizmos/GLGizmoMove.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoScale.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoRotate.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
#endif //slic3r_GLGizmos_hpp_

View File

@ -56,7 +56,8 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
// initialize default width_unit according to the width of the one symbol ("x") of the current system font
const wxSize size = GetTextExtent("m");
wxGetApp().set_em_unit(size.x-1);
// wxGetApp().set_em_unit(size.x-1);
wxGetApp().set_em_unit(std::max<size_t>(10, size.x - 1));
// initialize tabpanel and menubar
init_tabpanel();
@ -76,12 +77,14 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
sizer->SetSizeHints(this);
SetSizer(sizer);
Fit();
const wxSize min_size = wxSize(76*wxGetApp().em_unit(), 49*wxGetApp().em_unit());
#ifdef __APPLE__
// Using SetMinSize() on Mac messes up the window position in some cases
// cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
SetSize(wxSize(760, 490));
SetSize(min_size/*wxSize(760, 490)*/);
#else
SetMinSize(wxSize(760, 490));
SetMinSize(min_size/*wxSize(760, 490)*/);
SetSize(GetMinSize());
#endif
Layout();

View File

@ -51,8 +51,6 @@ public:
int get_extruder_idx() const { return extruder_idx; }
void check_selection();
std::string selected_preset_name;
private:
typedef std::size_t Marker;
enum { LABEL_ITEM_MARKER = 0x4d };

View File

@ -879,8 +879,7 @@ size_t PresetCollection::update_compatible_internal(const Preset &active_printer
// Hide the
void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui)
{
if (ui == nullptr ||
ui->selected_preset_name == this->get_selected_preset().name)
if (ui == nullptr)
return;
// Otherwise fill in the list from scratch.
@ -951,8 +950,6 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui)
ui->SetSelection(selected_preset_item);
ui->SetToolTip(ui->GetString(selected_preset_item));
ui->Thaw();
ui->selected_preset_name = this->get_selected_preset().name;
}
size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible)

View File

@ -1436,8 +1436,7 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out
void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
{
if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA ||
this->filament_presets.size() <= idx_extruder ||
ui->selected_preset_name == this->filaments.find_preset(this->filament_presets[idx_extruder])->name)
this->filament_presets.size() <= idx_extruder )
return;
unsigned char rgb[3];
@ -1526,8 +1525,6 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr
ui->SetSelection(selected_preset_item);
ui->SetToolTip(ui->GetString(selected_preset_item));
ui->Thaw();
ui->selected_preset_name = this->filaments.find_preset(this->filament_presets[idx_extruder])->name;
}
void PresetBundle::set_default_suppressed(bool default_suppressed)

View File

@ -2606,7 +2606,7 @@ void Tab::select_preset(std::string preset_name)
} else {
if (current_dirty)
m_presets->discard_current_changes();
m_presets->select_preset_by_name(preset_name, false);
const bool is_selected = m_presets->select_preset_by_name(preset_name, false);
// Mark the print & filament enabled if they are compatible with the currently selected preset.
// The following method should not discard changes of current print or filament presets on change of a printer profile,
// if they are compatible with the current printer.
@ -2615,6 +2615,28 @@ void Tab::select_preset(std::string preset_name)
// Initialize the UI from the current preset.
if (printer_tab)
static_cast<TabPrinter*>(this)->update_pages();
if (!is_selected && printer_tab)
{
/* There is a case, when :
* after Config Wizard applying we try to select previously selected preset, but
* in a current configuration this one:
* 1. doesn't exist now,
* 2. have another printer_technology
* So, it is necessary to update list of dependent tabs
* to the corresponding printer_technology
*/
const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology();
if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT ||
printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT )
{
m_dependent_tabs.clear();
if (printer_technology == ptFFF)
m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT };
else
m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL };
}
}
load_current_preset();
}
}

View File

@ -2,7 +2,7 @@
# (the version numbers are generated by the build script from the git current label)
set(SLIC3R_FORK_NAME "Slic3r Prusa Edition")
set(SLIC3R_VERSION "1.42.0-alpha7")
set(SLIC3R_VERSION "1.42.0-beta")
set(SLIC3R_BUILD "${SLIC3R_VERSION}+UNKNOWN")
set(SLIC3R_BUILD_ID "${SLIC3R_BUILD_ID}")
set(SLIC3R_RC_VERSION "1,42,0,0")