Merge remote-tracking branch 'remotes/origin/master' into vb_faster_tabs
This commit is contained in:
commit
b5894d334c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
return false;
|
||||
//continue;
|
||||
boost::nowide::cerr << "Unknown option --" << token.c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -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>";
|
||||
|
@ -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();
|
||||
|
@ -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
@ -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_
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define slic3r_GLTexture_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class wxImage;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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(); }
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
281
src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
Normal file
281
src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
Normal 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
|
182
src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
Normal file
182
src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
Normal 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_
|
257
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
Normal file
257
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
Normal 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
|
53
src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
Normal file
53
src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
Normal 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_
|
357
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
Normal file
357
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
Normal 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
|
67
src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
Normal file
67
src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
Normal 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_
|
255
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
Normal file
255
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
Normal 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
|
57
src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
Normal file
57
src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
Normal 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_
|
503
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
Normal file
503
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
Normal 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
|
142
src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
Normal file
142
src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
Normal 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_
|
362
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
Normal file
362
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
Normal 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
|
62
src/slic3r/GUI/Gizmos/GLGizmoScale.hpp
Normal file
62
src/slic3r/GUI/Gizmos/GLGizmoScale.hpp
Normal 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_
|
874
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
Normal file
874
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
Normal 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
|
128
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
Normal file
128
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
Normal 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_
|
11
src/slic3r/GUI/Gizmos/GLGizmos.hpp
Normal file
11
src/slic3r/GUI/Gizmos/GLGizmos.hpp
Normal 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_
|
@ -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();
|
||||
|
@ -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 };
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user